mirror of
https://github.com/Retropex/dolphin.git
synced 2025-06-04 16:32:31 +02:00
3711 lines
65 KiB
C++
3711 lines
65 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// Licensed under GPLv2+
|
|
// Refer to the license.txt file included.
|
|
|
|
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
|
|
|
#include "Common/CommonTypes.h"
|
|
|
|
#include "Core/DSP/DSPEmitter.h"
|
|
#include "Core/DSP/DSPIntExtOps.h"
|
|
#include "Core/DSP/DSPInterpreter.h"
|
|
#include "Core/DSP/DSPTables.h"
|
|
|
|
void nop(const UDSPInstruction opc)
|
|
{
|
|
// The real nop is 0. Anything else is bad.
|
|
if (opc)
|
|
{
|
|
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x", opc);
|
|
}
|
|
}
|
|
|
|
const DSPOPCTemplate opcodes[] = {
|
|
// # of parameters----+ {type, size,
|
|
// loc, lshift, mask}
|
|
// branch reads PC //
|
|
// instruction approximation
|
|
// name opcode mask interpreter function JIT function size-V V param 1
|
|
// param 2 param 3 extendable uncond. updates
|
|
// SR
|
|
{"NOP",
|
|
0x0000,
|
|
0xfffc,
|
|
nop,
|
|
&DSPEmitter::nop,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // no operation
|
|
|
|
{"DAR",
|
|
0x0004,
|
|
0xfffc,
|
|
DSPInterpreter::dar,
|
|
&DSPEmitter::dar,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arD--
|
|
{"IAR",
|
|
0x0008,
|
|
0xfffc,
|
|
DSPInterpreter::iar,
|
|
&DSPEmitter::iar,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arD++
|
|
{"SUBARN",
|
|
0x000c,
|
|
0xfffc,
|
|
DSPInterpreter::subarn,
|
|
&DSPEmitter::subarn,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arD -= $ixS
|
|
{"ADDARN",
|
|
0x0010,
|
|
0xfff0,
|
|
DSPInterpreter::addarn,
|
|
&DSPEmitter::addarn,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arD += $ixS
|
|
|
|
{"HALT",
|
|
0x0021,
|
|
0xffff,
|
|
DSPInterpreter::halt,
|
|
&DSPEmitter::halt,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
true,
|
|
false,
|
|
false}, // halt until reset
|
|
|
|
{"RETGE",
|
|
0x02d0,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if greater or equal
|
|
{"RETL",
|
|
0x02d1,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if less
|
|
{"RETG",
|
|
0x02d2,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if greater
|
|
{"RETLE",
|
|
0x02d3,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if less or equal
|
|
{"RETNZ",
|
|
0x02d4,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if not zero
|
|
{"RETZ",
|
|
0x02d5,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if zero
|
|
{"RETNC",
|
|
0x02d6,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if not carry
|
|
{"RETC",
|
|
0x02d7,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if carry
|
|
{"RETx8",
|
|
0x02d8,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if TODO
|
|
{"RETx9",
|
|
0x02d9,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if TODO
|
|
{"RETxA",
|
|
0x02da,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if TODO
|
|
{"RETxB",
|
|
0x02db,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if TODO
|
|
{"RETLNZ",
|
|
0x02dc,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if logic not zero
|
|
{"RETLZ",
|
|
0x02dd,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if logic zero
|
|
{"RETO",
|
|
0x02de,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // return if overflow
|
|
{"RET",
|
|
0x02df,
|
|
0xffff,
|
|
DSPInterpreter::ret,
|
|
&DSPEmitter::ret,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
true,
|
|
false,
|
|
false}, // unconditional return
|
|
|
|
{"RTI",
|
|
0x02ff,
|
|
0xffff,
|
|
DSPInterpreter::rti,
|
|
&DSPEmitter::rti,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
true,
|
|
false,
|
|
false}, // return from interrupt
|
|
|
|
{"CALLGE",
|
|
0x02b0,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if greater or equal
|
|
{"CALLL",
|
|
0x02b1,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if less
|
|
{"CALLG",
|
|
0x02b2,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if greater
|
|
{"CALLLE",
|
|
0x02b3,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if less or equal
|
|
{"CALLNZ",
|
|
0x02b4,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if not zero
|
|
{"CALLZ",
|
|
0x02b5,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if zero
|
|
{"CALLNC",
|
|
0x02b6,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if not carry
|
|
{"CALLC",
|
|
0x02b7,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if carry
|
|
{"CALLx8",
|
|
0x02b8,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if TODO
|
|
{"CALLx9",
|
|
0x02b9,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if TODO
|
|
{"CALLxA",
|
|
0x02ba,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if TODO
|
|
{"CALLxB",
|
|
0x02bb,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if TODO
|
|
{"CALLLNZ",
|
|
0x02bc,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if logic not zero
|
|
{"CALLLZ",
|
|
0x02bd,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if logic zero
|
|
{"CALLO",
|
|
0x02be,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call if overflow
|
|
{"CALL",
|
|
0x02bf,
|
|
0xffff,
|
|
DSPInterpreter::call,
|
|
&DSPEmitter::call,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // unconditional call
|
|
|
|
{"IFGE",
|
|
0x0270,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if greater or equal
|
|
{"IFL",
|
|
0x0271,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if less
|
|
{"IFG",
|
|
0x0272,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if greater
|
|
{"IFLE",
|
|
0x0273,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if less or equal
|
|
{"IFNZ",
|
|
0x0274,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if not zero
|
|
{"IFZ",
|
|
0x0275,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if zero
|
|
{"IFNC",
|
|
0x0276,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if not carry
|
|
{"IFC",
|
|
0x0277,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if carry
|
|
{"IFx8",
|
|
0x0278,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if TODO
|
|
{"IFx9",
|
|
0x0279,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if TODO
|
|
{"IFxA",
|
|
0x027a,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if TODO
|
|
{"IFxB",
|
|
0x027b,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if TODO
|
|
{"IFLNZ",
|
|
0x027c,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if logic not zero
|
|
{"IFLZ",
|
|
0x027d,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if logic zero
|
|
{"IFO",
|
|
0x027e,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // if overflow
|
|
{"IF",
|
|
0x027f,
|
|
0xffff,
|
|
DSPInterpreter::ifcc,
|
|
&DSPEmitter::ifcc,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // what is this, I don't even...
|
|
|
|
{"JGE",
|
|
0x0290,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if greater or equal
|
|
{"JL",
|
|
0x0291,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if less
|
|
{"JG",
|
|
0x0292,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if greater
|
|
{"JLE",
|
|
0x0293,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if less or equal
|
|
{"JNZ",
|
|
0x0294,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if not zero
|
|
{"JZ",
|
|
0x0295,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if zero
|
|
{"JNC",
|
|
0x0296,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if not carry
|
|
{"JC",
|
|
0x0297,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if carry
|
|
{"JMPx8",
|
|
0x0298,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if TODO
|
|
{"JMPx9",
|
|
0x0299,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if TODO
|
|
{"JMPxA",
|
|
0x029a,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if TODO
|
|
{"JMPxB",
|
|
0x029b,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if TODO
|
|
{"JLNZ",
|
|
0x029c,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if logic not zero
|
|
{"JLZ",
|
|
0x029d,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if logic zero
|
|
{"JO",
|
|
0x029e,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // jump if overflow
|
|
{"JMP",
|
|
0x029f,
|
|
0xffff,
|
|
DSPInterpreter::jcc,
|
|
&DSPEmitter::jcc,
|
|
2,
|
|
1,
|
|
{{P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // unconditional jump
|
|
|
|
{"JRGE",
|
|
0x1700,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if greater or equal
|
|
{"JRL",
|
|
0x1701,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if less
|
|
{"JRG",
|
|
0x1702,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if greater
|
|
{"JRLE",
|
|
0x1703,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if less or equal
|
|
{"JRNZ",
|
|
0x1704,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if not zero
|
|
{"JRZ",
|
|
0x1705,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if zero
|
|
{"JRNC",
|
|
0x1706,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if not carry
|
|
{"JRC",
|
|
0x1707,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if carry
|
|
{"JMPRx8",
|
|
0x1708,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if TODO
|
|
{"JMPRx9",
|
|
0x1709,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if TODO
|
|
{"JMPRxA",
|
|
0x170a,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if TODO
|
|
{"JMPRxB",
|
|
0x170b,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if TODO
|
|
{"JRLNZ",
|
|
0x170c,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if logic not zero
|
|
{"JRLZ",
|
|
0x170d,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if logic zero
|
|
{"JRO",
|
|
0x170e,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
false,
|
|
false}, // jump to $R if overflow
|
|
{"JMPR",
|
|
0x170f,
|
|
0xff1f,
|
|
DSPInterpreter::jmprcc,
|
|
&DSPEmitter::jmprcc,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
true,
|
|
false,
|
|
false}, // jump to $R
|
|
|
|
{"CALLRGE",
|
|
0x1710,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if greater or equal
|
|
{"CALLRL",
|
|
0x1711,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if less
|
|
{"CALLRG",
|
|
0x1712,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if greater
|
|
{"CALLRLE",
|
|
0x1713,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if less or equal
|
|
{"CALLRNZ",
|
|
0x1714,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if not zero
|
|
{"CALLRZ",
|
|
0x1715,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if zero
|
|
{"CALLRNC",
|
|
0x1716,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if not carry
|
|
{"CALLRC",
|
|
0x1717,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if carry
|
|
{"CALLRx8",
|
|
0x1718,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if TODO
|
|
{"CALLRx9",
|
|
0x1719,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if TODO
|
|
{"CALLRxA",
|
|
0x171a,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if TODO
|
|
{"CALLRxB",
|
|
0x171b,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if TODO
|
|
{"CALLRLNZ",
|
|
0x171c,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if logic not zero
|
|
{"CALLRLZ",
|
|
0x171d,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if logic zero
|
|
{"CALLRO",
|
|
0x171e,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
false,
|
|
true,
|
|
false}, // call $R if overflow
|
|
{"CALLR",
|
|
0x171f,
|
|
0xff1f,
|
|
DSPInterpreter::callr,
|
|
&DSPEmitter::callr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 5, 0x00e0}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // call $R
|
|
|
|
{"SBCLR",
|
|
0x1200,
|
|
0xff00,
|
|
DSPInterpreter::sbclr,
|
|
&DSPEmitter::sbclr,
|
|
1,
|
|
1,
|
|
{{P_IMM, 1, 0, 0, 0x0007}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $sr &= ~(I + 6)
|
|
{"SBSET",
|
|
0x1300,
|
|
0xff00,
|
|
DSPInterpreter::sbset,
|
|
&DSPEmitter::sbset,
|
|
1,
|
|
1,
|
|
{{P_IMM, 1, 0, 0, 0x0007}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $sr |= (I + 6)
|
|
|
|
{"LSL",
|
|
0x1400,
|
|
0xfec0,
|
|
DSPInterpreter::lsl,
|
|
&DSPEmitter::lsl,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR <<= I
|
|
{"LSR",
|
|
0x1440,
|
|
0xfec0,
|
|
DSPInterpreter::lsr,
|
|
&DSPEmitter::lsr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR >>= I (shifting in zeros)
|
|
{"ASL",
|
|
0x1480,
|
|
0xfec0,
|
|
DSPInterpreter::asl,
|
|
&DSPEmitter::asl,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR <<= I
|
|
{"ASR",
|
|
0x14c0,
|
|
0xfec0,
|
|
DSPInterpreter::asr,
|
|
&DSPEmitter::asr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR >>= I (shifting in sign bits)
|
|
|
|
// these two were discovered by ector
|
|
{"LSRN",
|
|
0x02ca,
|
|
0xffff,
|
|
DSPInterpreter::lsrn,
|
|
&DSPEmitter::lsrn,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $ac0 >>=/<<= $ac1.m[0-6]
|
|
{"ASRN",
|
|
0x02cb,
|
|
0xffff,
|
|
DSPInterpreter::asrn,
|
|
&DSPEmitter::asrn,
|
|
1,
|
|
0,
|
|
{},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $ac0 >>=/<<= $ac1.m[0-6] (arithmetic)
|
|
|
|
{"LRI",
|
|
0x0080,
|
|
0xffe0,
|
|
DSPInterpreter::lri,
|
|
&DSPEmitter::lri,
|
|
2,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false}, // $D = I
|
|
{"LR",
|
|
0x00c0,
|
|
0xffe0,
|
|
DSPInterpreter::lr,
|
|
&DSPEmitter::lr,
|
|
2,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false}, // $D = MEM[M]
|
|
{"SR",
|
|
0x00e0,
|
|
0xffe0,
|
|
DSPInterpreter::sr,
|
|
&DSPEmitter::sr,
|
|
2,
|
|
2,
|
|
{{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false}, // MEM[M] = $S
|
|
|
|
{"MRR",
|
|
0x1c00,
|
|
0xfc00,
|
|
DSPInterpreter::mrr,
|
|
&DSPEmitter::mrr,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $D = $S
|
|
|
|
{"SI",
|
|
0x1600,
|
|
0xff00,
|
|
DSPInterpreter::si,
|
|
&DSPEmitter::si,
|
|
2,
|
|
2,
|
|
{{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
false}, // MEM[M] = I
|
|
|
|
{"ADDIS",
|
|
0x0400,
|
|
0xfe00,
|
|
DSPInterpreter::addis,
|
|
&DSPEmitter::addis,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.hm += I
|
|
{"CMPIS",
|
|
0x0600,
|
|
0xfe00,
|
|
DSPInterpreter::cmpis,
|
|
&DSPEmitter::cmpis,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($acD - I)
|
|
{"LRIS",
|
|
0x0800,
|
|
0xf800,
|
|
DSPInterpreter::lris,
|
|
&DSPEmitter::lris,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $(D+24) = I
|
|
|
|
{"ADDI",
|
|
0x0200,
|
|
0xfeff,
|
|
DSPInterpreter::addi,
|
|
&DSPEmitter::addi,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $acD.hm += I
|
|
{"XORI",
|
|
0x0220,
|
|
0xfeff,
|
|
DSPInterpreter::xori,
|
|
&DSPEmitter::xori,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $acD.m ^= I
|
|
{"ANDI",
|
|
0x0240,
|
|
0xfeff,
|
|
DSPInterpreter::andi,
|
|
&DSPEmitter::andi,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $acD.m &= I
|
|
{"ORI",
|
|
0x0260,
|
|
0xfeff,
|
|
DSPInterpreter::ori,
|
|
&DSPEmitter::ori,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $acD.m |= I
|
|
{"CMPI",
|
|
0x0280,
|
|
0xfeff,
|
|
DSPInterpreter::cmpi,
|
|
&DSPEmitter::cmpi,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // FLAGS(($acD.hm - I) | $acD.l)
|
|
|
|
{"ANDF",
|
|
0x02a0,
|
|
0xfeff,
|
|
DSPInterpreter::andf,
|
|
&DSPEmitter::andf,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $sr.LZ = ($acD.m & I) == 0 ? 1 : 0
|
|
{"ANDCF",
|
|
0x02c0,
|
|
0xfeff,
|
|
DSPInterpreter::andcf,
|
|
&DSPEmitter::andcf,
|
|
2,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},
|
|
false,
|
|
false,
|
|
false,
|
|
true,
|
|
true}, // $sr.LZ = ($acD.m & I) == I ? 1 : 0
|
|
|
|
{"ILRR",
|
|
0x0210,
|
|
0xfefc,
|
|
DSPInterpreter::ilrr,
|
|
&DSPEmitter::ilrr,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $acD.m = IMEM[$arS]
|
|
{"ILRRD",
|
|
0x0214,
|
|
0xfefc,
|
|
DSPInterpreter::ilrrd,
|
|
&DSPEmitter::ilrrd,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $acD.m = IMEM[$arS--]
|
|
{"ILRRI",
|
|
0x0218,
|
|
0xfefc,
|
|
DSPInterpreter::ilrri,
|
|
&DSPEmitter::ilrri,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $acD.m = IMEM[$arS++]
|
|
{"ILRRN",
|
|
0x021c,
|
|
0xfefc,
|
|
DSPInterpreter::ilrrn,
|
|
&DSPEmitter::ilrrn,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $acD.m = IMEM[$arS]; $arS += $ixS
|
|
|
|
// LOOPS
|
|
{"LOOP",
|
|
0x0040,
|
|
0xffe0,
|
|
DSPInterpreter::loop,
|
|
&DSPEmitter::loop,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // run next instruction $R times
|
|
{"BLOOP",
|
|
0x0060,
|
|
0xffe0,
|
|
DSPInterpreter::bloop,
|
|
&DSPEmitter::bloop,
|
|
2,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // COMEFROM addr $R times
|
|
{"LOOPI",
|
|
0x1000,
|
|
0xff00,
|
|
DSPInterpreter::loopi,
|
|
&DSPEmitter::loopi,
|
|
1,
|
|
1,
|
|
{{P_IMM, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // run next instruction I times
|
|
{"BLOOPI",
|
|
0x1100,
|
|
0xff00,
|
|
DSPInterpreter::bloopi,
|
|
&DSPEmitter::bloopi,
|
|
2,
|
|
2,
|
|
{{P_IMM, 1, 0, 0, 0x00ff}, {P_ADDR_I, 2, 1, 0, 0xffff}},
|
|
false,
|
|
true,
|
|
true,
|
|
true,
|
|
false}, // COMEFROM addr I times
|
|
|
|
// load and store value pointed by indexing reg and increment; LRR/SRR variants
|
|
{"LRR",
|
|
0x1800,
|
|
0xff80,
|
|
DSPInterpreter::lrr,
|
|
&DSPEmitter::lrr,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $D = MEM[$arS]
|
|
{"LRRD",
|
|
0x1880,
|
|
0xff80,
|
|
DSPInterpreter::lrrd,
|
|
&DSPEmitter::lrrd,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $D = MEM[$arS--]
|
|
{"LRRI",
|
|
0x1900,
|
|
0xff80,
|
|
DSPInterpreter::lrri,
|
|
&DSPEmitter::lrri,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $D = MEM[$arS++]
|
|
{"LRRN",
|
|
0x1980,
|
|
0xff80,
|
|
DSPInterpreter::lrrn,
|
|
&DSPEmitter::lrrn,
|
|
1,
|
|
2,
|
|
{{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $D = MEM[$arS]; $arS += $ixS
|
|
|
|
{"SRR",
|
|
0x1a00,
|
|
0xff80,
|
|
DSPInterpreter::srr,
|
|
&DSPEmitter::srr,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$arD] = $S
|
|
{"SRRD",
|
|
0x1a80,
|
|
0xff80,
|
|
DSPInterpreter::srrd,
|
|
&DSPEmitter::srrd,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$arD--] = $S
|
|
{"SRRI",
|
|
0x1b00,
|
|
0xff80,
|
|
DSPInterpreter::srri,
|
|
&DSPEmitter::srri,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$arD++] = $S
|
|
{"SRRN",
|
|
0x1b80,
|
|
0xff80,
|
|
DSPInterpreter::srrn,
|
|
&DSPEmitter::srrn,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$arD] = $S; $arD += $ixD
|
|
|
|
// 2
|
|
{"LRS",
|
|
0x2000,
|
|
0xf800,
|
|
DSPInterpreter::lrs,
|
|
&DSPEmitter::lrs,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[($cr[0-7] << 8) | I]
|
|
{"SRS",
|
|
0x2800,
|
|
0xf800,
|
|
DSPInterpreter::srs,
|
|
&DSPEmitter::srs,
|
|
1,
|
|
2,
|
|
{{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[($cr[0-7] << 8) | I] = $(S+24)
|
|
|
|
// opcodes that can be extended
|
|
|
|
// 3 - main opcode defined by 9 bits, extension defined by last 7 bits!!
|
|
{"XORR",
|
|
0x3000,
|
|
0xfc80,
|
|
DSPInterpreter::xorr,
|
|
&DSPEmitter::xorr,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m ^= $axS.h
|
|
{"ANDR",
|
|
0x3400,
|
|
0xfc80,
|
|
DSPInterpreter::andr,
|
|
&DSPEmitter::andr,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m &= $axS.h
|
|
{"ORR",
|
|
0x3800,
|
|
0xfc80,
|
|
DSPInterpreter::orr,
|
|
&DSPEmitter::orr,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m |= $axS.h
|
|
{"ANDC",
|
|
0x3c00,
|
|
0xfe80,
|
|
DSPInterpreter::andc,
|
|
&DSPEmitter::andc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m &= $ac(1-D).m
|
|
{"ORC",
|
|
0x3e00,
|
|
0xfe80,
|
|
DSPInterpreter::orc,
|
|
&DSPEmitter::orc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m |= $ac(1-D).m
|
|
{"XORC",
|
|
0x3080,
|
|
0xfe80,
|
|
DSPInterpreter::xorc,
|
|
&DSPEmitter::xorc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m ^= $ac(1-D).m
|
|
{"NOT",
|
|
0x3280,
|
|
0xfe80,
|
|
DSPInterpreter::notc,
|
|
&DSPEmitter::notc,
|
|
1,
|
|
1,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.m = ~$acD.m
|
|
{"LSRNRX",
|
|
0x3480,
|
|
0xfc80,
|
|
DSPInterpreter::lsrnrx,
|
|
&DSPEmitter::lsrnrx,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD >>=/<<= $axS.h[0-6]
|
|
{"ASRNRX",
|
|
0x3880,
|
|
0xfc80,
|
|
DSPInterpreter::asrnrx,
|
|
&DSPEmitter::asrnrx,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD >>=/<<= $axS.h[0-6] (arithmetic)
|
|
{"LSRNR",
|
|
0x3c80,
|
|
0xfe80,
|
|
DSPInterpreter::lsrnr,
|
|
&DSPEmitter::lsrnr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD >>=/<<= $ac(1-D).m[0-6]
|
|
{"ASRNR",
|
|
0x3e80,
|
|
0xfe80,
|
|
DSPInterpreter::asrnr,
|
|
&DSPEmitter::asrnr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD >>=/<<= $ac(1-D).m[0-6] (arithmetic)
|
|
|
|
// 4
|
|
{"ADDR",
|
|
0x4000,
|
|
0xf800,
|
|
DSPInterpreter::addr,
|
|
&DSPEmitter::addr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD += $(S+24)
|
|
{"ADDAX",
|
|
0x4800,
|
|
0xfc00,
|
|
DSPInterpreter::addax,
|
|
&DSPEmitter::addax,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD += $axS
|
|
{"ADD",
|
|
0x4c00,
|
|
0xfe00,
|
|
DSPInterpreter::add,
|
|
&DSPEmitter::add,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD += $ac(1-D)
|
|
{"ADDP",
|
|
0x4e00,
|
|
0xfe00,
|
|
DSPInterpreter::addp,
|
|
&DSPEmitter::addp,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD += $prod
|
|
|
|
// 5
|
|
{"SUBR",
|
|
0x5000,
|
|
0xf800,
|
|
DSPInterpreter::subr,
|
|
&DSPEmitter::subr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD -= $(S+24)
|
|
{"SUBAX",
|
|
0x5800,
|
|
0xfc00,
|
|
DSPInterpreter::subax,
|
|
&DSPEmitter::subax,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD -= $axS
|
|
{"SUB",
|
|
0x5c00,
|
|
0xfe00,
|
|
DSPInterpreter::sub,
|
|
&DSPEmitter::sub,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD -= $ac(1-D)
|
|
{"SUBP",
|
|
0x5e00,
|
|
0xfe00,
|
|
DSPInterpreter::subp,
|
|
&DSPEmitter::subp,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD -= $prod
|
|
|
|
// 6
|
|
{"MOVR",
|
|
0x6000,
|
|
0xf800,
|
|
DSPInterpreter::movr,
|
|
&DSPEmitter::movr,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.hm = $(S+24); $acD.l = 0
|
|
{"MOVAX",
|
|
0x6800,
|
|
0xfc00,
|
|
DSPInterpreter::movax,
|
|
&DSPEmitter::movax,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_AX, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = $axS
|
|
{"MOV",
|
|
0x6c00,
|
|
0xfe00,
|
|
DSPInterpreter::mov,
|
|
&DSPEmitter::mov,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = $ax(1-D)
|
|
{"MOVP",
|
|
0x6e00,
|
|
0xfe00,
|
|
DSPInterpreter::movp,
|
|
&DSPEmitter::movp,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = $prod
|
|
|
|
// 7
|
|
{"ADDAXL",
|
|
0x7000,
|
|
0xfc00,
|
|
DSPInterpreter::addaxl,
|
|
&DSPEmitter::addaxl,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD += $axS.l
|
|
{"INCM",
|
|
0x7400,
|
|
0xfe00,
|
|
DSPInterpreter::incm,
|
|
&DSPEmitter::incm,
|
|
1,
|
|
1,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acsD++
|
|
{"INC",
|
|
0x7600,
|
|
0xfe00,
|
|
DSPInterpreter::inc,
|
|
&DSPEmitter::inc,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD++
|
|
{"DECM",
|
|
0x7800,
|
|
0xfe00,
|
|
DSPInterpreter::decm,
|
|
&DSPEmitter::decm,
|
|
1,
|
|
1,
|
|
{{P_ACCM, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acsD--
|
|
{"DEC",
|
|
0x7a00,
|
|
0xfe00,
|
|
DSPInterpreter::dec,
|
|
&DSPEmitter::dec,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD--
|
|
{"NEG",
|
|
0x7c00,
|
|
0xfe00,
|
|
DSPInterpreter::neg,
|
|
&DSPEmitter::neg,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = -$acD
|
|
{"MOVNP",
|
|
0x7e00,
|
|
0xfe00,
|
|
DSPInterpreter::movnp,
|
|
&DSPEmitter::movnp,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = -$prod
|
|
|
|
// 8
|
|
{"NX",
|
|
0x8000,
|
|
0xf700,
|
|
DSPInterpreter::nx,
|
|
&DSPEmitter::nx,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // extendable nop
|
|
{"CLR",
|
|
0x8100,
|
|
0xf700,
|
|
DSPInterpreter::clr,
|
|
&DSPEmitter::clr,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = 0
|
|
{"CMP",
|
|
0x8200,
|
|
0xff00,
|
|
DSPInterpreter::cmp,
|
|
&DSPEmitter::cmp,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($ac0 - $ac1)
|
|
{"MULAXH",
|
|
0x8300,
|
|
0xff00,
|
|
DSPInterpreter::mulaxh,
|
|
&DSPEmitter::mulaxh,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod = $ax0.h * $ax0.h
|
|
{"CLRP",
|
|
0x8400,
|
|
0xff00,
|
|
DSPInterpreter::clrp,
|
|
&DSPEmitter::clrp,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod = 0
|
|
{"TSTPROD",
|
|
0x8500,
|
|
0xff00,
|
|
DSPInterpreter::tstprod,
|
|
&DSPEmitter::tstprod,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($prod)
|
|
{"TSTAXH",
|
|
0x8600,
|
|
0xfe00,
|
|
DSPInterpreter::tstaxh,
|
|
&DSPEmitter::tstaxh,
|
|
1,
|
|
1,
|
|
{{P_REG1A, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($axR.h)
|
|
{"M2",
|
|
0x8a00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // enable "$prod *= 2" after every multiplication
|
|
{"M0",
|
|
0x8b00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // disable "$prod *= 2" after every multiplication
|
|
{"CLR15",
|
|
0x8c00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // set normal multiplication
|
|
{"SET15",
|
|
0x8d00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // set unsigned multiplication in MUL
|
|
{"SET16",
|
|
0x8e00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // set 16 bit sign extension width
|
|
{"SET40",
|
|
0x8f00,
|
|
0xff00,
|
|
DSPInterpreter::srbith,
|
|
&DSPEmitter::srbith,
|
|
1,
|
|
0,
|
|
{},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // set 40 bit sign extension width
|
|
|
|
// 9
|
|
{"MUL",
|
|
0x9000,
|
|
0xf700,
|
|
DSPInterpreter::mul,
|
|
&DSPEmitter::mul,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod = $axS.l * $axS.h
|
|
{"ASR16",
|
|
0x9100,
|
|
0xf700,
|
|
DSPInterpreter::asr16,
|
|
&DSPEmitter::asr16,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD >>= 16 (shifting in sign bits)
|
|
{"MULMVZ",
|
|
0x9200,
|
|
0xf600,
|
|
DSPInterpreter::mulmvz,
|
|
&DSPEmitter::mulmvz,
|
|
1,
|
|
3,
|
|
{{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR.hm = $prod.hm; $acR.l = 0; $prod = $axS.l * $axS.h
|
|
{"MULAC",
|
|
0x9400,
|
|
0xf600,
|
|
DSPInterpreter::mulac,
|
|
&DSPEmitter::mulac,
|
|
1,
|
|
3,
|
|
{{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR += $prod; $prod = $axS.l * $axS.h
|
|
{"MULMV",
|
|
0x9600,
|
|
0xf600,
|
|
DSPInterpreter::mulmv,
|
|
&DSPEmitter::mulmv,
|
|
1,
|
|
3,
|
|
{{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR = $prod; $prod = $axS.l * $axS.h
|
|
|
|
// a-b
|
|
{"MULX",
|
|
0xa000,
|
|
0xe700,
|
|
DSPInterpreter::mulx,
|
|
&DSPEmitter::mulx,
|
|
1,
|
|
2,
|
|
{{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod = $ax0.S * $ax1.T
|
|
{"ABS",
|
|
0xa100,
|
|
0xf700,
|
|
DSPInterpreter::abs,
|
|
&DSPEmitter::abs,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD = abs($acD)
|
|
{"MULXMVZ",
|
|
0xa200,
|
|
0xe600,
|
|
DSPInterpreter::mulxmvz,
|
|
&DSPEmitter::mulxmvz,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR.hm = $prod.hm; $acR.l = 0; $prod = $ax0.S * $ax1.T
|
|
{"MULXAC",
|
|
0xa400,
|
|
0xe600,
|
|
DSPInterpreter::mulxac,
|
|
&DSPEmitter::mulxac,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR += $prod; $prod = $ax0.S * $ax1.T
|
|
{"MULXMV",
|
|
0xa600,
|
|
0xe600,
|
|
DSPInterpreter::mulxmv,
|
|
&DSPEmitter::mulxmv,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR = $prod; $prod = $ax0.S * $ax1.T
|
|
{"TST",
|
|
0xb100,
|
|
0xf700,
|
|
DSPInterpreter::tst,
|
|
&DSPEmitter::tst,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($acR)
|
|
|
|
// c-d
|
|
{"MULC",
|
|
0xc000,
|
|
0xe700,
|
|
DSPInterpreter::mulc,
|
|
&DSPEmitter::mulc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod = $acS.m * $axS.h
|
|
{"CMPAR",
|
|
0xc100,
|
|
0xe700,
|
|
DSPInterpreter::cmpar,
|
|
&DSPEmitter::cmpar,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 12, 0x1000}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // FLAGS($acS - axR.h)
|
|
{"MULCMVZ",
|
|
0xc200,
|
|
0xe600,
|
|
DSPInterpreter::mulcmvz,
|
|
&DSPEmitter::mulcmvz,
|
|
1,
|
|
3,
|
|
{{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR.hm, $acR.l, $prod = $prod.hm, 0, $acS.m * $axS.h
|
|
{"MULCAC",
|
|
0xc400,
|
|
0xe600,
|
|
DSPInterpreter::mulcac,
|
|
&DSPEmitter::mulcac,
|
|
1,
|
|
3,
|
|
{{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR, $prod = $acR + $prod, $acS.m * $axS.h
|
|
{"MULCMV",
|
|
0xc600,
|
|
0xe600,
|
|
DSPInterpreter::mulcmv,
|
|
&DSPEmitter::mulcmv,
|
|
1,
|
|
3,
|
|
{{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR, $prod = $prod, $acS.m * $axS.h
|
|
|
|
// e
|
|
{"MADDX",
|
|
0xe000,
|
|
0xfc00,
|
|
DSPInterpreter::maddx,
|
|
&DSPEmitter::maddx,
|
|
1,
|
|
2,
|
|
{{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod += $ax0.S * $ax1.T
|
|
{"MSUBX",
|
|
0xe400,
|
|
0xfc00,
|
|
DSPInterpreter::msubx,
|
|
&DSPEmitter::msubx,
|
|
1,
|
|
2,
|
|
{{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod -= $ax0.S * $ax1.T
|
|
{"MADDC",
|
|
0xe800,
|
|
0xfc00,
|
|
DSPInterpreter::maddc,
|
|
&DSPEmitter::maddc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod += $acS.m * $axT.h
|
|
{"MSUBC",
|
|
0xec00,
|
|
0xfc00,
|
|
DSPInterpreter::msubc,
|
|
&DSPEmitter::msubc,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod -= $acS.m * $axT.h
|
|
|
|
// f
|
|
{"LSL16",
|
|
0xf000,
|
|
0xfe00,
|
|
DSPInterpreter::lsl16,
|
|
&DSPEmitter::lsl16,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR <<= 16
|
|
{"MADD",
|
|
0xf200,
|
|
0xfe00,
|
|
DSPInterpreter::madd,
|
|
&DSPEmitter::madd,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod += $axS.l * $axS.h
|
|
{"LSR16",
|
|
0xf400,
|
|
0xfe00,
|
|
DSPInterpreter::lsr16,
|
|
&DSPEmitter::lsr16,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR >>= 16
|
|
{"MSUB",
|
|
0xf600,
|
|
0xfe00,
|
|
DSPInterpreter::msub,
|
|
&DSPEmitter::msub,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $prod -= $axS.l * $axS.h
|
|
{"ADDPAXZ",
|
|
0xf800,
|
|
0xfc00,
|
|
DSPInterpreter::addpaxz,
|
|
&DSPEmitter::addpaxz,
|
|
1,
|
|
2,
|
|
{{P_ACC, 1, 0, 9, 0x0200}, {P_AX, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.hm = $prod.hm + $ax.h; $acD.l = 0
|
|
{"CLRL",
|
|
0xfc00,
|
|
0xfe00,
|
|
DSPInterpreter::clrl,
|
|
&DSPEmitter::clrl,
|
|
1,
|
|
1,
|
|
{{P_ACCL, 1, 0, 11, 0x0800}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acR.l = 0
|
|
{"MOVPZ",
|
|
0xfe00,
|
|
0xfe00,
|
|
DSPInterpreter::movpz,
|
|
&DSPEmitter::movpz,
|
|
1,
|
|
1,
|
|
{{P_ACC, 1, 0, 8, 0x0100}},
|
|
true,
|
|
false,
|
|
false,
|
|
false,
|
|
true}, // $acD.hm = $prod.hm; $acD.l = 0
|
|
};
|
|
|
|
const DSPOPCTemplate cw = {"CW", 0x0000, 0x0000, nop, nullptr, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},
|
|
false, false, false, false, false};
|
|
|
|
// extended opcodes
|
|
|
|
const DSPOPCTemplate opcodes_ext[] = {
|
|
{"XXX",
|
|
0x0000,
|
|
0x00fc,
|
|
DSPInterpreter::Ext::nop,
|
|
&DSPEmitter::nop,
|
|
1,
|
|
1,
|
|
{{P_VAL, 1, 0, 0, 0x00ff}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // no operation
|
|
|
|
{"DR",
|
|
0x0004,
|
|
0x00fc,
|
|
DSPInterpreter::Ext::dr,
|
|
&DSPEmitter::dr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arR--
|
|
{"IR",
|
|
0x0008,
|
|
0x00fc,
|
|
DSPInterpreter::Ext::ir,
|
|
&DSPEmitter::ir,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arR++
|
|
{"NR",
|
|
0x000c,
|
|
0x00fc,
|
|
DSPInterpreter::Ext::nr,
|
|
&DSPEmitter::nr,
|
|
1,
|
|
1,
|
|
{{P_REG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $arR += $ixR
|
|
{"MV",
|
|
0x0010,
|
|
0x00f0,
|
|
DSPInterpreter::Ext::mv,
|
|
&DSPEmitter::mv,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = $(S+28)
|
|
|
|
{"S",
|
|
0x0020,
|
|
0x00e4,
|
|
DSPInterpreter::Ext::s,
|
|
&DSPEmitter::s,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$D++] = $(S+28)
|
|
{"SN",
|
|
0x0024,
|
|
0x00e4,
|
|
DSPInterpreter::Ext::sn,
|
|
&DSPEmitter::sn,
|
|
1,
|
|
2,
|
|
{{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$D] = $(D+28); $D += $(D+4)
|
|
|
|
{"L",
|
|
0x0040,
|
|
0x00c4,
|
|
DSPInterpreter::Ext::l,
|
|
&DSPEmitter::l,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$S++]
|
|
{"LN",
|
|
0x0044,
|
|
0x00c4,
|
|
DSPInterpreter::Ext::ln,
|
|
&DSPEmitter::ln,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$S]; $S += $(S+4)
|
|
|
|
{"LS",
|
|
0x0080,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::ls,
|
|
&DSPEmitter::ls,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$ar0++]; MEM[$ar3++] = $acS.m
|
|
{"SL",
|
|
0x0082,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::sl,
|
|
&DSPEmitter::sl,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$ar0++] = $acS.m; $(D+24) = MEM[$ar3++]
|
|
{"LSN",
|
|
0x0084,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::lsn,
|
|
&DSPEmitter::lsn,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$ar0]; MEM[$ar3++] = $acS.m; $ar0 += $ix0
|
|
{"SLN",
|
|
0x0086,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::sln,
|
|
&DSPEmitter::sln,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$ar0] = $acS.m; $(D+24) = MEM[$ar3++]; $ar0 += $ix0
|
|
{"LSM",
|
|
0x0088,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::lsm,
|
|
&DSPEmitter::lsm,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$ar0++]; MEM[$ar3] = $acS.m; $ar3 += $ix3
|
|
{"SLM",
|
|
0x008a,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::slm,
|
|
&DSPEmitter::slm,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$ar0++] = $acS.m; $(D+24) = MEM[$ar3]; $ar3 += $ix3
|
|
{"LSNM",
|
|
0x008c,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::lsnm,
|
|
&DSPEmitter::lsnm,
|
|
1,
|
|
2,
|
|
{{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $(D+24) = MEM[$ar0]; MEM[$ar3] = $acS.m; $ar0 += $ix0; $ar3 += $ix3
|
|
{"SLNM",
|
|
0x008e,
|
|
0x00ce,
|
|
DSPInterpreter::Ext::slnm,
|
|
&DSPEmitter::slnm,
|
|
1,
|
|
2,
|
|
{{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // MEM[$ar0] = $acS.m; $(D+24) = MEM[$ar3]; $ar0 += $ix0; $ar3 += $ix3
|
|
|
|
{"LDAX",
|
|
0x00c3,
|
|
0x00cf,
|
|
DSPInterpreter::Ext::ldax,
|
|
&DSPEmitter::ldax,
|
|
1,
|
|
2,
|
|
{{P_AX, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $axR.h = MEM[$arS++]; $axR.l = MEM[$ar3++]
|
|
{"LDAXN",
|
|
0x00c7,
|
|
0x00cf,
|
|
DSPInterpreter::Ext::ldaxn,
|
|
&DSPEmitter::ldaxn,
|
|
1,
|
|
2,
|
|
{{P_AX, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $axR.h = MEM[$arS]; $axR.l = MEM[$ar3++]; $arS += $ixS
|
|
{"LDAXM",
|
|
0x00cb,
|
|
0x00cf,
|
|
DSPInterpreter::Ext::ldaxm,
|
|
&DSPEmitter::ldaxm,
|
|
1,
|
|
2,
|
|
{{P_AX, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $axR.h = MEM[$arS++]; $axR.l = MEM[$ar3]; $ar3 += $ix3
|
|
{"LDAXNM",
|
|
0x00cf,
|
|
0x00cf,
|
|
DSPInterpreter::Ext::ldaxnm,
|
|
&DSPEmitter::ldaxnm,
|
|
1,
|
|
2,
|
|
{{P_AX, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $axR.h = MEM[$arS]; $axR.l = MEM[$ar3]; $arS += $ixS; $ar3 += $ix3
|
|
|
|
{"LD",
|
|
0x00c0,
|
|
0x00cc,
|
|
DSPInterpreter::Ext::ld,
|
|
&DSPEmitter::ld,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $ax0.D = MEM[$arS++]; $ax1.R = MEM[$ar3++]
|
|
{"LDN",
|
|
0x00c4,
|
|
0x00cc,
|
|
DSPInterpreter::Ext::ldn,
|
|
&DSPEmitter::ldn,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3++]; $arS += $ixS
|
|
{"LDM",
|
|
0x00c8,
|
|
0x00cc,
|
|
DSPInterpreter::Ext::ldm,
|
|
&DSPEmitter::ldm,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $ax0.D = MEM[$arS++]; $ax1.R = MEM[$ar3]; $ar3 += $ix3
|
|
{"LDNM",
|
|
0x00cc,
|
|
0x00cc,
|
|
DSPInterpreter::Ext::ldnm,
|
|
&DSPEmitter::ldnm,
|
|
1,
|
|
3,
|
|
{{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
false}, // $ax0.D = MEM[$arS]; $ax1.R = MEM[$ar3]; $arS += $ixS; $ar3 += $ix3
|
|
};
|
|
|
|
const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
|
|
const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
|
|
|
|
const pdlabel_t pdlabels[] = {
|
|
{
|
|
0xffa0, "COEF_A1_0", "COEF_A1_0",
|
|
},
|
|
{
|
|
0xffa1, "COEF_A2_0", "COEF_A2_0",
|
|
},
|
|
{
|
|
0xffa2, "COEF_A1_1", "COEF_A1_1",
|
|
},
|
|
{
|
|
0xffa3, "COEF_A2_1", "COEF_A2_1",
|
|
},
|
|
{
|
|
0xffa4, "COEF_A1_2", "COEF_A1_2",
|
|
},
|
|
{
|
|
0xffa5, "COEF_A2_2", "COEF_A2_2",
|
|
},
|
|
{
|
|
0xffa6, "COEF_A1_3", "COEF_A1_3",
|
|
},
|
|
{
|
|
0xffa7, "COEF_A2_3", "COEF_A2_3",
|
|
},
|
|
{
|
|
0xffa8, "COEF_A1_4", "COEF_A1_4",
|
|
},
|
|
{
|
|
0xffa9, "COEF_A2_4", "COEF_A2_4",
|
|
},
|
|
{
|
|
0xffaa, "COEF_A1_5", "COEF_A1_5",
|
|
},
|
|
{
|
|
0xffab, "COEF_A2_5", "COEF_A2_5",
|
|
},
|
|
{
|
|
0xffac, "COEF_A1_6", "COEF_A1_6",
|
|
},
|
|
{
|
|
0xffad, "COEF_A2_6", "COEF_A2_6",
|
|
},
|
|
{
|
|
0xffae, "COEF_A1_7", "COEF_A1_7",
|
|
},
|
|
{
|
|
0xffaf, "COEF_A2_7", "COEF_A2_7",
|
|
},
|
|
|
|
{
|
|
0xffb0, "0xffb0", nullptr,
|
|
},
|
|
{
|
|
0xffb1, "0xffb1", nullptr,
|
|
},
|
|
{
|
|
0xffb2, "0xffb2", nullptr,
|
|
},
|
|
{
|
|
0xffb3, "0xffb3", nullptr,
|
|
},
|
|
{
|
|
0xffb4, "0xffb4", nullptr,
|
|
},
|
|
{
|
|
0xffb5, "0xffb5", nullptr,
|
|
},
|
|
{
|
|
0xffb6, "0xffb6", nullptr,
|
|
},
|
|
{
|
|
0xffb7, "0xffb7", nullptr,
|
|
},
|
|
{
|
|
0xffb8, "0xffb8", nullptr,
|
|
},
|
|
{
|
|
0xffb9, "0xffb9", nullptr,
|
|
},
|
|
{
|
|
0xffba, "0xffba", nullptr,
|
|
},
|
|
{
|
|
0xffbb, "0xffbb", nullptr,
|
|
},
|
|
{
|
|
0xffbc, "0xffbc", nullptr,
|
|
},
|
|
{
|
|
0xffbd, "0xffbd", nullptr,
|
|
},
|
|
{
|
|
0xffbe, "0xffbe", nullptr,
|
|
},
|
|
{
|
|
0xffbf, "0xffbf", nullptr,
|
|
},
|
|
|
|
{
|
|
0xffc0, "0xffc0", nullptr,
|
|
},
|
|
{
|
|
0xffc1, "0xffc1", nullptr,
|
|
},
|
|
{
|
|
0xffc2, "0xffc2", nullptr,
|
|
},
|
|
{
|
|
0xffc3, "0xffc3", nullptr,
|
|
},
|
|
{
|
|
0xffc4, "0xffc4", nullptr,
|
|
},
|
|
{
|
|
0xffc5, "0xffc5", nullptr,
|
|
},
|
|
{
|
|
0xffc6, "0xffc6", nullptr,
|
|
},
|
|
{
|
|
0xffc7, "0xffc7", nullptr,
|
|
},
|
|
{
|
|
0xffc8, "0xffc8", nullptr,
|
|
},
|
|
{
|
|
0xffc9, "DSCR", "DSP DMA Control Reg",
|
|
},
|
|
{
|
|
0xffca, "0xffca", nullptr,
|
|
},
|
|
{
|
|
0xffcb, "DSBL", "DSP DMA Block Length",
|
|
},
|
|
{
|
|
0xffcc, "0xffcc", nullptr,
|
|
},
|
|
{
|
|
0xffcd, "DSPA", "DSP DMA DMEM Address",
|
|
},
|
|
{
|
|
0xffce, "DSMAH", "DSP DMA Mem Address H",
|
|
},
|
|
{
|
|
0xffcf, "DSMAL", "DSP DMA Mem Address L",
|
|
},
|
|
|
|
{
|
|
0xffd0, "0xffd0", nullptr,
|
|
},
|
|
{
|
|
0xffd1, "SampleFormat", "SampleFormat",
|
|
},
|
|
{
|
|
0xffd2, "0xffd2", nullptr,
|
|
},
|
|
{
|
|
0xffd3, "UnkZelda", "Unk Zelda reads/writes from/to it",
|
|
},
|
|
{
|
|
0xffd4, "ACSAH", "Accelerator start address H",
|
|
},
|
|
{
|
|
0xffd5, "ACSAL", "Accelerator start address L",
|
|
},
|
|
{
|
|
0xffd6, "ACEAH", "Accelerator end address H",
|
|
},
|
|
{
|
|
0xffd7, "ACEAL", "Accelerator end address L",
|
|
},
|
|
{
|
|
0xffd8, "ACCAH", "Accelerator current address H",
|
|
},
|
|
{
|
|
0xffd9, "ACCAL", "Accelerator current address L",
|
|
},
|
|
{
|
|
0xffda, "pred_scale", "pred_scale",
|
|
},
|
|
{
|
|
0xffdb, "yn1", "yn1",
|
|
},
|
|
{
|
|
0xffdc, "yn2", "yn2",
|
|
},
|
|
{
|
|
0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",
|
|
},
|
|
{
|
|
0xffde, "GAIN", "Gain",
|
|
},
|
|
{
|
|
0xffdf, "0xffdf", nullptr,
|
|
},
|
|
|
|
{
|
|
0xffe0, "0xffe0", nullptr,
|
|
},
|
|
{
|
|
0xffe1, "0xffe1", nullptr,
|
|
},
|
|
{
|
|
0xffe2, "0xffe2", nullptr,
|
|
},
|
|
{
|
|
0xffe3, "0xffe3", nullptr,
|
|
},
|
|
{
|
|
0xffe4, "0xffe4", nullptr,
|
|
},
|
|
{
|
|
0xffe5, "0xffe5", nullptr,
|
|
},
|
|
{
|
|
0xffe6, "0xffe6", nullptr,
|
|
},
|
|
{
|
|
0xffe7, "0xffe7", nullptr,
|
|
},
|
|
{
|
|
0xffe8, "0xffe8", nullptr,
|
|
},
|
|
{
|
|
0xffe9, "0xffe9", nullptr,
|
|
},
|
|
{
|
|
0xffea, "0xffea", nullptr,
|
|
},
|
|
{
|
|
0xffeb, "0xffeb", nullptr,
|
|
},
|
|
{
|
|
0xffec, "0xffec", nullptr,
|
|
},
|
|
{
|
|
0xffed, "0xffed", nullptr,
|
|
},
|
|
{
|
|
0xffee, "0xffee", nullptr,
|
|
},
|
|
{
|
|
0xffef, "AMDM", "ARAM DMA Request Mask",
|
|
},
|
|
|
|
{
|
|
0xfff0, "0xfff0", nullptr,
|
|
},
|
|
{
|
|
0xfff1, "0xfff1", nullptr,
|
|
},
|
|
{
|
|
0xfff2, "0xfff2", nullptr,
|
|
},
|
|
{
|
|
0xfff3, "0xfff3", nullptr,
|
|
},
|
|
{
|
|
0xfff4, "0xfff4", nullptr,
|
|
},
|
|
{
|
|
0xfff5, "0xfff5", nullptr,
|
|
},
|
|
{
|
|
0xfff6, "0xfff6", nullptr,
|
|
},
|
|
{
|
|
0xfff7, "0xfff7", nullptr,
|
|
},
|
|
{
|
|
0xfff8, "0xfff8", nullptr,
|
|
},
|
|
{
|
|
0xfff9, "0xfff9", nullptr,
|
|
},
|
|
{
|
|
0xfffa, "0xfffa", nullptr,
|
|
},
|
|
{
|
|
0xfffb, "DIRQ", "DSP IRQ Request",
|
|
},
|
|
{
|
|
0xfffc, "DMBH", "DSP Mailbox H",
|
|
},
|
|
{
|
|
0xfffd, "DMBL", "DSP Mailbox L",
|
|
},
|
|
{
|
|
0xfffe, "CMBH", "CPU Mailbox H",
|
|
},
|
|
{
|
|
0xffff, "CMBL", "CPU Mailbox L",
|
|
},
|
|
};
|
|
|
|
const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t);
|
|
|
|
const pdlabel_t regnames[] = {
|
|
{
|
|
0x00, "AR0", "Addr Reg 00",
|
|
},
|
|
{
|
|
0x01, "AR1", "Addr Reg 01",
|
|
},
|
|
{
|
|
0x02, "AR2", "Addr Reg 02",
|
|
},
|
|
{
|
|
0x03, "AR3", "Addr Reg 03",
|
|
},
|
|
{
|
|
0x04, "IX0", "Index Reg 0",
|
|
},
|
|
{
|
|
0x05, "IX1", "Index Reg 1",
|
|
},
|
|
{
|
|
0x06, "IX2", "Index Reg 2",
|
|
},
|
|
{
|
|
0x07, "IX3", "Index Reg 3",
|
|
},
|
|
{
|
|
0x08, "WR0", "Wrapping Register 0",
|
|
},
|
|
{
|
|
0x09, "WR1", "Wrapping Register 1",
|
|
},
|
|
{
|
|
0x0a, "WR2", "Wrapping Register 2",
|
|
},
|
|
{
|
|
0x0b, "WR3", "Wrapping Register 3",
|
|
},
|
|
{
|
|
0x0c, "ST0", "Call stack",
|
|
},
|
|
{
|
|
0x0d, "ST1", "Data stack",
|
|
},
|
|
{
|
|
0x0e, "ST2", "Loop addr stack",
|
|
},
|
|
{
|
|
0x0f, "ST3", "Loop counter",
|
|
},
|
|
{
|
|
0x10, "AC0.H", "Accu High 0",
|
|
},
|
|
{
|
|
0x11, "AC1.H", "Accu High 1",
|
|
},
|
|
{
|
|
0x12, "CR", "Config Register",
|
|
},
|
|
{
|
|
0x13, "SR", "Special Register",
|
|
},
|
|
{
|
|
0x14, "PROD.L", "Prod L",
|
|
},
|
|
{
|
|
0x15, "PROD.M1", "Prod M1",
|
|
},
|
|
{
|
|
0x16, "PROD.H", "Prod H",
|
|
},
|
|
{
|
|
0x17, "PROD.M2", "Prod M2",
|
|
},
|
|
{
|
|
0x18, "AX0.L", "Extra Accu L 0",
|
|
},
|
|
{
|
|
0x19, "AX1.L", "Extra Accu L 1",
|
|
},
|
|
{
|
|
0x1a, "AX0.H", "Extra Accu H 0",
|
|
},
|
|
{
|
|
0x1b, "AX1.H", "Extra Accu H 1",
|
|
},
|
|
{
|
|
0x1c, "AC0.L", "Accu Low 0",
|
|
},
|
|
{
|
|
0x1d, "AC1.L", "Accu Low 1",
|
|
},
|
|
{
|
|
0x1e, "AC0.M", "Accu Mid 0",
|
|
},
|
|
{
|
|
0x1f, "AC1.M", "Accu Mid 1",
|
|
},
|
|
|
|
// To resolve combined register names.
|
|
{
|
|
0x20, "ACC0", "Accu Full 0",
|
|
},
|
|
{
|
|
0x21, "ACC1", "Accu Full 1",
|
|
},
|
|
{
|
|
0x22, "AX0", "Extra Accu 0",
|
|
},
|
|
{
|
|
0x23, "AX1", "Extra Accu 1",
|
|
},
|
|
};
|
|
|
|
const DSPOPCTemplate* opTable[OPTABLE_SIZE];
|
|
const DSPOPCTemplate* extOpTable[EXT_OPTABLE_SIZE];
|
|
u16 writeBackLog[WRITEBACKLOGSIZE];
|
|
int writeBackLogIdx[WRITEBACKLOGSIZE];
|
|
|
|
const char* pdname(u16 val)
|
|
{
|
|
static char tmpstr[12]; // nasty
|
|
|
|
for (const pdlabel_t& pdlabel : pdlabels)
|
|
{
|
|
if (pdlabel.addr == val)
|
|
return pdlabel.name;
|
|
}
|
|
|
|
sprintf(tmpstr, "0x%04x", val);
|
|
return tmpstr;
|
|
}
|
|
|
|
const char* pdregname(int val)
|
|
{
|
|
return regnames[val].name;
|
|
}
|
|
|
|
const char* pdregnamelong(int val)
|
|
{
|
|
return regnames[val].description;
|
|
}
|
|
|
|
const DSPOPCTemplate* GetOpTemplate(const UDSPInstruction& inst)
|
|
{
|
|
return opTable[inst];
|
|
}
|
|
|
|
// This function could use the above GetOpTemplate, but then we'd lose the
|
|
// nice property that it catches colliding op masks.
|
|
void InitInstructionTable()
|
|
{
|
|
// ext op table
|
|
for (int i = 0; i < EXT_OPTABLE_SIZE; i++)
|
|
{
|
|
extOpTable[i] = &cw;
|
|
|
|
for (const DSPOPCTemplate& ext : opcodes_ext)
|
|
{
|
|
u16 mask = ext.opcode_mask;
|
|
if ((mask & i) == ext.opcode)
|
|
{
|
|
if (extOpTable[i] == &cw)
|
|
{
|
|
extOpTable[i] = &ext;
|
|
}
|
|
else
|
|
{
|
|
// if the entry already in the table
|
|
// is a strict subset, allow it
|
|
if ((extOpTable[i]->opcode_mask | ext.opcode_mask) != extOpTable[i]->opcode_mask)
|
|
{
|
|
ERROR_LOG(DSPLLE, "opcode ext table place %d already in use by %s when inserting %s", i,
|
|
extOpTable[i]->name, ext.name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// op table
|
|
for (const DSPOPCTemplate*& opcode : opTable)
|
|
{
|
|
opcode = &cw;
|
|
}
|
|
|
|
for (int i = 0; i < OPTABLE_SIZE; i++)
|
|
{
|
|
for (const DSPOPCTemplate& opcode : opcodes)
|
|
{
|
|
u16 mask = opcode.opcode_mask;
|
|
if ((mask & i) == opcode.opcode)
|
|
{
|
|
if (opTable[i] == &cw)
|
|
opTable[i] = &opcode;
|
|
else
|
|
ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcode.name);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int& elem : writeBackLogIdx)
|
|
{
|
|
elem = -1;
|
|
}
|
|
}
|