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