pureikyubu/SRC/DSP/DspAnalyzer.cpp
2020-07-13 22:59:14 +03:00

1732 lines
44 KiB
C++

// DSP analyzer
#include "pch.h"
namespace DSP
{
void Analyzer::ResetInfo(AnalyzeInfo& info)
{
info.sizeInBytes = 0;
info.instr = DspInstruction::Unknown;
info.instrEx = DspInstructionEx::Unknown;
info.extendedOpcodePresent = false;
info.numParameters = 0;
info.numParametersEx = 0;
info.flowControl = false;
info.logic = false;
info.madd = false;
}
bool Analyzer::Group0_Logic(uint8_t* instrPtr, size_t instrMaxSize, AnalyzeInfo& info, DspInstruction instr, bool logic)
{
if ((info.instrBits & 0xf) == 0)
{
if (instrMaxSize < sizeof(uint16_t))
return false;
int dd = ((info.instrBits & 0b100000000) != 0) ? 1 : 0;
info.instr = instr;
info.logic = logic;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + dd), dd))
return false;
uint16_t imm = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::UnsignedShort, imm))
return false;
}
return true;
}
bool Analyzer::Group0(uint8_t* instrPtr, size_t instrMaxSize, AnalyzeInfo& info)
{
info.instr = DspInstruction::Unknown;
if ((info.instrBits & 0b0000'1111'0000'0000) == 0)
{
//NOP * 0000 0000 [000]0 0000
//DAR * 0000 0000 [000]0 01dd
//IAR * 0000 0000 [000]0 10dd
//ADDARN * 0000 0000 [000]1 ssdd
//HALT * 0000 0000 [001]0 0001
//LOOP * 0000 0000 [010]r rrrr
//BLOOP * 0000 0000 [011]r rrrr aaaa aaaa aaaa aaaa
//LRI * 0000 0000 [100]r rrrr iiii iiii iiii iiii
//LR * 0000 0000 [110]r rrrr mmmm mmmm mmmm mmmm
//SR * 0000 0000 [111]r rrrr mmmm mmmm mmmm mmmm
switch ((info.instrBits >> 5) & 7)
{
case 0b000:
if (info.instrBits & 0b10000)
{
// ADDARN
int dd = info.instrBits & 3;
int ss = (info.instrBits >> 2) & 3;
info.instr = DspInstruction::ADDARN;
if (!AddParam(info, (DspParameter)((int)DspParameter::ar0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ix0 + ss), ss))
return false;
}
else
{
switch ((info.instrBits >> 2) & 3)
{
case 0b00: // NOP
if ((info.instrBits & 3) == 0)
{
info.instr = DspInstruction::NOP;
}
break;
case 0b01: // DAR
{
int dd = info.instrBits & 3;
info.instr = DspInstruction::DAR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ar0 + dd), dd))
return false;
break;
}
case 0b10: // IAR
{
int dd = info.instrBits & 3;
info.instr = DspInstruction::IAR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ar0 + dd), dd))
return false;
break;
}
default:
break;
}
}
break;
case 0b001: // HALT
if ((info.instrBits & 0b11111) == 0b00001)
{
info.instr = DspInstruction::HALT;
info.flowControl = true;
}
break;
case 0b010: // LOOP
{
uint16_t r = info.instrBits & 0b11111;
info.instr = DspInstruction::LOOP;
info.flowControl = true;
if (!AddParam(info, (DspParameter)r, r))
return false;
break;
}
case 0b011: // BLOOP
{
if (instrMaxSize < sizeof(uint16_t))
return false;
uint16_t r = info.instrBits & 0b11111;
info.instr = DspInstruction::BLOOP;
info.flowControl = true;
if (!AddParam(info, (DspParameter)r, r))
return false;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, (DspAddress)addr))
return false;
break;
}
case 0b100: // LRI
{
if (instrMaxSize < sizeof(uint16_t))
return false;
uint16_t r = info.instrBits & 0b11111;
info.instr = DspInstruction::LRI;
if (!AddParam(info, (DspParameter)r, r))
return false;
uint16_t imm = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::UnsignedShort, imm))
return false;
break;
}
case 0b110: // LR
{
if (instrMaxSize < sizeof(uint16_t))
return false;
uint16_t r = info.instrBits & 0b11111;
info.instr = DspInstruction::LR;
if (!AddParam(info, (DspParameter)r, r))
return false;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, (DspAddress)addr))
return false;
break;
}
case 0b111: // SR
{
if (instrMaxSize < sizeof(uint16_t))
return false;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, (DspAddress)addr))
return false;
uint16_t r = info.instrBits & 0b11111;
info.instr = DspInstruction::SR;
if (!AddParam(info, (DspParameter)r, r))
return false;
break;
}
default:
break;
}
return true;
}
else if ((info.instrBits & 0b0000'1110'0000'0000) == 0b0000'0010'0000'0000)
{
//IF cc * 0000 00[1]0 [0111] cccc
//JMP cc * 0000 00[1]0 [1001] cccc aaaa aaaa aaaa aaaa
//CALL cc * 0000 00[1]0 [1011] cccc aaaa aaaa aaaa aaaa
//RET cc * 0000 00[1]0 [1101] cccc
//RTI 0000 00[1]0 [1111] 1111
//ADDI * 0000 00[1]d [0000] 0000 iiii iiii iiii iiii
//XORI * 0000 00[1]d [0010] 0000 iiii iiii iiii iiii
//ANDI * 0000 00[1]d [0100] 0000 iiii iiii iiii iiii
//ORI * 0000 00[1]d [0110] 0000 iiii iiii iiii iiii
//CMPI * 0000 00[1]d [1000] 0000 iiii iiii iiii iiii
//TCLR * 0000 00[1]d [1010] 0000 iiii iiii iiii iiii
//TSET * 0000 00[1]d [1100] 0000 iiii iiii iiii iiii
//LSN 0000 00[1]0 [1100] 1010
//ASN 0000 00[1]0 [1100] 1011
//ILRR * 0000 00[1]d [0001] 00ss
//ILRRD * 0000 00[1]d [0001] 01ss
//ILRRI * 0000 00[1]d [0001] 10ss
//ILRRN * 0000 00[1]d [0001] 11ss
if (info.instrBits == 0x02ca)
{
info.logic = true;
info.instr = DspInstruction::LSN;
return true;
}
else if (info.instrBits == 0x02cb)
{
info.logic = true;
info.instr = DspInstruction::ASN;
return true;
}
switch ((info.instrBits >> 4) & 0xf)
{
case 0b0111: // IF cc
{
info.instr = DspInstruction::IFcc;
info.cc = (ConditionCode)(info.instrBits & 0xf);
info.flowControl = true;
break;
}
case 0b1001: // JMP cc
{
if (instrMaxSize < sizeof(uint16_t))
return false;
info.instr = DspInstruction::Jcc;
info.cc = (ConditionCode)(info.instrBits & 0xf);
info.flowControl = true;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, (DspAddress)addr))
return false;
break;
}
case 0b1011: // CALL cc
{
if (instrMaxSize < sizeof(uint16_t))
return false;
info.instr = DspInstruction::CALLcc;
info.cc = (ConditionCode)(info.instrBits & 0xf);
info.flowControl = true;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, (DspAddress)addr))
return false;
break;
}
case 0b1101: // RET cc
{
info.instr = DspInstruction::RETcc;
info.cc = (ConditionCode)(info.instrBits & 0xf);
info.flowControl = true;
break;
}
case 0b1111: // RTI
{
if ((info.instrBits & 0xf) == 0xf)
{
info.instr = DspInstruction::RTI;
info.flowControl = true;
}
break;
}
case 0b0000: // ADDI
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::ADDI, true);
break;
case 0b0010: // XORI
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::XORI, true);
break;
case 0b0100: // ANDI
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::ANDI, true);
break;
case 0b0110: // ORI
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::ORI, true);
break;
case 0b1000: // CMPI
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::CMPI, false);
break;
case 0b1010: // TCLR
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::TCLR, true);
break;
case 0b1100: // TSET
return Group0_Logic(instrPtr, instrMaxSize, info, DspInstruction::TSET, true);
break;
case 0b0001: // ILRR's
{
switch ((info.instrBits >> 2) & 3)
{
case 0:
info.instr = DspInstruction::ILRR;
break;
case 1:
info.instr = DspInstruction::ILRRD;
break;
case 2:
info.instr = DspInstruction::ILRRI;
break;
case 3:
info.instr = DspInstruction::ILRRN;
break;
}
int dd = ((info.instrBits & 0b100000000) != 0) ? 1 : 0;
int ss = info.instrBits & 3;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::Indexed_ar0 + ss), ss))
return false;
break;
}
}
return true;
}
else if (info.instrBits & 0b0000'1000'0000'0000)
{
//LRIS * 0000 1ddd iiii iiii
info.instr = DspInstruction::LRIS;
int dd = (info.instrBits >> 8) & 7;
int8_t ii = info.instrBits & 0xff;
if (!AddParam(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
if (!AddImmOperand(info, DspParameter::SignedByte, ii))
return false;
return true;
}
else if (info.instrBits & 0b0000'0100'0000'0000)
{
//ADDIS * 0000 01[0]d iiii iiii
//CMPIS * 0000 01[1]d iiii iiii
if (info.instrBits & 0b1000000000)
{
info.instr = DspInstruction::CMPIS;
}
else
{
info.instr = DspInstruction::ADDIS;
}
int dd = (info.instrBits >> 8) & 1;
int8_t ii = info.instrBits & 0xff;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + dd), dd))
return false;
if (!AddImmOperand(info, DspParameter::SignedByte, ii))
return false;
return true;
}
return true;
}
bool Analyzer::Group1(uint8_t* instrPtr, size_t instrMaxSize, AnalyzeInfo& info)
{
//LOOPI * 0001 [00]00 iiii iiii
//BLOOPI 0001 [00]01 iiii iiii aaaa aaaa aaaa aaaa
//SBSET * 0001 [00]10 0000 0iii
//SBCLR * 0001 [00]11 0000 0iii
//LSL 0001 [01]0r 00ii iiii
//LSR 0001 [01]0r 01ii iiii
//ASL 0001 [01]0r 10ii iiii
//ASR 0001 [01]0r 11ii iiii
//SI * 0001 [01]10 mmmm mmmm iiii iiii iiii iiii
//CALLR * 0001 [01]11 rrr1 1111
//JMPR * 0001 [01]11 rrr0 1111
//LRR * 0001 [10]00 0ssd dddd
//LRRD * 0001 [10]00 1ssd dddd
//LRRI * 0001 [10]01 0ssd dddd
//LRRN * 0001 [10]01 1ssd dddd
//SRR * 0001 [10]10 0ssd dddd
//SRRD * 0001 [10]10 1ssd dddd
//SRRI * 0001 [10]11 0ssd dddd
//SRRN * 0001 [10]11 1ssd dddd
//MRR * 0001 [11]dd ddds ssss
switch ((info.instrBits >> 10) & 3)
{
case 0:
switch ((info.instrBits >> 8) & 3)
{
case 0: // LOOPI
{
info.instr = DspInstruction::LOOPI;
info.flowControl = true;
if (!AddImmOperand(info, DspParameter::Byte, (uint8_t)(info.instrBits & 0xff)))
return false;
break;
}
case 1: // BLOOPI
{
if (instrMaxSize < sizeof(uint16_t))
return false;
info.instr = DspInstruction::BLOOPI;
info.flowControl = true;
uint16_t addr = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Byte, (uint8_t)(info.instrBits & 0xff)))
return false;
if (!AddImmOperand(info, DspParameter::Address2, (DspAddress)addr))
return false;
break;
}
case 2: // SBSET
if ((info.instrBits & 0b11111000) == 0)
{
info.instr = DspInstruction::SBSET;
int ii = 6 + (info.instrBits & 7);
if (!AddImmOperand(info, DspParameter::SignedByte, (int8_t)ii))
return false;
}
break;
case 3: // SBCLR
if ((info.instrBits & 0b11111000) == 0)
{
info.instr = DspInstruction::SBCLR;
int ii = 6 + (info.instrBits & 7);
if (!AddImmOperand(info, DspParameter::SignedByte, (int8_t)ii))
return false;
}
break;
}
break;
case 1:
if ((info.instrBits & 0b10'0000'0000) != 0)
{
if ((info.instrBits & 0b1'0000'0000) != 0)
{
if ((info.instrBits & 0xf) == 0xf)
{
// CALLR, JMPR
if ((info.instrBits & 0b10000) != 0)
{
info.instr = DspInstruction::CALLR;
}
else
{
info.instr = DspInstruction::JMPR;
}
info.flowControl = true;
int rr = (info.instrBits >> 5) & 7;
if (!AddParam(info, (DspParameter)rr, rr))
return false;
}
}
else
{
// SI
if (instrMaxSize < sizeof(uint16_t))
return false;
info.instr = DspInstruction::SI;
DspAddress mm = (DspAddress)(uint16_t)(int16_t)(int8_t)(uint8_t)(info.instrBits & 0xff);
uint16_t imm = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
return false;
if (!AddImmOperand(info, DspParameter::Address, mm))
return false;
if (!AddImmOperand(info, DspParameter::UnsignedShort2, imm))
return false;
}
}
else
{
// LSL, LSR, ASL, ASR
bool rightShift = false;
switch ((info.instrBits >> 6) & 3)
{
case 0:
info.instr = DspInstruction::LSL;
break;
case 1:
info.instr = DspInstruction::LSR;
rightShift = true;
break;
case 2:
info.instr = DspInstruction::ASL;
break;
case 3:
info.instr = DspInstruction::ASR;
rightShift = true;
break;
}
info.logic = true;
uint16_t rr = ((info.instrBits & 0b100000000) != 0) ? 1 : 0;
uint8_t ii = info.instrBits & 0x3f;
// This strange shift behavior is suspiciously looks like bit rotation, but let it be as it is
if (rightShift)
{
if (ii & 0b100000)
ii |= 0b11000000;
}
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + rr), rr))
return false;
if (rightShift)
{
if (!AddImmOperand(info, DspParameter::SignedByte, (int8_t)ii))
return false;
}
else
{
if (!AddImmOperand(info, DspParameter::Byte, ii))
return false;
}
}
break;
case 2: // LRR / SRR
{
bool load = false;
switch ((info.instrBits >> 7) & 7)
{
case 0b000:
info.instr = DspInstruction::LRR;
load = true;
break;
case 0b001:
info.instr = DspInstruction::LRRD;
load = true;
break;
case 0b010:
info.instr = DspInstruction::LRRI;
load = true;
break;
case 0b011:
info.instr = DspInstruction::LRRN;
load = true;
break;
case 0b100:
info.instr = DspInstruction::SRR;
load = false;
break;
case 0b101:
info.instr = DspInstruction::SRRD;
load = false;
break;
case 0b110:
info.instr = DspInstruction::SRRI;
load = false;
break;
case 0b111:
info.instr = DspInstruction::SRRN;
load = false;
break;
}
if (load)
{
int dd = (info.instrBits & 0x1f);
int ss = (info.instrBits >> 5) & 3;
if (!AddParam(info, (DspParameter)dd, dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::Indexed_regs + ss), ss))
return false;
}
else
{
int ss = (info.instrBits & 0x1f);
int dd = (info.instrBits >> 5) & 3;
if (!AddParam(info, (DspParameter)((int)DspParameter::Indexed_regs + dd), dd))
return false;
if (!AddParam(info, (DspParameter)ss, ss))
return false;
}
break;
}
case 3: // MRR
{
int dd = (info.instrBits >> 5) & 0x1f;
int ss = (info.instrBits & 0x1f);
info.instr = DspInstruction::MRR;
if (!AddParam(info, (DspParameter)dd, dd))
return false;
if (!AddParam(info, (DspParameter)ss, ss))
return false;
break;
}
}
return true;
}
bool Analyzer::Group2(AnalyzeInfo& info)
{
//LRS * 0010 0ddd mmmm mmmm
//SRS * 0010 1sss mmmm mmmm
if ((info.instrBits & 0b1000'0000'0000) != 0)
{
info.instr = DspInstruction::SRS;
int ss = (info.instrBits >> 8) & 7;
DspAddress addr = (DspAddress)(0xFF00 | (info.instrBits & 0xff)); // By default bank reg = 0xFF
if (!AddImmOperand(info, DspParameter::Address, addr))
return false;
if (!AddParam(info, (DspParameter)(0x18 + ss), 0x18 + ss))
return false;
}
else
{
info.instr = DspInstruction::LRS;
int dd = (info.instrBits >> 8) & 7;
DspAddress addr = (DspAddress)(0xFF00 | (info.instrBits & 0xff)); // By default bank reg = 0xFF
if (!AddParam(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
if (!AddImmOperand(info, DspParameter::Address, addr))
return false;
}
return true;
}
bool Analyzer::Group3(AnalyzeInfo& info)
{
//XORR * 0011 00sd xxxx xxxx // XORR $acD.m, $axS.h
//ANDR * 0011 01sd xxxx xxxx // ANDR $acD.m, $axS.h
//ORR * 0011 10sd xxxx xxxx // ORR $acD.m, $axS.h
//ANDC * 0011 110d xxxx xxxx // ANDC $acD.m, $ac(1-D).m
//ORC * 0011 111d xxxx xxxx // ORC $acD.m, $ac(1-D).m
info.logic = true;
if (((info.instrBits >> 10) & 3) == 0b11) // ANDC, ORC
{
int dd = (info.instrBits >> 8) & 1;
if (info.instrBits & 0b10'0000'0000)
{
info.instr = DspInstruction::ORC;
}
else
{
info.instr = DspInstruction::ANDC;
}
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + (1 - dd)), (1 - dd)))
return false;
}
else // XORR, ANDR, ORR
{
int ss = (info.instrBits >> 9) & 1;
int dd = (info.instrBits >> 8) & 1;
switch ((info.instrBits >> 10) & 3)
{
case 0:
info.instr = DspInstruction::XORR;
break;
case 1:
info.instr = DspInstruction::ANDR;
break;
case 2:
info.instr = DspInstruction::ORR;
break;
}
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + dd), dd))
return false;
if (!AddParam(info, ss ? DspParameter::ax1h : DspParameter::ax0h, ss))
return false;
}
return true;
}
bool Analyzer::Group4(AnalyzeInfo& info)
{
//ADDR * 0100 0ssd xxxx xxxx // ADDR $acD, $(0x18+S)
//ADDAX * 0100 10sd xxxx xxxx // ADDAX $acD, $axS
//ADD * 0100 110d xxxx xxxx // ADD $acD, $ac(1-D)
//ADDP * 0100 111d xxxx xxxx // ADDP $acD
int dd = (info.instrBits >> 8) & 1;
if ((info.instrBits & 0b1000'0000'0000) != 0)
{
if ((info.instrBits & 0b0100'0000'0000) != 0)
{
if ((info.instrBits & 0b0010'0000'0000) != 0)
{
// ADDP
info.instr = DspInstruction::ADDP;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
}
else
{
// ADD
info.instr = DspInstruction::ADD;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + (1-dd)), (1-dd)))
return false;
}
}
else
{
// ADDAX
int ss = (info.instrBits >> 9) & 1;
info.instr = DspInstruction::ADDAX;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ax0 + ss), ss))
return false;
}
}
else
{
// ADDR
int ss = (info.instrBits >> 9) & 3;
info.instr = DspInstruction::ADDR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)(0x18 + ss), 0x18 + ss))
return false;
}
return true;
}
bool Analyzer::Group5(AnalyzeInfo& info)
{
//SUBR * 0101 0ssd xxxx xxxx // SUBR $acD, $(0x18+S)
//SUBAX * 0101 10sd xxxx xxxx // SUBAX $acD, $axS
//SUB * 0101 110d xxxx xxxx // SUB $acD, $ac(1-D)
//SUBP * 0101 111d xxxx xxxx // SUBP $acD
int dd = (info.instrBits >> 8) & 1;
if ((info.instrBits & 0b1000'0000'0000) != 0)
{
if ((info.instrBits & 0b0100'0000'0000) != 0)
{
if ((info.instrBits & 0b0010'0000'0000) != 0)
{
// SUBP
info.instr = DspInstruction::SUBP;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
}
else
{
// SUB
info.instr = DspInstruction::SUB;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + (1 - dd)), (1 - dd)))
return false;
}
}
else
{
// SUBAX
int ss = (info.instrBits >> 9) & 1;
info.instr = DspInstruction::SUBAX;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ax0 + ss), ss))
return false;
}
}
else
{
// SUBR
int ss = (info.instrBits >> 9) & 3;
info.instr = DspInstruction::SUBR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)(0x18 + ss), 0x18 + ss))
return false;
}
return true;
}
bool Analyzer::Group6(AnalyzeInfo& info)
{
//MOVR * 0110 0ssd xxxx xxxx // MOVR $acD, $(0x18+S)
//MOVAX * 0110 10sd xxxx xxxx // MOVAX $acD, $axS
//MOV * 0110 110d xxxx xxxx // MOV $acD, $ac(1-D)
//MOVP * 0110 111d xxxx xxxx // MOVP $acD
int dd = (info.instrBits >> 8) & 1;
if ((info.instrBits & 0b1000'0000'0000) != 0)
{
if ((info.instrBits & 0b0100'0000'0000) != 0)
{
if ((info.instrBits & 0b0010'0000'0000) != 0)
{
// MOVP
info.instr = DspInstruction::MOVP;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
}
else
{
// MOV
info.instr = DspInstruction::MOV;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + (1 - dd)), (1 - dd)))
return false;
}
}
else
{
// MOVAX
int ss = (info.instrBits >> 9) & 1;
info.instr = DspInstruction::MOVAX;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)((int)DspParameter::ax0 + ss), ss))
return false;
}
}
else
{
// MOVR
int ss = (info.instrBits >> 9) & 3;
info.instr = DspInstruction::MOVR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, (DspParameter)(0x18 + ss), 0x18 + ss))
return false;
}
return true;
}
bool Analyzer::Group7(AnalyzeInfo& info)
{
//ADDAXL * 0111 00sd xxxx xxxx // ADDAXL $acD, $axS.l
//INCM * 0111 010d xxxx xxxx // INCM $acsD (mid accum)
//INC * 0111 011d xxxx xxxx // INC $acD
//DECM * 0111 100d xxxx xxxx // DECM $acsD (mid)
//DEC * 0111 101d xxxx xxxx // DEC $acD
//NEG * 0111 110d xxxx xxxx // NEG $acD
//MOVNP * 0111 111d xxxx xxxx // MOVNP $acD
int dd = (info.instrBits >> 8) & 1;
if ((info.instrBits & 0b1100'0000'0000) != 0)
{
// Others
switch ((info.instrBits >> 9) & 7)
{
case 0b010:
info.instr = DspInstruction::INCM;
break;
case 0b011:
info.instr = DspInstruction::INC;
break;
case 0b100:
info.instr = DspInstruction::DECM;
break;
case 0b101:
info.instr = DspInstruction::DEC;
break;
case 0b110:
info.instr = DspInstruction::NEG;
break;
case 0b111:
info.instr = DspInstruction::MOVNP;
break;
}
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
}
else
{
// ADDAXL
int ss = (info.instrBits >> 9) & 1;
info.instr = DspInstruction::ADDAXL;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, ss ? DspParameter::ax1l : DspParameter::ax0l, ss))
return false;
}
return true;
}
bool Analyzer::Group8(AnalyzeInfo& info)
{
//NX * 1000 r000 xxxx xxxx (possibly mov r, r)
//CLR * 1000 r001 xxxx xxxx
//CMP * 1000 0010 xxxx xxxx
//UNUSED* 1000 0011 xxxx xxxx
//CLRP * 1000 0100 xxxx xxxx
//TSTAXH 1000 011r xxxx xxxx
//M2/M0 1000 101x xxxx xxxx
//CLR15/SET15 1000 110x xxxx xxxx
//CLR40/SET40 1000 111x xxxx xxxx
switch ((info.instrBits >> 8) & 0xf)
{
case 0b0000: // NX
case 0b1000:
info.instr = DspInstruction::NX;
break;
case 0b0001: // CLR acR
case 0b1001:
{
int r = (info.instrBits >> 11) & 1;
info.instr = DspInstruction::CLR;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + r), r))
return false;
break;
}
case 0b0010: // CMP
info.instr = DspInstruction::CMP;
break;
case 0b0100: // CLRP
info.instr = DspInstruction::CLRP;
break;
case 0b0110: // TSTAXH axR.h
case 0b0111:
{
int r = (info.instrBits >> 8) & 1;
info.instr = DspInstruction::TSTAXH;
if (!AddParam(info, r ? DspParameter::ax1h : DspParameter::ax0h, r))
return false;
break;
}
case 0b1010: // M2
info.instr = DspInstruction::M2;
break;
case 0b1011: // M0
info.instr = DspInstruction::M0;
break;
case 0b1100: // CLR15
info.instr = DspInstruction::CLR15;
break;
case 0b1101: // SET15
info.instr = DspInstruction::SET15;
break;
case 0b1110: // CLR40
info.instr = DspInstruction::CLR40;
break;
case 0b1111: // SET40
info.instr = DspInstruction::SET40;
break;
}
return true;
}
bool Analyzer::Group9(AnalyzeInfo& info)
{
//MUL * 1001 s000 xxxx xxxx // MUL $axS.l, $axS.h
//ASR16 * 1001 s001 xxxx xxxx // ASR16 $acS
//MULMVZ * 1001 s01r xxxx xxxx // MULMVZ $axS.l, $axS.h, $acR
//MULAC * 1001 s10r xxxx xxxx // MULAC $axS.l, $axS.h, $acR
//MULMV * 1001 s11r xxxx xxxx // MULMV $axS.l, $axS.h, $acR
int ss = (info.instrBits >> 11) & 1;
int rr = (info.instrBits >> 8) & 1;
info.madd = true;
bool hasR = false;
switch ((info.instrBits >> 9) & 3)
{
case 0:
if ((info.instrBits & 0b1'0000'0000) != 0)
{
// ASR16
info.madd = false;
info.instr = DspInstruction::ASR16;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + ss), ss))
return false;
}
else
{
// MUL
info.instr = DspInstruction::MUL;
hasR = false;
}
break;
case 1: // MULMVZ
info.instr = DspInstruction::MULMVZ;
hasR = true;
break;
case 2: // MULAC
info.instr = DspInstruction::MULAC;
hasR = true;
break;
case 3: // MULMV
info.instr = DspInstruction::MULMV;
hasR = true;
break;
}
if (info.madd)
{
if (!AddParam(info, ss ? DspParameter::ax1l : DspParameter::ax0l, ss))
return false;
if (!AddParam(info, ss ? DspParameter::ax1h : DspParameter::ax0h, ss))
return false;
if (hasR)
{
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + rr), rr))
return false;
}
}
return true;
}
bool Analyzer::GroupAB(AnalyzeInfo& info)
{
//MULX * 101s t000 xxxx xxxx // MULX $ax0.S, $ax1.T
//ABS 1010 t001 xxxx xxxx // ABS $acT
//TST 1011 t001 xxxx xxxx // TST $acT
//MULXMVZ * 101s t01r xxxx xxxx // MULXMVZ $ax0.S, $ax1.T, $acR
//MULXAC * 101s t10r xxxx xxxx // MULXAC $ax0.S, $ax1.T, $acR
//MULXMV * 101s t11r xxxx xxxx // MULXMV $ax0.S, $ax1.T, $acR
info.madd = true;
int ss = (info.instrBits >> 12) & 1;
int tt = (info.instrBits >> 11) & 1;
int rr = (info.instrBits >> 8) & 1;
bool hasR = false;
switch ((info.instrBits >> 9) & 3)
{
case 0:
if ((info.instrBits & 0b1'0000'0000) != 0)
{
info.madd = false;
if ((info.instrBits & 0b1'0000'0000'0000) != 0)
{
// TST
info.instr = DspInstruction::TST;
}
else
{
// ABS
info.instr = DspInstruction::ABS;
}
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + tt), tt))
return false;
}
else
{
// MULX
info.instr = DspInstruction::MULX;
hasR = false;
}
break;
case 1: // MULXMVZ
info.instr = DspInstruction::MULXMVZ;
hasR = true;
break;
case 2: // MULXAC
info.instr = DspInstruction::MULXAC;
hasR = true;
break;
case 3: // MULXMV
info.instr = DspInstruction::MULXMV;
hasR = true;
break;
}
if (info.madd)
{
if (!AddParam(info, ss ? DspParameter::ax0h : DspParameter::ax0l, ss))
return false;
if (!AddParam(info, tt ? DspParameter::ax1h : DspParameter::ax1l, tt))
return false;
if (hasR)
{
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + rr), rr))
return false;
}
}
return true;
}
bool Analyzer::GroupCD(AnalyzeInfo& info)
{
//MULC * 110s t000 xxxx xxxx // MULC $acS.m, $axT.h
//CMPAR * 110r s001 xxxx xxxx // CMPAR $acS.m, $ax[0|1].h
//MULCMVZ * 110s t01r xxxx xxxx // MULCMVZ $acS.m, $axT.h, $acR
//MULCAC * 110s t10r xxxx xxxx // MULCAC $acS.m, $axT.h, $acR
//MULCMV * 110s t11r xxxx xxxx // MULCMV $acS.m, $axT.h, $acR
info.madd = true;
int ss = (info.instrBits >> 12) & 1;
int tt = (info.instrBits >> 11) & 1;
int rr = (info.instrBits >> 8) & 1;
bool hasR = false;
switch ((info.instrBits >> 9) & 3)
{
case 0:
if ((info.instrBits & 0b1'0000'0000) != 0)
{
// CMPAR
info.madd = false;
info.instr = DspInstruction::CMPAR;
ss = (info.instrBits >> 11) & 1;
rr = (info.instrBits >> 12) & 1;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0m + ss), ss))
return false;
if (!AddParam(info, rr ? DspParameter::ax1h : DspParameter::ax0h, rr))
return false;
}
else
{
// MULC
info.instr = DspInstruction::MULC;
hasR = false;
}
break;
case 1: // MULCMVZ
info.instr = DspInstruction::MULCMVZ;
hasR = true;
break;
case 2: // MULCAC
info.instr = DspInstruction::MULCAC;
hasR = true;
break;
case 3: // MULCMV
info.instr = DspInstruction::MULCMV;
hasR = true;
break;
}
if (info.madd)
{
if (!AddParam(info, ss ? DspParameter::ac1m : DspParameter::ac0m, ss))
return false;
if (!AddParam(info, tt ? DspParameter::ax1h : DspParameter::ax0h, tt))
return false;
if (hasR)
{
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + rr), rr))
return false;
}
}
return true;
}
bool Analyzer::GroupE(AnalyzeInfo& info)
{
//MADDX ** 1110 00st xxxx xxxx // MADDX $(0x18+S*2), $(0x19+T*2)
//MSUBX ** 1110 01st xxxx xxxx // MSUBX $(0x18+S*2), $(0x19+T*2)
//MADDC ** 1110 10st xxxx xxxx // MADDC $acS.m, $axT.h
//MSUBC ** 1110 11st xxxx xxxx // MSUBC $acS.m, $axT.h
info.madd = true;
int ss = (info.instrBits >> 9) & 1;
int tt = (info.instrBits >> 8) & 1;
if ((info.instrBits & 0b1000'0000'0000) != 0)
{
// MADDC, MSUBC
info.instr = (info.instrBits & 0b0100'0000'0000) ?
DspInstruction::MSUBC : DspInstruction::MADDC;
if (!AddParam(info, ss ? DspParameter::ac1m : DspParameter::ac0m, ss))
return false;
if (!AddParam(info, tt ? DspParameter::ax1h : DspParameter::ax0h, tt))
return false;
}
else
{
// MADDX, MSUBX
info.instr = (info.instrBits & 0b0100'0000'0000) ?
DspInstruction::MSUBX : DspInstruction::MADDX;
if (!AddParam(info, (DspParameter)(0x18 + ss * 2), 0x18 + ss * 2))
return false;
if (!AddParam(info, (DspParameter)(0x19 + tt * 2), 0x19 + tt * 2))
return false;
}
return true;
}
bool Analyzer::GroupF(AnalyzeInfo& info)
{
//LSL16 * 1111 000d xxxx xxxx // LSL16 $acD
//MADD * 1111 001d xxxx xxxx // MADD $axD.l, $axD.h
//LSR16 * 1111 010d xxxx xxxx // LSR16 $acD
//MSUB * 1111 011d xxxx xxxx // MSUB $axD.l, $axD.h
//ADDPAXZ * 1111 10sd xxxx xxxx // ADDPAXZ $acD, $axS.h
//CLRL * 1111 110d xxxx xxxx // CLRL $acD.l
//MOVPZ * 1111 111d xxxx xxxx // MOVPZ $acD
int dd = (info.instrBits >> 8) & 1;
int ss = (info.instrBits >> 9) & 1;
switch ((info.instrBits >> 9) & 7)
{
case 0b000: // LSL16
info.logic = true;
info.instr = DspInstruction::LSL16;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
break;
case 0b001: // MADD
info.madd = true;
info.instr = DspInstruction::MADD;
if (!AddParam(info, dd ? DspParameter::ax1l : DspParameter::ax0l, dd))
return false;
if (!AddParam(info, dd ? DspParameter::ax1h : DspParameter::ax0h, dd))
return false;
break;
case 0b010: // LSR16
info.logic = true;
info.instr = DspInstruction::LSR16;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
break;
case 0b011: // MSUB
info.madd = true;
info.instr = DspInstruction::MSUB;
if (!AddParam(info, dd ? DspParameter::ax1l : DspParameter::ax0l, dd))
return false;
if (!AddParam(info, dd ? DspParameter::ax1h : DspParameter::ax0h, dd))
return false;
break;
case 0b100: // ADDPAXZ
case 0b101:
info.instr = DspInstruction::ADDPAXZ;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
if (!AddParam(info, ss ? DspParameter::ax1h : DspParameter::ax0h, ss))
return false;
break;
case 0b110: // CLRL
info.instr = DspInstruction::CLRL;
if (!AddParam(info, dd ? DspParameter::ac1l : DspParameter::ac0l, dd))
return false;
break;
case 0b111: // MOVPZ
info.instr = DspInstruction::MOVPZ;
if (!AddParam(info, (DspParameter)((int)DspParameter::ac0 + dd), dd))
return false;
break;
}
return true;
}
// DSP instructions are in a hybrid format: some instructions occupy a full 16-bit word, and some can be packed as two 8-bit instructions per word.
// Extended opcodes represents lower-part of instruction pair.
bool Analyzer::GroupPacked(AnalyzeInfo& info)
{
// x is used as part of Group3. Otherwise x=0.
//?? * xxxx xxxx x000 00rr // NOP2 (effectivly $arR = $arR + 0)
//DR * xxxx xxxx x000 01rr // DR $arR
//IR * xxxx xxxx x000 10rr // IR $arR
//NR * xxxx xxxx x000 11rr // NR $arR, ixR
//MV * xxxx xxxx x001 ddss // MV $(0x18+D), $(0x1c+S)
//S * xxxx xxxx x01s s0dd // S @$rD, $(0x1c+s)
//SN * xxxx xxxx x01s s1dd // SN @$rD, $(0x1c+s)
//L * xxxx xxxx x1dd d0ss // L $(0x18+D), @$rS
//LN * xxxx xxxx x1dd d1ss // LN $(0x18+D), @$rS
// Cannot be used with Group3 (bit7 is used as part of Group3 upper instruction)
//LS * xxxx xxxx 10dd 000s // LS $(0x18+D), $acS.m
//SL * xxxx xxxx 10dd 001s // SL $acS.m, $(0x18+D)
//LSN * xxxx xxxx 10dd 010s // LSN $(0x18+D), $acS.m
//SLN * xxxx xxxx 10dd 011s // SLN $acS.m, $(0x18+D)
//LSM * xxxx xxxx 10dd 100s // LSM $(0x18+D), $acS.m
//SLM * xxxx xxxx 10dd 101s // SLM $acS.m, $(0x18+D)
//LSNM * xxxx xxxx 10dd 110s // LSNM $(0x18+D), $acS.m
//SLNM * xxxx xxxx 10dd 111s // SLNM $acS.m, $(0x18+D)
//LD xxxx xxxx 11dr 00ss // LD $ax0.d, $ax1.r, @$arS
//LDN xxxx xxxx 11dr 01ss // LDN $ax0.d, $ax1.r, @$arS
//LDM xxxx xxxx 11dr 10ss // LDM $ax0.d, $ax1.r, @$arS
//LDNM xxxx xxxx 11dr 11ss // LDNM $ax0.d, $ax1.r, @$arS
//LDAX xxxx xxxx 11sr 0011 // LDAX $axR, @$arS
//LDAXN xxxx xxxx 11sr 0111 // LDAXN $axR, @$arS
//LDAXM xxxx xxxx 11sr 1011 // LDAXM $axR, @$arS
//LDAXNM xxxx xxxx 11sr 1111 // LDAXNM $axR, @$arS
info.extendedOpcodePresent = true;
info.instrExBits = info.instrBits & 0xff;
// Not all can be used with Group3 (paired logic)
if ((info.instrBits >> 12) == 3)
{
info.instrExBits &= 0x7f;
}
switch (info.instrExBits >> 6)
{
case 0:
{
if ((info.instrExBits & 0b100000) != 0) // S, SN
{
int ss = (info.instrExBits >> 3) & 3;
int dd = info.instrExBits & 3;
if ((info.instrExBits & 0b100) != 0)
{
info.instrEx = DspInstructionEx::SN;
}
else
{
info.instrEx = DspInstructionEx::S;
}
if (!AddParamEx(info, (DspParameter)((int)DspParameter::Indexed_regs + dd), dd))
return false;
if (!AddParamEx(info, (DspParameter)(0x1c + ss), 0x1c + ss))
return false;
}
else if ((info.instrExBits & 0b10000) != 0) // MV
{
int dd = (info.instrExBits >> 2) & 3;
int ss = info.instrExBits & 3;
info.instrEx = DspInstructionEx::MV;
if (!AddParamEx(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
if (!AddParamEx(info, (DspParameter)(0x1c + ss), 0x1c + ss))
return false;
}
else // NOP2, DR, IR, NR
{
int rr = info.instrExBits & 3;
switch ((info.instrExBits >> 2) & 3)
{
case 0:
info.instrEx = DspInstructionEx::NOP2;
break;
case 1:
info.instrEx = DspInstructionEx::DR;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ar0 + rr), rr))
return false;
break;
case 2:
info.instrEx = DspInstructionEx::IR;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ar0 + rr), rr))
return false;
break;
case 3:
info.instrEx = DspInstructionEx::NR;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ar0 + rr), rr))
return false;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ix0 + rr), rr))
return false;
break;
}
}
break;
}
case 1: // L, LN
{
int dd = (info.instrExBits >> 3) & 7;
int ss = info.instrExBits & 3;
if (info.instrExBits & 0b100)
{
info.instrEx = DspInstructionEx::LN;
}
else
{
info.instrEx = DspInstructionEx::L;
}
if (!AddParamEx(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::Indexed_regs + ss), ss))
return false;
break;
}
case 2: // LSx, SLx
{
int dd = (info.instrExBits >> 4) & 3;
int ss = info.instrExBits & 1;
bool load = false;
switch ((info.instrExBits >> 1) & 7)
{
case 0b000:
info.instrEx = DspInstructionEx::LS;
load = true;
break;
case 0b001:
info.instrEx = DspInstructionEx::SL;
load = false;
break;
case 0b010:
info.instrEx = DspInstructionEx::LSN;
load = true;
break;
case 0b011:
info.instrEx = DspInstructionEx::SLN;
load = false;
break;
case 0b100:
info.instrEx = DspInstructionEx::LSM;
load = true;
break;
case 0b101:
info.instrEx = DspInstructionEx::SLM;
load = false;
break;
case 0b110:
info.instrEx = DspInstructionEx::LSNM;
load = true;
break;
case 0b111:
info.instrEx = DspInstructionEx::SLNM;
load = false;
break;
}
if (load)
{
if (!AddParamEx(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ac0m + ss), ss))
return false;
}
else
{
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ac0m + ss), ss))
return false;
if (!AddParamEx(info, (DspParameter)(0x18 + dd), 0x18 + dd))
return false;
}
break;
}
case 3: // LDx
{
if ((info.instrExBits & 3) == 0b11)
{
int ss = (info.instrExBits >> 5) & 1;
int rr = (info.instrExBits >> 4) & 1;
switch ((info.instrExBits >> 2) & 3)
{
case 0:
info.instrEx = DspInstructionEx::LDAX;
break;
case 1:
info.instrEx = DspInstructionEx::LDAXN;
break;
case 2:
info.instrEx = DspInstructionEx::LDAXM;
break;
case 3:
info.instrEx = DspInstructionEx::LDAXNM;
break;
}
if (!AddParamEx(info, (DspParameter)((int)DspParameter::ax0 + rr), rr))
return false;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::Indexed_ar0 + ss), ss))
return false;
}
else
{
int dd = (info.instrExBits >> 5) & 1;
int rr = (info.instrExBits >> 4) & 1;
int ss = info.instrExBits & 3;
switch ((info.instrExBits >> 2) & 3)
{
case 0:
info.instrEx = DspInstructionEx::LD;
break;
case 1:
info.instrEx = DspInstructionEx::LDN;
break;
case 2:
info.instrEx = DspInstructionEx::LDM;
break;
case 3:
info.instrEx = DspInstructionEx::LDNM;
break;
}
if (!AddParamEx(info, dd ? DspParameter::ax0h : DspParameter::ax0l, dd))
return false;
if (!AddParamEx(info, rr ? DspParameter::ax1h : DspParameter::ax1l, rr))
return false;
if (!AddParamEx(info, (DspParameter)((int)DspParameter::Indexed_ar0 + ss), ss))
return false;
}
break;
}
}
return true;
}
bool Analyzer::AddParam(AnalyzeInfo& info, DspParameter param, uint16_t paramBits)
{
if (info.numParameters >= _countof(info.params))
return false;
info.params[info.numParameters] = param;
info.paramBits[info.numParameters] = paramBits;
info.numParameters++;
return true;
}
bool Analyzer::AddParamEx(AnalyzeInfo& info, DspParameter param, uint16_t paramBits)
{
if (info.numParametersEx >= _countof(info.paramsEx))
return false;
info.paramsEx[info.numParametersEx] = param;
info.paramExBits[info.numParametersEx] = paramBits;
info.numParametersEx++;
return true;
}
bool Analyzer::AddBytes(uint8_t* instrPtr, size_t bytes, AnalyzeInfo& info)
{
if (info.sizeInBytes >= sizeof(info.bytes))
return false;
memcpy(&info.bytes[info.sizeInBytes], instrPtr, bytes);
info.sizeInBytes += bytes;
return true;
}
bool Analyzer::Analyze(uint8_t* instrPtr, size_t instrMaxSize, AnalyzeInfo& info)
{
// Reset info
ResetInfo(info);
// Get opcode and determine its group
if (instrMaxSize < sizeof(uint16_t))
{
return false;
}
info.instrBits = _byteswap_ushort(*(uint16_t*)instrPtr);
if (!AddBytes(instrPtr, sizeof(uint16_t), info))
{
return false;
}
instrPtr += sizeof(info.instrBits);
instrMaxSize -= sizeof(info.instrBits);
int group = (info.instrBits >> 12);
// Select by group. Groups 3-F in packed format.
switch (group)
{
case 0:
return Group0(instrPtr, instrMaxSize, info);
case 1:
return Group1(instrPtr, instrMaxSize, info);
case 2:
return Group2(info);
case 3:
if (!Group3(info))
return false;
return GroupPacked(info);
case 4:
if (!Group4(info))
return false;
return GroupPacked(info);
case 5:
if (!Group5(info))
return false;
return GroupPacked(info);
case 6:
if (!Group6(info))
return false;
return GroupPacked(info);
case 7:
if (!Group7(info))
return false;
return GroupPacked(info);
case 8:
if (!Group8(info))
return false;
return GroupPacked(info);
case 9:
if (!Group9(info))
return false;
return GroupPacked(info);
case 0xa:
case 0xb:
if (!GroupAB(info))
return false;
return GroupPacked(info);
case 0xc:
case 0xd:
if (!GroupCD(info))
return false;
return GroupPacked(info);
case 0xe:
if (!GroupE(info))
return false;
return GroupPacked(info);
case 0xf:
if (!GroupF(info))
return false;
return GroupPacked(info);
}
return true;
}
}