hp64k: DMA added to HP hybrid CPU (working?)

This commit is contained in:
fulivi 2015-06-17 15:55:04 +02:00
parent da5de0d3d9
commit bf377a6b8f
2 changed files with 49 additions and 7 deletions

View File

@ -42,6 +42,7 @@ enum {
#define HPHYBRID_IRL_BIT 9 // IRL requested
#define HPHYBRID_IRH_SVC_BIT 10 // IRH in service
#define HPHYBRID_IRL_SVC_BIT 11 // IRL in service
#define HPHYBRID_DMAR_BIT 12 // DMA request
#define HPHYBRID_IV_MASK 0xfff0 // IV mask
@ -51,6 +52,15 @@ enum {
const device_type HP_5061_3011 = &device_creator<hp_5061_3011_cpu_device>;
WRITE_LINE_MEMBER(hp_hybrid_cpu_device::dmar_w)
{
if (state) {
BIT_SET(m_flags , HPHYBRID_DMAR_BIT);
} else {
BIT_CLR(m_flags , HPHYBRID_DMAR_BIT);
}
}
hp_hybrid_cpu_device::hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname)
: cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__),
m_program_config("program", ENDIANNESS_BIG, 16, 16, -1),
@ -127,13 +137,16 @@ void hp_hybrid_cpu_device::device_reset()
void hp_hybrid_cpu_device::execute_run()
{
do {
if (BIT(m_flags , HPHYBRID_DMAEN_BIT) && BIT(m_flags , HPHYBRID_DMAR_BIT)) {
handle_dma();
} else {
debugger_instruction_hook(this, m_reg_P);
// Check for interrupts
check_for_interrupts();
// TODO: check dma
m_reg_I = execute_one(m_reg_I);
}
} while (m_icount > 0);
}
@ -768,6 +781,32 @@ void hp_hybrid_cpu_device::check_for_interrupts(void)
m_reg_I = RM(m_reg_P);
}
void hp_hybrid_cpu_device::handle_dma(void)
{
// Patent hints at the fact that terminal count is detected by bit 15 of dmac being 1 after decrementing
bool tc = BIT(--m_dmac , 15) != 0;
UINT16 tmp;
if (BIT(m_flags , HPHYBRID_DMADIR_BIT)) {
// "Outward" DMA: memory -> peripheral
tmp = RM(m_dmama++);
WIO(m_dmapa , tc ? 2 : 0 , tmp);
m_icount -= 10;
} else {
// "Inward" DMA: peripheral -> memory
tmp = RIO(m_dmapa , tc ? 2 : 0);
WM(m_dmama++ , tmp);
m_icount -= 9;
}
// This is the one of the biggest question marks: is the DMA automatically disabled on TC?
// Here we assume it is. After all it would make no difference because there is no way
// to read the DMA enable flag back, so each time the DMA is needed it has to be enabled again.
if (tc) {
BIT_CLR(m_flags , HPHYBRID_DMAEN_BIT);
}
}
UINT16 hp_hybrid_cpu_device::RM(UINT16 addr)
{
UINT16 tmp;

View File

@ -65,6 +65,8 @@
class hp_hybrid_cpu_device : public cpu_device
{
public:
DECLARE_WRITE_LINE_MEMBER(dmar_w);
protected:
hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname);
@ -124,6 +126,7 @@ private:
UINT16 get_skip_addr_sc(UINT16 opcode , UINT16& v , unsigned n);
void do_pw(UINT16 opcode);
void check_for_interrupts(void);
void handle_dma(void);
UINT16 RM(UINT16 addr);
void WM(UINT16 addr , UINT16 v);