SH4: cleanup and better common/interpreter separation [R. Belmont]

This commit is contained in:
R. Belmont 2011-01-16 00:35:56 +00:00
parent 74bbf1d033
commit b85af379a8
5 changed files with 189 additions and 73 deletions

View File

@ -28,14 +28,9 @@
#include "sh4regs.h"
#include "sh4comn.h"
CPU_DISASSEMBLE( sh4 );
#ifndef USE_SH4DRC
INLINE sh4_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SH4);
return (sh4_state *)downcast<legacy_cpu_device *>(device)->token();
}
CPU_DISASSEMBLE( sh4 );
/* Called for unimplemented opcodes */
static void TODO(sh4_state *sh4)
@ -2079,27 +2074,6 @@ INLINE void LDCSPC(sh4_state *sh4, UINT32 m)
sh4->spc = sh4->r[m];
}
static UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address)
{
if (!sh4->sh4_mmu_enabled)
return address;
else
{
int i;
UINT32 topaddr = address&0xfff00000;
for (i=0;i<64;i++)
{
UINT32 topcmp = sh4->sh4_tlb_address[i]&0xfff00000;
if (topcmp==topaddr)
return (address&0x000fffff) | ((sh4->sh4_tlb_data[i])&0xfff00000);
}
}
return address;
}
/* PREF @Rn */
INLINE void PREFM(sh4_state *sh4, UINT32 n)
{
@ -3622,43 +3596,6 @@ static ADDRESS_MAP_START( sh4_internal_map, ADDRESS_SPACE_PROGRAM, 64 )
ADDRESS_MAP_END
#endif
static READ64_HANDLER( sh4_tlb_r )
{
sh4_state *sh4 = get_safe_token(space->cpu);
int offs = offset*8;
if (offs >= 0x01000000)
{
UINT8 i = (offs>>8)&63;
return sh4->sh4_tlb_data[i];
}
else
{
UINT8 i = (offs>>8)&63;
return sh4->sh4_tlb_address[i];
}
}
static WRITE64_HANDLER( sh4_tlb_w )
{
sh4_state *sh4 = get_safe_token(space->cpu);
int offs = offset*8;
if (offs >= 0x01000000)
{
UINT8 i = (offs>>8)&63;
sh4->sh4_tlb_data[i] = data&0xffffffff;
}
else
{
UINT8 i = (offs>>8)&63;
sh4->sh4_tlb_address[i] = data&0xffffffff;
}
}
/*When OC index mode is on (CCR.OIX = 1)*/
static ADDRESS_MAP_START( sh4_internal_map, ADDRESS_SPACE_PROGRAM, 64 )
AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000)
@ -3884,3 +3821,5 @@ CPU_GET_INFO( sh4 )
}
DEFINE_LEGACY_CPU_DEVICE(SH4, sh4);
#endif // USE_SH4DRC

View File

@ -100,5 +100,19 @@ void sh4_set_irln_input(device_t *device, int value);
void sh4_set_ftcsr_callback(device_t *device, sh4_ftcsr_callback callback);
void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s);
/***************************************************************************
COMPILER-SPECIFIC OPTIONS
***************************************************************************/
#define SH4DRC_STRICT_VERIFY 0x0001 /* verify all instructions */
#define SH4DRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
#define SH4DRC_STRICT_PCREL 0x0004 /* do actual loads on MOVLI/MOVWI instead of collapsing to immediates */
#define SH4DRC_COMPATIBLE_OPTIONS (SH4DRC_STRICT_VERIFY | SH4DRC_FLUSH_PC | SH4DRC_STRICT_PCREL)
#define SH4DRC_FASTEST_OPTIONS (0)
void sh4drc_set_options(device_t *device, UINT32 options);
void sh4drc_add_pcflush(device_t *device, offs_t address);
#endif /* __SH4_H__ */

View File

@ -30,13 +30,6 @@ static const UINT16 tcnt[] = { TCNT0, TCNT1, TCNT2 };
static const UINT16 tcor[] = { TCOR0, TCOR1, TCOR2 };
static const UINT16 tcr[] = { TCR0, TCR1, TCR2 };
INLINE sh4_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SH4);
return (sh4_state *)downcast<legacy_cpu_device *>(device)->token();
}
void sh4_change_register_bank(sh4_state *sh4, int to)
{
int s;
@ -1314,3 +1307,60 @@ void sh4_dma_ddt(device_t *device, struct sh4_ddt_dma *s)
}
}
UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address)
{
if (!sh4->sh4_mmu_enabled)
return address;
else
{
int i;
UINT32 topaddr = address&0xfff00000;
for (i=0;i<64;i++)
{
UINT32 topcmp = sh4->sh4_tlb_address[i]&0xfff00000;
if (topcmp==topaddr)
return (address&0x000fffff) | ((sh4->sh4_tlb_data[i])&0xfff00000);
}
}
return address;
}
READ64_HANDLER( sh4_tlb_r )
{
sh4_state *sh4 = get_safe_token(space->cpu);
int offs = offset*8;
if (offs >= 0x01000000)
{
UINT8 i = (offs>>8)&63;
return sh4->sh4_tlb_data[i];
}
else
{
UINT8 i = (offs>>8)&63;
return sh4->sh4_tlb_address[i];
}
}
WRITE64_HANDLER( sh4_tlb_w )
{
sh4_state *sh4 = get_safe_token(space->cpu);
int offs = offset*8;
if (offs >= 0x01000000)
{
UINT8 i = (offs>>8)&63;
sh4->sh4_tlb_data[i] = data&0xffffffff;
}
else
{
UINT8 i = (offs>>8)&63;
sh4->sh4_tlb_address[i] = data&0xffffffff;
}
}

View File

@ -18,6 +18,17 @@
#define VERBOSE 0
#ifdef USE_SH4DRC
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
class sh4_frontend;
#endif
#define CPU_TYPE_SH3 (2)
#define CPU_TYPE_SH4 (3)
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
#define EXPPRI(pl,po,p,n) (((4-(pl)) << 24) | ((15-(po)) << 16) | ((p) << 8) | (255-(n)))
@ -99,8 +110,88 @@ typedef struct
UINT32 sh4_tlb_data[64];
UINT8 sh4_mmu_enabled;
#ifdef USE_SH4DRC
int icount;
int cpu_type;
int pcfsel; // last pcflush entry set
int maxpcfsel; // highest valid pcflush entry
UINT32 pcflushes[16]; // pcflush entries
drc_cache * cache; /* pointer to the DRC code cache */
drcuml_state * drcuml; /* DRC UML generator state */
sh4_frontend * drcfe; /* pointer to the DRC front-end class */
UINT32 drcoptions; /* configurable DRC options */
/* internal stuff */
UINT8 cache_dirty; /* true if we need to flush the cache */
/* parameters for subroutines */
UINT64 numcycles; /* return value from gettotalcycles */
UINT32 arg0; /* print_debug argument 1 */
UINT32 arg1; /* print_debug argument 2 */
UINT32 irq; /* irq we're taking */
/* register mappings */
drcuml_parameter regmap[16]; /* parameter to register mappings for all 16 integer registers */
drcuml_codehandle * entry; /* entry point */
drcuml_codehandle * read8; /* read byte */
drcuml_codehandle * write8; /* write byte */
drcuml_codehandle * read16; /* read half */
drcuml_codehandle * write16; /* write half */
drcuml_codehandle * read32; /* read word */
drcuml_codehandle * write32; /* write word */
drcuml_codehandle * interrupt; /* interrupt */
drcuml_codehandle * nocode; /* nocode */
drcuml_codehandle * out_of_cycles; /* out of cycles exception handler */
UINT32 prefadr;
UINT32 target;
#endif
} sh4_state;
#ifdef USE_SH4DRC
class sh4_frontend : public drc_frontend
{
public:
sh4_frontend(sh4_state &state, UINT32 window_start, UINT32 window_end, UINT32 max_sequence);
protected:
virtual bool describe(opcode_desc &desc, const opcode_desc *prev);
private:
bool describe_group_0(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_2(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_3(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_4(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_6(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_8(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_12(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
bool describe_group_15(opcode_desc &desc, const opcode_desc *prev, UINT16 opcode);
sh4_state &m_context;
};
INLINE sh4_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SH3 ||
device->type() == SH4);
return *(sh4_state **)downcast<legacy_cpu_device *>(device)->token();
}
#else
INLINE sh4_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SH3 ||
device->type() == SH4);
return (sh4_state *)downcast<legacy_cpu_device *>(device)->token();
}
#endif
enum
{
ICF = 0x00800000,
@ -135,6 +226,24 @@ enum
#define Rn ((opcode>>8)&15)
#define Rm ((opcode>>4)&15)
#define REGFLAG_R(n) (1 << (n))
#define REGFLAG_FR(n) (1 << (n))
#define REGFLAG_XR(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)
#define REGFLAG_SGR (1 << 6)
#define REGFLAG_FPUL (1 << 7)
#define REGFLAG_FPSCR (1 << 8)
#define REGFLAG_DBR (1 << 9)
#define REGFLAG_SSR (1 << 10)
#define REGFLAG_SPC (1 << 11)
void sh4_exception_recompute(sh4_state *sh4); // checks if there is any interrupt with high enough priority
void sh4_exception_request(sh4_state *sh4, int exception); // start requesting an exception
void sh4_exception_unrequest(sh4_state *sh4, int exception); // stop requesting an exception
@ -150,6 +259,10 @@ void sh4_set_irq_line(sh4_state *sh4, int irqline, int state); // set state of e
void sh4_swap_fp_couples(sh4_state *sh4);
#endif
void sh4_common_init(device_t *device);
UINT32 sh4_getsqremap(sh4_state *sh4, UINT32 address);
READ64_HANDLER( sh4_tlb_r );
WRITE64_HANDLER( sh4_tlb_w );
INLINE void sh4_check_pending_irq(sh4_state *sh4, const char *message) // look for highest priority active exception and handle it
{

View File

@ -783,7 +783,7 @@ static UINT32 op1111(char *buffer, UINT32 pc, UINT16 opcode)
return 0;
}
static unsigned DasmSH4(char *buffer, unsigned pc, UINT16 opcode)
unsigned DasmSH4(char *buffer, unsigned pc, UINT16 opcode)
{
UINT32 flags;