summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/unsp/unsp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/unsp/unsp.h')
-rw-r--r--src/devices/cpu/unsp/unsp.h181
1 files changed, 164 insertions, 17 deletions
diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h
index ad3f8250785..460198451fa 100644
--- a/src/devices/cpu/unsp/unsp.h
+++ b/src/devices/cpu/unsp/unsp.h
@@ -17,7 +17,32 @@
#pragma once
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define ENABLE_UNSP_DRC (1)
+
#define UNSP_LOG_OPCODES (0)
+#define UNSP_LOG_REGS (0)
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+class unsp_frontend;
+
+// ======================> unsp_device
enum
{
@@ -36,7 +61,7 @@ enum
UNSP_FIQ_EN,
UNSP_IRQ,
UNSP_FIQ,
-#if UNSP_LOG_OPCODES
+#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
UNSP_SB,
UNSP_LOG_OPS
#else
@@ -62,16 +87,38 @@ enum
class unsp_device : public cpu_device
{
+ friend class unsp_frontend;
+
public:
// construction/destruction
unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- void set_timer_interval(int timer, uint32_t interval);
+ // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
+ // Therefore, to avoid an unnecessary scheduler sync when the external spg2xx_device sets or
+ // clears an interrupt line, we provide this direct accessor.
+ // A more correct but longer-term solution will be to move spg2xx_device to be internal to
+ // a subclass of unsp_device rather than its own standalone device.
+ void set_state_unsynced(int inputnum, int state);
+
+ uint8_t get_csb();
+
+ void set_ds(uint16_t ds);
+ uint16_t get_ds();
+
+ inline void ccfunc_unimplemented();
+ void invalidate_cache();
+
+#if UNSP_LOG_REGS
+ void log_regs();
+ void log_write(uint32_t addr, uint32_t data);
+ void cfunc_log_write();
+#endif
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
+ virtual void device_stop() override;
// device_execute_interface overrides
virtual uint32_t execute_min_cycles() const override { return 5; }
@@ -92,27 +139,69 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
+ // compilation boundaries -- how far back/forward does the analysis extend?
+ enum : uint32_t
+ {
+ COMPILE_BACKWARDS_BYTES = 128,
+ COMPILE_FORWARDS_BYTES = 512,
+ COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 4) + (COMPILE_FORWARDS_BYTES / 4),
+ COMPILE_MAX_SEQUENCE = 64
+ };
+
+ // exit codes
+ enum : int
+ {
+ EXECUTE_OUT_OF_CYCLES = 0,
+ EXECUTE_MISSING_CODE = 1,
+ EXECUTE_UNMAPPED_CODE = 2,
+ EXECUTE_RESET_CACHE = 3
+ };
+
+ enum : uint32_t
+ {
+ REG_SP = 0,
+ REG_R1,
+ REG_R2,
+ REG_R3,
+ REG_R4,
+ REG_BP,
+ REG_SR,
+ REG_PC
+ };
+
void add_lpc(const int32_t offset);
inline void execute_one(const uint16_t op);
- address_space_config m_program_config;
+ struct internal_unsp_state
+ {
+ uint32_t m_r[8];
+ uint32_t m_enable_irq;
+ uint32_t m_enable_fiq;
+ uint32_t m_irq;
+ uint32_t m_fiq;
+ uint32_t m_curirq;
+ uint32_t m_sirq;
+ uint32_t m_sb;
+ uint32_t m_saved_sb[3];
- uint16_t m_r[16];
- bool m_enable_irq;
- bool m_enable_fiq;
- bool m_irq;
- bool m_fiq;
- uint16_t m_curirq;
- uint16_t m_sirq;
- uint8_t m_sb;
- uint8_t m_saved_sb[3];
+ uint32_t m_arg0;
+ uint32_t m_arg1;
+ uint32_t m_jmpdest;
+ int m_icount;
+ };
+
+ address_space_config m_program_config;
address_space *m_program;
- int m_icount;
+ std::function<u16 (offs_t)> m_pr16;
+ std::function<const void * (offs_t)> m_prptr;
+
+ /* core state */
+ internal_unsp_state *m_core;
uint32_t m_debugger_temp;
-#if UNSP_LOG_OPCODES
+#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
uint32_t m_log_ops;
#endif
@@ -120,12 +209,70 @@ private:
inline uint16_t read16(uint32_t address);
inline void write16(uint32_t address, uint16_t data);
inline void update_nz(uint32_t value);
- inline void update_sc(uint32_t value, uint16_t r0, uint16_t r1);
- inline void push(uint16_t value, uint16_t *reg);
- inline uint16_t pop(uint16_t *reg);
+ inline void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1);
+ inline void push(uint32_t value, uint32_t *reg);
+ inline uint16_t pop(uint32_t *reg);
inline void trigger_fiq();
inline void trigger_irq(int line);
inline void check_irqs();
+
+ drc_cache m_cache;
+ std::unique_ptr<drcuml_state> m_drcuml;
+ std::unique_ptr<unsp_frontend> m_drcfe;
+ uint32_t m_drcoptions;
+ uint8_t m_cache_dirty;
+
+ uml::parameter m_regmap[16];
+ uml::code_handle *m_entry;
+ uml::code_handle *m_nocode;
+ uml::code_handle *m_out_of_cycles;
+ uml::code_handle *m_check_interrupts;
+ uml::code_handle *m_trigger_fiq;
+ uml::code_handle *m_trigger_irq;
+
+ uml::code_handle *m_mem_read;
+ uml::code_handle *m_mem_write;
+
+ bool m_enable_drc;
+
+ /* internal compiler state */
+ struct compiler_state
+ {
+ compiler_state(compiler_state const &) = delete;
+ compiler_state &operator=(compiler_state const &) = delete;
+
+ uint32_t m_cycles; /* accumulated cycles */
+ uml::code_label m_labelnum; /* index for local labels */
+ };
+
+ void execute_run_drc();
+ void flush_drc_cache();
+ void code_flush_cache();
+ void code_compile_block(offs_t pc);
+ void load_fast_iregs(drcuml_block &block);
+ void save_fast_iregs(drcuml_block &block);
+
+ void static_generate_entry_point();
+ void static_generate_nocode_handler();
+ void static_generate_out_of_cycles();
+ void static_generate_check_interrupts();
+ void static_generate_trigger_fiq();
+ void static_generate_trigger_irq();
+ void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr);
+
+ void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+ void generate_check_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);
+ void generate_add_lpc(drcuml_block &block, int32_t offset);
+ void generate_update_nzsc(drcuml_block &block);
+ void generate_update_nz(drcuml_block &block);
+ void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
+ bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
+
+#if UNSP_LOG_REGS
+ FILE *m_log_file;
+#endif
};