summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2015-06-17 15:55:04 +0200
committer fulivi <fulivi@users.noreply.github.com>2015-06-17 15:55:04 +0200
commitbf377a6b8f55ca3b5b584c46b4635ee6a4ffe7bc (patch)
tree872af9291891bb8dfcfba9bda06394b5d932f6d6
parentda5de0d3d9bf14413f868315b88890b5cc256340 (diff)
hp64k: DMA added to HP hybrid CPU (working?)
-rw-r--r--src/emu/cpu/hphybrid/hphybrid.c53
-rw-r--r--src/emu/cpu/hphybrid/hphybrid.h3
2 files changed, 49 insertions, 7 deletions
diff --git a/src/emu/cpu/hphybrid/hphybrid.c b/src/emu/cpu/hphybrid/hphybrid.c
index 8a50c78368d..e5c0ccb98d9 100644
--- a/src/emu/cpu/hphybrid/hphybrid.c
+++ b/src/emu/cpu/hphybrid/hphybrid.c
@@ -32,8 +32,8 @@ enum {
// Bits in m_flags
#define HPHYBRID_C_BIT 0 // Carry/extend
#define HPHYBRID_O_BIT 1 // Overflow
-#define HPHYBRID_CB_BIT 2 // Cb
-#define HPHYBRID_DB_BIT 3 // Db
+#define HPHYBRID_CB_BIT 2 // Cb
+#define HPHYBRID_DB_BIT 3 // Db
#define HPHYBRID_INTEN_BIT 4 // Interrupt enable
#define HPHYBRID_DMAEN_BIT 5 // DMA enable
#define HPHYBRID_DMADIR_BIT 6 // DMA direction (1 = OUT)
@@ -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 {
- debugger_instruction_hook(this, m_reg_P);
+ 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();
+ // Check for interrupts
+ check_for_interrupts();
- // TODO: check dma
- m_reg_I = execute_one(m_reg_I);
+ 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;
diff --git a/src/emu/cpu/hphybrid/hphybrid.h b/src/emu/cpu/hphybrid/hphybrid.h
index 1d24a1cfd14..438c7528767 100644
--- a/src/emu/cpu/hphybrid/hphybrid.h
+++ b/src/emu/cpu/hphybrid/hphybrid.h
@@ -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);