mirror of
https://github.com/holub/mame
synced 2025-10-05 08:41:31 +03:00
HP9825: added 9825T variant (#4629)
* hphybrid: added cbs to expose memory cycles & fetched opcodes * hp9825: 9825T variant added
This commit is contained in:
parent
7da2a8feaf
commit
a3bf00db9e
@ -175,6 +175,8 @@ uint8_t hp_hybrid_cpu_device::pa_r() const
|
||||
hp_hybrid_cpu_device::hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth)
|
||||
: cpu_device(mconfig, type, tag, owner, clock)
|
||||
, m_pa_changed_func(*this)
|
||||
, m_opcode_func(*this)
|
||||
, m_stm_func(*this)
|
||||
, m_addr_mask((1U << addrwidth) - 1)
|
||||
, m_relative_mode(true)
|
||||
, m_r_cycles(DEF_MEM_R_CYCLES)
|
||||
@ -241,6 +243,11 @@ void hp_hybrid_cpu_device::device_start()
|
||||
set_icountptr(m_icount);
|
||||
|
||||
m_pa_changed_func.resolve_safe();
|
||||
m_opcode_func.resolve();
|
||||
m_stm_func.resolve();
|
||||
// Cache active state of m_stm_func & m_opcode_func
|
||||
m_opcode_func_defd = bool(m_opcode_func);
|
||||
m_stm_func_defd = bool(m_stm_func);
|
||||
}
|
||||
|
||||
void hp_hybrid_cpu_device::device_reset()
|
||||
@ -260,6 +267,7 @@ void hp_hybrid_cpu_device::device_reset()
|
||||
m_dmapa = 0;
|
||||
m_dmama = 0;
|
||||
m_dmac = 0;
|
||||
m_curr_cycle = 0;
|
||||
m_forced_bsc_25 = m_boot_mode;
|
||||
|
||||
m_last_pa = ~0;
|
||||
@ -312,7 +320,7 @@ uint16_t hp_hybrid_cpu_device::execute_one(uint16_t opcode)
|
||||
}
|
||||
// Indirect addressing in EXE instruction seems to use AEC case A instead of case C
|
||||
// (because it's an opcode fetch)
|
||||
return RM(add_mae(AEC_CASE_A , fetch_addr));
|
||||
return fetch_at(add_mae(AEC_CASE_A , fetch_addr));
|
||||
} else {
|
||||
uint16_t next_P;
|
||||
if (!execute_one_bpc(opcode , next_P) &&
|
||||
@ -952,6 +960,11 @@ uint16_t hp_hybrid_cpu_device::RM(uint32_t addr)
|
||||
// Any access to internal registers removes forcing of BSC 2x
|
||||
m_forced_bsc_25 = false;
|
||||
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_RAL_MASK | CYCLE_RD_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
|
||||
// Memory mapped BPC registers
|
||||
uint16_t tmp;
|
||||
switch (addr_wo_bsc) {
|
||||
@ -1016,6 +1029,10 @@ uint16_t hp_hybrid_cpu_device::RM(uint32_t addr)
|
||||
return tmp;
|
||||
} else {
|
||||
m_icount -= m_r_cycles;
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_RD_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
return m_cache->read_word(addr);
|
||||
}
|
||||
}
|
||||
@ -1065,6 +1082,11 @@ void hp_hybrid_cpu_device::WM(uint32_t addr , uint16_t v)
|
||||
// Any access to internal registers removes forcing of BSC 2x
|
||||
m_forced_bsc_25 = false;
|
||||
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_RAL_MASK | CYCLE_WR_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
|
||||
// Memory mapped BPC registers
|
||||
switch (addr_wo_bsc) {
|
||||
case HP_REG_A_ADDR:
|
||||
@ -1130,6 +1152,10 @@ void hp_hybrid_cpu_device::WM(uint32_t addr , uint16_t v)
|
||||
m_icount -= REGISTER_RW_CYCLES;
|
||||
} else {
|
||||
m_icount -= m_w_cycles;
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
m_program->write_word(addr , v);
|
||||
}
|
||||
}
|
||||
@ -1168,7 +1194,17 @@ bool hp_hybrid_cpu_device::write_emc_reg(uint16_t addr , uint16_t v)
|
||||
uint16_t hp_hybrid_cpu_device::fetch()
|
||||
{
|
||||
m_genpc = add_mae(AEC_CASE_A , m_reg_P);
|
||||
return RM(m_genpc);
|
||||
return fetch_at(m_genpc);
|
||||
}
|
||||
|
||||
uint16_t hp_hybrid_cpu_device::fetch_at(uint32_t addr)
|
||||
{
|
||||
m_curr_cycle |= CYCLE_IFETCH_MASK;
|
||||
uint16_t opcode = RM(addr);
|
||||
if (m_opcode_func_defd) {
|
||||
m_opcode_func(opcode);
|
||||
}
|
||||
return opcode;
|
||||
}
|
||||
|
||||
uint16_t hp_hybrid_cpu_device::get_indirect_target(uint32_t addr)
|
||||
@ -1586,6 +1622,10 @@ bool hp_5061_3011_cpu_device::execute_no_bpc(uint16_t opcode , uint16_t& next_pc
|
||||
// 16 bits units.
|
||||
WM(tmp_addr >> 1 , tmp);
|
||||
} else {
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
// Extend address, form byte address
|
||||
uint16_t mask = BIT(tmp_addr , 0) ? 0x00ff : 0xff00;
|
||||
tmp_addr = add_mae(AEC_CASE_C , tmp_addr >> 1);
|
||||
@ -1674,6 +1714,7 @@ void hp_5061_3011_cpu_device::handle_dma()
|
||||
bool tc = BIT(--m_dmac , 15) != 0;
|
||||
uint16_t tmp;
|
||||
|
||||
m_curr_cycle |= CYCLE_DMA_MASK;
|
||||
// Timing here assumes that DMA transfers are isolated and not done in bursts
|
||||
if (BIT(m_flags , HPHYBRID_DMADIR_BIT)) {
|
||||
// "Outward" DMA: memory -> peripheral
|
||||
@ -1955,6 +1996,10 @@ bool hp_09825_67907_cpu_device::execute_no_bpc(uint16_t opcode , uint16_t& next_
|
||||
// 16 bits units.
|
||||
WM(tmp_addr , tmp);
|
||||
} else {
|
||||
if (m_stm_func_defd) {
|
||||
m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
|
||||
m_curr_cycle = 0;
|
||||
}
|
||||
uint16_t mask = BIT(*ptr_reg , 15) ? 0xff00 : 0x00ff;
|
||||
m_program->write_word(tmp_addr , tmp , mask);
|
||||
m_icount -= m_w_cycles;
|
||||
@ -2037,6 +2082,7 @@ void hp_09825_67907_cpu_device::handle_dma()
|
||||
uint16_t tmp;
|
||||
|
||||
// Timing here assumes that DMA transfers are isolated and not done in bursts
|
||||
m_curr_cycle |= CYCLE_DMA_MASK;
|
||||
if (BIT(m_dmama , 15)) {
|
||||
// "Outward" DMA: memory -> peripheral
|
||||
tmp = RM(AEC_CASE_D , m_dmama);
|
||||
|
@ -64,6 +64,29 @@ public:
|
||||
void set_relative_mode(bool rela) { m_relative_mode = rela; }
|
||||
void set_rw_cycles(unsigned read_cycles , unsigned write_cycles) { m_r_cycles = read_cycles; m_w_cycles = write_cycles; }
|
||||
|
||||
// Possible combinations:
|
||||
// 00 No r/w cycle in progress
|
||||
// 01 Non-ifetch rd cycle
|
||||
// 05 Ifetch rd cycle
|
||||
// 09 DMA rd cycle
|
||||
// 02 Wr cycle
|
||||
// 0a DMA wr cycle
|
||||
//
|
||||
// CYCLE_RAL_MASK is set when access is into register space [0..1f]
|
||||
enum : uint8_t {
|
||||
CYCLE_RD_MASK = 0x01,
|
||||
CYCLE_WR_MASK = 0x02,
|
||||
CYCLE_IFETCH_MASK = 0x04,
|
||||
CYCLE_DMA_MASK = 0x08,
|
||||
CYCLE_RAL_MASK = 0x10
|
||||
};
|
||||
|
||||
// Called at start of each memory access
|
||||
auto stm_cb() { return m_stm_func.bind(); }
|
||||
|
||||
// Tap into fetched opcodes
|
||||
auto opcode_cb() { return m_opcode_func.bind(); }
|
||||
|
||||
protected:
|
||||
hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth);
|
||||
|
||||
@ -123,6 +146,7 @@ protected:
|
||||
void WIO(uint8_t pa , uint8_t ic , uint16_t v);
|
||||
|
||||
uint16_t fetch();
|
||||
uint16_t fetch_at(uint32_t addr);
|
||||
virtual uint16_t get_indirect_target(uint32_t addr);
|
||||
virtual void enter_isr();
|
||||
virtual void handle_dma() = 0;
|
||||
@ -133,6 +157,10 @@ protected:
|
||||
|
||||
devcb_write8 m_pa_changed_func;
|
||||
uint8_t m_last_pa;
|
||||
bool m_opcode_func_defd;
|
||||
devcb_write16 m_opcode_func;
|
||||
bool m_stm_func_defd;
|
||||
devcb_write8 m_stm_func;
|
||||
|
||||
int m_icount;
|
||||
uint32_t m_addr_mask;
|
||||
@ -159,6 +187,8 @@ protected:
|
||||
uint16_t m_dmac; // DMA counter
|
||||
uint16_t m_reg_I; // Instruction register
|
||||
uint32_t m_genpc; // Full PC
|
||||
uint8_t m_curr_cycle; // Current cycle type
|
||||
|
||||
// EMC registers
|
||||
uint16_t m_reg_ar2[ 4 ]; // AR2 register
|
||||
uint16_t m_reg_se; // SE register (4 bits)
|
||||
|
@ -8,8 +8,8 @@
|
||||
// **** Temporary header, will hopefully evolve into proper doc ****
|
||||
//
|
||||
// What's in:
|
||||
// - Emulation of 9825B system
|
||||
// - 12 kw of RAMs
|
||||
// - Emulation of 9825B and 9825T systems
|
||||
// - 12 kw (9825B) or 31kw (9825T) of RAM
|
||||
// - 12 kw of system ROM
|
||||
// - Keyboard (SHIFT LOCK & RESET not implemented)
|
||||
// - Display & run light
|
||||
@ -18,6 +18,8 @@
|
||||
// - Beeper
|
||||
// - Internal expansion ROMs
|
||||
// - I/O expansion slots: 98032, 98034 & 98035 modules can be connected
|
||||
// - For 9825T: the so-called SKOAL mechanism that transparently overlays RAM & ROM
|
||||
// in the same address space
|
||||
// What's not yet in:
|
||||
// - External expansion ROMs
|
||||
// - Configurable RAM size
|
||||
@ -27,8 +29,11 @@
|
||||
// by re-assembling the source code (this is the reason why it's marked as
|
||||
// a BAD_DUMP). And thanks to Ansgar Kueckes for adapting his assembler to
|
||||
// handle HP9825 source files.
|
||||
// For what regards the 9825T, I'd like to thank again Dyke Shaffer for
|
||||
// publishing a lot of internal HP docs about the SKOAL card. I recovered the
|
||||
// content of SKOAL ROM from its printed & scanned dump.
|
||||
//
|
||||
// 9825A & 9825T can also be emulated. At the moment I haven't all the necessary
|
||||
// 9825A can also be emulated. At the moment I haven't all the necessary
|
||||
// ROM dumps, though.
|
||||
|
||||
#include "emu.h"
|
||||
@ -42,6 +47,10 @@
|
||||
#include "sound/beep.h"
|
||||
#include "hp9825.lh"
|
||||
|
||||
// Debugging
|
||||
#define VERBOSE 0
|
||||
#include "logmacro.h"
|
||||
|
||||
// CPU clock (generated by a trimmered RC oscillator)
|
||||
constexpr unsigned MAIN_CLOCK = 6000000;
|
||||
|
||||
@ -81,6 +90,9 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
// +--------------+
|
||||
// | hp9825_state |
|
||||
// +--------------+
|
||||
class hp9825_state : public driver_device
|
||||
{
|
||||
public:
|
||||
@ -103,15 +115,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
void hp9825b(machine_config &config);
|
||||
void hp9825_base(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void device_reset() override;
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
required_device<hp_09825_67907_cpu_device> m_cpu;
|
||||
|
||||
private:
|
||||
required_device<hp98x5_io_sys_device> m_io_sys;
|
||||
required_device<timer_device> m_cursor_timer;
|
||||
required_device<hp9825_tape_device> m_tape;
|
||||
@ -144,7 +157,6 @@ private:
|
||||
int m_slot_sc[ 3 ];
|
||||
|
||||
void cpu_io_map(address_map &map);
|
||||
void cpu_mem_map(address_map &map);
|
||||
|
||||
DECLARE_READ16_MEMBER(kb_scancode_r);
|
||||
DECLARE_WRITE16_MEMBER(disp_w);
|
||||
@ -228,16 +240,6 @@ void hp9825_state::cpu_io_map(address_map &map)
|
||||
// TODO:
|
||||
}
|
||||
|
||||
void hp9825_state::cpu_mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
// map(0x0000 , 0x2fff).rom();
|
||||
// map(0x3400 , 0x3bff).rom();
|
||||
map(0x0000 , 0x3bff).rom();
|
||||
map(0x4000 , 0x4fff).rom();
|
||||
map(0x5000 , 0x7fff).ram();
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp9825_state::kb_scancode_r)
|
||||
{
|
||||
uint8_t res = m_scancode;
|
||||
@ -620,12 +622,11 @@ void hp9825_state::set_dmar_slot(unsigned slot , int state)
|
||||
m_io_sys->set_dmar(uint8_t(sc) , state);
|
||||
}
|
||||
|
||||
MACHINE_CONFIG_START(hp9825_state::hp9825b)
|
||||
MACHINE_CONFIG_START(hp9825_state::hp9825_base)
|
||||
HP_09825_67907(config , m_cpu , MAIN_CLOCK);
|
||||
// Just guessing... settings borrowed from hp9845
|
||||
m_cpu->set_rw_cycles(6 , 6);
|
||||
m_cpu->set_relative_mode(false);
|
||||
m_cpu->set_addrmap(AS_PROGRAM , &hp9825_state::cpu_mem_map);
|
||||
m_cpu->set_addrmap(AS_IO , &hp9825_state::cpu_io_map);
|
||||
m_cpu->set_irq_acknowledge_callback("io_sys" , FUNC(hp98x5_io_sys_device::irq_callback));
|
||||
m_cpu->pa_changed_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::pa_w));
|
||||
@ -826,6 +827,251 @@ static INPUT_PORTS_START(hp9825)
|
||||
PORT_BIT(IOP_MASK(0) , IP_ACTIVE_HIGH , IPT_KEYBOARD) PORT_CODE(KEYCODE_LSHIFT) PORT_CHAR(UCHAR_SHIFT_1) // Shift
|
||||
INPUT_PORTS_END
|
||||
|
||||
// +---------------+
|
||||
// | hp9825b_state |
|
||||
// +---------------+
|
||||
class hp9825b_state : public hp9825_state
|
||||
{
|
||||
public:
|
||||
hp9825b_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: hp9825_state(mconfig , type , tag)
|
||||
{
|
||||
}
|
||||
|
||||
void hp9825b(machine_config &config);
|
||||
|
||||
private:
|
||||
void cpu_mem_map(address_map &map);
|
||||
};
|
||||
|
||||
MACHINE_CONFIG_START(hp9825b_state::hp9825b)
|
||||
hp9825_base(config);
|
||||
m_cpu->set_addrmap(AS_PROGRAM , &hp9825b_state::cpu_mem_map);
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
void hp9825b_state::cpu_mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(0x0000 , 0x3bff).rom();
|
||||
map(0x4000 , 0x4fff).rom();
|
||||
map(0x5000 , 0x7fff).ram();
|
||||
}
|
||||
|
||||
// +---------------+
|
||||
// | hp9825t_state |
|
||||
// +---------------+
|
||||
class hp9825t_state : public hp9825_state
|
||||
{
|
||||
public:
|
||||
hp9825t_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: hp9825_state(mconfig , type , tag)
|
||||
, m_rom_region(*this , "rom")
|
||||
, m_skoalrom(*this , "skoalrom")
|
||||
{
|
||||
}
|
||||
|
||||
void hp9825t(machine_config &config);
|
||||
|
||||
protected:
|
||||
virtual void machine_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
required_memory_region m_rom_region;
|
||||
required_memory_region m_skoalrom;
|
||||
std::unique_ptr<uint16_t[]> m_ram;
|
||||
|
||||
uint8_t m_cycle_type;
|
||||
|
||||
// SKOAL state
|
||||
bool m_skoalbit; // U53
|
||||
bool m_second_access; // U57-3
|
||||
bool m_mref; // U57-4
|
||||
bool m_ifetch_4400; // U57-5
|
||||
uint8_t m_special_opt; // U42
|
||||
uint16_t m_fetch_addr;
|
||||
|
||||
void cpu_mem_map(address_map &map);
|
||||
DECLARE_READ16_MEMBER(cpu_mem_r);
|
||||
DECLARE_WRITE16_MEMBER(cpu_mem_w);
|
||||
void stm(uint8_t cycle_type);
|
||||
void on_cycle_end();
|
||||
void opcode_fetch(uint16_t opcode);
|
||||
uint8_t get_skoalrom(uint16_t addr);
|
||||
bool is_rom(uint16_t addr , uint8_t cycle_type) const;
|
||||
};
|
||||
|
||||
MACHINE_CONFIG_START(hp9825t_state::hp9825t)
|
||||
hp9825_base(config);
|
||||
m_cpu->set_addrmap(AS_PROGRAM , &hp9825t_state::cpu_mem_map);
|
||||
m_cpu->stm_cb().set(FUNC(hp9825t_state::stm));
|
||||
m_cpu->opcode_cb().set(FUNC(hp9825t_state::opcode_fetch));
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
void hp9825t_state::machine_start()
|
||||
{
|
||||
hp9825_state::machine_start();
|
||||
|
||||
// 32kw of RAM (the 1st kw is not accessible in normal operation)
|
||||
m_ram = std::make_unique<uint16_t[]>(32768);
|
||||
save_pointer(NAME(m_ram) , 32768);
|
||||
}
|
||||
|
||||
void hp9825t_state::device_reset()
|
||||
{
|
||||
hp9825_state::device_reset();
|
||||
|
||||
// This has to be done before CPU reset or first instruction won't be fetched correctly
|
||||
m_cycle_type = 0;
|
||||
m_special_opt = 0xf;
|
||||
}
|
||||
|
||||
void hp9825t_state::cpu_mem_map(address_map &map)
|
||||
{
|
||||
map.unmap_value_low();
|
||||
map(0x0000 , 0x7fff).rw(FUNC(hp9825t_state::cpu_mem_r) , FUNC(hp9825t_state::cpu_mem_w));
|
||||
}
|
||||
|
||||
READ16_MEMBER(hp9825t_state::cpu_mem_r)
|
||||
{
|
||||
bool from_rom;
|
||||
|
||||
if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_RD_MASK) {
|
||||
if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) {
|
||||
m_fetch_addr = offset;
|
||||
}
|
||||
from_rom = is_rom(offset , m_cycle_type);
|
||||
LOG("rd @%04x CYC=%x %d%d%d%d ROM=%d\n" , offset , m_cycle_type , m_skoalbit , m_second_access , m_mref , m_ifetch_4400 , from_rom);
|
||||
if (!(m_cycle_type & (hp_hybrid_cpu_device::CYCLE_IFETCH_MASK | hp_hybrid_cpu_device::CYCLE_DMA_MASK))) {
|
||||
on_cycle_end();
|
||||
}
|
||||
m_cycle_type = 0;
|
||||
// TODO: diagnostic read
|
||||
} else {
|
||||
// Read coming from debugger and not from CPU: fake an ifetch
|
||||
from_rom = is_rom(offset , hp_hybrid_cpu_device::CYCLE_IFETCH_MASK);
|
||||
}
|
||||
|
||||
return from_rom ? m_rom_region->as_u16(offset) : m_ram[ offset ];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hp9825t_state::cpu_mem_w)
|
||||
{
|
||||
if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_WR_MASK) {
|
||||
if (!(m_cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK)) {
|
||||
on_cycle_end();
|
||||
}
|
||||
m_cycle_type = 0;
|
||||
}
|
||||
// All write cycles go to RAM
|
||||
m_ram[ offset ] = (m_ram[ offset ] & ~mem_mask) | (data & mem_mask);
|
||||
}
|
||||
|
||||
void hp9825t_state::stm(uint8_t cycle_type)
|
||||
{
|
||||
LOG("stm %x\n" , cycle_type);
|
||||
m_cycle_type = cycle_type;
|
||||
if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) {
|
||||
m_second_access = false;
|
||||
m_mref = false;
|
||||
m_ifetch_4400 = false;
|
||||
// In case of ifetch from register area this is kept at 0 (because cpu_mem_r is not called)
|
||||
// In case of ifetch from RAM/ROM this is set by cpu_mem_r to the fetch address
|
||||
m_fetch_addr = 0;
|
||||
} else if (m_cycle_type & hp_hybrid_cpu_device::CYCLE_RAL_MASK) {
|
||||
if (!(m_cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK)) {
|
||||
on_cycle_end();
|
||||
}
|
||||
m_cycle_type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void hp9825t_state::on_cycle_end()
|
||||
{
|
||||
m_second_access = false;
|
||||
}
|
||||
|
||||
void hp9825t_state::opcode_fetch(uint16_t opcode)
|
||||
{
|
||||
LOG("oc %04x\n" , opcode);
|
||||
m_cycle_type = 0;
|
||||
// memory referencing instructions
|
||||
m_mref = (opcode & 0x7000) != 0x7000;
|
||||
m_second_access = true;
|
||||
m_ifetch_4400 = (m_fetch_addr & 0x7f00) == 0x0900;
|
||||
if (BIT(m_special_opt , 3) && BIT(m_special_opt , 2)) {
|
||||
// Set SKOAL bit
|
||||
if (m_fetch_addr < 0x20) {
|
||||
// Fetch from registers -> SKOAL bit = 0
|
||||
m_skoalbit = false;
|
||||
} else if ((m_fetch_addr & 0x6000) == 0x6000) {
|
||||
// Fetch in [6000..7fff] range -> SKOAL bit = 0
|
||||
m_skoalbit = false;
|
||||
} else {
|
||||
uint8_t tmp = get_skoalrom(m_fetch_addr);
|
||||
m_skoalbit = (tmp >> ((~m_fetch_addr >> 12) & 7)) & 1;
|
||||
}
|
||||
}
|
||||
// Decode SKOAL instructions. They are ignored by the hybrid processor
|
||||
// as they are not recognized.
|
||||
if ((opcode & 0xffc0) == 0x7040) {
|
||||
m_special_opt = opcode & 0xf;
|
||||
if (!BIT(m_special_opt , 3)) {
|
||||
// RAM/ == 0
|
||||
m_skoalbit = false;
|
||||
} else if (!BIT(m_special_opt , 2)) {
|
||||
// ROM/ == 0
|
||||
m_skoalbit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t hp9825t_state::get_skoalrom(uint16_t addr)
|
||||
{
|
||||
return m_skoalrom->as_u8(~addr & 0x0fff);
|
||||
}
|
||||
|
||||
bool hp9825t_state::is_rom(uint16_t addr , uint8_t cycle_type) const
|
||||
{
|
||||
if ((addr & 0x6000) == 0x6000) {
|
||||
// [6000..7fff] -> always RAM
|
||||
return false;
|
||||
} else if ((cycle_type & hp_hybrid_cpu_device::CYCLE_DMA_MASK) != 0 ||
|
||||
!BIT(m_special_opt , 1)) {
|
||||
// DMA cycle or BIT/ == 0 -> RAM
|
||||
return false;
|
||||
} else if (addr >= 0x400 && !BIT(m_special_opt , 0)) {
|
||||
// [0400..5fff] and BIN/ == 0 -> RAM
|
||||
return false;
|
||||
} else {
|
||||
bool addr_0800_7fff = (addr & 0x7800) != 0;
|
||||
bool addr_0400_07ff = !addr_0800_7fff && BIT(addr , 10);
|
||||
bool addr_0000_03ff = !addr_0800_7fff && !BIT(addr , 10);
|
||||
|
||||
// U58-6
|
||||
bool force_rom;
|
||||
|
||||
// ROM when one or more of these is true:
|
||||
// - addr in [0000..03ff]
|
||||
// - Ifetch cycle and addr in [0800..5fff]
|
||||
// - 2nd access of a memory-referencing instruction not in [0400..07ff] range
|
||||
// - skoalbit = 1 and instruction fetched in [0900..09ff] range
|
||||
force_rom =
|
||||
addr_0000_03ff ||
|
||||
((cycle_type & hp_hybrid_cpu_device::CYCLE_IFETCH_MASK) != 0 && addr_0800_7fff) ||
|
||||
(m_second_access && m_mref && (!BIT(m_special_opt , 2) || !addr_0400_07ff)) ||
|
||||
(m_skoalbit && m_ifetch_4400);
|
||||
|
||||
if (force_rom) {
|
||||
return true;
|
||||
} else if (addr_0400_07ff && BIT(m_special_opt , 2)) {
|
||||
return false;
|
||||
} else {
|
||||
return m_skoalbit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ROM_START(hp9825b)
|
||||
ROM_REGION(0xa000 , "cpu" , ROMREGION_16BIT | ROMREGION_BE)
|
||||
ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0))
|
||||
@ -839,5 +1085,23 @@ ROM_START(hp9825b)
|
||||
ROM_LOAD("strings_t.bin",0x9800 , 0x0800 , CRC(b5ca5da5) SHA1(af13abb3c15836c566863c656e1659f7e6f96d04))
|
||||
ROM_END
|
||||
|
||||
ROM_START(hp9825t)
|
||||
ROM_REGION(0xc000 , "rom" , ROMREGION_16BIT | ROMREGION_BE | ROMREGION_ERASE | ROMREGION_ERASE00)
|
||||
ROM_LOAD("sysrom1.bin" , 0x0000 , 0x2000 , CRC(fe429268) SHA1(f2fe7c5abca92bd13f81b4385fc4fce0cafb0da0))
|
||||
ROM_LOAD("sysrom2.bin" , 0x2000 , 0x2000 , CRC(96093b5d) SHA1(c6ec4cafd019887df0fa849b3c7070bb74faee54))
|
||||
ROM_LOAD("sysrom3.bin" , 0x4000 , 0x2000 , CRC(f9470f67) SHA1(b80cb4a366d93bd7acc3508ce987bb11c5986b2a))
|
||||
ROM_LOAD("98217.bin" , 0x6000 , 0x0800 , BAD_DUMP CRC(ea1fcf63) SHA1(e535c82897210a1c67c1ca16f44f936d4c470463))
|
||||
ROM_LOAD("genio_t.bin" , 0x6800 , 0x0800 , CRC(ade1d1ed) SHA1(9af74a65b29ef1885f74164238ecf8d16ac995d6))
|
||||
ROM_LOAD("plot72.bin" , 0x7000 , 0x0800 , CRC(0a9cb8db) SHA1(d0d126fca108f2715e1e408cb31b09ba69385ac4))
|
||||
ROM_LOAD("advpgm_t.bin", 0x8000 , 0x0800 , CRC(965b5e5a) SHA1(ff44dd15f8fa4ca03dfd970ed8b200e8a071ec13))
|
||||
ROM_LOAD("extio_t.bin" , 0x8800 , 0x1000 , CRC(a708b978) SHA1(baf53c8a2b24d059f95252baf1452188eaf6e4be))
|
||||
ROM_LOAD("strings_t.bin",0x9800 , 0x0800 , CRC(b5ca5da5) SHA1(af13abb3c15836c566863c656e1659f7e6f96d04))
|
||||
ROM_LOAD("syspgm.bin" , 0xa000 , 0x0800 , CRC(8915588f) SHA1(037f497b5ecc3216fb6b8356767cc361fb0b2945))
|
||||
|
||||
ROM_REGION(0x1000 , "skoalrom" , 0)
|
||||
ROM_LOAD("skoalrom.bin" , 0 , 0x1000 , CRC(5e8124d5) SHA1(dedf7f8a10c62b444f04213956083089e97bf219))
|
||||
ROM_END
|
||||
|
||||
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS
|
||||
COMP(1980, hp9825b, 0, 0, hp9825b, hp9825, hp9825_state, empty_init, "Hewlett-Packard", "HP 9825B", 0)
|
||||
COMP(1980, hp9825b, 0, 0, hp9825b, hp9825, hp9825b_state,empty_init, "Hewlett-Packard", "HP 9825B", 0)
|
||||
COMP(1980, hp9825t, 0, 0, hp9825t, hp9825, hp9825t_state,empty_init, "Hewlett-Packard", "HP 9825T", 0)
|
||||
|
@ -15426,6 +15426,7 @@ hp95lx //
|
||||
|
||||
@source:hp9825.cpp
|
||||
hp9825b // HP 9825B
|
||||
hp9825t // HP 9825T
|
||||
|
||||
@source:hp9845.cpp
|
||||
hp9835a //
|
||||
|
Loading…
Reference in New Issue
Block a user