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