📄 maverick.c
字号:
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, 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)
{
int opcode2;
opcode2 = BITS (5, 7);
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];
}
/* Compute LSW in a double and a long long. */
void
mv_compute_host_endianness (ARMul_State * state)
{
static union
{
long long ll;
long ints[2];
long i;
double d;
float floats[2];
float f;
} conv;
/* Calculate where's the LSW in a 64bit int. */
conv.ll = 45;
if (conv.ints[0] == 0)
{
msw_int_index = 0;
lsw_int_index = 1;
}
else
{
assert (conv.ints[1] == 0);
msw_int_index = 1;
lsw_int_index = 0;
}
/* Calculate where's the LSW in a double. */
conv.d = 3.0;
if (conv.ints[0] == 0)
{
msw_float_index = 0;
lsw_float_index = 1;
}
else
{
assert (conv.ints[1] == 0);
msw_float_index = 1;
lsw_float_index = 0;
}
printfdbg ("lsw_int_index %d\n", lsw_int_index);
printfdbg ("lsw_float_index %d\n", lsw_float_index);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -