// GameCube DSP interpreter #include "pch.h" namespace DSP { DspInterpreter::DspInterpreter(DspCore* parent) { core = parent; } DspInterpreter::~DspInterpreter() { } #pragma region "Top Instructions" void DspInterpreter::ABS(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].sbits = SignExtend40(core->regs.ac[n].sbits) >= 0 ? core->regs.ac[n].sbits : -core->regs.ac[n].sbits; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::ADD(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; DspLongAccumulator b; b.sbits = SignExtend40(core->regs.ac[1 - d].sbits); core->regs.ac[d].sbits = SignExtend40(core->regs.ac[d].sbits); core->regs.ac[d].sbits += SignExtend40(core->regs.ac[1 - d].sbits); Flags(a, b, core->regs.ac[d]); } void DspInterpreter::ADDARN(AnalyzeInfo& info) { core->regs.ar[info.paramBits[0]] += core->regs.ix[info.paramBits[1]]; } void DspInterpreter::ADDAX(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = SignExtend40((int64_t)core->regs.ax[info.paramBits[1]].sbits); core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits += SignExtend40((int64_t)core->regs.ax[info.paramBits[1]].sbits); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ADDAXL(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = SignExtend16(core->regs.ax[info.paramBits[1]].l); core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits += SignExtend16(core->regs.ax[info.paramBits[1]].l); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ADDI(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.shm = (int32_t)(int16_t)info.ImmOperand.UnsignedShort; b.l = 0; core->regs.ac[info.paramBits[0]].shm += (int32_t)(int16_t)info.ImmOperand.UnsignedShort; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ADDIS(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.shm = (int32_t)(int16_t)info.ImmOperand.SignedByte; b.l = 0; core->regs.ac[info.paramBits[0]].shm += (int32_t)(int16_t)info.ImmOperand.SignedByte; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ADDP(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = core->PackProd(); core->regs.ac[info.paramBits[0]].sbits += core->PackProd(); Flags(a, b, core->regs.ac[info.paramBits[0]]); } // Fixed error in original Duddie doc: addpaxz acD.m, ax1.[l|h] void DspInterpreter::ADDPAXZ(AnalyzeInfo& info) { DspLongAccumulator a, b, c; a.sbits = core->PackProd(); b.shm = info.paramBits[1] ? (int32_t)(int16_t)core->regs.ax[1].h : (int32_t)(int16_t)core->regs.ax[1].l; b.l = 0; c.shm = a.shm + b.shm; c.l = 0; core->regs.ac[info.paramBits[0]] = c; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ADDR(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = SignExtend16(core->MoveFromReg(info.paramBits[1])); core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits += SignExtend16(core->MoveFromReg(info.paramBits[1])); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ANDC(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].m &= core->regs.ac[1 - n].m; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::TCLR(AnalyzeInfo& info) { core->regs.sr.ok = (core->regs.ac[info.paramBits[0]].m & info.ImmOperand.UnsignedShort) == 0; } void DspInterpreter::TSET(AnalyzeInfo& info) { core->regs.sr.ok = (core->regs.ac[info.paramBits[0]].m & info.ImmOperand.UnsignedShort) == info.ImmOperand.UnsignedShort; } void DspInterpreter::ANDI(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].m &= info.ImmOperand.UnsignedShort; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::ANDR(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; core->regs.ac[d].m &= core->regs.ax[info.paramBits[1]].h; Flags(a, a, core->regs.ac[d]); } void DspInterpreter::ASL(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].sbits <<= info.ImmOperand.SignedByte; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ASR(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits >>= -info.ImmOperand.SignedByte; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::ASR16(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits >>= 16; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::BLOOP(AnalyzeInfo& info) { if (core->MoveFromReg(info.paramBits[0]) != 0) { SetLoop(core->regs.pc + 2, info.ImmOperand.Address, core->MoveFromReg(info.paramBits[0])); core->regs.pc += 2; } else { core->regs.pc = info.ImmOperand.Address + 1; } } void DspInterpreter::BLOOPI(AnalyzeInfo& info) { if (info.ImmOperand.Byte != 0) { SetLoop(core->regs.pc + 2, info.ImmOperand2.Address, info.ImmOperand.Byte); core->regs.pc += 2; } else { core->regs.pc = info.ImmOperand2.Address + 1; } } void DspInterpreter::CALLcc(AnalyzeInfo& info) { if (Condition(info.cc)) { core->regs.st[0].push_back(core->regs.pc + 2); core->regs.pc = info.ImmOperand.Address; } else { core->regs.pc += 2; } } void DspInterpreter::CALLR(AnalyzeInfo& info) { core->regs.st[0].push_back(core->regs.pc + 1); core->regs.pc = core->MoveFromReg(info.paramBits[0]); } void DspInterpreter::CLR(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].bits = 0; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::CLRL(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].l = 0; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::CLRP(AnalyzeInfo& info) { core->regs.prod.l = 0; core->regs.prod.m1 = 0; core->regs.prod.h = 0; core->regs.prod.m2 = 0; } void DspInterpreter::CMP(AnalyzeInfo& info) { DspLongAccumulator a, b, c; a.sbits = SignExtend40(core->regs.ac[0].sbits); b.sbits = -SignExtend40(core->regs.ac[1].sbits); c.sbits = a.sbits + b.sbits; Flags(a, b, c); } void DspInterpreter::CMPI(AnalyzeInfo& info) { DspLongAccumulator a, b, c; a.hm = core->regs.ac[info.paramBits[0]].hm; a.l = 0; b.hm = (int32_t)(int16_t)info.ImmOperand.UnsignedShort; b.l = 0; b.sbits = -b.sbits; c.sbits = a.sbits + b.sbits; Flags(a, b, c); } void DspInterpreter::CMPIS(AnalyzeInfo& info) { DspLongAccumulator a, b, c; a.hm = core->regs.ac[info.paramBits[0]].hm; a.l = 0; b.hm = (int32_t)(int16_t)info.ImmOperand.SignedByte; b.l = 0; b.sbits = -b.sbits; c.sbits = a.sbits + b.sbits; Flags(a, b, c); } // Compares accumulator $acS.m with accumulator ax1.[l|h] void DspInterpreter::CMPAR(AnalyzeInfo& info) { DspLongAccumulator a, b, c; a.sbits = SignExtend16(core->regs.ac[info.paramBits[0]].m); b.sbits = info.paramBits[1] ? SignExtend16(core->regs.ax[1].h) : SignExtend16(core->regs.ax[1].l); b.sbits = -b.sbits; c.sbits = a.sbits + b.sbits; Flags(a, b, c); } void DspInterpreter::DAR(AnalyzeInfo& info) { core->regs.ar[info.paramBits[0]]--; } void DspInterpreter::DEC(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].sbits--; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::DECM(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].hm--; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::HALT(AnalyzeInfo& info) { core->Suspend(); } void DspInterpreter::IAR(AnalyzeInfo& info) { core->regs.ar[info.paramBits[0]]++; } void DspInterpreter::INC(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].sbits++; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::INCM(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; core->regs.ac[info.paramBits[0]].hm++; Flags(a, a, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::IFcc(AnalyzeInfo& info) { if (Condition(info.cc)) { core->regs.pc++; } else { core->regs.pc += 2; } } void DspInterpreter::ILRR(AnalyzeInfo& info) { core->regs.ac[info.paramBits[0]].m = core->ReadIMem(core->regs.ar[info.paramBits[1]]); } void DspInterpreter::ILRRD(AnalyzeInfo& info) { core->regs.ac[info.paramBits[0]].m = core->ReadIMem(core->regs.ar[info.paramBits[1]]); core->regs.ar[info.paramBits[1]]--; } void DspInterpreter::ILRRI(AnalyzeInfo& info) { core->regs.ac[info.paramBits[0]].m = core->ReadIMem(core->regs.ar[info.paramBits[1]]); core->regs.ar[info.paramBits[1]]++; } void DspInterpreter::ILRRN(AnalyzeInfo& info) { core->regs.ac[info.paramBits[0]].m = core->ReadIMem(core->regs.ar[info.paramBits[1]]); core->regs.ar[info.paramBits[1]] += core->regs.ix[info.paramBits[1]]; } void DspInterpreter::Jcc(AnalyzeInfo& info) { if (Condition(info.cc)) { core->regs.pc = info.ImmOperand.Address; } else { core->regs.pc += 2; } } void DspInterpreter::JMPR(AnalyzeInfo& info) { core->regs.pc = core->MoveFromReg(info.paramBits[0]); } void DspInterpreter::LOOP(AnalyzeInfo& info) { if (core->MoveFromReg(info.paramBits[0]) != 0) { SetLoop(core->regs.pc + 1, core->regs.pc + 1, core->MoveFromReg(info.paramBits[0])); core->regs.pc++; } else { core->regs.pc += 2; } } void DspInterpreter::LOOPI(AnalyzeInfo& info) { if (info.ImmOperand.Byte != 0) { SetLoop(core->regs.pc + 1, core->regs.pc + 1, info.ImmOperand.Byte); core->regs.pc++; } else { core->regs.pc += 2; } } void DspInterpreter::LR(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem(info.ImmOperand.UnsignedShort)); } void DspInterpreter::LRI(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], info.ImmOperand.UnsignedShort); } void DspInterpreter::LRIS(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], (uint16_t)(int16_t)info.ImmOperand.SignedByte); } void DspInterpreter::LRR(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem(core->regs.ar[info.paramBits[1]])); } void DspInterpreter::LRRD(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem(core->regs.ar[info.paramBits[1]])); core->regs.ar[info.paramBits[1]]--; } void DspInterpreter::LRRI(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem(core->regs.ar[info.paramBits[1]])); core->regs.ar[info.paramBits[1]]++; } void DspInterpreter::LRRN(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem(core->regs.ar[info.paramBits[1]])); core->regs.ar[info.paramBits[1]] += core->regs.ix[info.paramBits[1]]; } void DspInterpreter::LRS(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->ReadDMem( (core->regs.bank << 8) | (uint8_t)info.ImmOperand.Address)); } void DspInterpreter::LSL(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].bits <<= info.ImmOperand.Byte; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::LSL16(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].bits <<= 16; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::LSR(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].bits >>= -info.ImmOperand.SignedByte; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::LSR16(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; core->regs.ac[n].bits >>= 16; Flags(a, a, core->regs.ac[n]); } void DspInterpreter::M2(AnalyzeInfo& info) { core->regs.sr.am = 0; } void DspInterpreter::M0(AnalyzeInfo& info) { core->regs.sr.am = 1; } void DspInterpreter::CLR15(AnalyzeInfo& info) { core->regs.sr.su = 0; } void DspInterpreter::SET15(AnalyzeInfo& info) { core->regs.sr.su = 1; } void DspInterpreter::CLR40(AnalyzeInfo& info) { core->regs.sr.sxm = 0; } void DspInterpreter::SET40(AnalyzeInfo& info) { core->regs.sr.sxm = 1; } void DspInterpreter::MOV(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; DspLongAccumulator b = core->regs.ac[1 - d]; core->regs.ac[d] = core->regs.ac[1 - d]; Flags(a, b, core->regs.ac[d]); } void DspInterpreter::MOVAX(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = (int64_t)core->regs.ax[info.paramBits[1]].sbits; core->regs.ac[info.paramBits[0]].sbits = (int64_t)core->regs.ax[info.paramBits[1]].sbits; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::MOVNP(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = -core->PackProd(); core->regs.ac[info.paramBits[0]].sbits = -core->PackProd(); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::MOVP(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = core->PackProd(); core->regs.ac[info.paramBits[0]].sbits = core->PackProd(); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::MOVPZ(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = core->PackProd(); core->regs.ac[info.paramBits[0]].sbits = core->PackProd(); core->regs.ac[info.paramBits[0]].l = 0; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::MOVR(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.hm = (int32_t)(int16_t)core->MoveFromReg(info.paramBits[1]); b.l = 0; core->regs.ac[info.paramBits[0]].hm = (int32_t)(int16_t)core->MoveFromReg(info.paramBits[1]); core->regs.ac[info.paramBits[0]].l = 0; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::MRR(AnalyzeInfo& info) { core->MoveToReg(info.paramBits[0], core->MoveFromReg(info.paramBits[1])); } void DspInterpreter::NEG(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; DspLongAccumulator b; b.sbits = -SignExtend40(core->regs.ac[n].sbits); core->regs.ac[n].sbits = -SignExtend40(core->regs.ac[n].sbits); Flags(a, b, core->regs.ac[n]); } void DspInterpreter::ORC(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; DspLongAccumulator b; b.sbits = core->regs.ac[1 - n].m; core->regs.ac[n].m |= core->regs.ac[1 - n].m; Flags(a, b, core->regs.ac[n]); } void DspInterpreter::ORI(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; DspLongAccumulator b; b.sbits = info.ImmOperand.UnsignedShort; core->regs.ac[n].m |= info.ImmOperand.UnsignedShort; Flags(a, b, core->regs.ac[n]); } void DspInterpreter::ORR(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; DspLongAccumulator b; b.sbits = core->regs.ax[info.paramBits[1]].h; core->regs.ac[d].m |= core->regs.ax[info.paramBits[1]].h; Flags(a, b, core->regs.ac[d]); } void DspInterpreter::RETcc(AnalyzeInfo& info) { if (Condition(info.cc)) { core->regs.pc = core->regs.st[0].back(); core->regs.st[0].pop_back(); } else { core->regs.pc++; } } void DspInterpreter::RTI(AnalyzeInfo& info) { core->ReturnFromException(); } void DspInterpreter::SBSET(AnalyzeInfo& info) { core->regs.sr.bits |= (1 << info.ImmOperand.Byte); } void DspInterpreter::SBCLR(AnalyzeInfo& info) { core->regs.sr.bits &= ~(1 << info.ImmOperand.Byte); } void DspInterpreter::SI(AnalyzeInfo& info) { core->WriteDMem(info.ImmOperand.Address, info.ImmOperand2.UnsignedShort); } void DspInterpreter::SR(AnalyzeInfo& info) { core->WriteDMem(info.ImmOperand.Address, core->MoveFromReg(info.paramBits[1])); } void DspInterpreter::SRR(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramBits[0]], core->MoveFromReg(info.paramBits[1])); } void DspInterpreter::SRRD(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramBits[0]], core->MoveFromReg(info.paramBits[1])); core->regs.ar[info.paramBits[0]]--; } void DspInterpreter::SRRI(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramBits[0]], core->MoveFromReg(info.paramBits[1])); core->regs.ar[info.paramBits[0]]++; } void DspInterpreter::SRRN(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramBits[0]], core->MoveFromReg(info.paramBits[1])); core->regs.ar[info.paramBits[0]] += core->regs.ix[info.paramBits[0]]; } void DspInterpreter::SRS(AnalyzeInfo& info) { core->WriteDMem( (core->regs.bank << 8) | (uint8_t)info.ImmOperand.Address, core->MoveFromReg(info.paramBits[1])); } void DspInterpreter::SUB(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; DspLongAccumulator b; b.sbits = -SignExtend40(core->regs.ac[1 - d].sbits); core->regs.ac[d].sbits = SignExtend40(core->regs.ac[d].sbits); core->regs.ac[d].sbits -= SignExtend40(core->regs.ac[1 - d].sbits); Flags(a, b, core->regs.ac[d]); } void DspInterpreter::SUBAX(AnalyzeInfo& info) { int64_t ax = (int64_t)core->regs.ax[info.paramBits[1]].sbits; DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = -ax; core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits -= ax; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::SUBP(AnalyzeInfo& info) { DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = -core->PackProd(); core->regs.ac[info.paramBits[0]].sbits -= core->PackProd(); Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::SUBR(AnalyzeInfo& info) { int64_t reg = SignExtend16(core->MoveFromReg(info.paramBits[1])); DspLongAccumulator a = core->regs.ac[info.paramBits[0]]; DspLongAccumulator b; b.sbits = -reg; core->regs.ac[info.paramBits[0]].sbits = SignExtend40(core->regs.ac[info.paramBits[0]].sbits); core->regs.ac[info.paramBits[0]].sbits -= reg; Flags(a, b, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::TST(AnalyzeInfo& info) { DspLongAccumulator zr = { 0 }; Flags(zr, zr, core->regs.ac[info.paramBits[0]]); } void DspInterpreter::TSTAXH(AnalyzeInfo& info) { DspLongAccumulator zr = { 0 }; DspLongAccumulator axh; axh.sbits = SignExtend16(core->regs.ax[info.paramBits[0]].h); Flags(zr, zr, axh); } void DspInterpreter::XORI(AnalyzeInfo& info) { int n = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[n]; DspLongAccumulator b; b.sbits = info.ImmOperand.UnsignedShort; core->regs.ac[n].m ^= info.ImmOperand.UnsignedShort; Flags(a, b, core->regs.ac[n]); } void DspInterpreter::XORR(AnalyzeInfo& info) { int d = info.paramBits[0]; DspLongAccumulator a = core->regs.ac[d]; DspLongAccumulator b; b.sbits = core->regs.ax[info.paramBits[1]].h; core->regs.ac[d].m ^= core->regs.ax[info.paramBits[1]].h; Flags(a, b, core->regs.ac[d]); } #pragma endregion "Top Instructions" #pragma region "Multiplier Instructions" void DspInterpreter::MADD(AnalyzeInfo& info) { // Multiply low part $axS.l of secondary accumulator $axS by high part $axS.h of secondary accumulator $axS // (treat them both as signed) and add result to product register. //Madd16x16 core->PackProd(0); } void DspInterpreter::MADDC(AnalyzeInfo& info) { // Multiply middle part of accumulator $acS.m by high part of secondary accumulator $axT.h // (treat them both as signed) and add result to product register. //Madd32x16 core->PackProd(0); } void DspInterpreter::MADDX(AnalyzeInfo& info) { //Multiply one part of secondary accumulator $ax0 (selected by S) by one part of secondary accumulator $ax1 (selected by T) // (treat them both as signed) and add result to product register. //Madd16x16 core->PackProd(0); } void DspInterpreter::MSUB(AnalyzeInfo& info) { //Multiply low part $axS.l of secondary accumulator $axS by high part $axS.h of secondary accumulator $axS //(treat them both as signed) and subtract result from product register. //Msub16x16 core->PackProd(0); } void DspInterpreter::MSUBC(AnalyzeInfo& info) { //Multiply middle part of accumulator $acS.m by high part of secondary accumulator $axT.h // (treat them both as signed) and subtract result from product register. //Msub32x16 core->PackProd(0); } void DspInterpreter::MSUBX(AnalyzeInfo& info) { //Multiply one part of secondary accumulator $ax0 (selected by S) by one part of secondary accumulator $ax1 (selected by T) // (treat them both as signed) and subtract result from product register. //Msub16x16 core->PackProd(0); } void DspInterpreter::MUL(AnalyzeInfo& info) { //Multiply low part $axS.l of secondary accumulator $axS by high part $axS.h of secondary accumulator $axS (treat them both as signed). //Mul16x16 core->PackProd(0); } void DspInterpreter::MULAC(AnalyzeInfo& info) { // Add product register to accumulator register $acR. // Multiply low part $axS.l of secondary accumulator $axS by high part $axS.h of secondary accumulator $axS(treat them both as signed). //Mul16x16 core->PackProd(0); } void DspInterpreter::MULC(AnalyzeInfo& info) { //Multiply mid part of accumulator register $acS.m by high part $axS.h of secondary accumulator $axS (treat them both as signed). //Mul32x16 core->PackProd(0); } void DspInterpreter::MULCAC(AnalyzeInfo& info) { // Multiply mid part of accumulator register $acS.m by high part $axS.h of secondary accumulator $axS(treat them both as signed). // Add product register before multiplication to accumulator $acR. //Mul32x16 core->PackProd(0); } void DspInterpreter::MULCMV(AnalyzeInfo& info) { // Multiply mid part of accumulator register $acS.m by high part $axS.h of secondary accumulator $axS(treat them both as signed). // Move product register before multiplication to accumulator $acR. //Mul32x16 core->PackProd(0); } void DspInterpreter::MULCMVZ(AnalyzeInfo& info) { // Multiply mid part of accumulator register $acS.m by high part $axS.h of secondary accumulator $axS (treat them both as signed). // Move product register before multiplication to accumulator $acR. Set low part of accumulator $acR.l to zero. //Mul32x16 core->PackProd(0); } void DspInterpreter::MULMV(AnalyzeInfo& info) { // Move product register to accumulator register $acR. Multiply low part $axS.l of secondary accumulator Register$axS by high part $axS.h of secondary accumulator $axS // (treat them both as signed). //Mul16x16 core->PackProd(0); } void DspInterpreter::MULMVZ(AnalyzeInfo& info) { // Move product register to accumulator register $acRand clear low part of accumulator register $acR.l. // Multiply low part $axS.l of secondary accumulator $axS by high part $axS.h of secondary accumulator $axS(treat them both as signed). //Mul16x16 core->PackProd(0); } void DspInterpreter::MULX(AnalyzeInfo& info) { int64_t a = SignExtend16(info.paramBits[0] ? core->regs.ax[0].h : core->regs.ax[0].l); int64_t b = SignExtend16(info.paramBits[1] ? core->regs.ax[1].h : core->regs.ax[1].l); core->PackProd(a * b); } void DspInterpreter::MULXAC(AnalyzeInfo& info) { core->regs.ac[info.paramBits[2]].sbits += core->PackProd(); int64_t a = SignExtend16(info.paramBits[0] ? core->regs.ax[0].h : core->regs.ax[0].l); int64_t b = SignExtend16(info.paramBits[1] ? core->regs.ax[1].h : core->regs.ax[1].l); core->PackProd(a * b); } void DspInterpreter::MULXMV(AnalyzeInfo& info) { core->regs.ac[info.paramBits[2]].sbits = core->PackProd(); int64_t a = SignExtend16(info.paramBits[0] ? core->regs.ax[0].h : core->regs.ax[0].l); int64_t b = SignExtend16(info.paramBits[1] ? core->regs.ax[1].h : core->regs.ax[1].l); core->PackProd(a * b); } void DspInterpreter::MULXMVZ(AnalyzeInfo& info) { //Move product register to accumulator register $acR and clear low part of accumulator register $acR.l. //Multiply one part $ax0 by one part $ax1 (treat them both as signed). //Part is selected by S and T bits. Zero selects low part, one selects high part. //Mul16x16 core->PackProd(0); } #pragma region "Multiplier Instructions" #pragma region "Bottom Instructions" void DspInterpreter::DR(AnalyzeInfo& info) { core->regs.ar[info.paramExBits[0]]--; } void DspInterpreter::IR(AnalyzeInfo& info) { core->regs.ar[info.paramExBits[0]]++; } void DspInterpreter::NR(AnalyzeInfo& info) { core->regs.ar[info.paramExBits[0]] += core->regs.ix[info.paramExBits[0]]; } void DspInterpreter::MV(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->MoveFromReg(info.paramExBits[1])); } void DspInterpreter::S(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramExBits[0]], core->MoveFromReg(info.paramExBits[1])); core->regs.ar[info.paramExBits[0]]++; } void DspInterpreter::SN(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[info.paramExBits[0]], core->MoveFromReg(info.paramExBits[1])); core->regs.ar[info.paramExBits[0]] += core->regs.ix[info.paramExBits[0]]; } void DspInterpreter::L(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[info.paramExBits[1]])); core->regs.ar[info.paramExBits[1]]++; } void DspInterpreter::LN(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[info.paramExBits[1]])); core->regs.ar[info.paramExBits[1]] += core->regs.ix[info.paramExBits[1]]; } void DspInterpreter::LS(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[0])); core->WriteDMem(core->regs.ar[3], core->regs.ac[info.paramExBits[1]].m); core->regs.ar[0]++; core->regs.ar[3]++; } void DspInterpreter::SL(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[0], core->regs.ac[info.paramExBits[0]].m); core->MoveToReg(info.paramExBits[1], core->ReadDMem(core->regs.ar[3])); core->regs.ar[0]++; core->regs.ar[3]++; } void DspInterpreter::LSN(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[0])); core->WriteDMem(core->regs.ar[3], core->regs.ac[info.paramExBits[1]].m); core->regs.ar[0] += core->regs.ix[0]; core->regs.ar[3]++; } void DspInterpreter::SLN(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[0], core->regs.ac[info.paramExBits[0]].m); core->MoveToReg(info.paramExBits[1], core->ReadDMem(core->regs.ar[3])); core->regs.ar[0] += core->regs.ix[0]; core->regs.ar[3]++; } void DspInterpreter::LSM(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[0])); core->WriteDMem(core->regs.ar[3], core->regs.ac[info.paramExBits[1]].m); core->regs.ar[0]++; core->regs.ar[3] += core->regs.ix[3]; } void DspInterpreter::SLM(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[0], core->regs.ac[info.paramExBits[0]].m); core->MoveToReg(info.paramExBits[1], core->ReadDMem(core->regs.ar[3])); core->regs.ar[0]++; core->regs.ar[3] += core->regs.ix[3]; } void DspInterpreter::LSNM(AnalyzeInfo& info) { core->MoveToReg(info.paramExBits[0], core->ReadDMem(core->regs.ar[0])); core->WriteDMem(core->regs.ar[3], core->regs.ac[info.paramExBits[1]].m); core->regs.ar[0] += core->regs.ix[0]; core->regs.ar[3] += core->regs.ix[3]; } void DspInterpreter::SLNM(AnalyzeInfo& info) { core->WriteDMem(core->regs.ar[0], core->regs.ac[info.paramExBits[0]].m); core->MoveToReg(info.paramExBits[1], core->ReadDMem(core->regs.ar[3])); core->regs.ar[0] += core->regs.ix[0]; core->regs.ar[3] += core->regs.ix[3]; } // TODO: The last 2 groups of opcodes look very crazy. Need to reverse UCodes and understand in context how they actually work. // Подозрительно похоже что вместо ar3 на самом деле используется ar[S] и ar[3-S], как мы это видели в опкодах ранее. // Поэтому на ar[S] и ar[3] в примерах показанные как ar[0] и ar[3] на самом деле будут ar[0] и ar[3 - 0]. // Suspiciously, instead of ar3 - ar[S] and ar[3-S] are actually used, as we saw in the opcodes earlier. // Therefore, on ar[S] and ar[3] in the examples shown as ar[0] and ar[3] will actually be ar[0] and ar[3-0]. // LD $ax0.d, $ax1.r, @$arS // ax0.d (d = Low/High) = *arS; ax1.r (r = Low/High) = *ar3 // Postincrement arS, ar3 void DspInterpreter::LDCommon(AnalyzeInfo& info) { if (info.paramExBits[0]) { core->regs.ax[0].l = core->ReadDMem(core->regs.ar[info.paramExBits[2]]); // S } else { core->regs.ax[0].h = core->ReadDMem(core->regs.ar[info.paramExBits[2]]); // S } if (info.paramExBits[1]) { core->regs.ax[1].l = core->ReadDMem(core->regs.ar[3]); // 3 - S ??? } else { core->regs.ax[1].h = core->ReadDMem(core->regs.ar[3]); // 3 - S ??? } } void DspInterpreter::LD(AnalyzeInfo& info) { LDCommon(info); core->regs.ar[info.paramExBits[2]]++; core->regs.ar[3]++; } void DspInterpreter::LDN(AnalyzeInfo& info) { LDCommon(info); core->regs.ar[info.paramExBits[2]] += core->regs.ix[info.paramExBits[2]]; core->regs.ar[3]++; } void DspInterpreter::LDM(AnalyzeInfo& info) { LDCommon(info); core->regs.ar[info.paramExBits[2]]++; core->regs.ar[3] += core->regs.ix[3]; } void DspInterpreter::LDNM(AnalyzeInfo& info) { LDCommon(info); core->regs.ar[info.paramExBits[2]] += core->regs.ix[info.paramExBits[2]]; core->regs.ar[3] += core->regs.ix[3]; } // LDAX $axR, @$arS // axR.h = *arS; axR.l = *ar3; // Postincrement arS, ar3 void DspInterpreter::LDAXCommon(AnalyzeInfo& info) { core->regs.ax[info.paramExBits[0]].h = core->ReadDMem(core->regs.ar[info.paramExBits[1]]); // S core->regs.ax[info.paramExBits[0]].l = core->ReadDMem(core->regs.ar[3]); // 3 - S ??? } void DspInterpreter::LDAX(AnalyzeInfo& info) { LDAXCommon(info); core->regs.ar[info.paramExBits[1]]++; core->regs.ar[3]++; } void DspInterpreter::LDAXN(AnalyzeInfo& info) { LDAXCommon(info); core->regs.ar[info.paramExBits[1]] += core->regs.ix[info.paramExBits[1]]; core->regs.ar[3]++; } void DspInterpreter::LDAXM(AnalyzeInfo& info) { LDAXCommon(info); core->regs.ar[info.paramExBits[1]]++; core->regs.ar[3] += core->regs.ix[3]; } void DspInterpreter::LDAXNM(AnalyzeInfo& info) { LDAXCommon(info); core->regs.ar[info.paramExBits[1]] += core->regs.ix[info.paramExBits[1]]; core->regs.ar[3] += core->regs.ix[3]; } #pragma endregion "Bottom Instructions" int64_t DspInterpreter::SignExtend40(int64_t a) { if (a & 0x8000000000) { a |= 0xffffff0000000000; } return a; } int64_t DspInterpreter::SignExtend16(int16_t a) { int64_t res = a; if (res & 0x8000) { res |= 0xffffffffffff0000; } return res; } bool DspInterpreter::Condition(ConditionCode cc) { switch (cc) { case ConditionCode::GE: return core->regs.sr.s == core->regs.sr.o; case ConditionCode::L: return core->regs.sr.s != core->regs.sr.o; case ConditionCode::G: return (core->regs.sr.s == core->regs.sr.o) && (core->regs.sr.z == 0); case ConditionCode::LE: return (core->regs.sr.s != core->regs.sr.o) && (core->regs.sr.z != 0); case ConditionCode::NE: return core->regs.sr.z == 0; case ConditionCode::EQ: return core->regs.sr.z != 0; case ConditionCode::NC: return core->regs.sr.c == 0; case ConditionCode::C: return core->regs.sr.c != 0; case ConditionCode::BelowS32: return core->regs.sr.as == 0; case ConditionCode::AboveS32: return core->regs.sr.as != 0; case ConditionCode::NOK: return core->regs.sr.ok == 0; case ConditionCode::OK: return core->regs.sr.ok != 0; case ConditionCode::O: return core->regs.sr.o != 0; case ConditionCode::Always: return true; } return false; } // 32-bit accumulator does not involved in flags calculations void DspInterpreter::Flags40(int64_t a, int64_t b, int64_t res) { bool carry = (res & 0x10000000000) != 0; bool zero = (res & 0xffffffffff) == 0; bool aboveS32 = (res & 0xff00000000) == 0; // Correct? bool msb = (res & 0x8000000000) != 0 ? true : false; bool afterMsb = (res & 0x4000000000) != 0 ? true : false; // http://teaching.idallen.com/dat2343/10f/notes/040_overflow.txt //1. If the sum of two numbers with the sign bits off yields a result number // with the sign bit on, the "overflow" flag is turned on. // 0100 + 0100 = 1000 (overflow flag is turned on) //2. If the sum of two numbers with the sign bits on yields a result number // with the sign bit off, the "overflow" flag is turned on. // 1000 + 1000 = 0000 (overflow flag is turned on) //A human need only remember that, when doing signed math, adding //two numbers of the same sign must produce a result of the same sign, //otherwise overflow happened. bool aMsb = (a & 0x8000000000) != 0 ? true : false; bool bMsb = (b & 0x8000000000) != 0 ? true : false; bool ovf = false; if (aMsb == bMsb) { ovf = aMsb != msb; } core->regs.sr.c = carry; core->regs.sr.o = ovf; core->regs.sr.z = zero; core->regs.sr.s = msb; core->regs.sr.tt = msb == afterMsb; core->regs.sr.as = aboveS32; } void DspInterpreter::Flags(DspLongAccumulator a, DspLongAccumulator b, DspLongAccumulator res) { Flags40(SignExtend40(a.bits), SignExtend40(b.bits), SignExtend40(res.bits)); } void DspInterpreter::FlagsLogic(DspLongAccumulator a) { } void DspInterpreter::SetLoop(DspAddress startAddr, DspAddress endAddr, uint16_t count) { core->regs.st[0].push_back(startAddr); core->regs.st[2].push_back(endAddr); core->regs.st[3].push_back(count); } bool DspInterpreter::CheckLoop() { while (!core->regs.st[3].empty()) { if (core->regs.st[3].back() != 0) { if (core->regs.pc == core->regs.st[2].back()) { core->regs.pc = core->regs.st[0].back(); core->regs.st[3].back()--; return true; } break; } else { core->regs.st[0].pop_back(); core->regs.st[2].pop_back(); core->regs.st[3].pop_back(); } } return false; } void DspInterpreter::Dispatch(AnalyzeInfo& info) { // Test breakpoints and canaries if (core->IsRunning()) { if (core->TestBreakpoint(core->regs.pc)) { DBHalt("DSP: IMEM breakpoint at 0x%04X\n", core->regs.pc); core->Suspend(); return; } core->TestCanary(core->regs.pc); } // Regular instructions ("top") switch (info.instr) { case DspInstruction::ABS: ABS(info); break; case DspInstruction::ADD: ADD(info); break; case DspInstruction::ADDARN: ADDARN(info); break; case DspInstruction::ADDAX: ADDAX(info); break; case DspInstruction::ADDAXL: ADDAXL(info); break; case DspInstruction::ADDI: ADDI(info); break; case DspInstruction::ADDIS: ADDIS(info); break; case DspInstruction::ADDP: ADDP(info); break; case DspInstruction::ADDPAXZ: ADDPAXZ(info); break; case DspInstruction::ADDR: ADDR(info); break; case DspInstruction::ANDC: ANDC(info); break; case DspInstruction::TCLR: TCLR(info); break; case DspInstruction::TSET: TSET(info); break; case DspInstruction::ANDI: ANDI(info); break; case DspInstruction::ANDR: ANDR(info); break; case DspInstruction::ASL: ASL(info); break; case DspInstruction::ASR: ASR(info); break; case DspInstruction::ASR16: ASR16(info); break; case DspInstruction::BLOOP: BLOOP(info); break; case DspInstruction::BLOOPI: BLOOPI(info); break; case DspInstruction::CALLcc: CALLcc(info); break; case DspInstruction::CALLR: CALLR(info); break; case DspInstruction::CLR: CLR(info); break; case DspInstruction::CLRL: CLRL(info); break; case DspInstruction::CLRP: CLRP(info); break; case DspInstruction::CMP: CMP(info); break; case DspInstruction::CMPI: CMPI(info); break; case DspInstruction::CMPIS: CMPIS(info); break; case DspInstruction::CMPAR: CMPAR(info); break; case DspInstruction::DAR: DAR(info); break; case DspInstruction::DEC: DEC(info); break; case DspInstruction::DECM: DECM(info); break; case DspInstruction::HALT: HALT(info); break; case DspInstruction::IAR: IAR(info); break; case DspInstruction::INC: INC(info); break; case DspInstruction::INCM: INCM(info); break; case DspInstruction::IFcc: IFcc(info); break; case DspInstruction::ILRR: ILRR(info); break; case DspInstruction::ILRRD: ILRRD(info); break; case DspInstruction::ILRRI: ILRRI(info); break; case DspInstruction::ILRRN: ILRRN(info); break; case DspInstruction::Jcc: Jcc(info); break; case DspInstruction::JMPR: JMPR(info); break; case DspInstruction::LOOP: LOOP(info); break; case DspInstruction::LOOPI: LOOPI(info); break; case DspInstruction::LR: LR(info); break; case DspInstruction::LRI: LRI(info); break; case DspInstruction::LRIS: LRIS(info); break; case DspInstruction::LRR: LRR(info); break; case DspInstruction::LRRD: LRRD(info); break; case DspInstruction::LRRI: LRRI(info); break; case DspInstruction::LRRN: LRRN(info); break; case DspInstruction::LRS: LRS(info); break; case DspInstruction::LSL: LSL(info); break; case DspInstruction::LSL16: LSL16(info); break; case DspInstruction::LSR: LSR(info); break; case DspInstruction::LSR16: LSR16(info); break; case DspInstruction::M2: M2(info); break; case DspInstruction::M0: M0(info); break; case DspInstruction::CLR15: CLR15(info); break; case DspInstruction::SET15: SET15(info); break; case DspInstruction::CLR40: CLR40(info); break; case DspInstruction::SET40: SET40(info); break; case DspInstruction::MOV: MOV(info); break; case DspInstruction::MOVAX: MOVAX(info); break; case DspInstruction::MOVNP: MOVNP(info); break; case DspInstruction::MOVP: MOVP(info); break; case DspInstruction::MOVPZ: MOVPZ(info); break; case DspInstruction::MOVR: MOVR(info); break; case DspInstruction::MRR: MRR(info); break; case DspInstruction::NEG: NEG(info); break; case DspInstruction::ORC: ORC(info); break; case DspInstruction::ORI: ORI(info); break; case DspInstruction::ORR: ORR(info); break; case DspInstruction::RETcc: RETcc(info); break; case DspInstruction::RTI: RTI(info); break; case DspInstruction::SBSET: SBSET(info); break; case DspInstruction::SBCLR: SBCLR(info); break; case DspInstruction::SI: SI(info); break; case DspInstruction::SR: SR(info); break; case DspInstruction::SRR: SRR(info); break; case DspInstruction::SRRD: SRRD(info); break; case DspInstruction::SRRI: SRRI(info); break; case DspInstruction::SRRN: SRRN(info); break; case DspInstruction::SRS: SRS(info); break; case DspInstruction::SUB: SUB(info); break; case DspInstruction::SUBAX: SUBAX(info); break; case DspInstruction::SUBP: SUBP(info); break; case DspInstruction::SUBR: SUBR(info); break; case DspInstruction::TST: TST(info); break; case DspInstruction::TSTAXH: TSTAXH(info); break; case DspInstruction::XORI: XORI(info); break; case DspInstruction::XORR: XORR(info); break; //case DspInstruction::MADD: MADD(info); break; //case DspInstruction::MADDC: MADDC(info); break; //case DspInstruction::MADDX: MADDX(info); break; //case DspInstruction::MSUB: MSUB(info); break; //case DspInstruction::MSUBC: MSUBC(info); break; //case DspInstruction::MSUBX: MSUBX(info); break; //case DspInstruction::MUL: MUL(info); break; //case DspInstruction::MULAC: MULAC(info); break; //case DspInstruction::MULC: MULC(info); break; //case DspInstruction::MULCAC: MULCAC(info); break; //case DspInstruction::MULCMV: MULCMV(info); break; //case DspInstruction::MULCMVZ: MULCMVZ(info); break; //case DspInstruction::MULMV: MULMV(info); break; //case DspInstruction::MULMVZ: MULMVZ(info); break; case DspInstruction::MULX: MULX(info); break; case DspInstruction::MULXAC: MULXAC(info); break; case DspInstruction::MULXMV: MULXMV(info); break; //case DspInstruction::MULXMVZ: MULXMVZ(info); break; case DspInstruction::NOP: case DspInstruction::NX: break; default: DBHalt("DSP Unknown instruction at 0x%04X\n", core->regs.pc); core->Suspend(); return; } // Packed tuple ("bottom") if (info.extendedOpcodePresent) { switch (info.instrEx) { case DspInstructionEx::DR: DR(info); break; case DspInstructionEx::IR: IR(info); break; case DspInstructionEx::NR: NR(info); break; case DspInstructionEx::MV: MV(info); break; case DspInstructionEx::S: S(info); break; case DspInstructionEx::SN: SN(info); break; case DspInstructionEx::L: L(info); break; case DspInstructionEx::LN: LN(info); break; case DspInstructionEx::LS: LS(info); break; case DspInstructionEx::SL: SL(info); break; case DspInstructionEx::LSN: LSN(info); break; case DspInstructionEx::SLN: SLN(info); break; case DspInstructionEx::LSM: LSM(info); break; case DspInstructionEx::SLM: SLM(info); break; case DspInstructionEx::LSNM: LSNM(info); break; case DspInstructionEx::SLNM: SLNM(info); break; case DspInstructionEx::LD: LD(info); break; case DspInstructionEx::LDN: LDN(info); break; case DspInstructionEx::LDM: LDM(info); break; case DspInstructionEx::LDNM: LDNM(info); break; case DspInstructionEx::LDAX: LDAX(info); break; case DspInstructionEx::LDAXN: LDAXN(info); break; case DspInstructionEx::LDAXM: LDAXM(info); break; case DspInstructionEx::LDAXNM: LDAXNM(info); break; case DspInstructionEx::NOP2: break; default: DBHalt("DSP Unknown packed instruction at 0x%04X\n", core->regs.pc); core->Suspend(); return; } } if (!info.flowControl && !CheckLoop()) { core->regs.pc += (DspAddress)(info.sizeInBytes >> 1); } } void DspInterpreter::ExecuteInstr() { AnalyzeInfo info; // Fetch, analyze and dispatch instruction at pc addr DspAddress imemAddr = core->regs.pc; uint8_t* imemPtr = core->TranslateIMem(imemAddr); if (imemPtr == nullptr) { DBHalt("DSP TranslateIMem failed on dsp addr: 0x%04X\n", imemAddr); core->Suspend(); return; } if (!Analyzer::Analyze(imemPtr, DspCore::MaxInstructionSizeInBytes, info)) { DBHalt("DSP Analyzer failed on dsp addr: 0x%04X\n", imemAddr); core->Suspend(); return; } Dispatch(info); } }