summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sh/sh.h')
-rw-r--r--src/devices/cpu/sh/sh.h471
1 files changed, 471 insertions, 0 deletions
diff --git a/src/devices/cpu/sh/sh.h b/src/devices/cpu/sh/sh.h
new file mode 100644
index 00000000000..96b02afb8c6
--- /dev/null
+++ b/src/devices/cpu/sh/sh.h
@@ -0,0 +1,471 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_CPU_SH_SH_H
+#define MAME_CPU_SH_SH_H
+
+#pragma once
+
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+/***************************************************************************
+ DEBUGGING
+**************************************************************************/
+
+#define DISABLE_FAST_REGISTERS (0) // set to 1 to turn off usage of register caching
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define SET_EA (0) // makes slower but "shows work" in the EA fake register like the interpreter
+
+#if SET_EA
+#define SETEA(x) UML_MOV(block, mem(&m_sh2_state->ea), ireg(x))
+#else
+#define SETEA(x)
+#endif
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* speed up delay loops, bail out of tight loops (can cause timer issues) */
+#define BUSY_LOOP_HACKS 0
+
+/* compilation boundaries -- how far back/forward does the analysis extend? */
+#define COMPILE_BACKWARDS_BYTES 64
+#define COMPILE_FORWARDS_BYTES 256
+#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/2) + (COMPILE_FORWARDS_BYTES/2))
+#define COMPILE_MAX_SEQUENCE 64
+
+#define SH2DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define SH2DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
+#define SH2DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */
+
+#define SH2DRC_COMPATIBLE_OPTIONS (SH2DRC_STRICT_VERIFY | SH2DRC_FLUSH_PC | SH2DRC_STRICT_PCREL)
+#define SH2DRC_FASTEST_OPTIONS (0)
+
+/* size of the execution code cache */
+#define CACHE_SIZE (32 * 1024 * 1024)
+
+#define SH2_MAX_FASTRAM 4
+
+/* map variables */
+#define MAPVAR_PC M0
+#define MAPVAR_CYCLES M1
+
+/* exit codes */
+#define EXECUTE_OUT_OF_CYCLES 0
+#define EXECUTE_MISSING_CODE 1
+#define EXECUTE_UNMAPPED_CODE 2
+#define EXECUTE_RESET_CACHE 3
+
+#define PROBE_ADDRESS ~0
+
+#define CPU_TYPE_SH1 (0)
+#define CPU_TYPE_SH2 (1)
+#define CPU_TYPE_SH3 (2)
+#define CPU_TYPE_SH4 (3)
+
+#define Rn ((opcode>>8)&15)
+#define Rm ((opcode>>4)&15)
+
+/* Bits in SR */
+#define SH_T 0x00000001
+#define SH_S 0x00000002
+#define SH_I 0x000000f0
+#define SH_Q 0x00000100
+#define SH_M 0x00000200
+
+#define SH_FLAGS (SH_M|SH_Q|SH_I|SH_S|SH_T)
+
+#define REGFLAG_R(n) (1 << (n))
+
+/* register flags 1 */
+#define REGFLAG_PR (1 << 0)
+#define REGFLAG_MACL (1 << 1)
+#define REGFLAG_MACH (1 << 2)
+#define REGFLAG_GBR (1 << 3)
+#define REGFLAG_VBR (1 << 4)
+#define REGFLAG_SR (1 << 5)
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#define SH2_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(2,0)) // sh2
+#define SH34LE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(0,6)) // naomi
+#define SH34BE_CODE_XOR(a) ((a) ^ NATIVE_ENDIAN_VALUE_LE_BE(6,0)) // cave
+
+#define R32(reg) m_regmap[reg]
+
+extern unsigned DasmSH2(std::ostream &stream, unsigned pc, uint16_t opcode);
+
+enum
+{
+ SH4_PC = 1, SH_SR, SH4_PR, SH4_GBR, SH4_VBR, SH4_DBR, SH4_MACH, SH4_MACL,
+ SH4_R0, SH4_R1, SH4_R2, SH4_R3, SH4_R4, SH4_R5, SH4_R6, SH4_R7,
+ SH4_R8, SH4_R9, SH4_R10, SH4_R11, SH4_R12, SH4_R13, SH4_R14, SH4_R15, SH4_EA
+};
+
+class sh_common_execution : public cpu_device
+{
+
+public:
+ sh_common_execution(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness, address_map_constructor internal)
+ : cpu_device(mconfig, type, tag, owner, clock)
+ , m_sh2_state(nullptr)
+ , m_cache(CACHE_SIZE + sizeof(internal_sh2_state))
+ , m_drcuml(nullptr)
+ , m_drcoptions(0)
+ , m_entry(nullptr)
+ , m_read8(nullptr)
+ , m_write8(nullptr)
+ , m_read16(nullptr)
+ , m_write16(nullptr)
+ , m_read32(nullptr)
+ , m_write32(nullptr)
+ , m_interrupt(nullptr)
+ , m_nocode(nullptr)
+ , m_out_of_cycles(nullptr)
+ , m_xor(0)
+ { }
+
+ // Data that needs to be stored close to the generated DRC code
+ struct internal_sh2_state
+ {
+ uint32_t pc;
+ uint32_t pr;
+ uint32_t sr;
+ uint32_t mach;
+ uint32_t macl;
+ uint32_t r[16];
+ uint32_t ea;
+
+ uint32_t pending_irq;
+ uint32_t pending_nmi;
+ int32_t irqline;
+ uint32_t evec; // exception vector for DRC
+ uint32_t irqsr; // IRQ-time old SR for DRC
+ uint32_t target; // target for jmp/jsr/etc so the delay slot can't kill it
+ int internal_irq_level;
+ int icount;
+ uint8_t sleep_mode;
+ uint32_t arg0; /* print_debug argument 1 */
+ uint32_t arg1;
+ uint32_t gbr;
+ uint32_t vbr;
+
+ uint32_t m_delay;
+ };
+
+ internal_sh2_state *m_sh2_state;
+
+ virtual uint8_t RB(offs_t A) = 0;
+ virtual uint16_t RW(offs_t A) = 0;
+ virtual uint32_t RL(offs_t A) = 0;
+ virtual void WB(offs_t A, uint8_t V) = 0;
+ virtual void WW(offs_t A, uint16_t V) = 0;
+ virtual void WL(offs_t A, uint32_t V) = 0;
+
+protected:
+
+ void ADD(uint32_t m, uint32_t n);
+ void ADDI(uint32_t i, uint32_t n);
+ void ADDC(uint32_t m, uint32_t n);
+ void ADDV(uint32_t m, uint32_t n);
+ void AND(uint32_t m, uint32_t n);
+ void ANDI(uint32_t i);
+ void ANDM(uint32_t i);
+ void BF(uint32_t d);
+ void BFS(uint32_t d);
+ void BRA(uint32_t d);
+ void BRAF(uint32_t m);
+ void BSR(uint32_t d);
+ void BSRF(uint32_t m);
+ void BT(uint32_t d);
+ void BTS(uint32_t d);
+ void CLRMAC();
+ void CLRT();
+ void CMPEQ(uint32_t m, uint32_t n);
+ void CMPGE(uint32_t m, uint32_t n);
+ void CMPGT(uint32_t m, uint32_t n);
+ void CMPHI(uint32_t m, uint32_t n);
+ void CMPHS(uint32_t m, uint32_t n);
+ void CMPPL(uint32_t n);
+ void CMPPZ(uint32_t n);
+ void CMPSTR(uint32_t m, uint32_t n);
+ void CMPIM(uint32_t i);
+ void DIV0S(uint32_t m, uint32_t n);
+ void DIV0U();
+ void DIV1(uint32_t m, uint32_t n);
+ void DMULS(uint32_t m, uint32_t n);
+ void DMULU(uint32_t m, uint32_t n);
+ void DT(uint32_t n);
+ void EXTSB(uint32_t m, uint32_t n);
+ void EXTSW(uint32_t m, uint32_t n);
+ void EXTUB(uint32_t m, uint32_t n);
+ void EXTUW(uint32_t m, uint32_t n);
+ void JMP(uint32_t m);
+ void JSR(uint32_t m);
+ void LDCGBR(uint32_t m);
+ void LDCVBR(uint32_t m);
+ void LDCMGBR(uint32_t m);
+ void LDCMVBR(uint32_t m);
+ void LDSMACH(uint32_t m);
+ void LDSMACL(uint32_t m);
+ void LDSPR(uint32_t m);
+ void LDSMMACH(uint32_t m);
+ void LDSMMACL(uint32_t m);
+ void LDSMPR(uint32_t m);
+ void MAC_L(uint32_t m, uint32_t n);
+ void MAC_W(uint32_t m, uint32_t n);
+ void MOV(uint32_t m, uint32_t n);
+ void MOVBS(uint32_t m, uint32_t n);
+ void MOVWS(uint32_t m, uint32_t n);
+ void MOVLS(uint32_t m, uint32_t n);
+ void MOVBL(uint32_t m, uint32_t n);
+ void MOVWL(uint32_t m, uint32_t n);
+ void MOVLL(uint32_t m, uint32_t n);
+ void MOVBM(uint32_t m, uint32_t n);
+ void MOVWM(uint32_t m, uint32_t n);
+ void MOVLM(uint32_t m, uint32_t n);
+ void MOVBP(uint32_t m, uint32_t n);
+ void MOVWP(uint32_t m, uint32_t n);
+ void MOVLP(uint32_t m, uint32_t n);
+ void MOVBS0(uint32_t m, uint32_t n);
+ void MOVWS0(uint32_t m, uint32_t n);
+ void MOVLS0(uint32_t m, uint32_t n);
+ void MOVBL0(uint32_t m, uint32_t n);
+ void MOVWL0(uint32_t m, uint32_t n);
+ void MOVLL0(uint32_t m, uint32_t n);
+ void MOVI(uint32_t i, uint32_t n);
+ void MOVWI(uint32_t d, uint32_t n);
+ void MOVLI(uint32_t d, uint32_t n);
+ void MOVBLG(uint32_t d);
+ void MOVWLG(uint32_t d);
+ void MOVLLG(uint32_t d);
+ void MOVBSG(uint32_t d);
+ void MOVWSG(uint32_t d);
+ void MOVLSG(uint32_t d);
+ void MOVBS4(uint32_t d, uint32_t n);
+ void MOVWS4(uint32_t d, uint32_t n);
+ void MOVLS4(uint32_t m, uint32_t d, uint32_t n);
+ void MOVBL4(uint32_t m, uint32_t d);
+ void MOVWL4(uint32_t m, uint32_t d);
+ void MOVLL4(uint32_t m, uint32_t d, uint32_t n);
+ void MOVA(uint32_t d);
+ void MOVT(uint32_t n);
+ void MULL(uint32_t m, uint32_t n);
+ void MULS(uint32_t m, uint32_t n);
+ void MULU(uint32_t m, uint32_t n);
+ void NEG(uint32_t m, uint32_t n);
+ void NEGC(uint32_t m, uint32_t n);
+ void NOP(void);
+ void NOT(uint32_t m, uint32_t n);
+ void OR(uint32_t m, uint32_t n);
+ void ORI(uint32_t i);
+ void ORM(uint32_t i);
+ void ROTCL(uint32_t n);
+ void ROTCR(uint32_t n);
+ void ROTL(uint32_t n);
+ void ROTR(uint32_t n);
+ void RTS();
+ void SETT();
+ void SHAL(uint32_t n);
+ void SHAR(uint32_t n);
+ void SHLL(uint32_t n);
+ void SHLL2(uint32_t n);
+ void SHLL8(uint32_t n);
+ void SHLL16(uint32_t n);
+ void SHLR(uint32_t n);
+ void SHLR2(uint32_t n);
+ void SHLR8(uint32_t n);
+ void SHLR16(uint32_t n);
+ void SLEEP();
+ void STCSR(uint32_t n);
+ void STCGBR(uint32_t n);
+ void STCVBR(uint32_t n);
+ void STCMSR(uint32_t n);
+ void STCMGBR(uint32_t n);
+ void STCMVBR(uint32_t n);
+ void STSMACH(uint32_t n);
+ void STSMACL(uint32_t n);
+ void STSPR(uint32_t n);
+ void STSMMACH(uint32_t n);
+ void STSMMACL(uint32_t n);
+ void STSMPR(uint32_t n);
+ void SUB(uint32_t m, uint32_t n);
+ void SUBC(uint32_t m, uint32_t n);
+ void SUBV(uint32_t m, uint32_t n);
+ void SWAPB(uint32_t m, uint32_t n);
+ void SWAPW(uint32_t m, uint32_t n);
+ void TAS(uint32_t n);
+ void TST(uint32_t m, uint32_t n);
+ void TSTI(uint32_t i);
+ void TSTM(uint32_t i);
+ void XOR(uint32_t m, uint32_t n);
+ void XORI(uint32_t i);
+ void XORM(uint32_t i);
+ void XTRCT(uint32_t m, uint32_t n);
+
+ void op0010(uint16_t opcode);
+ void op0011(uint16_t opcode);
+ void op0110(uint16_t opcode);
+ void op1000(uint16_t opcode);
+ void op1100(uint16_t opcode);
+
+ void execute_one(const uint16_t opcode);
+
+ virtual void execute_one_0000(uint16_t opcode);
+ virtual void execute_one_4000(uint16_t opcode);
+ virtual void execute_one_f000(uint16_t opcode) = 0;
+
+ virtual void RTE() = 0;
+ virtual void LDCSR(const uint16_t opcode) = 0;
+ virtual void LDCMSR(const uint16_t opcode) = 0;
+ virtual void TRAPA(uint32_t i) = 0;
+ virtual void ILLEGAL() = 0;
+
+ drc_cache m_cache; /* pointer to the DRC code cache */
+
+public:
+ /* fast RAM */
+ uint32_t m_fastram_select;
+ struct
+ {
+ offs_t start; /* start of the RAM block */
+ offs_t end; /* end of the RAM block */
+ bool readonly; /* true if read-only */
+ void * base; /* base in memory where the RAM lives */
+ } m_fastram[SH2_MAX_FASTRAM];
+
+ int m_pcfsel; // last pcflush entry set
+ uint32_t m_pcflushes[16]; // pcflush entries
+
+ virtual void init_drc_frontend() = 0;
+
+ void drc_start();
+
+ void sh2drc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base);
+
+ direct_read_data *m_direct;
+ address_space *m_program;
+
+ std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */
+ uint32_t m_drcoptions; /* configurable DRC options */
+
+ /* internal stuff */
+ uint8_t m_cache_dirty; /* true if we need to flush the cache */
+
+ /* register mappings */
+ uml::parameter m_regmap[16]; /* parameter to register mappings for all 16 integer registers */
+
+ uml::code_handle * m_entry; /* entry point */
+ uml::code_handle * m_read8; /* read byte */
+ uml::code_handle * m_write8; /* write byte */
+ uml::code_handle * m_read16; /* read half */
+ uml::code_handle * m_write16; /* write half */
+ uml::code_handle * m_read32; /* read word */
+ uml::code_handle * m_write32; /* write word */
+
+ uml::code_handle * m_interrupt; /* interrupt */
+ uml::code_handle * m_nocode; /* nocode */
+ uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */
+
+ /* internal compiler state */
+ struct compiler_state
+ {
+ uint32_t cycles; /* accumulated cycles */
+ uint8_t checkints; /* need to check interrupts before next instruction */
+ uml::code_label labelnum; /* index for local labels */
+ };
+
+ virtual void sh2_exception(const char *message, int irqline) { fatalerror("sh2_exception in base classs\n"); };
+
+ virtual void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, bool allow_exception) = 0;
+
+ virtual bool generate_group_0_RTE(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ virtual bool generate_group_4_LDCSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ virtual bool generate_group_4_LDCMSR(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ virtual bool generate_group_12_TRAPA(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+
+
+ bool generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc);
+ virtual bool generate_group_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ bool generate_group_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ bool generate_group_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, uint32_t ovrpc);
+ virtual bool generate_group_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ bool generate_group_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ bool generate_group_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ bool generate_group_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+ virtual bool generate_group_15(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint16_t opcode, int in_delay_slot, uint32_t ovrpc);
+
+ void func_printf_probe();
+ void func_unimplemented();
+ void func_MAC_W();
+ void func_MAC_L();
+ void func_DIV1();
+ void func_ADDV();
+ void func_SUBV();
+
+ int m_cpu_type;
+ uint32_t m_am;
+ bool m_isdrc;
+ int m_xor;
+
+ void sh2drc_set_options(uint32_t options);
+ void sh2drc_add_pcflush(offs_t address);
+
+ virtual void static_generate_entry_point() = 0;
+ virtual void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle **handleptr) = 0;
+ virtual const opcode_desc* get_desclist(offs_t pc) = 0;
+
+ uint32_t epc(const opcode_desc *desc);
+ 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);
+ const char *log_desc_flags_to_string(uint32_t flags);
+ void log_register_list(drcuml_state *drcuml, const char *string, const uint32_t *reglist, const uint32_t *regnostarlist);
+ void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+ void log_add_disasm_comment(drcuml_block *block, uint32_t pc, uint32_t op);
+ void generate_delay_slot(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, uint32_t ovrpc);
+ 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, uint32_t ovrpc);
+ void static_generate_nocode_handler();
+ void static_generate_out_of_cycles();
+ void code_flush_cache();
+ void execute_run_drc();
+ void code_compile_block(uint8_t mode, offs_t pc);
+
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+};
+
+class sh_frontend : public drc_frontend
+{
+public:
+ sh_frontend(sh_common_execution *device, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
+
+protected:
+ virtual uint16_t read_word(opcode_desc &desc);
+ virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
+
+private:
+ bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+
+protected:
+ virtual bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ virtual bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode);
+ virtual bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, uint16_t opcode) = 0;
+
+ sh_common_execution *m_sh;
+};
+
+#endif // MAME_CPU_SH2_SH2_H