mirror of
https://github.com/holub/mame
synced 2025-10-07 09:25:34 +03:00
hp64k: Improved HP Hybrid CPU (still no DMA)
This commit is contained in:
parent
7717489f3e
commit
eecc50b48a
@ -1,5 +1,8 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:F. Ulivi
|
||||
//
|
||||
// TODO:
|
||||
// - DMA
|
||||
|
||||
#include "emu.h"
|
||||
#include "debugger.h"
|
||||
@ -46,8 +49,6 @@ enum {
|
||||
|
||||
#define HP_RESET_ADDR 0x0020
|
||||
|
||||
#define MAKE_IOADDR(pa , ic) (((pa) << HP_IOADDR_PA_SHIFT) | ((ic) << HP_IOADDR_IC_SHIFT))
|
||||
|
||||
const device_type HP_5061_3011 = &device_creator<hp_5061_3011_cpu_device>;
|
||||
|
||||
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)
|
||||
@ -127,7 +128,10 @@ void hp_hybrid_cpu_device::execute_run()
|
||||
{
|
||||
do {
|
||||
debugger_instruction_hook(this, m_reg_P);
|
||||
// TODO: check interrupts
|
||||
|
||||
// Check for interrupts
|
||||
check_for_interrupts();
|
||||
|
||||
// TODO: check dma
|
||||
m_reg_I = execute_one(m_reg_I);
|
||||
} while (m_icount > 0);
|
||||
@ -135,6 +139,13 @@ void hp_hybrid_cpu_device::execute_run()
|
||||
|
||||
void hp_hybrid_cpu_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
if (inputnum < HPHYBRID_INT_LVLS) {
|
||||
if (state) {
|
||||
BIT_SET(m_flags , HPHYBRID_IRH_BIT + inputnum);
|
||||
} else {
|
||||
BIT_CLR(m_flags , HPHYBRID_IRH_BIT + inputnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -706,6 +717,57 @@ void hp_hybrid_cpu_device::do_pw(UINT16 opcode)
|
||||
}
|
||||
}
|
||||
|
||||
void hp_hybrid_cpu_device::check_for_interrupts(void)
|
||||
{
|
||||
if (!BIT(m_flags , HPHYBRID_INTEN_BIT) || BIT(m_flags , HPHYBRID_IRH_SVC_BIT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int irqline;
|
||||
|
||||
if (BIT(m_flags , HPHYBRID_IRH_BIT)) {
|
||||
// Service high-level interrupt
|
||||
BIT_SET(m_flags , HPHYBRID_IRH_SVC_BIT);
|
||||
irqline = HPHYBRID_IRH;
|
||||
} else if (BIT(m_flags , HPHYBRID_IRL_BIT) && !BIT(m_flags , HPHYBRID_IRL_SVC_BIT)) {
|
||||
// Service low-level interrupt
|
||||
BIT_SET(m_flags , HPHYBRID_IRL_SVC_BIT);
|
||||
irqline = HPHYBRID_IRL;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get interrupt vector in low byte
|
||||
UINT8 vector = (UINT8)standard_irq_callback(irqline);
|
||||
UINT8 new_PA;
|
||||
|
||||
// Get highest numbered 1
|
||||
// Don't know what happens if vector is 0, here we assume bit 7 = 1
|
||||
if (vector == 0) {
|
||||
new_PA = 7;
|
||||
} else {
|
||||
for (new_PA = 7; new_PA && !BIT(vector , 7); new_PA--, vector <<= 1) {
|
||||
}
|
||||
}
|
||||
if (irqline == HPHYBRID_IRH) {
|
||||
BIT_SET(new_PA , 3);
|
||||
}
|
||||
|
||||
// Push PA stack
|
||||
memmove(&m_reg_PA[ 1 ] , &m_reg_PA[ 0 ] , HPHYBRID_INT_LVLS);
|
||||
|
||||
CURRENT_PA = new_PA;
|
||||
|
||||
// Is this correct? Patent @ pg 210 suggests that the whole interrupt recognition sequence
|
||||
// lasts for 32 cycles (6 are already accounted for in get_ea for one indirection)
|
||||
m_icount -= 26;
|
||||
|
||||
// Do a double-indirect JSM IV,I instruction
|
||||
WM(++m_reg_R , m_reg_P);
|
||||
m_reg_P = RM(get_ea(0xc008));
|
||||
m_reg_I = RM(m_reg_P);
|
||||
}
|
||||
|
||||
UINT16 hp_hybrid_cpu_device::RM(UINT16 addr)
|
||||
{
|
||||
UINT16 tmp;
|
||||
@ -732,7 +794,12 @@ UINT16 hp_hybrid_cpu_device::RM(UINT16 addr)
|
||||
return RIO(CURRENT_PA , addr - HP_REG_R4_ADDR);
|
||||
|
||||
case HP_REG_IV_ADDR:
|
||||
// Correct?
|
||||
if (!BIT(m_flags , HPHYBRID_IRH_SVC_BIT) && !BIT(m_flags , HPHYBRID_IRL_SVC_BIT)) {
|
||||
return m_reg_IV;
|
||||
} else {
|
||||
return m_reg_IV | CURRENT_PA;
|
||||
}
|
||||
|
||||
case HP_REG_PA_ADDR:
|
||||
return CURRENT_PA;
|
||||
@ -844,16 +911,15 @@ void hp_hybrid_cpu_device::WMB(UINT32 addr , UINT8 v)
|
||||
|
||||
UINT16 hp_hybrid_cpu_device::RIO(UINT8 pa , UINT8 ic)
|
||||
{
|
||||
return m_io->read_word(MAKE_IOADDR(pa, ic) << 1);
|
||||
return m_io->read_word(HP_MAKE_IOADDR(pa, ic) << 1);
|
||||
}
|
||||
|
||||
void hp_hybrid_cpu_device::WIO(UINT8 pa , UINT8 ic , UINT16 v)
|
||||
{
|
||||
m_io->write_word(MAKE_IOADDR(pa, ic) << 1 , v);
|
||||
m_io->write_word(HP_MAKE_IOADDR(pa, ic) << 1 , v);
|
||||
}
|
||||
|
||||
hp_5061_3011_cpu_device::hp_5061_3011_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: hp_hybrid_cpu_device(mconfig, HP_5061_3011, "HP_5061_3011", tag, owner, clock, "5061-3011")
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,11 @@
|
||||
// discrete implementation of the 1960s into a multi-chip module (hence the "hybrid" name).
|
||||
// This emulator currently supports the 5061-3011 version only.
|
||||
//
|
||||
// There is very little information around on this processor.
|
||||
// For this emulator I mainly relied on these sources:
|
||||
// - http://www.hp9845.net/ website
|
||||
// - HP manual "Assembly development ROM manual for the HP9845": this is the most precious
|
||||
// and "enabling" resource of all
|
||||
// - US Patent 4,180,854 describing the HP9845 system
|
||||
// - Some manual for the 2116 processor
|
||||
// - Study of disassembly of firmware of HP64000 system
|
||||
// - A lot of "educated" guessing
|
||||
|
||||
@ -40,6 +38,9 @@
|
||||
#define HP_IOADDR_PA_SHIFT 2
|
||||
#define HP_IOADDR_IC_SHIFT 0
|
||||
|
||||
// Compose an I/O address from PA & IC
|
||||
#define HP_MAKE_IOADDR(pa , ic) (((pa) << HP_IOADDR_PA_SHIFT) | ((ic) << HP_IOADDR_IC_SHIFT))
|
||||
|
||||
// Addresses of memory mapped registers
|
||||
#define HP_REG_A_ADDR 0x0000
|
||||
#define HP_REG_B_ADDR 0x0001
|
||||
@ -122,6 +123,7 @@ protected:
|
||||
UINT16 get_skip_addr(UINT16 opcode , bool condition) const;
|
||||
UINT16 get_skip_addr_sc(UINT16 opcode , UINT16& v , unsigned n);
|
||||
void do_pw(UINT16 opcode);
|
||||
void check_for_interrupts(void);
|
||||
|
||||
UINT16 RM(UINT16 addr);
|
||||
void WM(UINT16 addr , UINT16 v);
|
||||
|
Loading…
Reference in New Issue
Block a user