pureikyubu/src/dspdec.cpp
2023-08-02 23:43:02 +03:00

1683 lines
45 KiB
C++

// DSP instruction decoder
#include "pch.h"
namespace DSP
{
void Decoder::ResetInfo(DecoderInfo& info)
{
info.sizeInBytes = 0;
info.parallel = false;
info.parallelMemInstr = DspParallelMemInstruction::Unknown;
info.instr = DspRegularInstruction::Unknown;
info.numParameters = 0;
info.numParametersEx = 0;
info.flowControl = false;
}
void Decoder::AddParam(DecoderInfo& info, DspParameter param)
{
assert(info.numParameters < DspDecoderNumParam);
info.params[info.numParameters] = param;
info.numParameters++;
}
void Decoder::AddParamEx(DecoderInfo& info, DspParameter param)
{
assert(info.numParametersEx < DspDecoderNumParam);
info.paramsEx[info.numParametersEx] = param;
info.numParametersEx++;
}
void Decoder::AddImmOperand(DecoderInfo& info, DspParameter param, uint8_t imm)
{
AddParam(info, param);
if (param == DspParameter::Byte)
info.ImmOperand.Byte = imm;
else if (param == DspParameter::Byte2)
info.ImmOperand2.Byte = imm;
}
void Decoder::AddImmOperand(DecoderInfo& info, DspParameter param, int8_t imm)
{
AddParam(info, param);
if (param == DspParameter::SignedByte)
info.ImmOperand.SignedByte = imm;
else if (param == DspParameter::SignedByte2)
info.ImmOperand2.SignedByte = imm;
}
void Decoder::AddImmOperand(DecoderInfo& info, DspParameter param, uint16_t imm)
{
AddParam(info, param);
if (param == DspParameter::UnsignedShort)
info.ImmOperand.UnsignedShort = imm;
else if (param == DspParameter::UnsignedShort2)
info.ImmOperand2.UnsignedShort = imm;
}
void Decoder::AddImmOperand(DecoderInfo& info, DspParameter param, int16_t imm)
{
AddParam(info, param);
if (param == DspParameter::SignedShort)
info.ImmOperand.SignedShort = imm;
else if (param == DspParameter::SignedShort2)
info.ImmOperand2.SignedShort = imm;
}
void Decoder::AddImmOperand(DecoderInfo& info, DspParameter param, DspAddress imm)
{
AddParam(info, param);
if (param == DspParameter::Address)
info.ImmOperand.Address = imm;
else if (param == DspParameter::Address2)
info.ImmOperand2.Address = imm;
}
void Decoder::AddBytes(uint8_t* instrPtr, size_t bytes, DecoderInfo& info)
{
assert(info.sizeInBytes < sizeof(info.bytes));
memcpy(&info.bytes[info.sizeInBytes], instrPtr, bytes);
info.sizeInBytes += bytes;
}
void Decoder::Group0(uint8_t* instrPtr, size_t instrMaxSize, DecoderInfo& info, uint16_t instrBits)
{
static DspParameter addressreg[] = {
DspParameter::r0,
DspParameter::r1,
DspParameter::r2,
DspParameter::r3,
};
static DspParameter topreg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
DspParameter::a0,
DspParameter::b0,
DspParameter::a1,
DspParameter::b1,
};
static DspParameter modifier[] = { // pld
DspParameter::mod_none,
DspParameter::mod_dec,
DspParameter::mod_inc,
DspParameter::mod_plus_m,
};
static DspParameter modifier_n[] = {
DspParameter::mod_plus_m0,
DspParameter::mod_plus_m1,
DspParameter::mod_plus_m2,
DspParameter::mod_plus_m3,
};
switch ((instrBits >> 8) & 0xf)
{
//|nop |0000 0000 0[00]0 0000|
//|mr rn,mn |0000 0000 0[00]m mmrr|
//|trap |0000 0000 0[01]0 0000|
//|wait |0000 0000 0[01]0 0001|
//|repr reg |0000 0000 0[10]r rrrr|
//|loop reg,ea |0000 0000 0[11]r rrrr aaaa aaaa aaaa aaaa|
//|mvli d,li |0000 0000 1[00]d dddd iiii iiii iiii iiii|
//|ldla d,la |0000 0000 1[10]d dddd aaaa aaaa aaaa aaaa|
//|stla la,s |0000 0000 1[11]s ssss aaaa aaaa aaaa aaaa|
case 0:
if ((instrBits & 0x80) == 0)
{
switch ((instrBits >> 5) & 3)
{
case 0: // nop, mr
{
int r = instrBits & 3;
int m = (instrBits >> 2) & 7;
if ((r == 0) && (m == 0))
{
info.instr = DspRegularInstruction::nop;
}
else
{
info.instr = DspRegularInstruction::mr;
AddParam(info, addressreg[r]);
AddParam(info, (DspParameter)((int)DspParameter::mod_base + m));
}
break;
}
case 1: // trap, wait
{
info.instr = (instrBits & 1) == 0 ? DspRegularInstruction::trap : DspRegularInstruction::wait;
info.flowControl = true;
break;
}
case 2: // rep r
{
info.instr = DspRegularInstruction::rep;
info.flowControl = true;
int r = instrBits & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + r));
break;
}
case 3: // loop r
{
info.instr = DspRegularInstruction::loop;
info.flowControl = true;
int r = instrBits & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + r));
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::Address, addr);
break;
}
}
}
else
{
switch ((instrBits >> 5) & 3)
{
case 0: // mvli
{
info.instr = DspRegularInstruction::mvli;
int r = instrBits & 0x1f;
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddParam(info, (DspParameter)((int)DspParameter::regs + r));
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 1:
// Reserved
break;
case 2: // ldla
{
info.instr = DspRegularInstruction::ldla;
int r = instrBits & 0x1f;
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddParam(info, (DspParameter)((int)DspParameter::regs + r));
AddImmOperand(info, DspParameter::Address, addr);
break;
}
case 3: // stla
{
info.instr = DspRegularInstruction::stla;
int r = instrBits & 0x1f;
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::Address, addr);
AddParam(info, (DspParameter)((int)DspParameter::regs + r));
break;
}
}
}
break;
case 1:
// Reserved
break;
//|adli d,li |0000 001d 0000 0000 iiii iiii iiii iiii|
//|norm d,rn |0000 001d 0000 01rr|
//|negc d |0000 001d 0000 1101|
//|pld d,rn,mn |0000 001d 0001 mmrr|
//|xorli d,li |0000 001d 0010 0000 iiii iiii iiii iiii|
//|anli d,li |0000 001d 0100 0000 iiii iiii iiii iiii|
//|orli d,li |0000 001d 0110 0000 iiii iiii iiii iiii|
//|div d,s |0000 001d 0ss0 1000|
//|max d,s |0000 001d 0ss0 1001|
//|lsf d,s |0000 001d 01s0 1010|
//|asf d,s |0000 001d 01s0 1011|
//|exec(cc) |0000 0010 0111 cccc|
//|cmpli s,li |0000 001s 1000 0000 iiii iiii iiii iiii|
//|addc d,s |0000 001d 10s0 1100|
//|subc d,s |0000 001d 10s0 1101|
//|jmp(cc) ta |0000 0010 1001 cccc aaaa aaaa aaaa aaaa|
//|btstl d,bs |0000 001d 1010 0000 bbbb bbbb bbbb bbbb|
//|call(cc) ta |0000 0010 1011 cccc aaaa aaaa aaaa aaaa|
//|btsth d,bs |0000 001d 1100 0000 bbbb bbbb bbbb bbbb|
//|lsf d,s |0000 001d 1100 1010|
//|asf d,s |0000 001d 1100 1011|
//|rets(cc) |0000 0010 1101 cccc|
//|reti(cc) |0000 0010 1111 cccc|
case 2:
case 3:
switch ((instrBits >> 4) & 0xf)
{
case 0: // adli, norm, negc + div, max
switch (instrBits & 0xf)
{
case 0: // adli
{
info.instr = DspRegularInstruction::adli;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::SignedShort, imm);
break;
}
case 4: // norm
case 5:
case 6:
case 7:
{
info.instr = DspRegularInstruction::norm;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int r = instrBits & 3;
AddParam(info, addressreg[r]);
break;
}
case 8: // div
{
info.instr = DspRegularInstruction::div;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 9: // max
{
info.instr = DspRegularInstruction::max;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 0xd: // negc
{
info.instr = DspRegularInstruction::negc;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
}
}
break;
case 1: // pld
{
info.instr = DspRegularInstruction::pld;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
int r = instrBits & 3;
AddParam(info, addressreg[r]);
int m = (instrBits >> 2) & 3;
AddParam(info, modifier[m] == DspParameter::mod_plus_m ? modifier_n[r] : modifier[m]);
break;
}
case 2: // xorli + div, max
switch (instrBits & 0xf)
{
case 0: // xorli
{
info.instr = DspRegularInstruction::xorli;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 8: // div
{
info.instr = DspRegularInstruction::div;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 9: // max
{
info.instr = DspRegularInstruction::max;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
}
break;
case 3:
case 5:
// Reserved
break;
case 4: // anli + div, max + lsf, asf
switch (instrBits & 0xf)
{
case 0: // anli
{
info.instr = DspRegularInstruction::anli;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 8: // div
{
info.instr = DspRegularInstruction::div;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 9: // max
{
info.instr = DspRegularInstruction::max;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 0xa: // lsf
{
info.instr = DspRegularInstruction::lsf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
}
case 0xb: // asf
{
info.instr = DspRegularInstruction::asf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
}
}
break;
case 6: // orli + div, max + lsf, asf
switch (instrBits & 0xf)
{
case 0: // orli
{
info.instr = DspRegularInstruction::orli;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 8: // div
{
info.instr = DspRegularInstruction::div;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 9: // max
{
info.instr = DspRegularInstruction::max;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits >> 5) & 3;
AddParam(info, topreg[s]);
break;
}
case 0xa: // lsf
{
info.instr = DspRegularInstruction::lsf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
}
case 0xb: // asf
{
info.instr = DspRegularInstruction::asf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
}
}
break;
case 7: // exec
{
info.instr = DspRegularInstruction::exec;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
break;
}
case 8: // cmpli + addc, subc
switch (instrBits & 0xf)
{
case 0: // cmpli
{
info.instr = DspRegularInstruction::cmpli;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::SignedShort, imm);
break;
}
case 0xc: // addc
{
info.instr = DspRegularInstruction::addc;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x : DspParameter::y);
break;
}
case 0xd: // subc
{
info.instr = DspRegularInstruction::subc;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x : DspParameter::y);
break;
}
}
break;
case 9: // jmp
{
info.instr = DspRegularInstruction::jmp;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::Address, addr);
break;
}
case 0xa: // btstl + addc, subc
switch (instrBits & 0xf)
{
case 0: // btstl
{
info.instr = DspRegularInstruction::btstl;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 0xc: // addc
{
info.instr = DspRegularInstruction::addc;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x : DspParameter::y);
break;
}
case 0xd: // subc
{
info.instr = DspRegularInstruction::subc;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
int s = (instrBits & 0x20) ? 1 : 0;
AddParam(info, s == 0 ? DspParameter::x : DspParameter::y);
break;
}
}
break;
case 0xb: // call
{
info.instr = DspRegularInstruction::call;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::Address, addr);
break;
}
case 0xc: // btsth, lsf, asf
switch (instrBits & 0xf)
{
case 0: // btsth
{
info.instr = DspRegularInstruction::btsth;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort, imm);
break;
}
case 0xa: // lsf
{
info.instr = DspRegularInstruction::lsf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, d == 0 ? DspParameter::b1 : DspParameter::a1);
break;
}
case 0xb: // asf
{
info.instr = DspRegularInstruction::asf;
int d = (instrBits & 0x100) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, d == 0 ? DspParameter::b1 : DspParameter::a1);
break;
}
}
break;
case 0xd: // rets
{
info.instr = DspRegularInstruction::rets;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
break;
}
case 0xe:
// Reserved
break;
case 0xf: // reti
{
info.instr = DspRegularInstruction::reti;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
break;
}
}
break;
//|adsi d,si |0000 010d iiii iiii|
case 4:
case 5:
{
info.instr = DspRegularInstruction::adsi;
int r = (instrBits & 0x100) ? 1 : 0;
AddParam(info, r == 0 ? DspParameter::a : DspParameter::b);
AddImmOperand(info, DspParameter::SignedByte, (int8_t)instrBits);
break;
}
//|cmpsi s,si |0000 011s iiii iiii|
case 6:
case 7:
{
info.instr = DspRegularInstruction::cmpsi;
int r = (instrBits & 0x100) ? 1 : 0;
AddParam(info, r == 0 ? DspParameter::a : DspParameter::b);
AddImmOperand(info, DspParameter::SignedByte, (int8_t)instrBits);
break;
}
//|mvsi d,si |0000 1ddd iiii iiii|
case 8:
case 9:
case 0xa:
case 0xb:
case 0xc:
case 0xd:
case 0xe:
case 0xf:
{
info.instr = DspRegularInstruction::mvsi;
AddParam(info, topreg[(instrBits >> 8) & 7]);
AddImmOperand(info, DspParameter::SignedByte, (int8_t)instrBits);
break;
}
}
}
void Decoder::Group1(uint8_t* instrPtr, size_t instrMaxSize, DecoderInfo& info, uint16_t instrBits)
{
static DspParameter addressreg[] = {
DspParameter::r0,
DspParameter::r1,
DspParameter::r2,
DspParameter::r3,
};
static DspParameter modifier[] = {
DspParameter::mod_none,
DspParameter::mod_dec,
DspParameter::mod_inc,
DspParameter::mod_plus_m,
};
static DspParameter modifier_n[] = {
DspParameter::mod_plus_m0,
DspParameter::mod_plus_m1,
DspParameter::mod_plus_m2,
DspParameter::mod_plus_m3,
};
//|rep rc |0001 0000 cccc cccc|
//|loop lc,ea |0001 0001 cccc cccc aaaa aaaa aaaa aaaa|
//|clr b |0001 0010 0000 0bbb|
//|set b |0001 0011 0000 0bbb|
//|lsfi d,si |0001 010d 0iii iiii|
//|asfi d,si |0001 010d 1iii iiii|
//|stli sa,li |0001 0110 aaaa aaaa iiii iiii iiii iiii|
//|jmp(cc) rn |0001 0111 0rr0 cccc|
//|call(cc) rn |0001 0111 0rr1 cccc|
//|ld d,r,m |0001 100m mrrd dddd|
//|st r,m,s |0001 101m mrrs ssss|
//|mv d,s |0001 11dd ddds ssss|
switch ((instrBits >> 8) & 0xf)
{
case 0: // rep
{
info.instr = DspRegularInstruction::rep;
info.flowControl = true;
AddImmOperand(info, DspParameter::Byte, (uint8_t)instrBits);
break;
}
case 1: // loop
{
info.instr = DspRegularInstruction::loop;
info.flowControl = true;
AddImmOperand(info, DspParameter::Byte, (uint8_t)instrBits);
DspAddress addr = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::Address2, addr);
break;
}
case 2: // clr
{
int b = instrBits & 7;
if (b != 7)
{
info.instr = DspRegularInstruction::clr;
AddParam(info, (DspParameter)((int)DspParameter::psr_tb + b));
}
break;
}
case 3: // set
{
int b = instrBits & 7;
if (b != 7)
{
info.instr = DspRegularInstruction::set;
AddParam(info, (DspParameter)((int)DspParameter::psr_tb + b));
}
break;
}
case 4: // lsfi, asfi
case 5:
{
int d = (instrBits & 0x100) ? 1 : 0;
int8_t si = instrBits & 0x7f;
if (si & 0x40)
{
si |= 0x80;
}
info.instr = (instrBits & 0x80) == 0 ? DspRegularInstruction::lsfi : DspRegularInstruction::asfi;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddImmOperand(info, DspParameter::SignedByte, si);
break;
}
case 6: // stli
{
info.instr = DspRegularInstruction::stli;
DspAddress addr = 0xff00 | (instrBits & 0xff);
AddImmOperand(info, DspParameter::Address, addr);
uint16_t imm = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
AddImmOperand(info, DspParameter::UnsignedShort2, imm);
break;
}
case 7: // jmp, call
{
info.instr = (instrBits & 0x10) == 0 ? DspRegularInstruction::jmp : DspRegularInstruction::call;
info.flowControl = true;
info.cc = (ConditionCode)(instrBits & 0xf);
int r = (instrBits >> 5) & 3;
AddParam(info, addressreg[r]);
break;
}
case 8: // ld
case 9:
{
info.instr = DspRegularInstruction::ld;
int d = instrBits & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + d));
int r = (instrBits >> 5) & 3;
AddParam(info, addressreg[r]);
int m = (instrBits >> 7) & 3;
AddParam(info, modifier[m] == DspParameter::mod_plus_m ? modifier_n[r] : modifier[m]);
break;
}
case 0xa: // st
case 0xb:
{
info.instr = DspRegularInstruction::st;
int r = (instrBits >> 5) & 3;
AddParam(info, addressreg[r]);
int m = (instrBits >> 7) & 3;
AddParam(info, modifier[m] == DspParameter::mod_plus_m ? modifier_n[r] : modifier[m]);
int s = instrBits & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + s));
break;
}
case 0xc: // mv
case 0xd:
case 0xe:
case 0xf:
{
info.instr = DspRegularInstruction::mv;
int d = (instrBits >> 5) & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + d));
int s = instrBits & 0x1f;
AddParam(info, (DspParameter)((int)DspParameter::regs + s));
break;
}
}
}
void Decoder::Group2(DecoderInfo& info, uint16_t instrBits)
{
static DspParameter ldsa_reg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
DspParameter::a0,
DspParameter::b0,
DspParameter::a1,
DspParameter::b1,
};
static DspParameter stsa_reg[] = {
DspParameter::a2,
DspParameter::b2,
DspParameter::Unknown,
DspParameter::Unknown,
DspParameter::a0,
DspParameter::b0,
DspParameter::a1,
DspParameter::b1,
};
//|ldsa d,sa |0010 0ddd aaaa aaaa|
//|stsa sa,s |0010 1sss aaaa aaaa|
if ((instrBits & 0x800) == 0)
{
// ldsa
info.instr = DspRegularInstruction::ldsa;
int d = (instrBits >> 8) & 7;
AddParam(info, ldsa_reg[d]);
AddImmOperand(info, DspParameter::Address, (DspAddress)(uint8_t)instrBits);
}
else
{
// stsa
info.instr = DspRegularInstruction::stsa;
AddImmOperand(info, DspParameter::Address, (DspAddress)(uint8_t)instrBits);
int s = (instrBits >> 8) & 7;
AddParam(info, stsa_reg[s]);
}
}
void Decoder::Group3(DecoderInfo& info, uint16_t instrBits)
{
//|xor d,s |0011 00sd 0xxx xxxx|
//|xor d,s |0011 000d 1xxx xxxx|
//|not d |0011 001d 1xxx xxxx|
//|and d,s |0011 01sd 0xxx xxxx|
//|lsf d,s |0011 01sd 1xxx xxxx|
//|or d,s |0011 10sd 0xxx xxxx|
//|asf d,s |0011 10sd 1xxx xxxx|
//|and d,s |0011 110d 0xxx xxxx|
//|lsf d,s |0011 110d 1xxx xxxx|
//|or d,s |0011 111d 0xxx xxxx|
//|asf d,s |0011 111d 1xxx xxxx|
bool msb = (instrBits & 0x80) ? true : false;
switch ((instrBits >> 9) & 7)
{
case 0: // xor
{
info.parallelInstr = DspParallelInstruction::_xor;
if (!msb)
{
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
else
{
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, d == 0 ? DspParameter::b1 : DspParameter::a1);
}
break;
}
case 1: // not + xor
{
if (!msb)
{
// xor
info.parallelInstr = DspParallelInstruction::_xor;
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
else
{
// not
info.parallelInstr = DspParallelInstruction::_not;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
}
break;
}
case 2: // and, lsf
case 3:
{
if (!msb)
{
// and
info.parallelInstr = DspParallelInstruction::_and;
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
else
{
// lsf
info.parallelInstr = DspParallelInstruction::lsf;
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
break;
}
case 4: // or, asf
case 5:
{
if (!msb)
{
// or
info.parallelInstr = DspParallelInstruction::_or;
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
else
{
// asf
info.parallelInstr = DspParallelInstruction::asf;
int s = (instrBits >> 9) & 1;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
break;
}
case 6: // and, lsf
{
if (!msb)
{
// and
info.parallelInstr = DspParallelInstruction::_and;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, d == 0 ? DspParameter::b1 : DspParameter::a1);
}
else
{
// lsf
info.parallelInstr = DspParallelInstruction::lsf;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, d == 0 ? DspParameter::x1 : DspParameter::y1);
}
break;
}
case 7: // or, asf
{
if (!msb)
{
// or
info.parallelInstr = DspParallelInstruction::_or;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a1 : DspParameter::b1);
AddParam(info, d == 0 ? DspParameter::b1 : DspParameter::a1);
}
else
{
// asf
info.parallelInstr = DspParallelInstruction::asf;
int d = (instrBits >> 8) & 1;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, d == 0 ? DspParameter::x1 : DspParameter::y1);
}
break;
}
}
GroupMemOps3(info, instrBits);
}
void Decoder::Group4_6(DecoderInfo& info, uint16_t instrBits)
{
//|add d,s |0100 sssd xxxx xxxx|
//|sub d,s |0101 sssd xxxx xxxx|
//|amv d,s |0110 sssd xxxx xxxx|
static DspParameter srcreg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
DspParameter::x,
DspParameter::y,
DspParameter::a,
DspParameter::prod,
};
switch (instrBits >> 12)
{
case 4:
info.parallelInstr = DspParallelInstruction::add;
break;
case 5:
info.parallelInstr = DspParallelInstruction::sub;
break;
case 6:
info.parallelInstr = DspParallelInstruction::amv;
break;
}
int d = (instrBits & 0x100) ? 1 : 0;
int s = (instrBits >> 9) & 7;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, srcreg[s] == DspParameter::a ? (d == 0 ? DspParameter::b : DspParameter::a) : srcreg[s]);
GroupMemOps4_F(info, instrBits);
}
void Decoder::Group7(DecoderInfo& info, uint16_t instrBits)
{
//|addl d,s |0111 00sd xxxx xxxx|
//|inc d |0111 01dd xxxx xxxx|
//|dec d |0111 10dd xxxx xxxx|
//|neg d |0111 110d xxxx xxxx|
//|neg d,p |0111 111d xxxx xxxx|
static DspParameter increg[] = {
DspParameter::a1,
DspParameter::b1,
DspParameter::a,
DspParameter::b
};
int s = (instrBits & 0x200) ? 1 : 0;
int d = (instrBits & 0x100) ? 1 : 0;
int dd = (instrBits >> 8) & 3;
switch ((instrBits >> 9) & 7)
{
case 0:
case 1:
info.parallelInstr = DspParallelInstruction::addl;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, s == 0 ? DspParameter::x0 : DspParameter::y0);
break;
case 2:
case 3:
info.parallelInstr = DspParallelInstruction::inc;
AddParam(info, increg[dd]);
break;
case 4:
case 5:
info.parallelInstr = DspParallelInstruction::dec;
AddParam(info, increg[dd]);
break;
case 6:
info.parallelInstr = DspParallelInstruction::neg;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
case 7:
info.parallelInstr = DspParallelInstruction::neg;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, DspParameter::prod);
break;
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::Group8(DecoderInfo& info, uint16_t instrBits)
{
//|nop |1000 0000 xxxx xxxx|
//|clr d |1000 d001 xxxx xxxx|
//|cmp a,b |1000 0010 xxxx xxxx|
//|mpy x1,x1 |1000 0011 xxxx xxxx|
//|clr p |1000 0100 xxxx xxxx|
//|tst p |1000 0101 xxxx xxxx|
//|tst s |1000 011s xxxx xxxx|
//|clr im |1000 1010 xxxx xxxx|
//|set im |1000 1011 xxxx xxxx|
//|clr dp |1000 1100 xxxx xxxx|
//|set dp |1000 1101 xxxx xxxx|
//|clr xl |1000 1110 xxxx xxxx|
//|set xl |1000 1111 xxxx xxxx|
switch ((instrBits >> 8) & 0xf)
{
case 0: // nop
info.parallelInstr = DspParallelInstruction::nop;
break;
case 1: // clr d
case 9:
{
int d = (instrBits >> 11) & 1;
info.parallelInstr = DspParallelInstruction::clr;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
}
case 2: // cmp a,b
info.parallelInstr = DspParallelInstruction::cmp;
AddParam(info, DspParameter::a);
AddParam(info, DspParameter::b);
break;
case 3: // mpy x1,x1
info.parallelInstr = DspParallelInstruction::mpy;
AddParam(info, DspParameter::x1);
AddParam(info, DspParameter::x1);
break;
case 4: // clr p
info.parallelInstr = DspParallelInstruction::clr;
AddParam(info, DspParameter::prod);
break;
case 5: // tst p
info.parallelInstr = DspParallelInstruction::tst;
AddParam(info, DspParameter::prod);
break;
case 6: // tst s (Form 2)
case 7:
{
int s = (instrBits >> 8) & 1;
info.parallelInstr = DspParallelInstruction::tst;
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
}
case 8:
// Reserved
break;
case 0xa: // clr im
info.parallelInstr = DspParallelInstruction::clr;
AddParam(info, DspParameter::psr_im);
break;
case 0xb: // set im
info.parallelInstr = DspParallelInstruction::set;
AddParam(info, DspParameter::psr_im);
break;
case 0xc: // clr dp
info.parallelInstr = DspParallelInstruction::clr;
AddParam(info, DspParameter::psr_dp);
break;
case 0xd: // set dp
info.parallelInstr = DspParallelInstruction::set;
AddParam(info, DspParameter::psr_dp);
break;
case 0xe: // clr xl
info.parallelInstr = DspParallelInstruction::clr;
AddParam(info, DspParameter::psr_xl);
break;
case 0xf: // set xl
info.parallelInstr = DspParallelInstruction::set;
AddParam(info, DspParameter::psr_xl);
break;
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::Group9_B(DecoderInfo& info, uint16_t instrBits)
{
//|asr16 d |1001 d001 xxxx xxxx|
//|abs d |1010 d001 xxxx xxxx|
//|tst s |1011 s001 xxxx xxxx|
if (((instrBits >> 8) & 7) == 1)
{
switch (instrBits >> 12)
{
case 9:
info.parallelInstr = DspParallelInstruction::asr16;
break;
case 0xa:
info.parallelInstr = DspParallelInstruction::abs;
break;
case 0xb:
info.parallelInstr = DspParallelInstruction::tst;
break;
}
int d = (instrBits & 0x800) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::GroupCD(DecoderInfo& info, uint16_t instrBits)
{
//|cmp d,s |110s d001 xxxx xxxx|
if (((instrBits >> 8) & 7) == 1)
{
info.parallelInstr = DspParallelInstruction::cmp;
int s = (instrBits & 0x1000) ? 1 : 0;
int d = (instrBits & 0x800) ? 1 : 0;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::GroupE(DecoderInfo& info, uint16_t instrBits)
{
static DspParameter form1_regs[][2] = {
{ DspParameter::x0, DspParameter::y0 },
{ DspParameter::x0, DspParameter::y1 },
{ DspParameter::x1, DspParameter::y0 },
{ DspParameter::x1, DspParameter::y1 },
};
static DspParameter form2_regs[][2] = {
{ DspParameter::a1, DspParameter::x1 },
{ DspParameter::a1, DspParameter::y1 },
{ DspParameter::b1, DspParameter::x1 },
{ DspParameter::b1, DspParameter::y1 },
};
//|mac s1,s2 |1110 00ss xxxx xxxx|
//|mac s1,s2 |1110 10ss xxxx xxxx|
//|macn s1,s2 |1110 01ss xxxx xxxx|
//|macn s1,s2 |1110 11ss xxxx xxxx|
info.parallelInstr = (instrBits & 0x400) == 0 ? DspParallelInstruction::mac : DspParallelInstruction::macn;
int ss = (instrBits >> 8) & 3;
bool form1 = (instrBits & 0x800) == 0;
AddParam(info, form1 ? form1_regs[ss][0] : form2_regs[ss][0]);
AddParam(info, form1 ? form1_regs[ss][1] : form2_regs[ss][1]);
GroupMemOps4_F(info, instrBits);
}
void Decoder::GroupF(DecoderInfo& info, uint16_t instrBits)
{
//|lsl16 d |1111 000d xxxx xxxx|
//|mac s1,s2 |1111 001s xxxx xxxx|
//|lsr16 d |1111 010d xxxx xxxx|
//|macn s1,s2 |1111 011s xxxx xxxx|
//|addp d,s |1111 10sd xxxx xxxx|
//|rnd d |1111 110d xxxx xxxx|
//|rndp d |1111 111d xxxx xxxx|
int s = (instrBits & 0x200) ? 1 : 0;
int d = (instrBits & 0x100) ? 1 : 0;
switch ((instrBits >> 9) & 7)
{
case 0:
info.parallelInstr = DspParallelInstruction::lsl16;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
case 1:
info.parallelInstr = DspParallelInstruction::mac;
AddParam(info, d == 0 ? DspParameter::x1 : DspParameter::y1);
AddParam(info, d == 0 ? DspParameter::x0 : DspParameter::y0);
break;
case 2:
info.parallelInstr = DspParallelInstruction::lsr16;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
case 3:
info.parallelInstr = DspParallelInstruction::macn;
AddParam(info, d == 0 ? DspParameter::x1 : DspParameter::y1);
AddParam(info, d == 0 ? DspParameter::x0 : DspParameter::y0);
break;
case 4:
case 5:
info.parallelInstr = DspParallelInstruction::addp;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, s == 0 ? DspParameter::x1 : DspParameter::y1);
break;
case 6:
info.parallelInstr = DspParallelInstruction::rnd;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
case 7:
info.parallelInstr = DspParallelInstruction::rndp;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
break;
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::GroupMpy(DecoderInfo& info, uint16_t instrBits)
{
static DspParameter mpy_regs[][2] = {
{ DspParameter::Unknown, DspParameter::Unknown },
{ DspParameter::Unknown, DspParameter::Unknown },
{ DspParameter::x1, DspParameter::x0 },
{ DspParameter::y1, DspParameter::y0 },
{ DspParameter::x0, DspParameter::y0 },
{ DspParameter::x0, DspParameter::y1 },
{ DspParameter::x1, DspParameter::y0 },
{ DspParameter::x1, DspParameter::y1 },
{ DspParameter::a1, DspParameter::x1 },
{ DspParameter::a1, DspParameter::y1 },
{ DspParameter::b1, DspParameter::x1 },
{ DspParameter::b1, DspParameter::y1 },
{ DspParameter::Unknown, DspParameter::Unknown },
{ DspParameter::Unknown, DspParameter::Unknown },
{ DspParameter::Unknown, DspParameter::Unknown },
{ DspParameter::Unknown, DspParameter::Unknown },
};
//|mpy s1,s2 |1sss s000 xxxx xxxx|
//|rnmpy d,s1,s2|1sss s01d xxxx xxxx|
//|admpy d,s1,s2|1sss s10d xxxx xxxx|
//|mvmpy d,s1,s2|1sss s11d xxxx xxxx|
int d = (instrBits & 0x100) ? 1 : 0;
int s = (instrBits >> 11) & 0xf;
switch ((instrBits >> 9) & 3)
{
case 0:
if (d == 0)
{
info.parallelInstr = DspParallelInstruction::mpy;
AddParam(info, mpy_regs[s][0]);
AddParam(info, mpy_regs[s][1]);
}
break;
case 1:
info.parallelInstr = DspParallelInstruction::rnmpy;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, mpy_regs[s][0]);
AddParam(info, mpy_regs[s][1]);
break;
case 2:
info.parallelInstr = DspParallelInstruction::admpy;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, mpy_regs[s][0]);
AddParam(info, mpy_regs[s][1]);
break;
case 3:
info.parallelInstr = DspParallelInstruction::mvmpy;
AddParam(info, d == 0 ? DspParameter::a : DspParameter::b);
AddParam(info, mpy_regs[s][0]);
AddParam(info, mpy_regs[s][1]);
break;
}
GroupMemOps4_F(info, instrBits);
}
void Decoder::GroupMemOps3(DecoderInfo& info, uint16_t instrBits)
{
static DspParameter addressreg[] = {
DspParameter::r0,
DspParameter::r1,
DspParameter::r2,
DspParameter::r3,
};
static DspParameter modifier[] = {
DspParameter::mod_none,
DspParameter::mod_dec,
DspParameter::mod_inc,
DspParameter::mod_plus_m,
};
static DspParameter modifier_n[] = {
DspParameter::mod_plus_m0,
DspParameter::mod_plus_m1,
DspParameter::mod_plus_m2,
DspParameter::mod_plus_m3,
};
static DspParameter dstreg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
};
static DspParameter srcreg[] = {
DspParameter::a0,
DspParameter::b0,
DspParameter::a1,
DspParameter::b1,
};
static DspParameter topreg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
DspParameter::a0,
DspParameter::b0,
DspParameter::a1,
DspParameter::b1,
};
//|mr rn,mn |0011 xxxx x000 mmrr|
//|mv d,s |0011 xxxx x001 ddss|
//|st rn,mn,s |0011 xxxx x01s smrr|
//|ld d,rn,mn |0011 xxxx x1dd dmrr|
switch ((instrBits >> 4) & 7)
{
case 0: // mr
{
int r = instrBits & 3;
int m = (instrBits >> 2) & 3;
if (r == 0 && m == 0)
{
info.parallelMemInstr = DspParallelMemInstruction::nop;
}
else
{
info.parallelMemInstr = DspParallelMemInstruction::mr;
AddParamEx(info, addressreg[r]);
AddParamEx(info, modifier[m] == DspParameter::mod_plus_m ? modifier_n[r] : modifier[m]);
}
break;
}
case 1: // mv
{
info.parallelMemInstr = DspParallelMemInstruction::mv;
int d = (instrBits >> 2) & 3;
AddParamEx(info, dstreg[d]);
int s = instrBits & 3;
AddParamEx(info, srcreg[s]);
break;
}
case 2: // st
case 3:
{
info.parallelMemInstr = DspParallelMemInstruction::st;
int r = instrBits & 3;
AddParamEx(info, addressreg[r]);
int m = (instrBits & 4) != 0 ? 1 : 0;
AddParamEx(info, m == 0 ? DspParameter::mod_inc : modifier_n[r]);
int s = (instrBits >> 3) & 3;
AddParamEx(info, srcreg[s]);
break;
}
case 4: // ld
case 5:
case 6:
case 7:
{
info.parallelMemInstr = DspParallelMemInstruction::ld;
int d = (instrBits >> 3) & 7;
AddParamEx(info, topreg[d]);
int r = instrBits & 3;
AddParamEx(info, addressreg[r]);
int m = (instrBits & 4) != 0 ? 1 : 0;
AddParamEx(info, m == 0 ? DspParameter::mod_inc : modifier_n[r]);
break;
}
}
}
void Decoder::GroupMemOps4_F(DecoderInfo& info, uint16_t instrBits)
{
static DspParameter addressreg[] = {
DspParameter::r0,
DspParameter::r1,
DspParameter::r2,
DspParameter::r3,
};
static DspParameter modifier[] = {
DspParameter::mod_plus_m0,
DspParameter::mod_plus_m1,
DspParameter::mod_plus_m2,
DspParameter::mod_plus_m3,
};
static DspParameter dstreg[] = {
DspParameter::x0,
DspParameter::y0,
DspParameter::x1,
DspParameter::y1,
};
static DspParameter ldd_regs[][2] = {
{ DspParameter::x0, DspParameter::y0 },
{ DspParameter::x0, DspParameter::y1 },
{ DspParameter::x1, DspParameter::y0 },
{ DspParameter::x1, DspParameter::y1 },
};
if (instrBits & 0x80)
{
//|ls d,r,m r,m,s |01xx xxxx 10dd mn0s|
//|ls d,r,m r,m,s |1xxx xxxx 10dd mn0s|
//|ls2 d,r,m r,m,s |01xx xxxx 10dd mn1s|
//|ls2 d,r,m r,m,s |1xxx xxxx 10dd mn1s|
if ((instrBits & 0x40) == 0)
{
int d = (instrBits >> 4) & 3;
int m = (instrBits & 8) ? 1 : 0;
int n = (instrBits & 4) ? 1 : 0;
int s = instrBits & 1;
info.parallelMemInstr = DspParallelMemInstruction::ls;
if ((instrBits & 2) == 0) // ls
{
// Load by r0, store by r3
// d, r0, n, r3, m, s
AddParamEx(info, dstreg[d]);
AddParamEx(info, DspParameter::r0);
AddParamEx(info, n == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m0);
AddParamEx(info, DspParameter::r3);
AddParamEx(info, m == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m3);
AddParamEx(info, s == 0 ? DspParameter::a1 : DspParameter::b1);
}
else // ls2
{
// Load by r3, store by r0
// d, r3, m, r0, n, s
AddParamEx(info, dstreg[d]);
AddParamEx(info, DspParameter::r3);
AddParamEx(info, m == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m3);
AddParamEx(info, DspParameter::r0);
AddParamEx(info, n == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m0);
AddParamEx(info, s == 0 ? DspParameter::a1 : DspParameter::b1);
}
}
else
{
//|ldd d1,rn,mn d2,r3,m3|1xxx xxxx 11dd mnrr|-|-|-|-|-|-|Load dual data (Form 1a)|1|
//|ldd d1,rn,mn d2,r3,m3|01xx xxxx 11dd mnrr|-|-|-|-|-|-|Load dual data (Form 1b)|1|
//|ldd2 d1,rn,mn d2,r3,m3|1xxx xxxx 11rd mn11|-|-|-|-|-|-|Load dual data (Form 2)|1|
int d = (instrBits >> 4) & 3;
int m = (instrBits & 8) ? 1 : 0;
int n = (instrBits & 4) ? 1 : 0;
int r = instrBits & 3;
info.parallelMemInstr = DspParallelMemInstruction::ldd;
if (r == 3 && (instrBits & 0x8000) != 0)
{
// ldd2
r = (instrBits & 0x20) ? 1 : 0;
d = (instrBits & 0x10) ? 1 : 0;
AddParamEx(info, d == 0 ? DspParameter::x1 : DspParameter::y1);
AddParamEx(info, addressreg[r]);
AddParamEx(info, n == 0 ? DspParameter::mod_inc : modifier[r]);
AddParamEx(info, d == 0 ? DspParameter::x0 : DspParameter::y0);
AddParamEx(info, DspParameter::r3);
AddParamEx(info, m == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m3);
}
else
{
// ldd
AddParamEx(info, ldd_regs[d][0]);
AddParamEx(info, addressreg[r]);
AddParamEx(info, n == 0 ? DspParameter::mod_inc : modifier[r]);
AddParamEx(info, ldd_regs[d][1]);
AddParamEx(info, DspParameter::r3);
AddParamEx(info, m == 0 ? DspParameter::mod_inc : DspParameter::mod_plus_m3);
}
}
}
else
{
//|mr rn,mn |01xx xxxx 0000 mmrr|
//|mv d,s |01xx xxxx 0001 ddss|
//|st rn,mn,s |01xx xxxx 001s smrr|
//|ld d,rn,mn |01xx xxxx 01dd dmrr|
GroupMemOps3(info, instrBits);
}
}
void Decoder::Decode(uint8_t* instrPtr, size_t instrMaxSize, DecoderInfo& info)
{
// Reset info
ResetInfo(info);
// Get opcode and determine its group
uint16_t instrBits = _BYTESWAP_UINT16(*(uint16_t*)instrPtr);
AddBytes(instrPtr, sizeof(uint16_t), info);
instrPtr += sizeof(instrBits);
instrMaxSize -= sizeof(instrBits);
int group = (instrBits >> 12);
// Select by group. Groups 3-F are parallel instructions.
info.parallel = group >= 3;
// Group mixed multiply (8-F)?
if ((instrBits & 0x8000) != 0)
{
int s = (instrBits >> 11) & 0xf;
if (s >= 2 && s <= 0xb)
{
switch ((instrBits >> 8) & 7)
{
case 0:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
GroupMpy(info, instrBits);
return;
}
}
}
// Other
switch (group)
{
case 0:
Group0(instrPtr, instrMaxSize, info, instrBits);
break;
case 1:
Group1(instrPtr, instrMaxSize, info, instrBits);
break;
case 2:
Group2(info, instrBits);
break;
case 3:
Group3(info, instrBits);
break;
case 4:
case 5:
case 6:
Group4_6(info, instrBits);
break;
case 7:
Group7(info, instrBits);
break;
case 8:
Group8(info, instrBits);
break;
case 9:
case 0xa:
case 0xb:
Group9_B(info, instrBits);
break;
case 0xc:
case 0xd:
GroupCD(info, instrBits);
break;
case 0xe:
GroupE(info, instrBits);
break;
case 0xf:
GroupF(info, instrBits);
break;
}
}
}