1 /* maverick.c -- Cirrus/DSP co-processor interface. 2 Copyright (C) 2003-2017 Free Software Foundation, Inc. 3 Contributed by Aldy Hernandez (aldyh@redhat.com). 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #include <assert.h> 19 #include "armdefs.h" 20 #include "ansidecl.h" 21 #include "armemu.h" 22 23 /*#define CIRRUS_DEBUG 1 */ 24 #if CIRRUS_DEBUG 25 # define printfdbg printf 26 #else 27 # define printfdbg printf_nothing 28 #endif 29 30 #define POS64(i) ( (~(i)) >> 63 ) 31 #define NEG64(i) ( (i) >> 63 ) 32 33 /* Define Co-Processor instruction handlers here. */ 34 35 /* Here's ARMulator's DSP definition. A few things to note: 36 1) it has 16 64-bit registers and 4 72-bit accumulators 37 2) you can only access its registers with MCR and MRC. */ 38 39 /* We can't define these in here because this file might not be linked 40 unless the target is arm9e-*. They are defined in wrapper.c. 41 Eventually the simulator should be made to handle any coprocessor 42 at run time. */ 43 struct maverick_regs 44 { 45 union 46 { 47 int i; 48 float f; 49 } upper; 50 51 union 52 { 53 int i; 54 float f; 55 } lower; 56 }; 57 58 union maverick_acc_regs 59 { 60 long double ld; /* Acc registers are 72-bits. */ 61 }; 62 63 struct maverick_regs DSPregs[16]; 64 union maverick_acc_regs DSPacc[4]; 65 ARMword DSPsc; 66 67 #define DEST_REG (BITS (12, 15)) 68 #define SRC1_REG (BITS (16, 19)) 69 #define SRC2_REG (BITS (0, 3)) 70 71 static int lsw_int_index, msw_int_index; 72 static int lsw_float_index, msw_float_index; 73 74 static double mv_getRegDouble (int); 75 static long long mv_getReg64int (int); 76 static void mv_setRegDouble (int, double val); 77 static void mv_setReg64int (int, long long val); 78 79 static union 80 { 81 double d; 82 long long ll; 83 int ints[2]; 84 } reg_conv; 85 86 static void 87 printf_nothing (void * foo, ...) 88 { 89 } 90 91 static void 92 cirrus_not_implemented (char * insn) 93 { 94 fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn); 95 fprintf (stderr, "aborting!\n"); 96 97 exit (1); 98 } 99 100 unsigned 101 DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED, 102 unsigned type ATTRIBUTE_UNUSED, 103 ARMword instr, 104 ARMword * value) 105 { 106 switch (BITS (5, 7)) 107 { 108 case 0: /* cfmvrdl */ 109 /* Move lower half of a DF stored in a DSP reg into an Arm reg. */ 110 printfdbg ("cfmvrdl\n"); 111 printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i); 112 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); 113 114 *value = (ARMword) DSPregs[SRC1_REG].lower.i; 115 break; 116 117 case 1: /* cfmvrdh */ 118 /* Move upper half of a DF stored in a DSP reg into an Arm reg. */ 119 printfdbg ("cfmvrdh\n"); 120 printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i); 121 printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); 122 123 *value = (ARMword) DSPregs[SRC1_REG].upper.i; 124 break; 125 126 case 2: /* cfmvrs */ 127 /* Move SF from upper half of a DSP register to an Arm register. */ 128 *value = (ARMword) DSPregs[SRC1_REG].upper.i; 129 printfdbg ("cfmvrs = mvf%d <-- %f\n", 130 SRC1_REG, 131 DSPregs[SRC1_REG].upper.f); 132 break; 133 134 #ifdef doesnt_work 135 case 4: /* cfcmps */ 136 { 137 float a, b; 138 int n, z, c, v; 139 140 a = DSPregs[SRC1_REG].upper.f; 141 b = DSPregs[SRC2_REG].upper.f; 142 143 printfdbg ("cfcmps\n"); 144 printfdbg ("\tcomparing %f and %f\n", a, b); 145 146 z = a == b; /* zero */ 147 n = a != b; /* negative */ 148 v = a > b; /* overflow */ 149 c = 0; /* carry */ 150 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 151 break; 152 } 153 154 case 5: /* cfcmpd */ 155 { 156 double a, b; 157 int n, z, c, v; 158 159 a = mv_getRegDouble (SRC1_REG); 160 b = mv_getRegDouble (SRC2_REG); 161 162 printfdbg ("cfcmpd\n"); 163 printfdbg ("\tcomparing %g and %g\n", a, b); 164 165 z = a == b; /* zero */ 166 n = a != b; /* negative */ 167 v = a > b; /* overflow */ 168 c = 0; /* carry */ 169 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 170 break; 171 } 172 #else 173 case 4: /* cfcmps */ 174 { 175 float a, b; 176 int n, z, c, v; 177 178 a = DSPregs[SRC1_REG].upper.f; 179 b = DSPregs[SRC2_REG].upper.f; 180 181 printfdbg ("cfcmps\n"); 182 printfdbg ("\tcomparing %f and %f\n", a, b); 183 184 z = a == b; /* zero */ 185 n = a < b; /* negative */ 186 c = a > b; /* carry */ 187 v = 0; /* fixme */ 188 printfdbg ("\tz = %d, n = %d\n", z, n); 189 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 190 break; 191 } 192 193 case 5: /* cfcmpd */ 194 { 195 double a, b; 196 int n, z, c, v; 197 198 a = mv_getRegDouble (SRC1_REG); 199 b = mv_getRegDouble (SRC2_REG); 200 201 printfdbg ("cfcmpd\n"); 202 printfdbg ("\tcomparing %g and %g\n", a, b); 203 204 z = a == b; /* zero */ 205 n = a < b; /* negative */ 206 c = a > b; /* carry */ 207 v = 0; /* fixme */ 208 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 209 break; 210 } 211 #endif 212 default: 213 fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr); 214 cirrus_not_implemented ("unknown"); 215 break; 216 } 217 218 return ARMul_DONE; 219 } 220 221 unsigned 222 DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED, 223 unsigned type ATTRIBUTE_UNUSED, 224 ARMword instr, 225 ARMword * value) 226 { 227 switch (BITS (5, 7)) 228 { 229 case 0: /* cfmvr64l */ 230 /* Move lower half of 64bit int from Cirrus to Arm. */ 231 *value = (ARMword) DSPregs[SRC1_REG].lower.i; 232 printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n", 233 DEST_REG, 234 (int) *value); 235 break; 236 237 case 1: /* cfmvr64h */ 238 /* Move upper half of 64bit int from Cirrus to Arm. */ 239 *value = (ARMword) DSPregs[SRC1_REG].upper.i; 240 printfdbg ("cfmvr64h <-- %d\n", (int) *value); 241 break; 242 243 case 4: /* cfcmp32 */ 244 { 245 int res; 246 int n, z, c, v; 247 unsigned int a, b; 248 249 printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", 250 SRC1_REG, 251 SRC2_REG); 252 253 /* FIXME: see comment for cfcmps. */ 254 a = DSPregs[SRC1_REG].lower.i; 255 b = DSPregs[SRC2_REG].lower.i; 256 257 res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i; 258 /* zero */ 259 z = res == 0; 260 /* negative */ 261 n = res < 0; 262 /* overflow */ 263 v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i, 264 res); 265 /* carry */ 266 c = (NEG (a) && POS (b)) 267 || (NEG (a) && POS (res)) 268 || (POS (b) && POS (res)); 269 270 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 271 break; 272 } 273 274 case 5: /* cfcmp64 */ 275 { 276 long long res; 277 int n, z, c, v; 278 unsigned long long a, b; 279 280 printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", 281 SRC1_REG, 282 SRC2_REG); 283 284 /* fixme: see comment for cfcmps. */ 285 286 a = mv_getReg64int (SRC1_REG); 287 b = mv_getReg64int (SRC2_REG); 288 289 res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG); 290 /* zero */ 291 z = res == 0; 292 /* negative */ 293 n = res < 0; 294 /* overflow */ 295 v = ((NEG64 (a) && POS64 (b) && POS64 (res)) 296 || (POS64 (a) && NEG64 (b) && NEG64 (res))); 297 /* carry */ 298 c = (NEG64 (a) && POS64 (b)) 299 || (NEG64 (a) && POS64 (res)) 300 || (POS64 (b) && POS64 (res)); 301 302 *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); 303 break; 304 } 305 306 default: 307 fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr); 308 cirrus_not_implemented ("unknown"); 309 break; 310 } 311 312 return ARMul_DONE; 313 } 314 315 unsigned 316 DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED, 317 unsigned type ATTRIBUTE_UNUSED, 318 ARMword instr, 319 ARMword * value) 320 { 321 switch (BITS (5, 7)) 322 { 323 case 0: /* cfmval32 */ 324 cirrus_not_implemented ("cfmval32"); 325 break; 326 327 case 1: /* cfmvam32 */ 328 cirrus_not_implemented ("cfmvam32"); 329 break; 330 331 case 2: /* cfmvah32 */ 332 cirrus_not_implemented ("cfmvah32"); 333 break; 334 335 case 3: /* cfmva32 */ 336 cirrus_not_implemented ("cfmva32"); 337 break; 338 339 case 4: /* cfmva64 */ 340 cirrus_not_implemented ("cfmva64"); 341 break; 342 343 case 5: /* cfmvsc32 */ 344 cirrus_not_implemented ("cfmvsc32"); 345 break; 346 347 default: 348 fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr); 349 cirrus_not_implemented ("unknown"); 350 break; 351 } 352 353 return ARMul_DONE; 354 } 355 356 unsigned 357 DSPMCR4 (ARMul_State * state, 358 unsigned type ATTRIBUTE_UNUSED, 359 ARMword instr, 360 ARMword value) 361 { 362 switch (BITS (5, 7)) 363 { 364 case 0: /* cfmvdlr */ 365 /* Move the lower half of a DF value from an Arm register into 366 the lower half of a Cirrus register. */ 367 printfdbg ("cfmvdlr <-- 0x%x\n", (int) value); 368 DSPregs[SRC1_REG].lower.i = (int) value; 369 break; 370 371 case 1: /* cfmvdhr */ 372 /* Move the upper half of a DF value from an Arm register into 373 the upper half of a Cirrus register. */ 374 printfdbg ("cfmvdhr <-- 0x%x\n", (int) value); 375 DSPregs[SRC1_REG].upper.i = (int) value; 376 break; 377 378 case 2: /* cfmvsr */ 379 /* Move SF from Arm register into upper half of Cirrus register. */ 380 printfdbg ("cfmvsr <-- 0x%x\n", (int) value); 381 DSPregs[SRC1_REG].upper.i = (int) value; 382 break; 383 384 default: 385 fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr); 386 cirrus_not_implemented ("unknown"); 387 break; 388 } 389 390 return ARMul_DONE; 391 } 392 393 unsigned 394 DSPMCR5 (ARMul_State * state, 395 unsigned type ATTRIBUTE_UNUSED, 396 ARMword instr, 397 ARMword value) 398 { 399 union 400 { 401 int s; 402 unsigned int us; 403 } val; 404 405 switch (BITS (5, 7)) 406 { 407 case 0: /* cfmv64lr */ 408 /* Move lower half of a 64bit int from an ARM register into the 409 lower half of a DSP register and sign extend it. */ 410 printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value); 411 DSPregs[SRC1_REG].lower.i = (int) value; 412 break; 413 414 case 1: /* cfmv64hr */ 415 /* Move upper half of a 64bit int from an ARM register into the 416 upper half of a DSP register. */ 417 printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n", 418 SRC1_REG, 419 (int) value); 420 DSPregs[SRC1_REG].upper.i = (int) value; 421 break; 422 423 case 2: /* cfrshl32 */ 424 printfdbg ("cfrshl32\n"); 425 val.us = value; 426 if (val.s > 0) 427 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value; 428 else 429 DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value; 430 break; 431 432 case 3: /* cfrshl64 */ 433 printfdbg ("cfrshl64\n"); 434 val.us = value; 435 if (val.s > 0) 436 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value); 437 else 438 mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value); 439 break; 440 441 default: 442 fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr); 443 cirrus_not_implemented ("unknown"); 444 break; 445 } 446 447 return ARMul_DONE; 448 } 449 450 unsigned 451 DSPMCR6 (ARMul_State * state, 452 unsigned type ATTRIBUTE_UNUSED, 453 ARMword instr, 454 ARMword value) 455 { 456 switch (BITS (5, 7)) 457 { 458 case 0: /* cfmv32al */ 459 cirrus_not_implemented ("cfmv32al"); 460 break; 461 462 case 1: /* cfmv32am */ 463 cirrus_not_implemented ("cfmv32am"); 464 break; 465 466 case 2: /* cfmv32ah */ 467 cirrus_not_implemented ("cfmv32ah"); 468 break; 469 470 case 3: /* cfmv32a */ 471 cirrus_not_implemented ("cfmv32a"); 472 break; 473 474 case 4: /* cfmv64a */ 475 cirrus_not_implemented ("cfmv64a"); 476 break; 477 478 case 5: /* cfmv32sc */ 479 cirrus_not_implemented ("cfmv32sc"); 480 break; 481 482 default: 483 fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr); 484 cirrus_not_implemented ("unknown"); 485 break; 486 } 487 488 return ARMul_DONE; 489 } 490 491 unsigned 492 DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED, 493 unsigned type, 494 ARMword instr, 495 ARMword data) 496 { 497 static unsigned words; 498 499 if (type != ARMul_DATA) 500 { 501 words = 0; 502 return ARMul_DONE; 503 } 504 505 if (BIT (22)) 506 { /* it's a long access, get two words */ 507 /* cfldrd */ 508 509 printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n", 510 data, words, state->bigendSig, DEST_REG); 511 512 if (words == 0) 513 { 514 if (state->bigendSig) 515 DSPregs[DEST_REG].upper.i = (int) data; 516 else 517 DSPregs[DEST_REG].lower.i = (int) data; 518 } 519 else 520 { 521 if (state->bigendSig) 522 DSPregs[DEST_REG].lower.i = (int) data; 523 else 524 DSPregs[DEST_REG].upper.i = (int) data; 525 } 526 527 ++ words; 528 529 if (words == 2) 530 { 531 printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG, 532 mv_getRegDouble (DEST_REG)); 533 534 return ARMul_DONE; 535 } 536 else 537 return ARMul_INC; 538 } 539 else 540 { 541 /* Get just one word. */ 542 543 /* cfldrs */ 544 printfdbg ("cfldrs\n"); 545 546 DSPregs[DEST_REG].upper.i = (int) data; 547 548 printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG, 549 DSPregs[DEST_REG].upper.f); 550 551 return ARMul_DONE; 552 } 553 } 554 555 unsigned 556 DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED, 557 unsigned type, 558 ARMword instr, 559 ARMword data) 560 { 561 static unsigned words; 562 563 if (type != ARMul_DATA) 564 { 565 words = 0; 566 return ARMul_DONE; 567 } 568 569 if (BIT (22)) 570 { 571 /* It's a long access, get two words. */ 572 573 /* cfldr64 */ 574 printfdbg ("cfldr64: %d\n", data); 575 576 if (words == 0) 577 { 578 if (state->bigendSig) 579 DSPregs[DEST_REG].upper.i = (int) data; 580 else 581 DSPregs[DEST_REG].lower.i = (int) data; 582 } 583 else 584 { 585 if (state->bigendSig) 586 DSPregs[DEST_REG].lower.i = (int) data; 587 else 588 DSPregs[DEST_REG].upper.i = (int) data; 589 } 590 591 ++ words; 592 593 if (words == 2) 594 { 595 printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG, 596 mv_getReg64int (DEST_REG)); 597 598 return ARMul_DONE; 599 } 600 else 601 return ARMul_INC; 602 } 603 else 604 { 605 /* Get just one word. */ 606 607 /* cfldr32 */ 608 printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data); 609 610 /* 32bit ints should be sign extended to 64bits when loaded. */ 611 mv_setReg64int (DEST_REG, (long long) data); 612 613 return ARMul_DONE; 614 } 615 } 616 617 unsigned 618 DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED, 619 unsigned type, 620 ARMword instr, 621 ARMword * data) 622 { 623 static unsigned words; 624 625 if (type != ARMul_DATA) 626 { 627 words = 0; 628 return ARMul_DONE; 629 } 630 631 if (BIT (22)) 632 { 633 /* It's a long access, get two words. */ 634 /* cfstrd */ 635 printfdbg ("cfstrd\n"); 636 637 if (words == 0) 638 { 639 if (state->bigendSig) 640 *data = (ARMword) DSPregs[DEST_REG].upper.i; 641 else 642 *data = (ARMword) DSPregs[DEST_REG].lower.i; 643 } 644 else 645 { 646 if (state->bigendSig) 647 *data = (ARMword) DSPregs[DEST_REG].lower.i; 648 else 649 *data = (ARMword) DSPregs[DEST_REG].upper.i; 650 } 651 652 ++ words; 653 654 if (words == 2) 655 { 656 printfdbg ("\tmem = mvd%d = %g\n", DEST_REG, 657 mv_getRegDouble (DEST_REG)); 658 659 return ARMul_DONE; 660 } 661 else 662 return ARMul_INC; 663 } 664 else 665 { 666 /* Get just one word. */ 667 /* cfstrs */ 668 printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG, 669 DSPregs[DEST_REG].upper.f); 670 671 *data = (ARMword) DSPregs[DEST_REG].upper.i; 672 673 return ARMul_DONE; 674 } 675 } 676 677 unsigned 678 DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED, 679 unsigned type, 680 ARMword instr, 681 ARMword * data) 682 { 683 static unsigned words; 684 685 if (type != ARMul_DATA) 686 { 687 words = 0; 688 return ARMul_DONE; 689 } 690 691 if (BIT (22)) 692 { 693 /* It's a long access, store two words. */ 694 /* cfstr64 */ 695 printfdbg ("cfstr64\n"); 696 697 if (words == 0) 698 { 699 if (state->bigendSig) 700 *data = (ARMword) DSPregs[DEST_REG].upper.i; 701 else 702 *data = (ARMword) DSPregs[DEST_REG].lower.i; 703 } 704 else 705 { 706 if (state->bigendSig) 707 *data = (ARMword) DSPregs[DEST_REG].lower.i; 708 else 709 *data = (ARMword) DSPregs[DEST_REG].upper.i; 710 } 711 712 ++ words; 713 714 if (words == 2) 715 { 716 printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG, 717 mv_getReg64int (DEST_REG)); 718 719 return ARMul_DONE; 720 } 721 else 722 return ARMul_INC; 723 } 724 else 725 { 726 /* Store just one word. */ 727 /* cfstr32 */ 728 *data = (ARMword) DSPregs[DEST_REG].lower.i; 729 730 printfdbg ("cfstr32 MEM = %d\n", (int) *data); 731 732 return ARMul_DONE; 733 } 734 } 735 736 unsigned 737 DSPCDP4 (ARMul_State * state, 738 unsigned type, 739 ARMword instr) 740 { 741 int opcode2; 742 743 opcode2 = BITS (5,7); 744 745 switch (BITS (20,21)) 746 { 747 case 0: 748 switch (opcode2) 749 { 750 case 0: /* cfcpys */ 751 printfdbg ("cfcpys mvf%d = mvf%d = %f\n", 752 DEST_REG, 753 SRC1_REG, 754 DSPregs[SRC1_REG].upper.f); 755 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f; 756 break; 757 758 case 1: /* cfcpyd */ 759 printfdbg ("cfcpyd mvd%d = mvd%d = %g\n", 760 DEST_REG, 761 SRC1_REG, 762 mv_getRegDouble (SRC1_REG)); 763 mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)); 764 break; 765 766 case 2: /* cfcvtds */ 767 printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n", 768 DEST_REG, 769 SRC1_REG, 770 (float) mv_getRegDouble (SRC1_REG)); 771 DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG); 772 break; 773 774 case 3: /* cfcvtsd */ 775 printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n", 776 DEST_REG, 777 SRC1_REG, 778 (double) DSPregs[SRC1_REG].upper.f); 779 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f); 780 break; 781 782 case 4: /* cfcvt32s */ 783 printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n", 784 DEST_REG, 785 SRC1_REG, 786 (float) DSPregs[SRC1_REG].lower.i); 787 DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i; 788 break; 789 790 case 5: /* cfcvt32d */ 791 printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n", 792 DEST_REG, 793 SRC1_REG, 794 (double) DSPregs[SRC1_REG].lower.i); 795 mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i); 796 break; 797 798 case 6: /* cfcvt64s */ 799 printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n", 800 DEST_REG, 801 SRC1_REG, 802 (float) mv_getReg64int (SRC1_REG)); 803 DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG); 804 break; 805 806 case 7: /* cfcvt64d */ 807 printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n", 808 DEST_REG, 809 SRC1_REG, 810 (double) mv_getReg64int (SRC1_REG)); 811 mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG)); 812 break; 813 } 814 break; 815 816 case 1: 817 switch (opcode2) 818 { 819 case 0: /* cfmuls */ 820 printfdbg ("cfmuls mvf%d = mvf%d = %f\n", 821 DEST_REG, 822 SRC1_REG, 823 DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f); 824 825 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f 826 * DSPregs[SRC2_REG].upper.f; 827 break; 828 829 case 1: /* cfmuld */ 830 printfdbg ("cfmuld mvd%d = mvd%d = %g\n", 831 DEST_REG, 832 SRC1_REG, 833 mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG)); 834 835 mv_setRegDouble (DEST_REG, 836 mv_getRegDouble (SRC1_REG) 837 * mv_getRegDouble (SRC2_REG)); 838 break; 839 840 default: 841 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr); 842 cirrus_not_implemented ("unknown"); 843 break; 844 } 845 break; 846 847 case 3: 848 switch (opcode2) 849 { 850 case 0: /* cfabss */ 851 DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ? 852 -DSPregs[SRC1_REG].upper.f 853 : DSPregs[SRC1_REG].upper.f); 854 printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", 855 DEST_REG, 856 SRC1_REG, 857 DSPregs[DEST_REG].upper.f); 858 break; 859 860 case 1: /* cfabsd */ 861 mv_setRegDouble (DEST_REG, 862 (mv_getRegDouble (SRC1_REG) < 0.0 ? 863 -mv_getRegDouble (SRC1_REG) 864 : mv_getRegDouble (SRC1_REG))); 865 printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n", 866 DEST_REG, 867 SRC1_REG, 868 mv_getRegDouble (DEST_REG)); 869 break; 870 871 case 2: /* cfnegs */ 872 DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f; 873 printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", 874 DEST_REG, 875 SRC1_REG, 876 DSPregs[DEST_REG].upper.f); 877 break; 878 879 case 3: /* cfnegd */ 880 mv_setRegDouble (DEST_REG, 881 -mv_getRegDouble (SRC1_REG)); 882 printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", 883 DEST_REG, 884 mv_getRegDouble (DEST_REG)); 885 break; 886 887 case 4: /* cfadds */ 888 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f 889 + DSPregs[SRC2_REG].upper.f; 890 printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n", 891 DEST_REG, 892 SRC1_REG, 893 SRC2_REG, 894 DSPregs[DEST_REG].upper.f); 895 break; 896 897 case 5: /* cfaddd */ 898 mv_setRegDouble (DEST_REG, 899 mv_getRegDouble (SRC1_REG) 900 + mv_getRegDouble (SRC2_REG)); 901 printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n", 902 DEST_REG, 903 SRC1_REG, 904 SRC2_REG, 905 mv_getRegDouble (DEST_REG)); 906 break; 907 908 case 6: /* cfsubs */ 909 DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f 910 - DSPregs[SRC2_REG].upper.f; 911 printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n", 912 DEST_REG, 913 SRC1_REG, 914 SRC2_REG, 915 DSPregs[DEST_REG].upper.f); 916 break; 917 918 case 7: /* cfsubd */ 919 mv_setRegDouble (DEST_REG, 920 mv_getRegDouble (SRC1_REG) 921 - mv_getRegDouble (SRC2_REG)); 922 printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n", 923 DEST_REG, 924 SRC1_REG, 925 SRC2_REG, 926 mv_getRegDouble (DEST_REG)); 927 break; 928 } 929 break; 930 931 default: 932 fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr); 933 cirrus_not_implemented ("unknown"); 934 break; 935 } 936 937 return ARMul_DONE; 938 } 939 940 unsigned 941 DSPCDP5 (ARMul_State * state, 942 unsigned type, 943 ARMword instr) 944 { 945 int opcode2; 946 char shift; 947 948 opcode2 = BITS (5,7); 949 950 /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */ 951 shift = BITS (0, 3) | (BITS (5, 7)) << 4; 952 if (shift & 0x40) 953 shift |= 0xc0; 954 955 switch (BITS (20,21)) 956 { 957 case 0: 958 /* cfsh32 */ 959 printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left", 960 shift); 961 if (shift < 0) 962 /* Negative shift is a right shift. */ 963 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift; 964 else 965 /* Positive shift is a left shift. */ 966 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift; 967 break; 968 969 case 1: 970 switch (opcode2) 971 { 972 case 0: /* cfmul32 */ 973 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i 974 * DSPregs[SRC2_REG].lower.i; 975 printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n", 976 DEST_REG, 977 SRC1_REG, 978 SRC2_REG, 979 DSPregs[DEST_REG].lower.i); 980 break; 981 982 case 1: /* cfmul64 */ 983 mv_setReg64int (DEST_REG, 984 mv_getReg64int (SRC1_REG) 985 * mv_getReg64int (SRC2_REG)); 986 printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n", 987 DEST_REG, 988 SRC1_REG, 989 SRC2_REG, 990 mv_getReg64int (DEST_REG)); 991 break; 992 993 case 2: /* cfmac32 */ 994 DSPregs[DEST_REG].lower.i 995 += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i; 996 printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n", 997 DEST_REG, 998 SRC1_REG, 999 SRC2_REG, 1000 DSPregs[DEST_REG].lower.i); 1001 break; 1002 1003 case 3: /* cfmsc32 */ 1004 DSPregs[DEST_REG].lower.i 1005 -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i; 1006 printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n", 1007 DEST_REG, 1008 SRC1_REG, 1009 SRC2_REG, 1010 DSPregs[DEST_REG].lower.i); 1011 break; 1012 1013 case 4: /* cfcvts32 */ 1014 /* fixme: this should round */ 1015 DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f; 1016 printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", 1017 DEST_REG, 1018 SRC1_REG, 1019 DSPregs[DEST_REG].lower.i); 1020 break; 1021 1022 case 5: /* cfcvtd32 */ 1023 /* fixme: this should round */ 1024 DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG); 1025 printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", 1026 DEST_REG, 1027 SRC1_REG, 1028 DSPregs[DEST_REG].lower.i); 1029 break; 1030 1031 case 6: /* cftruncs32 */ 1032 DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f; 1033 printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n", 1034 DEST_REG, 1035 SRC1_REG, 1036 DSPregs[DEST_REG].lower.i); 1037 break; 1038 1039 case 7: /* cftruncd32 */ 1040 DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG); 1041 printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n", 1042 DEST_REG, 1043 SRC1_REG, 1044 DSPregs[DEST_REG].lower.i); 1045 break; 1046 } 1047 break; 1048 1049 case 2: 1050 /* cfsh64 */ 1051 printfdbg ("cfsh64\n"); 1052 1053 if (shift < 0) 1054 /* Negative shift is a right shift. */ 1055 mv_setReg64int (DEST_REG, 1056 mv_getReg64int (SRC1_REG) >> -shift); 1057 else 1058 /* Positive shift is a left shift. */ 1059 mv_setReg64int (DEST_REG, 1060 mv_getReg64int (SRC1_REG) << shift); 1061 printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG)); 1062 break; 1063 1064 case 3: 1065 switch (opcode2) 1066 { 1067 case 0: /* cfabs32 */ 1068 DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0 1069 ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i); 1070 printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n", 1071 DEST_REG, 1072 SRC1_REG, 1073 SRC2_REG, 1074 DSPregs[DEST_REG].lower.i); 1075 break; 1076 1077 case 1: /* cfabs64 */ 1078 mv_setReg64int (DEST_REG, 1079 (mv_getReg64int (SRC1_REG) < 0 1080 ? -mv_getReg64int (SRC1_REG) 1081 : mv_getReg64int (SRC1_REG))); 1082 printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n", 1083 DEST_REG, 1084 SRC1_REG, 1085 SRC2_REG, 1086 mv_getReg64int (DEST_REG)); 1087 break; 1088 1089 case 2: /* cfneg32 */ 1090 DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i; 1091 printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n", 1092 DEST_REG, 1093 SRC1_REG, 1094 SRC2_REG, 1095 DSPregs[DEST_REG].lower.i); 1096 break; 1097 1098 case 3: /* cfneg64 */ 1099 mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG)); 1100 printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n", 1101 DEST_REG, 1102 SRC1_REG, 1103 SRC2_REG, 1104 mv_getReg64int (DEST_REG)); 1105 break; 1106 1107 case 4: /* cfadd32 */ 1108 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i 1109 + DSPregs[SRC2_REG].lower.i; 1110 printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n", 1111 DEST_REG, 1112 SRC1_REG, 1113 SRC2_REG, 1114 DSPregs[DEST_REG].lower.i); 1115 break; 1116 1117 case 5: /* cfadd64 */ 1118 mv_setReg64int (DEST_REG, 1119 mv_getReg64int (SRC1_REG) 1120 + mv_getReg64int (SRC2_REG)); 1121 printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n", 1122 DEST_REG, 1123 SRC1_REG, 1124 SRC2_REG, 1125 mv_getReg64int (DEST_REG)); 1126 break; 1127 1128 case 6: /* cfsub32 */ 1129 DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i 1130 - DSPregs[SRC2_REG].lower.i; 1131 printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n", 1132 DEST_REG, 1133 SRC1_REG, 1134 SRC2_REG, 1135 DSPregs[DEST_REG].lower.i); 1136 break; 1137 1138 case 7: /* cfsub64 */ 1139 mv_setReg64int (DEST_REG, 1140 mv_getReg64int (SRC1_REG) 1141 - mv_getReg64int (SRC2_REG)); 1142 printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n", 1143 DEST_REG, 1144 SRC1_REG, 1145 SRC2_REG, 1146 mv_getReg64int (DEST_REG)); 1147 break; 1148 } 1149 break; 1150 1151 default: 1152 fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr); 1153 cirrus_not_implemented ("unknown"); 1154 break; 1155 } 1156 1157 return ARMul_DONE; 1158 } 1159 1160 unsigned 1161 DSPCDP6 (ARMul_State * state, 1162 unsigned type, 1163 ARMword instr) 1164 { 1165 switch (BITS (20,21)) 1166 { 1167 case 0: 1168 /* cfmadd32 */ 1169 cirrus_not_implemented ("cfmadd32"); 1170 break; 1171 1172 case 1: 1173 /* cfmsub32 */ 1174 cirrus_not_implemented ("cfmsub32"); 1175 break; 1176 1177 case 2: 1178 /* cfmadda32 */ 1179 cirrus_not_implemented ("cfmadda32"); 1180 break; 1181 1182 case 3: 1183 /* cfmsuba32 */ 1184 cirrus_not_implemented ("cfmsuba32"); 1185 break; 1186 1187 default: 1188 fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr); 1189 } 1190 1191 return ARMul_DONE; 1192 } 1193 1194 /* Conversion functions. 1195 1196 32-bit integers are stored in the LOWER half of a 64-bit physical 1197 register. 1198 1199 Single precision floats are stored in the UPPER half of a 64-bit 1200 physical register. */ 1201 1202 static double 1203 mv_getRegDouble (int regnum) 1204 { 1205 reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i; 1206 reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i; 1207 return reg_conv.d; 1208 } 1209 1210 static void 1211 mv_setRegDouble (int regnum, double val) 1212 { 1213 reg_conv.d = val; 1214 DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index]; 1215 DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index]; 1216 } 1217 1218 static long long 1219 mv_getReg64int (int regnum) 1220 { 1221 reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i; 1222 reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i; 1223 return reg_conv.ll; 1224 } 1225 1226 static void 1227 mv_setReg64int (int regnum, long long val) 1228 { 1229 reg_conv.ll = val; 1230 DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index]; 1231 DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index]; 1232 } 1233