summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/scudsp/scudsp.h
blob: 866a98f7df0e7afbfcd0292bb13b152f5bf5b857 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// license:BSD-3-Clause
// copyright-holders:Angelo Salese, Mariusz Wojcieszek
/*****************************************************************************
 *
 * Sega SCUDSP emulator
 *
 *****************************************************************************/

#ifndef MAME_CPU_SCUDSP_SCUDSP_H
#define MAME_CPU_SCUDSP_SCUDSP_H

#pragma once

enum
{
	SCUDSP_PC=1,
	SCUDSP_FLAGS,
	SCUDSP_DELAY,
	SCUDSP_TOP,
	SCUDSP_LOP,
	SCUDSP_RX,
	SCUDSP_MUL,
	SCUDSP_RY,
	SCUDSP_ALU,
	SCUDSP_PH,
	SCUDSP_PL,
	SCUDSP_ACH,
	SCUDSP_ACL,
	SCUDSP_RA0,
	SCUDSP_WA0,
	SCUDSP_RA,
	SCUDSP_CT0,
	SCUDSP_CT1,
	SCUDSP_CT2,
	SCUDSP_CT3
};


#define MCFG_SCUDSP_OUT_IRQ_CB(_devcb) \
	devcb = &scudsp_cpu_device::set_out_irq_callback(*device, DEVCB_##_devcb);

#define MCFG_SCUDSP_IN_DMA_CB(_devcb) \
	devcb = &scudsp_cpu_device::set_in_dma_callback(*device, DEVCB_##_devcb);

#define MCFG_SCUDSP_OUT_DMA_CB(_devcb) \
	devcb = &scudsp_cpu_device::set_out_dma_callback(*device, DEVCB_##_devcb);


#define SCUDSP_RESET        INPUT_LINE_RESET    /* Non-Maskable */

class scudsp_cpu_device : public cpu_device
{
public:
	// construction/destruction
	scudsp_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);

	template <class Object> static devcb_base &set_out_irq_callback(device_t &device, Object &&cb) { return downcast<scudsp_cpu_device &>(device).m_out_irq_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> static devcb_base &set_in_dma_callback(device_t &device, Object &&cb) { return downcast<scudsp_cpu_device &>(device).m_in_dma_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> static devcb_base &set_out_dma_callback(device_t &device, Object &&cb) { return downcast<scudsp_cpu_device &>(device).m_out_dma_cb.set_callback(std::forward<Object>(cb)); }

	/* port 0 */
	DECLARE_READ32_MEMBER( program_control_r );
	DECLARE_WRITE32_MEMBER( program_control_w );
	/* port 1 */
	DECLARE_WRITE32_MEMBER( program_w );
	/* port 2 */
	DECLARE_WRITE32_MEMBER( ram_address_control_w );
	/* port 3 */
	DECLARE_READ32_MEMBER( ram_address_r );
	DECLARE_WRITE32_MEMBER( ram_address_w );

protected:
	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	// device_execute_interface overrides
	virtual uint32_t execute_min_cycles() const override { return 1; }
	virtual uint32_t execute_max_cycles() const override { return 7; }
	virtual uint32_t execute_input_lines() const override { return 0; }
	virtual void execute_run() override;
	virtual void execute_set_input(int inputnum, int state) override;

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// device_state_interface overrides
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// device_disasm_interface overrides
	virtual util::disasm_interface *create_disassembler() override;

	devcb_write_line     m_out_irq_cb;
	devcb_read16         m_in_dma_cb;
	devcb_write16        m_out_dma_cb;

private:
	union SCUDSPREG32 {
		int32_t  si;
		uint32_t ui;
	};

	union SCUDSPREG16 {
		int16_t  si;
		uint16_t ui;
	};

	address_space_config m_program_config;
	address_space_config m_data_config;

	uint8_t   m_pc;   /* registers */
	uint32_t  m_flags;  /* flags */
	uint8_t   m_ra;
	uint8_t   m_ct0,m_ct1,m_ct2,m_ct3;
	uint8_t   m_delay;                                   /* Delay */
	uint8_t   m_top;                                     /*Jump Command memory*/
	uint16_t  m_lop;                                    /*Counter Register*/   /*12-bits*/
	SCUDSPREG32 m_rx;                                /*X-Bus register*/
	int64_t   m_mul;                                     /*Multiplier register*//*48-bits*/
	SCUDSPREG32 m_ry;                                /*Y-Bus register*/
	int64_t   m_alu;                                    /*ALU register*/       /*48-bits*/
	SCUDSPREG16 m_ph;                                /*ALU high register*/
	SCUDSPREG32 m_pl;                                /*ALU low register*/
	SCUDSPREG16 m_ach;                               /*ALU external high register*/
	SCUDSPREG32 m_acl;                               /*ALU external low register*/
	uint32_t  m_ra0,m_wa0;                                /*DSP DMA registers*/
	struct{
		uint32_t src, dst;
		uint16_t add;
		uint16_t size, update, ex, dir, count;
	}m_dma;
	address_space *m_program;
	address_space *m_data;
	int m_icount;
	uint8_t m_update_mul;

	uint32_t scudsp_get_source_mem_reg_value( uint32_t mode );
	uint32_t scudsp_get_source_mem_value(uint8_t mode);
	void scudsp_set_dest_mem_reg( uint32_t mode, uint32_t value );
	void scudsp_set_dest_mem_reg_2( uint32_t mode, uint32_t value );
	uint32_t scudsp_compute_condition( uint32_t condition );
	uint32_t scudsp_get_mem_source_dma( uint32_t memcode, uint32_t counter );
	void scudsp_set_dest_dma_mem( uint32_t memcode, uint32_t value, uint32_t counter );

	void scudsp_illegal(uint32_t opcode);
	void scudsp_operation(uint32_t opcode);
	void scudsp_move_immediate(uint32_t opcode);
	void scudsp_dma(uint32_t opcode);
	void scudsp_jump(uint32_t opcode);
	void scudsp_loop(uint32_t opcode);
	void scudsp_end(uint32_t opcode);
	void scudsp_exec_dma();
};


DECLARE_DEVICE_TYPE(SCUDSP, scudsp_cpu_device)

#endif // MAME_CPU_SCUDSP_SCUDSP_H
erride; void program_map(address_map &map); void preprogrammed_map(address_map &map); void register_map(address_map &map); private: address_space_config m_program_config; address_space_config m_data_config; address_space_config m_register_config; memory_access<16, 0, 0, ENDIANNESS_BIG>::cache m_cache; memory_access<16, 0, 0, ENDIANNESS_BIG>::specific m_program; memory_access<16, 0, 0, ENDIANNESS_BIG>::specific m_data; memory_access< 8, 0, 0, ENDIANNESS_BIG>::specific m_regs; // callbacks devcb_read8::array<4> m_input_cb; devcb_write8::array<4> m_output_cb; uint32_t m_rom_size; // basic registers uint16_t m_pc; // program counter uint16_t m_ppc; // program counter at last opcode fetch PAIR16 m_sp; // stack pointer (8-bit for internal stack, 16-bit for external stack) uint8_t m_rp; // register pointer uint8_t m_flags; // condition flags uint8_t m_imr; // interrupt mask uint8_t m_irq; // interrupt request uint8_t m_ipr; // interrupt priority // port registers uint8_t m_input[4]; // port input latches uint8_t m_output[4]; // port output latches uint8_t m_p01m; // port 0/1 mode uint8_t m_p2m; // port 2 mode uint8_t m_p3m; // port 3 mode uint8_t m_p3_output; // port 3 output (alternate functions included) // timer registers uint8_t m_tmr; // timer mode uint8_t m_t[2]; // initial values uint8_t m_count[2]; // current counts uint8_t m_pre[2]; // prescalers uint8_t m_pre_count[2]; // prescaler counts bool m_tout; // toggle output // serial transmitter registers uint16_t m_transmit_sr; // transmitter shift register uint8_t m_transmit_count; // counter for transmitter timing bool m_transmit_parity; // transmitter parity calculation // serial receiver registers uint8_t m_receive_buffer; // received character uint16_t m_receive_sr; // receiver shift register uint8_t m_receive_count; // counter for receiver timing bool m_receive_parity; // receiver parity calculation bool m_receive_started; // true if receiver has seen start bit // interrupts int m_irq_line[4]; bool m_irq_taken; bool m_irq_initialized; // IRQ must be unlocked by EI after reset // execution logic int32_t m_icount; // instruction counter // timers emu_timer *m_internal_timer[2]; bool get_serial_in(); void sio_receive(); void sio_transmit(); template <int T> void timer_start(); template <int T> void timer_stop(); template <int T> void timer_end(); void t1_trigger(); void tout_init(); void tout_toggle(); template <int T> TIMER_CALLBACK_MEMBER(timeout); void request_interrupt(int irq); void take_interrupt(int irq); void process_interrupts(); uint8_t p0_read(); void p0_write(uint8_t data); uint8_t p1_read(); void p1_write(uint8_t data); uint8_t p2_read(); void p2_write(uint8_t data); uint8_t p3_read(); void p3_write(uint8_t data); void p3_update_output(); uint8_t sio_read(); void sio_write(uint8_t data); uint8_t tmr_read(); void tmr_write(uint8_t data); uint8_t t0_read(); void t0_write(uint8_t data); uint8_t t1_read(); void t1_write(uint8_t data); void pre0_write(uint8_t data); void pre1_write(uint8_t data); void p01m_write(uint8_t data); void p2m_write(uint8_t data); void p3m_write(uint8_t data); void ipr_write(uint8_t data); uint8_t irq_read(); void irq_write(uint8_t data); uint8_t imr_read(); void imr_write(uint8_t data); uint8_t flags_read(); void flags_write(uint8_t data); uint8_t rp_read(); void rp_write(uint8_t data); uint8_t sph_read(); void sph_write(uint8_t data); uint8_t spl_read(); void spl_write(uint8_t data); inline uint16_t mask_external_address(uint16_t addr); inline uint8_t fetch(); inline uint8_t fetch_opcode(); inline uint16_t fetch_word(); inline uint8_t register_read(uint8_t offset) { return m_regs.read_byte(offset); } inline uint16_t register_pair_read(uint8_t offset); inline void register_write(uint8_t offset, uint8_t data) { m_regs.write_byte(offset, data); } inline void register_pair_write(uint8_t offset, uint16_t data); inline uint8_t get_working_register(int offset) const; inline uint8_t get_register(uint8_t offset) const; inline uint8_t get_intermediate_register(int offset); inline void stack_push_byte(uint8_t src); inline void stack_push_word(uint16_t src); inline uint8_t stack_pop_byte(); inline uint16_t stack_pop_word(); inline void set_flag(uint8_t flag, int state); inline void clear(uint8_t dst); inline void load(uint8_t dst, uint8_t src); inline void load_from_memory(memory_access<16, 0, 0, ENDIANNESS_BIG>::specific &space); inline void load_to_memory(memory_access<16, 0, 0, ENDIANNESS_BIG>::specific &space); inline void load_from_memory_autoinc(memory_access<16, 0, 0, ENDIANNESS_BIG>::specific &space); inline void load_to_memory_autoinc(memory_access<16, 0, 0, ENDIANNESS_BIG>::specific &space); inline void pop(uint8_t dst); inline void push(uint8_t src); inline void add_carry(uint8_t dst, uint8_t src); inline void add(uint8_t dst, uint8_t src); inline void compare(uint8_t dst, uint8_t src); inline void decimal_adjust(uint8_t dst); inline void decrement(uint8_t dst); inline void decrement_word(uint8_t dst); inline void increment(uint8_t dst); inline void increment_word(uint8_t dst); inline void subtract_carry(uint8_t dst, uint8_t src); inline void subtract(uint8_t dst, uint8_t src); inline void _and(uint8_t dst, uint8_t src); inline void complement(uint8_t dst); inline void _or(uint8_t dst, uint8_t src); inline void _xor(uint8_t dst, uint8_t src); inline void call(uint16_t dst); inline void jump(uint16_t dst); inline bool check_condition_code(int cc); inline void test_complement_under_mask(uint8_t dst, uint8_t src); inline void test_under_mask(uint8_t dst, uint8_t src); inline void rotate_left(uint8_t dst); inline void rotate_left_carry(uint8_t dst); inline void rotate_right(uint8_t dst); inline void rotate_right_carry(uint8_t dst); inline void shift_right_arithmetic(uint8_t dst); inline void swap(uint8_t dst); #define INSTRUCTION(inst) void inst(uint8_t opcode, int *cycles); INSTRUCTION( illegal ) INSTRUCTION( clr_R1 ) INSTRUCTION( clr_IR1 ) INSTRUCTION( ld_r1_IM ) INSTRUCTION( ld_r1_R2 ) INSTRUCTION( ld_r2_R1 ) INSTRUCTION( ld_Ir1_r2 ) INSTRUCTION( ld_R2_IR1 ) INSTRUCTION( ld_r1_x_R2 ) INSTRUCTION( ld_r2_x_R1 ) INSTRUCTION( ld_r1_r2 ) INSTRUCTION( ld_r1_Ir2 ) INSTRUCTION( ld_R2_R1 ) INSTRUCTION( ld_IR2_R1 ) INSTRUCTION( ld_R1_IM ) INSTRUCTION( ld_IR1_IM ) INSTRUCTION( ldc_r1_Irr2 ) INSTRUCTION( ldc_r2_Irr1 ) INSTRUCTION( ldci_Ir1_Irr2 ) INSTRUCTION( ldci_Ir2_Irr1 ) INSTRUCTION( lde_r1_Irr2 ) INSTRUCTION( lde_r2_Irr1 ) INSTRUCTION( ldei_Ir1_Irr2 ) INSTRUCTION( ldei_Ir2_Irr1 ) INSTRUCTION( pop_R1 ) INSTRUCTION( pop_IR1 ) INSTRUCTION( push_R2 ) INSTRUCTION( push_IR2 ) INSTRUCTION( adc_r1_r2 ) INSTRUCTION( adc_r1_Ir2 ) INSTRUCTION( adc_R2_R1 ) INSTRUCTION( adc_IR2_R1 ) INSTRUCTION( adc_R1_IM ) INSTRUCTION( adc_IR1_IM ) INSTRUCTION( add_r1_r2 ) INSTRUCTION( add_r1_Ir2 ) INSTRUCTION( add_R2_R1 ) INSTRUCTION( add_IR2_R1 ) INSTRUCTION( add_R1_IM ) INSTRUCTION( add_IR1_IM ) INSTRUCTION( cp_r1_r2 ) INSTRUCTION( cp_r1_Ir2 ) INSTRUCTION( cp_R2_R1 ) INSTRUCTION( cp_IR2_R1 ) INSTRUCTION( cp_R1_IM ) INSTRUCTION( cp_IR1_IM ) INSTRUCTION( da_R1 ) INSTRUCTION( da_IR1 ) INSTRUCTION( dec_R1 ) INSTRUCTION( dec_IR1 ) INSTRUCTION( decw_RR1 ) INSTRUCTION( decw_IR1 ) INSTRUCTION( inc_r1 ) INSTRUCTION( inc_R1 ) INSTRUCTION( inc_IR1 ) INSTRUCTION( incw_RR1 ) INSTRUCTION( incw_IR1 ) INSTRUCTION( sbc_r1_r2 ) INSTRUCTION( sbc_r1_Ir2 ) INSTRUCTION( sbc_R2_R1 ) INSTRUCTION( sbc_IR2_R1 ) INSTRUCTION( sbc_R1_IM ) INSTRUCTION( sbc_IR1_IM ) INSTRUCTION( sub_r1_r2 ) INSTRUCTION( sub_r1_Ir2 ) INSTRUCTION( sub_R2_R1 ) INSTRUCTION( sub_IR2_R1 ) INSTRUCTION( sub_R1_IM ) INSTRUCTION( sub_IR1_IM ) INSTRUCTION( and_r1_r2 ) INSTRUCTION( and_r1_Ir2 ) INSTRUCTION( and_R2_R1 ) INSTRUCTION( and_IR2_R1 ) INSTRUCTION( and_R1_IM ) INSTRUCTION( and_IR1_IM ) INSTRUCTION( com_R1 ) INSTRUCTION( com_IR1 ) INSTRUCTION( or_r1_r2 ) INSTRUCTION( or_r1_Ir2 ) INSTRUCTION( or_R2_R1 ) INSTRUCTION( or_IR2_R1 ) INSTRUCTION( or_R1_IM ) INSTRUCTION( or_IR1_IM ) INSTRUCTION( xor_r1_r2 ) INSTRUCTION( xor_r1_Ir2 ) INSTRUCTION( xor_R2_R1 ) INSTRUCTION( xor_IR2_R1 ) INSTRUCTION( xor_R1_IM ) INSTRUCTION( xor_IR1_IM ) INSTRUCTION( call_IRR1 ) INSTRUCTION( call_DA ) INSTRUCTION( djnz_r1_RA ) INSTRUCTION( iret ) INSTRUCTION( ret ) INSTRUCTION( jp_IRR1 ) INSTRUCTION( jp_cc_DA ) INSTRUCTION( jr_cc_RA ) INSTRUCTION( tcm_r1_r2 ) INSTRUCTION( tcm_r1_Ir2 ) INSTRUCTION( tcm_R2_R1 ) INSTRUCTION( tcm_IR2_R1 ) INSTRUCTION( tcm_R1_IM ) INSTRUCTION( tcm_IR1_IM ) INSTRUCTION( tm_r1_r2 ) INSTRUCTION( tm_r1_Ir2 ) INSTRUCTION( tm_R2_R1 ) INSTRUCTION( tm_IR2_R1 ) INSTRUCTION( tm_R1_IM ) INSTRUCTION( tm_IR1_IM ) INSTRUCTION( rl_R1 ) INSTRUCTION( rl_IR1 ) INSTRUCTION( rlc_R1 ) INSTRUCTION( rlc_IR1 ) INSTRUCTION( rr_R1 ) INSTRUCTION( rr_IR1 ) INSTRUCTION( rrc_R1 ) INSTRUCTION( rrc_IR1 ) INSTRUCTION( sra_R1 ) INSTRUCTION( sra_IR1 ) INSTRUCTION( swap_R1 ) INSTRUCTION( swap_IR1 ) INSTRUCTION( ccf ) INSTRUCTION( di ) INSTRUCTION( ei ) INSTRUCTION( nop ) INSTRUCTION( rcf ) INSTRUCTION( scf ) INSTRUCTION( srp_IM ) #undef INSTRUCTION typedef void (z8_device::*z8_opcode_func) (uint8_t opcode, int *cycles); struct z8_opcode_map { z8_opcode_func function; int execution_cycles; int pipeline_cycles; }; static const z8_opcode_map Z8601_OPCODE_MAP[256]; }; class z8601_device : public z8_device { public: z8601_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class ub8830d_device : public z8_device { public: ub8830d_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class z8611_device : public z8_device { public: z8611_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class z8671_device : public z8_device { public: z8671_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: const tiny_rom_entry *device_rom_region() const override; }; class z8681_device : public z8_device { public: z8681_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; class z8682_device : public z8_device { public: z8682_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: const tiny_rom_entry *device_rom_region() const override; }; // Zilog Z8601 DECLARE_DEVICE_TYPE(Z8601, z8601_device) // VEB Mikroelektronik Erfurt UB8830D MME DECLARE_DEVICE_TYPE(UB8830D, ub8830d_device) // Zilog Z8611 DECLARE_DEVICE_TYPE(Z8611, z8611_device) // Zilog Z8671 BASIC/DEBUG interpreter DECLARE_DEVICE_TYPE(Z8671, z8671_device) // Zilog Z8681 ROMless DECLARE_DEVICE_TYPE(Z8681, z8681_device) // Zilog Z8682 ROMless (boot to 0812H) DECLARE_DEVICE_TYPE(Z8682, z8682_device) #endif // MAME_CPU_Z8_Z8_H