mirror of
https://github.com/holub/mame
synced 2025-04-24 01:11:11 +03:00
M740 updates: [R. Belmont]
- Added JMP (zp) instruction - Working interrupts - Moved 6502 family V line to make room for up to 16 IRQs
This commit is contained in:
parent
fb25423e7a
commit
4bafebcd59
@ -1,5 +1,5 @@
|
||||
# m740 device
|
||||
brk_imp ora_idx kil_non bbs_acc nop_zpg ora_zpg asl_zpg bbs_bzr php_imp ora_imm asl_acc seb_acc nop_aba ora_aba asl_aba seb_biz
|
||||
brk740_imp ora_idx kil_non bbs_acc nop_zpg ora_zpg asl_zpg bbs_bzr php_imp ora_imm asl_acc seb_acc nop_aba ora_aba asl_aba seb_biz
|
||||
bpl_rel ora_idy clt_imp bbc_acc nop_zpx ora_zpx asl_zpx bbc_bzr clc_imp ora_aby nop_imp clb_acc nop_abx ora_abx asl_abx clb_biz
|
||||
jsr_adr and_idx jsr_spg bbs_acc bit_zpg and_zpg rol_zpg bbs_bzr plp_imp and_imm rol_acc seb_acc bit_aba and_aba rol_aba seb_biz
|
||||
bmi_rel and_idy set_imp bbc_acc nop_zpx and_zpx rol_zpx bbc_bzr sec_imp and_aby nop_imp clb_acc ldm_imz and_abx rol_abx clb_biz
|
||||
@ -10,7 +10,7 @@ bvs_rel adc_idy kil_non bbc_acc nop_zpx adc_zpx ror_zpx
|
||||
bra_rel sta_idx rrf_zpg bbs_acc sty_zpg sta_zpg stx_zpg bbs_bzr dey_imp nop_imm txa_imp seb_acc sty_aba sta_aba stx_aba seb_biz
|
||||
bcc_rel sta_idy kil_non bbc_acc sty_zpx sta_zpx stx_zpy bbc_bzr tya_imp sta_aby txs_imp clb_acc shy_abx sta_abx shx_aby clb_biz
|
||||
ldy_imm lda_idx ldx_imm bbs_acc ldy_zpg lda_zpg ldx_zpg bbs_bzr tay_imp lda_imm tax_imp seb_acc ldy_aba lda_aba ldx_aba seb_biz
|
||||
bcs_rel lda_idy kil_non bbc_acc ldy_zpx lda_zpx ldx_zpy bbc_bzr clv_imp lda_aby tsx_imp clb_acc ldy_abx lda_abx ldx_aby clb_biz
|
||||
bcs_rel lda_idy jmp_zpi bbc_acc ldy_zpx lda_zpx ldx_zpy bbc_bzr clv_imp lda_aby tsx_imp clb_acc ldy_abx lda_abx ldx_aby clb_biz
|
||||
cpy_imm cmp_idx nop_imm bbs_acc cpy_zpg cmp_zpg dec_zpg bbs_bzr iny_imp cmp_imm dex_imp seb_acc cpy_aba cmp_aba dec_aba seb_biz
|
||||
bne_rel cmp_idy kil_non bbc_acc nop_zpx cmp_zpx dec_zpx bbc_bzr cld_imp cmp_aby nop_imp clb_acc nop_abx cmp_abx dec_abx clb_biz
|
||||
cpx_imm sbc_idx nop_imm bbs_acc cpx_zpg sbc_zpg inc_zpg bbs_bzr inx_imp sbc_imm nop_imp seb_acc cpx_aba sbc_aba inc_aba seb_biz
|
||||
|
@ -49,7 +49,7 @@ public:
|
||||
IRQ_LINE = INPUT_LINE_IRQ0,
|
||||
APU_IRQ_LINE = INPUT_LINE_IRQ1,
|
||||
NMI_LINE = INPUT_LINE_NMI,
|
||||
V_LINE = 10
|
||||
V_LINE = INPUT_LINE_IRQ0 + 16
|
||||
};
|
||||
|
||||
m6502_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
@ -63,6 +63,8 @@ void m740_device::device_reset()
|
||||
inst_substate = 0;
|
||||
nmi_state = false;
|
||||
irq_state = false;
|
||||
m_irq_multiplex = 0;
|
||||
m_irq_vector = 0xfffc;
|
||||
apu_irq_state = false;
|
||||
irq_taken = false;
|
||||
v_state = false;
|
||||
@ -86,7 +88,70 @@ UINT8 m740_device::do_seb(UINT8 in, UINT8 bit)
|
||||
// doesn't affect the flags
|
||||
UINT8 m740_device::do_rrf(UINT8 in)
|
||||
{
|
||||
return ((in&0xf)<<4) | ((in&0xf0)>>4);
|
||||
return ((in&0xf)<<4) | ((in&0xf0)>>4);
|
||||
}
|
||||
|
||||
void m740_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
switch(inputnum)
|
||||
{
|
||||
case M740_INT0_LINE:
|
||||
case M740_INT1_LINE:
|
||||
case M740_INT2_LINE:
|
||||
case M740_INT3_LINE:
|
||||
case M740_INT4_LINE:
|
||||
case M740_INT5_LINE:
|
||||
case M740_INT6_LINE:
|
||||
case M740_INT7_LINE:
|
||||
case M740_INT8_LINE:
|
||||
case M740_INT9_LINE:
|
||||
case M740_INT10_LINE:
|
||||
case M740_INT11_LINE:
|
||||
case M740_INT12_LINE:
|
||||
case M740_INT13_LINE:
|
||||
case M740_INT14_LINE: // 37450 has 15 IRQ lines, no other known variant has that many
|
||||
set_irq_line(inputnum - M740_INT0_LINE, state);
|
||||
break;
|
||||
|
||||
case V_LINE:
|
||||
if(!v_state && state == ASSERT_LINE)
|
||||
{
|
||||
P |= F_V;
|
||||
}
|
||||
v_state = state == ASSERT_LINE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void m740_device::set_irq_line(int line, int state)
|
||||
{
|
||||
assert(line > 0);
|
||||
assert(line <= M740_MAX_INT_LINE);
|
||||
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
m_irq_multiplex |= (1<<line);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_irq_multiplex &= ~(1<<line);
|
||||
}
|
||||
|
||||
irq_state = (m_irq_multiplex != 0);
|
||||
|
||||
if (irq_state)
|
||||
{
|
||||
for (int i = 0; i < M740_MAX_INT_LINE; i++)
|
||||
{
|
||||
if (m_irq_multiplex & (1 << i))
|
||||
{
|
||||
m_irq_vector = 0xfffc - (UINT16)(2 * i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printf("M740 single IRQ state is %d (MPX %08x, vector %x)\n", irq_state, m_irq_multiplex, m_irq_vector);
|
||||
}
|
||||
|
||||
#include "cpu/m6502/m740.inc"
|
||||
|
@ -44,16 +44,38 @@
|
||||
|
||||
class m740_device : public m6502_device {
|
||||
public:
|
||||
m740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
m740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
enum
|
||||
{
|
||||
M740_INT0_LINE = INPUT_LINE_IRQ0, // (fffc)
|
||||
M740_INT1_LINE, // (fffa)
|
||||
M740_INT2_LINE, // (fff8)
|
||||
M740_INT3_LINE, // (fff6)
|
||||
M740_INT4_LINE, // (fff4)
|
||||
M740_INT5_LINE, // (fff2)
|
||||
M740_INT6_LINE, // (fff0)
|
||||
M740_INT7_LINE, // (ffee)
|
||||
M740_INT8_LINE, // (ffec)
|
||||
M740_INT9_LINE, // (ffea)
|
||||
M740_INT10_LINE, // (ffe8)
|
||||
M740_INT11_LINE, // (ffe6)
|
||||
M740_INT12_LINE, // (ffe4)
|
||||
M740_INT13_LINE, // (ffe2)
|
||||
M740_INT14_LINE, // (ffe0)
|
||||
M740_MAX_INT_LINE = M740_INT14_LINE,
|
||||
M740_SET_OVERFLOW = m6502_device::V_LINE,
|
||||
};
|
||||
|
||||
virtual void device_reset();
|
||||
m740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
m740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
static const disasm_entry disasm_entries[0x100];
|
||||
virtual void device_reset();
|
||||
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
virtual void do_exec_full();
|
||||
virtual void do_exec_partial();
|
||||
static const disasm_entry disasm_entries[0x100];
|
||||
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
virtual void do_exec_full();
|
||||
virtual void do_exec_partial();
|
||||
virtual void execute_set_input(int inputnum, int state);
|
||||
|
||||
protected:
|
||||
#define O(o) void o ## _full(); void o ## _partial()
|
||||
@ -63,6 +85,7 @@ protected:
|
||||
UINT8 do_rrf(UINT8 in);
|
||||
|
||||
// m740 opcodes
|
||||
O(brk740_imp);
|
||||
O(clt_imp);
|
||||
O(set_imp);
|
||||
O(ldm_imz);
|
||||
@ -74,14 +97,14 @@ protected:
|
||||
O(bbs_bzr); O(bbs_acc);
|
||||
O(rrf_zpg);
|
||||
O(bra_rel);
|
||||
O(jmp_zpi);
|
||||
|
||||
#undef O
|
||||
};
|
||||
|
||||
enum {
|
||||
M740_IRQ_LINE = m6502_device::IRQ_LINE,
|
||||
M740_NMI_LINE = m6502_device::NMI_LINE,
|
||||
M740_SET_OVERFLOW = m6502_device::V_LINE,
|
||||
UINT32 m_irq_multiplex;
|
||||
UINT16 m_irq_vector;
|
||||
|
||||
void set_irq_line(int line, int state);
|
||||
};
|
||||
|
||||
extern const device_type M740;
|
||||
|
@ -102,8 +102,45 @@ bra_rel
|
||||
PC += INT8(TMP);
|
||||
prefetch();
|
||||
|
||||
jmp_zpi
|
||||
TMP2 = read_pc();
|
||||
TMP = read(TMP2 & 0xff);
|
||||
TMP = set_h(TMP, read((TMP2+1) & 0xff));
|
||||
PC = TMP;
|
||||
prefetch();
|
||||
|
||||
reset740
|
||||
PC = read_direct(0xfffe);
|
||||
PC = set_h(PC, read_direct(0xffff));
|
||||
prefetch();
|
||||
inst_state = -1;
|
||||
|
||||
brk740_imp
|
||||
// The 6502 bug when a nmi occurs in a brk is reproduced (case !irq_taken && nmi_state)
|
||||
if(irq_taken) {
|
||||
read_pc_noinc();
|
||||
} else {
|
||||
read_pc();
|
||||
}
|
||||
write(SP, PC >> 8);
|
||||
dec_SP();
|
||||
write(SP, PC);
|
||||
dec_SP();
|
||||
write(SP, irq_taken ? P & ~F_B : P);
|
||||
dec_SP();
|
||||
if(nmi_state) {
|
||||
PC = read_direct(0xfffa);
|
||||
PC = set_h(PC, read_direct(0xfffb));
|
||||
nmi_state = false;
|
||||
standard_irq_callback(NMI_LINE);
|
||||
} else {
|
||||
PC = read_direct(m_irq_vector);
|
||||
PC = set_h(PC, read_direct(m_irq_vector+1));
|
||||
if(irq_taken)
|
||||
standard_irq_callback(IRQ_LINE);
|
||||
}
|
||||
irq_taken = false;
|
||||
P |= F_I; // Do *not* move after the prefetch
|
||||
prefetch();
|
||||
inst_state = -1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user