commit 2bd2d12fccb3e7774837eef3a106ad5489af84b0
parent fad1023dcb322f47016badf7d7981cccad173a78
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Mon, 5 Aug 2024 19:22:49 +0200
replace DSP boot code with C++
Diffstat:
9 files changed, 173 insertions(+), 160 deletions(-)
diff --git a/source/hardwareLib/CMakeLists.txt b/source/hardwareLib/CMakeLists.txt
@@ -5,7 +5,7 @@ add_library(hardwareLib STATIC)
set(SOURCES
am29f.cpp am29f.h
- dspBootCode.h
+ dspBootCode.cpp dspBootCode.h
haltDSP.cpp haltDSP.h
i2c.cpp i2c.h
i2cFlash.cpp i2cFlash.h
diff --git a/source/hardwareLib/dspBootCode.cpp b/source/hardwareLib/dspBootCode.cpp
@@ -0,0 +1,66 @@
+#include "dspBootCode.h"
+
+#include "dsp56kEmu/dsp.h"
+
+namespace hwLib
+{
+ DspBoot::DspBoot(dsp56k::DSP& _dsp) : m_dsp(_dsp)
+ {
+ // H(D)I08 interface needs to be enabled after boot, set it up now already
+ auto enableHdi08 = [](dsp56k::HDI08& _hdi08)
+ {
+ _hdi08.writePortControlRegister(1<<dsp56k::HDI08::HPCR_HEN);
+ };
+
+ if(auto* periph56362 = dynamic_cast<dsp56k::Peripherals56362*>(m_dsp.getPeriph(0)))
+ enableHdi08(periph56362->getHDI08());
+ else if(auto* periph56303 = dynamic_cast<dsp56k::Peripherals56303*>(m_dsp.getPeriph(0)))
+ enableHdi08(periph56303->getHI08());
+ }
+
+ bool DspBoot::hdiWriteTX(const dsp56k::TWord& _val)
+ {
+ // DSP Boot Code emulation. The following bytes are sent to the DSP via HDI08:
+ //
+ // * Length = number of words to be received
+ // * Address = target address where words will be written to
+ // * 'Length' number of words
+ //
+ // After completion, DSP jumps to 'Address' to execute the code it just received
+
+ switch (m_state)
+ {
+ case State::Length:
+ m_remaining = _val;
+ m_state = State::Address;
+ return false;
+ case State::Address:
+ m_address = _val;
+
+ LOG("DSP Boot: " << m_remaining << " words, initial PC " << HEX(m_address));
+
+ // r0 is used as counter, r1 holds the initial PC
+ m_dsp.regs().r[0].var = static_cast<int32_t>(m_address + m_remaining);
+ m_dsp.regs().r[1].var = static_cast<int32_t>(m_address);
+
+ m_dsp.regs().sr.var &= ~0xff; // ccr is cleared before jump to r1
+ m_dsp.setPC(m_address); // jmp (r1)
+
+ m_state = State::Data;
+ return false;
+ case State::Data:
+ m_dsp.memory().set(dsp56k::MemArea_P, m_address++, _val);
+ if(0 == --m_remaining)
+ {
+ LOG("DSP Boot: finished");
+ m_state = State::Finished;
+ return true;
+ }
+ return false;
+ case State::Finished:
+ return true;
+ }
+ assert(false && "invalid state");
+ return false;
+ }
+}
diff --git a/source/hardwareLib/dspBootCode.h b/source/hardwareLib/dspBootCode.h
@@ -1,74 +1,37 @@
#pragma once
-#include <cstdint>
+#include "dsp56kEmu/types.h"
+
+namespace dsp56k
+{
+ class DSP;
+}
namespace hwLib
{
- static constexpr uint32_t g_dspBootCode56362[] =
+ class DspBoot
{
- 0x350013, 0x0afa23, 0xff0035, 0x0afa22,
- 0xff000e, 0x0afa01, 0xff0022, 0x0afa20,
- 0xff005e, 0x61f400, 0xff1000, 0x050c8f,
- 0x0afa00, 0xff0021, 0x31a900, 0x0afa01,
- 0xff0012, 0x0ad161, 0x04d191, 0x019191,
- 0xff0013, 0x044894, 0x019191, 0xff0016,
- 0x045094, 0x221100, 0x06c800, 0xff001f,
- 0x019191, 0xff001c, 0x009814, 0x000000,
- 0x050c5a, 0x050c5d, 0x62f400, 0xd00000,
- 0x08f4b8, 0xd00409, 0x060680, 0xff0029,
- 0x07da8a, 0x0c1c10, 0x219000, 0x219100,
- 0x06c800, 0xff0033, 0x060380, 0xff0031,
- 0x07da8a, 0x0c1c10, 0x07588c, 0x000000,
- 0x050c46, 0x0afa02, 0xff005c, 0x0afa01,
- 0xff003e, 0x0afa00, 0xff0046, 0x08f484,
- 0x000038, 0x050c0b, 0x0afa20, 0xff0043,
- 0x08f484, 0x005018, 0x050c06, 0x08f484,
- 0x000218, 0x050c03, 0x08f484, 0x001c1e,
- 0x0a8426, 0x0a8380, 0xff0049, 0x084806,
- 0x0a8380, 0xff004c, 0x085006, 0x221100,
- 0x06c800, 0xff0059, 0x0a83a0, 0xff0058,
- 0x0a8383, 0xff0052, 0x00008c, 0x050c03,
- 0x085846, 0x000000, 0x0000b9, 0x0ae180,
- 0x0afa01, 0xff005f, 0x050c00, 0x66f41b,
- 0xff0090, 0x0503a6, 0x04cfdd, 0x013f03,
- 0x013e23, 0x045517, 0x060980, 0xff008b,
- 0x07de85, 0x07de84, 0x07de86, 0x300013,
- 0x70f400, 0x001600, 0x06d820, 0x4258a2,
- 0x320013, 0x72f400, 0x000c00, 0x06da20,
- 0x075a86, 0x300013, 0x06d800, 0xff007d,
- 0x54e000, 0x200063, 0x200018, 0x5cd800,
- 0x200043, 0x200018, 0x320013, 0x06da00,
- 0xff0083, 0x07da8c, 0x200053, 0x200018,
- 0x022d07, 0x08d73c, 0x0d104a, 0x000005,
- 0x013d03, 0x00008c, 0x050c02, 0x017d03,
- 0x000200, 0x000086
- };
+ public:
+ enum class State
+ {
+ Length,
+ Address,
+ Data,
+ Finished
+ };
- static constexpr uint32_t g_dspBootCode56303[] =
- {
- 0x240a13, 0x0afa02, 0xff0028, 0x0afa01,
- 0xff0009, 0x0afa00, 0xff0011, 0x0af080,
- 0xff0014, 0x0afa20, 0xff000e, 0x08f484,
- 0x005018, 0x050c09, 0x08f484, 0x000218,
- 0x050c06, 0x08f484, 0x001c1e, 0x050c03,
- 0x08f484, 0x000038, 0x0a8426, 0x0a8380,
- 0xff0017, 0x084806, 0x0a8380, 0xff001a,
- 0x085006, 0x221100, 0x06c800, 0xff0026,
- 0x0a83a0, 0xff0026, 0x0a8383, 0xff0020,
- 0x00008c, 0x050c02, 0x085846, 0x050c52,
- 0x0afa01, 0xff0048, 0x07f41c, 0x000302,
- 0x07f41b, 0x00c000, 0x07f41f, 0x000007,
- 0x060680, 0xff0038, 0x019382, 0xff0032,
- 0x044a98, 0x019381, 0xff0035, 0x04ca95,
- 0x0c1c10, 0x219000, 0x219100, 0x06c800,
- 0xff0046, 0x060380, 0xff0045, 0x019382,
- 0xff003f, 0x044a98, 0x019381, 0xff0042,
- 0x04ca95, 0x0c1c10, 0x07588c, 0x050c12,
- 0x62f400, 0xd00000, 0x08f4b8, 0xd00409,
- 0x060680, 0xff004f, 0x07da8a, 0x0c1c10,
- 0x219000, 0x219100, 0x06c800, 0xff0058,
- 0x060380, 0xff0057, 0x07da8a, 0x0c1c10,
- 0x060380, 0xff0057, 0x07da8a, 0x0c1c10,
- 0x07588c, 0x0000b9, 0x0ae180
+ explicit DspBoot(dsp56k::DSP& _dsp);
+
+ bool hdiWriteTX(const dsp56k::TWord& _val);
+
+ bool finished() const { return m_state == State::Finished; }
+
+ private:
+ dsp56k::DSP& m_dsp;
+
+ State m_state = State::Length;
+
+ dsp56k::TWord m_remaining = 0;
+ dsp56k::TWord m_address = 0;
};
}
diff --git a/source/mqLib/mqdsp.cpp b/source/mqLib/mqdsp.cpp
@@ -8,8 +8,6 @@
#include "mc68k/hdi08.h"
-#include "hardwareLib/dspBootCode.h"
-
#include "dsp56kEmu/aar.h"
namespace mqLib
@@ -24,6 +22,7 @@ namespace mqLib
, m_periphX(nullptr)
, m_memory(g_memoryValidator, g_pMemSize, g_xyMemSize, g_bridgedAddr, m_memoryBuffer)
, m_dsp(m_memory, &m_periphX, &m_periphNop)
+ , m_boot(m_dsp)
{
if(!_hardware.isValid())
return;
@@ -54,25 +53,6 @@ namespace mqLib
m_dsp.getJit().notifyProgramMemWrite(i);
}
- // rewrite bootloader to work at address g_bootCodeBase instead of $ff0000
- for(uint32_t i=0; i<std::size(hwLib::g_dspBootCode56362); ++i)
- {
- uint32_t code = hwLib::g_dspBootCode56362[i];
- if((hwLib::g_dspBootCode56362[i] & 0xffff00) == 0xff0000)
- {
- code = g_bootCodeBase | (hwLib::g_dspBootCode56362[i] & 0xff);
- }
-
- m_memory.set(dsp56k::MemArea_P, i + g_bootCodeBase, code);
- m_dsp.getJit().notifyProgramMemWrite(i + g_bootCodeBase);
- }
-
-// m_memory.saveAssembly("dspBootDisasm.asm", g_bootCodeBase, static_cast<uint32_t>(std::size(g_dspBootCode)), true, true, &m_periphX, nullptr);
-
- // set OMR pins so that bootcode wants program data via HDI08 RX
- m_dsp.setPC(g_bootCodeBase);
- m_dsp.regs().omr.var |= OMR_MA | OMR_MB | OMR_MC | OMR_MD;
-
getPeriph().disableTimers(true); // only used to test DSP load, we report 0 all the time for now
m_periphX.getEsai().writeEmptyAudioIn(8);
@@ -86,7 +66,8 @@ namespace mqLib
});
m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
{
- hdiTransferUCtoDSP(_word);
+ if(m_boot.hdiWriteTX(_word))
+ onDspBootFinished();
});
m_hdiUC.setWriteIrqCallback([&](const uint8_t _irq)
{
@@ -96,14 +77,6 @@ namespace mqLib
{
return hdiUcReadIsr(_isr);
});
-
-#if DSP56300_DEBUGGER
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
-#else
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
-#endif
-
- m_thread->setLogToStdout(false);
}
void MqDsp::exec()
@@ -139,6 +112,22 @@ namespace mqLib
}
}
+ void MqDsp::onDspBootFinished()
+ {
+ m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
+ {
+ hdiTransferUCtoDSP(_word);
+ });
+
+#if DSP56300_DEBUGGER
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
+#else
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
+#endif
+
+ m_thread->setLogToStdout(false);
+ }
+
void MqDsp::onUCRxEmpty(bool _needMoreData)
{
hdi08().injectTXInterrupt();
diff --git a/source/mqLib/mqdsp.h b/source/mqLib/mqdsp.h
@@ -4,6 +4,8 @@
#include "dsp56kEmu/dspthread.h"
#include "dsp56kEmu/peripherals.h"
+#include "hardwareLib/dspBootCode.h"
+
#include "wLib/wDsp.h"
namespace mc68k
@@ -21,7 +23,6 @@ namespace mqLib
static constexpr dsp56k::TWord g_bridgedAddr = 0x080000; // start of external SRAM, mapped to X and Y
static constexpr dsp56k::TWord g_xyMemSize = 0x800000; // due to weird AAR mapping we just allocate enough so that everything fits into it
static constexpr dsp56k::TWord g_pMemSize = 0x2000; // only $0000 < $1400 for DSP, rest for us
- static constexpr dsp56k::TWord g_bootCodeBase = 0x1500;
MqDsp(Hardware& _hardware, mc68k::Hdi08& _hdiUC, uint32_t _index);
void exec();
@@ -52,6 +53,7 @@ namespace mqLib
bool haveSentTXToDSP() const { return m_haveSentTXtoDSP; }
bool receivedMagicEsaiPacket() const { return m_receivedMagicEsaiPacket; }
+ void onDspBootFinished();
private:
void onUCRxEmpty(bool _needMoreData);
@@ -76,5 +78,7 @@ namespace mqLib
std::unique_ptr<dsp56k::DSPThread> m_thread;
bool m_receivedMagicEsaiPacket = false;
+
+ hwLib::DspBoot m_boot;
};
}
diff --git a/source/nord/n2x/n2xLib/n2xdsp.cpp b/source/nord/n2x/n2xLib/n2xdsp.cpp
@@ -3,8 +3,9 @@
#include "n2xhardware.h"
#include "dsp56kDebugger/debugger.h"
+
#include "dsp56kEmu/dspthread.h"
-#include "hardwareLib/dspBootCode.h"
+
#include "mc68k/hdi08.h"
namespace n2x
@@ -12,7 +13,6 @@ namespace n2x
static constexpr dsp56k::TWord g_xyMemSize = 0x010000;
static constexpr dsp56k::TWord g_externalMemAddr = 0x008000;
static constexpr dsp56k::TWord g_pMemSize = 0x004000;
- static constexpr dsp56k::TWord g_bootCodeBase = 0x003f00;
namespace
{
@@ -26,6 +26,7 @@ namespace n2x
, m_memory(g_memValidator, g_pMemSize, g_xyMemSize, g_externalMemAddr)
, m_dsp(m_memory, &m_periphX, &m_periphNop)
, m_haltDSP(m_dsp)
+ , m_boot(m_dsp)
{
if(!_hw.isValid())
return;
@@ -80,23 +81,6 @@ namespace n2x
m_dsp.getJit().notifyProgramMemWrite(i);
}
- // rewrite bootloader to work at address g_bootCodeBase instead of $ff0000
- for(uint32_t i=0; i<std::size(hwLib::g_dspBootCode56362); ++i)
- {
- uint32_t code = hwLib::g_dspBootCode56362[i];
- if((hwLib::g_dspBootCode56362[i] & 0xffff00) == 0xff0000)
- {
- code = g_bootCodeBase | (hwLib::g_dspBootCode56362[i] & 0xff);
- }
-
- m_memory.set(dsp56k::MemArea_P, i + g_bootCodeBase, code);
- m_dsp.getJit().notifyProgramMemWrite(i + g_bootCodeBase);
- }
-
- // set OMR pins so that bootcode wants program data via HDI08 RX
- m_dsp.setPC(g_bootCodeBase);
- m_dsp.regs().omr.var |= OMR_MA | OMR_MB | OMR_MC | OMR_MD;
-
hdi08().setRXRateLimit(0);
m_periphX.getEsai().writeEmptyAudioIn(2);
@@ -105,9 +89,11 @@ namespace n2x
{
onUCRxEmpty(_needMoreData);
});
- m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
+
+ m_hdiUC.setWriteTxCallback([this](const uint32_t _word)
{
- hdiTransferUCtoDSP(_word);
+ if(m_boot.hdiWriteTX(_word))
+ onDspBootFinished();
});
m_hdiUC.setWriteIrqCallback([&](const uint8_t _irq)
{
@@ -124,15 +110,6 @@ namespace n2x
m_hdiUC.isr(m_hdiUC.isr() | mc68k::Hdi08::IsrBits::Txde | mc68k::Hdi08::IsrBits::Trdy);
});
-#if DSP56300_DEBUGGER
- if(!m_index)
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
- else
-#endif
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
-
- m_thread->setLogToStdout(false);
-
m_irqInterruptDone = dsp().registerInterruptFunc([this]
{
m_triggerInterruptDone.notify();
@@ -152,6 +129,23 @@ namespace n2x
m_thread->join();
}
+ void DSP::onDspBootFinished()
+ {
+ m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
+ {
+ hdiTransferUCtoDSP(_word);
+ });
+
+#if DSP56300_DEBUGGER
+ if(!m_index)
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
+ else
+#endif
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
+
+ m_thread->setLogToStdout(false);
+ }
+
void DSP::onUCRxEmpty(const bool _needMoreData)
{
if(_needMoreData)
diff --git a/source/nord/n2x/n2xLib/n2xdsp.h b/source/nord/n2x/n2xLib/n2xdsp.h
@@ -7,6 +7,8 @@
#include "dsp56kEmu/dspthread.h"
#include "baseLib/semaphore.h"
+
+#include "hardwareLib/dspBootCode.h"
#include "hardwareLib/haltDSP.h"
namespace mc68k
@@ -43,6 +45,7 @@ namespace n2x
void terminate();
void join() const;
+ void onDspBootFinished();
private:
void onUCRxEmpty(bool _needMoreData);
@@ -68,5 +71,7 @@ namespace n2x
uint32_t m_irqInterruptDone = 0;
hwLib::HaltDSP m_haltDSP;
+
+ hwLib::DspBoot m_boot;
};
}
diff --git a/source/xtLib/xtDSP.cpp b/source/xtLib/xtDSP.cpp
@@ -1,6 +1,5 @@
#include "xtDSP.h"
-#include "hardwareLib/dspBootCode.h"
#include "xtHardware.h"
#if DSP56300_DEBUGGER
@@ -8,6 +7,7 @@
#endif
#include "mc68k/hdi08.h"
+
#include "dsp56kEmu/aar.h"
#include "dsp56kEmu/types.h"
@@ -22,6 +22,7 @@ namespace xt
, m_periphX()
, m_memory(g_memoryValidator, g_pMemSize, g_xyMemSize, g_bridgedAddr, m_memoryBuffer)
, m_dsp(m_memory, &m_periphX, &m_periphNop)
+ , m_boot(m_dsp)
{
if(!_hardware.isValid())
return;
@@ -51,28 +52,7 @@ namespace xt
m_dsp.getJit().notifyProgramMemWrite(i);
}
- const auto& bootCode = hwLib::g_dspBootCode56303;
-
- // rewrite bootloader to work at address g_bootCodeBase instead of $ff0000
- for(uint32_t i=0; i<std::size(bootCode); ++i)
- {
- uint32_t code = bootCode[i];
- if((code & 0xffff00) == 0xff0000)
- {
- code = g_bootCodeBase | (bootCode[i] & 0xff);
- }
-
- m_memory.set(dsp56k::MemArea_P, i + g_bootCodeBase, code);
- m_dsp.getJit().notifyProgramMemWrite(i + g_bootCodeBase);
- }
-
-// m_memory.saveAssembly("dspBootDisasm.asm", g_bootCodeBase, static_cast<uint32_t>(std::size(bootCode)), true, true, &m_periphX, nullptr);
-
- // set OMR pins so that bootcode wants program data via HDI08 RX
- m_dsp.setPC(g_bootCodeBase);
- m_dsp.regs().omr.var |= OMR_MA | OMR_MB | OMR_MC | OMR_MD;
-
-// getPeriph().disableTimers(true); // only used to test DSP load, we report 0 all the time for now
+// getPeriph().disableTimers(true);
m_periphX.getEssi0().writeEmptyAudioIn(8);
@@ -85,7 +65,8 @@ namespace xt
});
m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
{
- hdiTransferUCtoDSP(_word);
+ if(m_boot.hdiWriteTX(_word))
+ onDspBooted();
});
m_hdiUC.setWriteIrqCallback([&](const uint8_t _irq)
{
@@ -95,14 +76,6 @@ namespace xt
{
return hdiUcReadIsr(_isr);
});
-
-#if DSP56300_DEBUGGER
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
-#else
- m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
-#endif
-
- m_thread->setLogToStdout(false);
}
void DSP::exec()
@@ -138,6 +111,22 @@ namespace xt
}
}
+ void DSP::onDspBooted()
+ {
+ m_hdiUC.setWriteTxCallback([&](const uint32_t _word)
+ {
+ hdiTransferUCtoDSP(_word);
+ });
+
+#if DSP56300_DEBUGGER
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str(), std::make_shared<dsp56kDebugger::Debugger>(m_dsp)));
+#else
+ m_thread.reset(new dsp56k::DSPThread(dsp(), m_name.c_str()));
+#endif
+
+ m_thread->setLogToStdout(false);
+ }
+
void DSP::onUCRxEmpty(bool _needMoreData)
{
hdi08().injectTXInterrupt();
diff --git a/source/xtLib/xtDSP.h b/source/xtLib/xtDSP.h
@@ -4,6 +4,8 @@
#include "dsp56kEmu/dspthread.h"
#include "dsp56kEmu/peripherals.h"
+#include "hardwareLib/dspBootCode.h"
+
#include "wLib/wDsp.h"
namespace mc68k
@@ -21,7 +23,6 @@ namespace xt
static constexpr dsp56k::TWord g_bridgedAddr = 0x020000; // start of external SRAM, mapped to X and Y
static constexpr dsp56k::TWord g_xyMemSize = 0x800000; // due to weird AAR mapping we just allocate enough so that everything fits into it
static constexpr dsp56k::TWord g_pMemSize = 0x020000; // DSP code does not use all of it, gives space for our boot code
- static constexpr dsp56k::TWord g_bootCodeBase = 0x010000;
DSP(Hardware& _hardware, mc68k::Hdi08& _hdiUC, uint32_t _index);
void exec();
@@ -50,6 +51,7 @@ namespace xt
dsp56k::DSPThread& thread() { return *m_thread; }
bool haveSentTXToDSP() const { return m_haveSentTXtoDSP; }
+ void onDspBooted();
private:
void onUCRxEmpty(bool _needMoreData);
@@ -72,5 +74,6 @@ namespace xt
uint32_t m_hdiHF01 = 0; // uc => DSP
std::unique_ptr<dsp56k::DSPThread> m_thread;
+ hwLib::DspBoot m_boot;
};
}