diff options
Diffstat (limited to 'src/devices/cpu/dspp/dspp.h')
-rw-r--r-- | src/devices/cpu/dspp/dspp.h | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/src/devices/cpu/dspp/dspp.h b/src/devices/cpu/dspp/dspp.h new file mode 100644 index 00000000000..848c2931714 --- /dev/null +++ b/src/devices/cpu/dspp/dspp.h @@ -0,0 +1,337 @@ +// license:BSD-3-Clause +// copyright-holders:Philip Bennett +/*************************************************************************** + + dspp.h + + Core implementation for the portable DSPP emulator. + +***************************************************************************/ + +#pragma once + +#ifndef __DSPP_H__ +#define __DSPP_H__ + +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" +#include "cpu/drcumlsh.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class dspp_frontend; + +// ======================> dspp_device + +class dspp_device : public cpu_device +{ + friend class dspp_frontend; +public: + // Construction/destruction + dspp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor code_map_ctor, + address_map_constructor data_map_ctor); + dspp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // Static configuration helpers + auto int_handler() { return m_int_handler.bind(); } + auto dma_read_handler() { return m_dma_read_handler.bind(); } + auto dma_write_handler() { return m_dma_write_handler.bind(); } + + // Public interfaces + DECLARE_READ32_MEMBER( read ); + DECLARE_WRITE32_MEMBER( write ); + + uint16_t read_output_fifo(); + + void dump_state(); // TODO: DEBUG REMOVE ME + + // Internal registers + DECLARE_READ16_MEMBER( input_r ); + DECLARE_WRITE16_MEMBER( output_w ); + DECLARE_READ16_MEMBER( fifo_osc_r ); + DECLARE_WRITE16_MEMBER( fifo_osc_w ); + DECLARE_WRITE16_MEMBER( input_control_w ); + DECLARE_WRITE16_MEMBER( output_control_w ); + DECLARE_READ16_MEMBER( input_status_r ); + DECLARE_READ16_MEMBER( output_status_r ); + DECLARE_WRITE16_MEMBER( cpu_int_w ); + DECLARE_READ16_MEMBER( pc_r ); + DECLARE_WRITE16_MEMBER( pc_w ); + DECLARE_READ16_MEMBER( audlock_r ); + DECLARE_WRITE16_MEMBER( audlock_w ); + DECLARE_READ16_MEMBER( clock_r ); + DECLARE_WRITE16_MEMBER( clock_w ); + DECLARE_READ16_MEMBER( noise_r ); + +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; + virtual uint32_t execute_max_cycles() const override; + virtual void execute_run() override; + + // device_memory_interface overrides + virtual space_config_vector memory_space_config() const override; + + // device_state_interface overrides + virtual void state_import(const device_state_entry &entry) override; + virtual void state_export(const device_state_entry &entry) override; + virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; + + // device_disasm_interface overrides + virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; + + void code_map(address_map &map); + void data_map(address_map &map); + +private: + // Constants + static const uint32_t PC_STACK_DEPTH = 4; + static const uint32_t MAX_OPERANDS = 8; + + static const uint32_t NUM_DMA_CHANNELS = 32; + static const uint32_t DMA_FIFO_DEPTH = 8; + static const uint32_t DMA_FIFO_MASK = DMA_FIFO_DEPTH - 1; + + static const uint32_t NUM_INPUTS = 2; + static const uint32_t NUM_OUTPUTS = 8; + static const uint32_t OUTPUT_FIFO_DEPTH = 8; + static const uint32_t OUTPUT_FIFO_MASK = OUTPUT_FIFO_DEPTH - 1; + + // Handlers + devcb_write_line m_int_handler; + devcb_read8 m_dma_read_handler; + devcb_write8 m_dma_write_handler; + + // Internal functions + uint16_t read_op(offs_t pc); + inline uint16_t read_data(offs_t addr); + inline void write_data(offs_t addr, uint16_t data); + + inline void update_pc(); + inline void update_ticks(); + inline void exec_control(); + inline void exec_super_special(); + inline void exec_special(); + inline void exec_branch(); + inline void exec_complex_branch(); + inline void exec_arithmetic(); + void parse_operands(uint32_t numops); + uint16_t read_next_operand(); + void write_next_operand(uint16_t value); + inline void push_pc(); + inline uint16_t pop_pc(); + inline void set_rbase(uint32_t base, uint32_t addr); + inline uint16_t translate_reg(uint16_t reg); + + void update_fifo_dma(); + void process_next_dma(int32_t channel); + void service_input_dma(int32_t channel); + void service_output_dma(int32_t channel); + int16_t read_fifo_to_dspp(int32_t channel); + int16_t read_fifo_to_dma(int32_t channel); + void write_dma_to_fifo(int32_t channel, int16_t value); + void write_dspp_to_fifo(int32_t channel, int16_t value); + + void run_oscillator(int32_t channel); + void reset_channel(int32_t channel); + void advance_audio_timer(); + void advance_audio_frame(); + int16_t decode_sqxd(int8_t val, int16_t prev); + + uint32_t get_interrupt_state(); + void update_host_interrupt(); + + uint32_t read_dma_stack(offs_t offset); + void write_dma_stack(offs_t offset, uint32_t data); + + uint32_t read_ext_control(offs_t offset); + void write_ext_control(offs_t offset, uint32_t data); + + bool m_isdrc; + + // Address spaces + const address_space_config m_code_config; + const address_space_config m_data_config; + address_space * m_code; + address_space * m_data; + memory_access_cache<1, -1, ENDIANNESS_BIG> *m_code_cache; + std::function<const void * (offs_t)> m_codeptr; + + struct dspp_internal_state + { + // Internal state + int m_icount; + uint16_t m_pc; + uint16_t m_stack[PC_STACK_DEPTH]; + uint32_t m_stack_ptr; + uint16_t m_rbase[4]; + uint32_t m_acc; + uint32_t m_tclock; + + uint32_t m_flag_carry; + uint32_t m_flag_zero; + uint32_t m_flag_neg; + uint32_t m_flag_over; + uint32_t m_flag_exact; + uint32_t m_flag_audlock; + uint32_t m_flag_sleep; + + uint32_t m_partial_int; + uint16_t m_op; + uint32_t m_opidx; + int32_t m_writeback; + + const char *m_format; + uint32_t m_arg0; + } * m_core; + + struct + { + uint32_t value; + uint32_t addr; + } m_operands[MAX_OPERANDS]; + + // DMA + struct fifo_dma + { + uint32_t m_current_addr; + int32_t m_current_count; + uint32_t m_next_addr; + uint32_t m_next_count; + uint32_t m_prev_value; + uint32_t m_prev_current; + uint8_t m_go_forever; + uint8_t m_next_valid; + uint8_t m_reserved; + uint16_t m_fifo[DMA_FIFO_DEPTH]; + uint32_t m_dma_ptr; + uint32_t m_dspi_ptr; + uint32_t m_depth; + } m_fifo_dma[NUM_DMA_CHANNELS]; + + // Oscillator + uint32_t m_last_frame_clock; + uint32_t m_last_osc_count; + uint32_t m_osc_phase; + uint32_t m_osc_freq; + + // Output FIFO + uint16_t m_outputs[NUM_OUTPUTS]; + uint16_t m_output_fifo[OUTPUT_FIFO_DEPTH]; + uint32_t m_output_fifo_start; + uint32_t m_output_fifo_count; + + // External control registers + uint32_t m_dspx_control; + uint32_t m_dspx_reset; + uint32_t m_dspx_int_enable; + uint32_t m_dspx_channel_enable; + uint32_t m_dspx_channel_complete; + uint32_t m_dspx_channel_direction; + uint32_t m_dspx_channel_8bit; + uint32_t m_dspx_channel_sqxd; + uint32_t m_dspx_shadow_current_addr; + uint32_t m_dspx_shadow_current_count; + uint32_t m_dspx_shadow_next_addr; + uint32_t m_dspx_shadow_next_count; + uint32_t m_dspx_dmanext_int; + uint32_t m_dspx_dmanext_enable; + uint32_t m_dspx_consumed_int; + uint32_t m_dspx_consumed_enable; + uint32_t m_dspx_underover_int; + uint32_t m_dspx_underover_enable; + uint32_t m_dspx_audio_time; + uint16_t m_dspx_audio_duration; + + // + // DRC + // + + // Core state + /* internal stuff */ + bool m_cache_dirty; + drc_cache m_cache; + std::unique_ptr<drcuml_state> m_drcuml; + std::unique_ptr<dspp_frontend> m_drcfe; + uint32_t m_drcoptions; + + /* internal compiler state */ + struct compiler_state + { + uint32_t cycles; /* accumulated cycles */ + uint8_t checkints; /* need to check interrupts before next instruction */ + uint8_t checksoftints; /* need to check software interrupts before next instruction */ + uml::code_label labelnum; /* index for local labels */ + }; + +public: // TODO + void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); + void load_fast_iregs(drcuml_block &block); + void save_fast_iregs(drcuml_block &block); +// void arm7_drc_init(); +// void arm7_drc_exit(); + void execute_run_drc(); +// void arm7drc_set_options(uint32_t options); +// void arm7drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base); +// void arm7drc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles); + void flush_cache(); + void compile_block(offs_t pc); + void cfunc_get_cycles(); + void cfunc_unimplemented(); + void static_generate_entry_point(); + void static_generate_nocode_handler(); + void static_generate_out_of_cycles(); + void static_generate_memory_accessor(int size, bool istlb, bool iswrite, const char *name, uml::code_handle **handleptr); + void generate_update_cycles(drcuml_block &block, compiler_state *compiler, uml::parameter param); + void generate_checksum_block(drcuml_block &block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); + void generate_sequence_instruction(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); + + bool generate_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc); + + + /* subroutines */ + uml::code_handle * m_entry; /* entry point */ + uml::code_handle * m_nocode; /* nocode exception handler */ + uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ +}; + + +/*************************************************************************** + COMPILER-SPECIFIC OPTIONS + ***************************************************************************/ + +#define DSPPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */ +#define DSPPDRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */ + +#define DSPPDRC_COMPATIBLE_OPTIONS (DSPPDRC_STRICT_VERIFY | DSPPDRC_FLUSH_PC) +#define DSPPDRC_FASTEST_OPTIONS (0) + + + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MCFG_DSPP_INT_HANDLER(_devcb) \ + devcb = &dspp_device::set_int_handler(*device, DEVCB_##_devcb); + +#define MCFG_DSPP_DMA_READ_HANDLER(_devcb) \ + devcb = &dspp_device::set_dma_read_handler(*device, DEVCB_##_devcb); + +#define MCFG_DSPP_DMA_WRITE_HANDLER(_devcb) \ + devcb = &dspp_device::set_dma_write_handler(*device, DEVCB_##_devcb); + + + +// device type definition +DECLARE_DEVICE_TYPE(DSPP, dspp_device); + + +#endif /* __DSPP_H__ */ |