summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/dspp/dspp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/dspp/dspp.h')
-rw-r--r--src/devices/cpu/dspp/dspp.h337
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__ */