diff options
Diffstat (limited to 'sim/arm/maverick.c')
-rw-r--r-- | sim/arm/maverick.c | 1210 |
1 files changed, 0 insertions, 1210 deletions
diff --git a/sim/arm/maverick.c b/sim/arm/maverick.c deleted file mode 100644 index da5b4ad..0000000 --- a/sim/arm/maverick.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* maverick.c -- Cirrus/DSP co-processor interface. - Copyright (C) 2003-2024 Free Software Foundation, Inc. - Contributed by Aldy Hernandez (aldyh@redhat.com). - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -/* This must come before any other includes. */ -#include "defs.h" - -#include <assert.h> -#include "armdefs.h" -#include "ansidecl.h" -#include "armemu.h" -#include "maverick.h" - -/*#define CIRRUS_DEBUG 1 */ -#if CIRRUS_DEBUG -# define printfdbg printf -#else -# define printfdbg printf_nothing -#endif - -#define POS64(i) ( (~(i)) >> 63 ) -#define NEG64(i) ( (i) >> 63 ) - -/* These variables are defined here and made extern in maverick.h for use - in wrapper.c for now. - Eventually the simulator should be made to handle any coprocessor at run - time. */ -struct maverick_regs DSPregs[16]; -union maverick_acc_regs DSPacc[4]; -ARMword DSPsc; - -#define DEST_REG (BITS (12, 15)) -#define SRC1_REG (BITS (16, 19)) -#define SRC2_REG (BITS (0, 3)) - -static int lsw_int_index, msw_int_index; -static int lsw_float_index, msw_float_index; - -static double mv_getRegDouble (int); -static long long mv_getReg64int (int); -static void mv_setRegDouble (int, double val); -static void mv_setReg64int (int, long long val); - -static union -{ - double d; - long long ll; - int ints[2]; -} reg_conv; - -static void -printf_nothing (void * foo, ...) -{ -} - -static void -cirrus_not_implemented (char * insn) -{ - fprintf (stderr, "Cirrus instruction '%s' not implemented.\n", insn); - fprintf (stderr, "aborting!\n"); - - exit (1); -} - -unsigned -DSPMRC4 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword * value) -{ - switch (BITS (5, 7)) - { - case 0: /* cfmvrdl */ - /* Move lower half of a DF stored in a DSP reg into an Arm reg. */ - printfdbg ("cfmvrdl\n"); - printfdbg ("\tlower half=0x%x\n", DSPregs[SRC1_REG].lower.i); - printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); - - *value = (ARMword) DSPregs[SRC1_REG].lower.i; - break; - - case 1: /* cfmvrdh */ - /* Move upper half of a DF stored in a DSP reg into an Arm reg. */ - printfdbg ("cfmvrdh\n"); - printfdbg ("\tupper half=0x%x\n", DSPregs[SRC1_REG].upper.i); - printfdbg ("\tentire thing=%g\n", mv_getRegDouble (SRC1_REG)); - - *value = (ARMword) DSPregs[SRC1_REG].upper.i; - break; - - case 2: /* cfmvrs */ - /* Move SF from upper half of a DSP register to an Arm register. */ - *value = (ARMword) DSPregs[SRC1_REG].upper.i; - printfdbg ("cfmvrs = mvf%d <-- %f\n", - SRC1_REG, - DSPregs[SRC1_REG].upper.f); - break; - -#ifdef doesnt_work - case 4: /* cfcmps */ - { - float a, b; - int n, z, c, v; - - a = DSPregs[SRC1_REG].upper.f; - b = DSPregs[SRC2_REG].upper.f; - - printfdbg ("cfcmps\n"); - printfdbg ("\tcomparing %f and %f\n", a, b); - - z = a == b; /* zero */ - n = a != b; /* negative */ - v = a > b; /* overflow */ - c = 0; /* carry */ - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } - - case 5: /* cfcmpd */ - { - double a, b; - int n, z, c, v; - - a = mv_getRegDouble (SRC1_REG); - b = mv_getRegDouble (SRC2_REG); - - printfdbg ("cfcmpd\n"); - printfdbg ("\tcomparing %g and %g\n", a, b); - - z = a == b; /* zero */ - n = a != b; /* negative */ - v = a > b; /* overflow */ - c = 0; /* carry */ - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } -#else - case 4: /* cfcmps */ - { - float a, b; - int n, z, c, v; - - a = DSPregs[SRC1_REG].upper.f; - b = DSPregs[SRC2_REG].upper.f; - - printfdbg ("cfcmps\n"); - printfdbg ("\tcomparing %f and %f\n", a, b); - - z = a == b; /* zero */ - n = a < b; /* negative */ - c = a > b; /* carry */ - v = 0; /* fixme */ - printfdbg ("\tz = %d, n = %d\n", z, n); - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } - - case 5: /* cfcmpd */ - { - double a, b; - int n, z, c, v; - - a = mv_getRegDouble (SRC1_REG); - b = mv_getRegDouble (SRC2_REG); - - printfdbg ("cfcmpd\n"); - printfdbg ("\tcomparing %g and %g\n", a, b); - - z = a == b; /* zero */ - n = a < b; /* negative */ - c = a > b; /* carry */ - v = 0; /* fixme */ - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } -#endif - default: - fprintf (stderr, "unknown opcode in DSPMRC4 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPMRC5 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword * value) -{ - switch (BITS (5, 7)) - { - case 0: /* cfmvr64l */ - /* Move lower half of 64bit int from Cirrus to Arm. */ - *value = (ARMword) DSPregs[SRC1_REG].lower.i; - printfdbg ("cfmvr64l ARM_REG = mvfx%d <-- %d\n", - DEST_REG, - (int) *value); - break; - - case 1: /* cfmvr64h */ - /* Move upper half of 64bit int from Cirrus to Arm. */ - *value = (ARMword) DSPregs[SRC1_REG].upper.i; - printfdbg ("cfmvr64h <-- %d\n", (int) *value); - break; - - case 4: /* cfcmp32 */ - { - int res; - int n, z, c, v; - unsigned int a, b; - - printfdbg ("cfcmp32 mvfx%d - mvfx%d\n", - SRC1_REG, - SRC2_REG); - - /* FIXME: see comment for cfcmps. */ - a = DSPregs[SRC1_REG].lower.i; - b = DSPregs[SRC2_REG].lower.i; - - res = DSPregs[SRC1_REG].lower.i - DSPregs[SRC2_REG].lower.i; - /* zero */ - z = res == 0; - /* negative */ - n = res < 0; - /* overflow */ - v = SubOverflow (DSPregs[SRC1_REG].lower.i, DSPregs[SRC2_REG].lower.i, - res); - /* carry */ - c = (NEG (a) && POS (b)) - || (NEG (a) && POS (res)) - || (POS (b) && POS (res)); - - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } - - case 5: /* cfcmp64 */ - { - long long res; - int n, z, c, v; - unsigned long long a, b; - - printfdbg ("cfcmp64 mvdx%d - mvdx%d\n", - SRC1_REG, - SRC2_REG); - - /* fixme: see comment for cfcmps. */ - - a = mv_getReg64int (SRC1_REG); - b = mv_getReg64int (SRC2_REG); - - res = mv_getReg64int (SRC1_REG) - mv_getReg64int (SRC2_REG); - /* zero */ - z = res == 0; - /* negative */ - n = res < 0; - /* overflow */ - v = ((NEG64 (a) && POS64 (b) && POS64 (res)) - || (POS64 (a) && NEG64 (b) && NEG64 (res))); - /* carry */ - c = (NEG64 (a) && POS64 (b)) - || (NEG64 (a) && POS64 (res)) - || (POS64 (b) && POS64 (res)); - - *value = (n << 31) | (z << 30) | (c << 29) | (v << 28); - break; - } - - default: - fprintf (stderr, "unknown opcode in DSPMRC5 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPMRC6 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword * value) -{ - switch (BITS (5, 7)) - { - case 0: /* cfmval32 */ - cirrus_not_implemented ("cfmval32"); - break; - - case 1: /* cfmvam32 */ - cirrus_not_implemented ("cfmvam32"); - break; - - case 2: /* cfmvah32 */ - cirrus_not_implemented ("cfmvah32"); - break; - - case 3: /* cfmva32 */ - cirrus_not_implemented ("cfmva32"); - break; - - case 4: /* cfmva64 */ - cirrus_not_implemented ("cfmva64"); - break; - - case 5: /* cfmvsc32 */ - cirrus_not_implemented ("cfmvsc32"); - break; - - default: - fprintf (stderr, "unknown opcode in DSPMRC6 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPMCR4 (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword value) -{ - switch (BITS (5, 7)) - { - case 0: /* cfmvdlr */ - /* Move the lower half of a DF value from an Arm register into - the lower half of a Cirrus register. */ - printfdbg ("cfmvdlr <-- 0x%x\n", (int) value); - DSPregs[SRC1_REG].lower.i = (int) value; - break; - - case 1: /* cfmvdhr */ - /* Move the upper half of a DF value from an Arm register into - the upper half of a Cirrus register. */ - printfdbg ("cfmvdhr <-- 0x%x\n", (int) value); - DSPregs[SRC1_REG].upper.i = (int) value; - break; - - case 2: /* cfmvsr */ - /* Move SF from Arm register into upper half of Cirrus register. */ - printfdbg ("cfmvsr <-- 0x%x\n", (int) value); - DSPregs[SRC1_REG].upper.i = (int) value; - break; - - default: - fprintf (stderr, "unknown opcode in DSPMCR4 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPMCR5 (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword value) -{ - union - { - int s; - unsigned int us; - } val; - - switch (BITS (5, 7)) - { - case 0: /* cfmv64lr */ - /* Move lower half of a 64bit int from an ARM register into the - lower half of a DSP register and sign extend it. */ - printfdbg ("cfmv64lr mvdx%d <-- 0x%x\n", SRC1_REG, (int) value); - DSPregs[SRC1_REG].lower.i = (int) value; - break; - - case 1: /* cfmv64hr */ - /* Move upper half of a 64bit int from an ARM register into the - upper half of a DSP register. */ - printfdbg ("cfmv64hr ARM_REG = mvfx%d <-- 0x%x\n", - SRC1_REG, - (int) value); - DSPregs[SRC1_REG].upper.i = (int) value; - break; - - case 2: /* cfrshl32 */ - printfdbg ("cfrshl32\n"); - val.us = value; - if (val.s > 0) - DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i << value; - else - DSPregs[SRC2_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -value; - break; - - case 3: /* cfrshl64 */ - printfdbg ("cfrshl64\n"); - val.us = value; - if (val.s > 0) - mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) << value); - else - mv_setReg64int (SRC2_REG, mv_getReg64int (SRC1_REG) >> -value); - break; - - default: - fprintf (stderr, "unknown opcode in DSPMCR5 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPMCR6 (ARMul_State * state, - unsigned type ATTRIBUTE_UNUSED, - ARMword instr, - ARMword value) -{ - switch (BITS (5, 7)) - { - case 0: /* cfmv32al */ - cirrus_not_implemented ("cfmv32al"); - break; - - case 1: /* cfmv32am */ - cirrus_not_implemented ("cfmv32am"); - break; - - case 2: /* cfmv32ah */ - cirrus_not_implemented ("cfmv32ah"); - break; - - case 3: /* cfmv32a */ - cirrus_not_implemented ("cfmv32a"); - break; - - case 4: /* cfmv64a */ - cirrus_not_implemented ("cfmv64a"); - break; - - case 5: /* cfmv32sc */ - cirrus_not_implemented ("cfmv32sc"); - break; - - default: - fprintf (stderr, "unknown opcode in DSPMCR6 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPLDC4 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type, - ARMword instr, - ARMword data) -{ - static unsigned words; - - if (type != ARMul_DATA) - { - words = 0; - return ARMul_DONE; - } - - if (BIT (22)) - { /* it's a long access, get two words */ - /* cfldrd */ - - printfdbg ("cfldrd: %x (words = %d) (bigend = %d) DESTREG = %d\n", - data, words, state->bigendSig, DEST_REG); - - if (words == 0) - { - if (state->bigendSig) - DSPregs[DEST_REG].upper.i = (int) data; - else - DSPregs[DEST_REG].lower.i = (int) data; - } - else - { - if (state->bigendSig) - DSPregs[DEST_REG].lower.i = (int) data; - else - DSPregs[DEST_REG].upper.i = (int) data; - } - - ++ words; - - if (words == 2) - { - printfdbg ("\tmvd%d <-- mem = %g\n", DEST_REG, - mv_getRegDouble (DEST_REG)); - - return ARMul_DONE; - } - else - return ARMul_INC; - } - else - { - /* Get just one word. */ - - /* cfldrs */ - printfdbg ("cfldrs\n"); - - DSPregs[DEST_REG].upper.i = (int) data; - - printfdbg ("\tmvf%d <-- mem = %f\n", DEST_REG, - DSPregs[DEST_REG].upper.f); - - return ARMul_DONE; - } -} - -unsigned -DSPLDC5 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type, - ARMword instr, - ARMword data) -{ - static unsigned words; - - if (type != ARMul_DATA) - { - words = 0; - return ARMul_DONE; - } - - if (BIT (22)) - { - /* It's a long access, get two words. */ - - /* cfldr64 */ - printfdbg ("cfldr64: %d\n", data); - - if (words == 0) - { - if (state->bigendSig) - DSPregs[DEST_REG].upper.i = (int) data; - else - DSPregs[DEST_REG].lower.i = (int) data; - } - else - { - if (state->bigendSig) - DSPregs[DEST_REG].lower.i = (int) data; - else - DSPregs[DEST_REG].upper.i = (int) data; - } - - ++ words; - - if (words == 2) - { - printfdbg ("\tmvdx%d <-- mem = %lld\n", DEST_REG, - mv_getReg64int (DEST_REG)); - - return ARMul_DONE; - } - else - return ARMul_INC; - } - else - { - /* Get just one word. */ - - /* cfldr32 */ - printfdbg ("cfldr32 mvfx%d <-- %d\n", DEST_REG, (int) data); - - /* 32bit ints should be sign extended to 64bits when loaded. */ - mv_setReg64int (DEST_REG, (long long) data); - - return ARMul_DONE; - } -} - -unsigned -DSPSTC4 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type, - ARMword instr, - ARMword * data) -{ - static unsigned words; - - if (type != ARMul_DATA) - { - words = 0; - return ARMul_DONE; - } - - if (BIT (22)) - { - /* It's a long access, get two words. */ - /* cfstrd */ - printfdbg ("cfstrd\n"); - - if (words == 0) - { - if (state->bigendSig) - *data = (ARMword) DSPregs[DEST_REG].upper.i; - else - *data = (ARMword) DSPregs[DEST_REG].lower.i; - } - else - { - if (state->bigendSig) - *data = (ARMword) DSPregs[DEST_REG].lower.i; - else - *data = (ARMword) DSPregs[DEST_REG].upper.i; - } - - ++ words; - - if (words == 2) - { - printfdbg ("\tmem = mvd%d = %g\n", DEST_REG, - mv_getRegDouble (DEST_REG)); - - return ARMul_DONE; - } - else - return ARMul_INC; - } - else - { - /* Get just one word. */ - /* cfstrs */ - printfdbg ("cfstrs mvf%d <-- %f\n", DEST_REG, - DSPregs[DEST_REG].upper.f); - - *data = (ARMword) DSPregs[DEST_REG].upper.i; - - return ARMul_DONE; - } -} - -unsigned -DSPSTC5 (ARMul_State * state ATTRIBUTE_UNUSED, - unsigned type, - ARMword instr, - ARMword * data) -{ - static unsigned words; - - if (type != ARMul_DATA) - { - words = 0; - return ARMul_DONE; - } - - if (BIT (22)) - { - /* It's a long access, store two words. */ - /* cfstr64 */ - printfdbg ("cfstr64\n"); - - if (words == 0) - { - if (state->bigendSig) - *data = (ARMword) DSPregs[DEST_REG].upper.i; - else - *data = (ARMword) DSPregs[DEST_REG].lower.i; - } - else - { - if (state->bigendSig) - *data = (ARMword) DSPregs[DEST_REG].lower.i; - else - *data = (ARMword) DSPregs[DEST_REG].upper.i; - } - - ++ words; - - if (words == 2) - { - printfdbg ("\tmem = mvd%d = %lld\n", DEST_REG, - mv_getReg64int (DEST_REG)); - - return ARMul_DONE; - } - else - return ARMul_INC; - } - else - { - /* Store just one word. */ - /* cfstr32 */ - *data = (ARMword) DSPregs[DEST_REG].lower.i; - - printfdbg ("cfstr32 MEM = %d\n", (int) *data); - - return ARMul_DONE; - } -} - -unsigned -DSPCDP4 (ARMul_State * state, - unsigned type, - ARMword instr) -{ - int opcode2; - - opcode2 = BITS (5,7); - - switch (BITS (20,21)) - { - case 0: - switch (opcode2) - { - case 0: /* cfcpys */ - printfdbg ("cfcpys mvf%d = mvf%d = %f\n", - DEST_REG, - SRC1_REG, - DSPregs[SRC1_REG].upper.f); - DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f; - break; - - case 1: /* cfcpyd */ - printfdbg ("cfcpyd mvd%d = mvd%d = %g\n", - DEST_REG, - SRC1_REG, - mv_getRegDouble (SRC1_REG)); - mv_setRegDouble (DEST_REG, mv_getRegDouble (SRC1_REG)); - break; - - case 2: /* cfcvtds */ - printfdbg ("cfcvtds mvf%d = (float) mvd%d = %f\n", - DEST_REG, - SRC1_REG, - (float) mv_getRegDouble (SRC1_REG)); - DSPregs[DEST_REG].upper.f = (float) mv_getRegDouble (SRC1_REG); - break; - - case 3: /* cfcvtsd */ - printfdbg ("cfcvtsd mvd%d = mvf%d = %g\n", - DEST_REG, - SRC1_REG, - (double) DSPregs[SRC1_REG].upper.f); - mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].upper.f); - break; - - case 4: /* cfcvt32s */ - printfdbg ("cfcvt32s mvf%d = mvfx%d = %f\n", - DEST_REG, - SRC1_REG, - (float) DSPregs[SRC1_REG].lower.i); - DSPregs[DEST_REG].upper.f = (float) DSPregs[SRC1_REG].lower.i; - break; - - case 5: /* cfcvt32d */ - printfdbg ("cfcvt32d mvd%d = mvfx%d = %g\n", - DEST_REG, - SRC1_REG, - (double) DSPregs[SRC1_REG].lower.i); - mv_setRegDouble (DEST_REG, (double) DSPregs[SRC1_REG].lower.i); - break; - - case 6: /* cfcvt64s */ - printfdbg ("cfcvt64s mvf%d = mvdx%d = %f\n", - DEST_REG, - SRC1_REG, - (float) mv_getReg64int (SRC1_REG)); - DSPregs[DEST_REG].upper.f = (float) mv_getReg64int (SRC1_REG); - break; - - case 7: /* cfcvt64d */ - printfdbg ("cfcvt64d mvd%d = mvdx%d = %g\n", - DEST_REG, - SRC1_REG, - (double) mv_getReg64int (SRC1_REG)); - mv_setRegDouble (DEST_REG, (double) mv_getReg64int (SRC1_REG)); - break; - } - break; - - case 1: - switch (opcode2) - { - case 0: /* cfmuls */ - printfdbg ("cfmuls mvf%d = mvf%d = %f\n", - DEST_REG, - SRC1_REG, - DSPregs[SRC1_REG].upper.f * DSPregs[SRC2_REG].upper.f); - - DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f - * DSPregs[SRC2_REG].upper.f; - break; - - case 1: /* cfmuld */ - printfdbg ("cfmuld mvd%d = mvd%d = %g\n", - DEST_REG, - SRC1_REG, - mv_getRegDouble (SRC1_REG) * mv_getRegDouble (SRC2_REG)); - - mv_setRegDouble (DEST_REG, - mv_getRegDouble (SRC1_REG) - * mv_getRegDouble (SRC2_REG)); - break; - - default: - fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - break; - - case 3: - switch (opcode2) - { - case 0: /* cfabss */ - DSPregs[DEST_REG].upper.f = (DSPregs[SRC1_REG].upper.f < 0.0F ? - -DSPregs[SRC1_REG].upper.f - : DSPregs[SRC1_REG].upper.f); - printfdbg ("cfabss mvf%d = |mvf%d| = %f\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].upper.f); - break; - - case 1: /* cfabsd */ - mv_setRegDouble (DEST_REG, - (mv_getRegDouble (SRC1_REG) < 0.0 ? - -mv_getRegDouble (SRC1_REG) - : mv_getRegDouble (SRC1_REG))); - printfdbg ("cfabsd mvd%d = |mvd%d| = %g\n", - DEST_REG, - SRC1_REG, - mv_getRegDouble (DEST_REG)); - break; - - case 2: /* cfnegs */ - DSPregs[DEST_REG].upper.f = -DSPregs[SRC1_REG].upper.f; - printfdbg ("cfnegs mvf%d = -mvf%d = %f\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].upper.f); - break; - - case 3: /* cfnegd */ - mv_setRegDouble (DEST_REG, - -mv_getRegDouble (SRC1_REG)); - printfdbg ("cfnegd mvd%d = -mvd%d = %g\n", - DEST_REG, DEST_REG, - mv_getRegDouble (DEST_REG)); - break; - - case 4: /* cfadds */ - DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f - + DSPregs[SRC2_REG].upper.f; - printfdbg ("cfadds mvf%d = mvf%d + mvf%d = %f\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].upper.f); - break; - - case 5: /* cfaddd */ - mv_setRegDouble (DEST_REG, - mv_getRegDouble (SRC1_REG) - + mv_getRegDouble (SRC2_REG)); - printfdbg ("cfaddd: mvd%d = mvd%d + mvd%d = %g\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getRegDouble (DEST_REG)); - break; - - case 6: /* cfsubs */ - DSPregs[DEST_REG].upper.f = DSPregs[SRC1_REG].upper.f - - DSPregs[SRC2_REG].upper.f; - printfdbg ("cfsubs: mvf%d = mvf%d - mvf%d = %f\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].upper.f); - break; - - case 7: /* cfsubd */ - mv_setRegDouble (DEST_REG, - mv_getRegDouble (SRC1_REG) - - mv_getRegDouble (SRC2_REG)); - printfdbg ("cfsubd: mvd%d = mvd%d - mvd%d = %g\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getRegDouble (DEST_REG)); - break; - } - break; - - default: - fprintf (stderr, "unknown opcode in DSPCDP4 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPCDP5 (ARMul_State * state, - unsigned type, - ARMword instr) -{ - int opcode2; - char shift; - - opcode2 = BITS (5,7); - - /* Shift constants are 7bit signed numbers in bits 0..3|5..7. */ - shift = BITS (0, 3) | (BITS (5, 7)) << 4; - if (shift & 0x40) - shift |= 0xc0; - - switch (BITS (20,21)) - { - case 0: - /* cfsh32 */ - printfdbg ("cfsh32 %s amount=%d\n", shift < 0 ? "right" : "left", - shift); - if (shift < 0) - /* Negative shift is a right shift. */ - DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i >> -shift; - else - /* Positive shift is a left shift. */ - DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i << shift; - break; - - case 1: - switch (opcode2) - { - case 0: /* cfmul32 */ - DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i - * DSPregs[SRC2_REG].lower.i; - printfdbg ("cfmul32 mvfx%d = mvfx%d * mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 1: /* cfmul64 */ - mv_setReg64int (DEST_REG, - mv_getReg64int (SRC1_REG) - * mv_getReg64int (SRC2_REG)); - printfdbg ("cfmul64 mvdx%d = mvdx%d * mvdx%d = %lld\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getReg64int (DEST_REG)); - break; - - case 2: /* cfmac32 */ - DSPregs[DEST_REG].lower.i - += DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i; - printfdbg ("cfmac32 mvfx%d += mvfx%d * mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 3: /* cfmsc32 */ - DSPregs[DEST_REG].lower.i - -= DSPregs[SRC1_REG].lower.i * DSPregs[SRC2_REG].lower.i; - printfdbg ("cfmsc32 mvfx%d -= mvfx%d * mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 4: /* cfcvts32 */ - /* fixme: this should round */ - DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f; - printfdbg ("cfcvts32 mvfx%d = mvf%d = %d\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 5: /* cfcvtd32 */ - /* fixme: this should round */ - DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG); - printfdbg ("cfcvtd32 mvdx%d = mvd%d = %d\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 6: /* cftruncs32 */ - DSPregs[DEST_REG].lower.i = (int) DSPregs[SRC1_REG].upper.f; - printfdbg ("cftruncs32 mvfx%d = mvf%d = %d\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 7: /* cftruncd32 */ - DSPregs[DEST_REG].lower.i = (int) mv_getRegDouble (SRC1_REG); - printfdbg ("cftruncd32 mvfx%d = mvd%d = %d\n", - DEST_REG, - SRC1_REG, - DSPregs[DEST_REG].lower.i); - break; - } - break; - - case 2: - /* cfsh64 */ - printfdbg ("cfsh64\n"); - - if (shift < 0) - /* Negative shift is a right shift. */ - mv_setReg64int (DEST_REG, - mv_getReg64int (SRC1_REG) >> -shift); - else - /* Positive shift is a left shift. */ - mv_setReg64int (DEST_REG, - mv_getReg64int (SRC1_REG) << shift); - printfdbg ("\t%llx\n", mv_getReg64int(DEST_REG)); - break; - - case 3: - switch (opcode2) - { - case 0: /* cfabs32 */ - DSPregs[DEST_REG].lower.i = (DSPregs[SRC1_REG].lower.i < 0 - ? -DSPregs[SRC1_REG].lower.i : DSPregs[SRC1_REG].lower.i); - printfdbg ("cfabs32 mvfx%d = |mvfx%d| = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 1: /* cfabs64 */ - mv_setReg64int (DEST_REG, - (mv_getReg64int (SRC1_REG) < 0 - ? -mv_getReg64int (SRC1_REG) - : mv_getReg64int (SRC1_REG))); - printfdbg ("cfabs64 mvdx%d = |mvdx%d| = %lld\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getReg64int (DEST_REG)); - break; - - case 2: /* cfneg32 */ - DSPregs[DEST_REG].lower.i = -DSPregs[SRC1_REG].lower.i; - printfdbg ("cfneg32 mvfx%d = -mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 3: /* cfneg64 */ - mv_setReg64int (DEST_REG, -mv_getReg64int (SRC1_REG)); - printfdbg ("cfneg64 mvdx%d = -mvdx%d = %lld\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getReg64int (DEST_REG)); - break; - - case 4: /* cfadd32 */ - DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i - + DSPregs[SRC2_REG].lower.i; - printfdbg ("cfadd32 mvfx%d = mvfx%d + mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 5: /* cfadd64 */ - mv_setReg64int (DEST_REG, - mv_getReg64int (SRC1_REG) - + mv_getReg64int (SRC2_REG)); - printfdbg ("cfadd64 mvdx%d = mvdx%d + mvdx%d = %lld\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getReg64int (DEST_REG)); - break; - - case 6: /* cfsub32 */ - DSPregs[DEST_REG].lower.i = DSPregs[SRC1_REG].lower.i - - DSPregs[SRC2_REG].lower.i; - printfdbg ("cfsub32 mvfx%d = mvfx%d - mvfx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - DSPregs[DEST_REG].lower.i); - break; - - case 7: /* cfsub64 */ - mv_setReg64int (DEST_REG, - mv_getReg64int (SRC1_REG) - - mv_getReg64int (SRC2_REG)); - printfdbg ("cfsub64 mvdx%d = mvdx%d - mvdx%d = %d\n", - DEST_REG, - SRC1_REG, - SRC2_REG, - mv_getReg64int (DEST_REG)); - break; - } - break; - - default: - fprintf (stderr, "unknown opcode in DSPCDP5 0x%x\n", instr); - cirrus_not_implemented ("unknown"); - break; - } - - return ARMul_DONE; -} - -unsigned -DSPCDP6 (ARMul_State * state, - unsigned type, - ARMword instr) -{ - switch (BITS (20,21)) - { - case 0: - /* cfmadd32 */ - cirrus_not_implemented ("cfmadd32"); - break; - - case 1: - /* cfmsub32 */ - cirrus_not_implemented ("cfmsub32"); - break; - - case 2: - /* cfmadda32 */ - cirrus_not_implemented ("cfmadda32"); - break; - - case 3: - /* cfmsuba32 */ - cirrus_not_implemented ("cfmsuba32"); - break; - - default: - fprintf (stderr, "unknown opcode in DSPCDP6 0x%x\n", instr); - } - - return ARMul_DONE; -} - -/* Conversion functions. - - 32-bit integers are stored in the LOWER half of a 64-bit physical - register. - - Single precision floats are stored in the UPPER half of a 64-bit - physical register. */ - -static double -mv_getRegDouble (int regnum) -{ - reg_conv.ints[lsw_float_index] = DSPregs[regnum].upper.i; - reg_conv.ints[msw_float_index] = DSPregs[regnum].lower.i; - return reg_conv.d; -} - -static void -mv_setRegDouble (int regnum, double val) -{ - reg_conv.d = val; - DSPregs[regnum].upper.i = reg_conv.ints[lsw_float_index]; - DSPregs[regnum].lower.i = reg_conv.ints[msw_float_index]; -} - -static long long -mv_getReg64int (int regnum) -{ - reg_conv.ints[lsw_int_index] = DSPregs[regnum].lower.i; - reg_conv.ints[msw_int_index] = DSPregs[regnum].upper.i; - return reg_conv.ll; -} - -static void -mv_setReg64int (int regnum, long long val) -{ - reg_conv.ll = val; - DSPregs[regnum].lower.i = reg_conv.ints[lsw_int_index]; - DSPregs[regnum].upper.i = reg_conv.ints[msw_int_index]; -} |