lowercasing filenames, part3

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@576 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2008-08-28 12:36:57 +00:00
parent d158df697d
commit 1cfc5cc4ce
71 changed files with 0 additions and 0 deletions

225
pico/carthw/carthw.c Normal file
View file

@ -0,0 +1,225 @@
/*
* Support for a few cart mappers.
*
* (c) Copyright 2008, Grazvydas "notaz" Ignotas
* Free for non-commercial use.
*
*
* I should better do some pointer stuff here. But as none of these bankswitch
* while the game runs, memcpy will suffice.
*/
#include "../pico_int.h"
/* 12-in-1 and 4-in-1. Assuming >= 2MB ROMs here. */
static unsigned int carthw_12in1_baddr = 0;
static carthw_state_chunk carthw_12in1_state[] =
{
{ CHUNK_CARTHW, sizeof(carthw_12in1_baddr), &carthw_12in1_baddr },
{ 0, 0, NULL }
};
static unsigned int carthw_12in1_read16(unsigned int a, int realsize)
{
// ??
elprintf(EL_UIO, "12-in-1: read [%06x] @ %06x", a, SekPc);
return 0;
}
static void carthw_12in1_write8(unsigned int a, unsigned int d, int realsize)
{
int len;
if (a < 0xA13000 || a >= 0xA13040) {
/* 4-in-1 has Real Deal Boxing, which uses serial eeprom,
* but I really doubt that pirate cart had it */
if (a != 0x200001)
elprintf(EL_ANOMALY, "12-in-1: unexpected write [%06x] %02x @ %06x", a, d, SekPc);
return;
}
carthw_12in1_baddr = a;
a &= 0x3f; a <<= 16;
len = Pico.romsize - a;
if (len <= 0) {
elprintf(EL_ANOMALY|EL_STATUS, "12-in-1: missing bank @ %06x", a);
return;
}
memcpy(Pico.rom, Pico.rom + Pico.romsize + a, len);
}
static void carthw_12in1_reset(void)
{
carthw_12in1_write8(0xA13000, 0, 0);
}
static void carthw_12in1_statef(void)
{
carthw_12in1_write8(carthw_12in1_baddr, 0, 0);
}
void carthw_12in1_startup(void)
{
void *tmp;
elprintf(EL_STATUS, "12-in-1 mapper detected");
tmp = realloc(Pico.rom, Pico.romsize * 2);
if (tmp == NULL)
{
elprintf(EL_STATUS, "OOM");
return;
}
Pico.rom = tmp;
memcpy(Pico.rom + Pico.romsize, Pico.rom, Pico.romsize);
PicoRead16Hook = carthw_12in1_read16;
PicoWrite8Hook = carthw_12in1_write8;
PicoResetHook = carthw_12in1_reset;
PicoLoadStateHook = carthw_12in1_statef;
carthw_chunks = carthw_12in1_state;
}
/* Realtec, based on TascoDLX doc
* http://www.sharemation.com/TascoDLX/REALTEC%20Cart%20Mapper%20-%20description%20v1.txt
*/
static int realtec_bank = 0x80000000, realtec_size = 0x80000000;
static int realtec_romsize = 0;
static void carthw_realtec_write8(unsigned int a, unsigned int d, int realsize)
{
int i, bank_old = realtec_bank, size_old = realtec_size;
if (a == 0x400000)
{
realtec_bank &= 0x0e0000;
realtec_bank |= 0x300000 & (d << 19);
if (realtec_bank != bank_old)
elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
}
else if (a == 0x402000)
{
realtec_size = (d << 17) & 0x3e0000;
if (realtec_size != size_old)
elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
}
else if (a == 0x404000)
{
realtec_bank &= 0x300000;
realtec_bank |= 0x0e0000 & (d << 17);
if (realtec_bank != bank_old)
elprintf(EL_ANOMALY, "write [%06x] %02x @ %06x", a, d, SekPc);
}
else
elprintf(EL_ANOMALY, "realtec: unexpected write [%06x] %02x @ %06x", a, d, SekPc);
if (realtec_bank >= 0 && realtec_size >= 0 &&
(realtec_bank != bank_old || realtec_size != size_old))
{
elprintf(EL_ANOMALY, "realtec: new bank %06x, size %06x", realtec_bank, realtec_size, SekPc);
if (realtec_size > realtec_romsize - realtec_bank || realtec_bank >= realtec_romsize)
{
elprintf(EL_ANOMALY, "realtec: bank too large / out of range?");
return;
}
for (i = 0; i < 0x400000; i += realtec_size)
memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_bank, realtec_size);
}
}
static void carthw_realtec_reset(void)
{
int i;
/* map boot code */
for (i = 0; i < 0x400000; i += 0x2000)
memcpy(Pico.rom + i, Pico.rom + 0x400000 + realtec_romsize - 0x2000, 0x2000);
realtec_bank = realtec_size = 0x80000000;
}
void carthw_realtec_startup(void)
{
void *tmp;
elprintf(EL_STATUS, "Realtec mapper detected");
realtec_romsize = Pico.romsize;
Pico.romsize = 0x400000;
tmp = realloc(Pico.rom, 0x400000 + realtec_romsize);
if (tmp == NULL)
{
elprintf(EL_STATUS, "OOM");
return;
}
Pico.rom = tmp;
memcpy(Pico.rom + 0x400000, Pico.rom, realtec_romsize);
PicoWrite8Hook = carthw_realtec_write8;
PicoResetHook = carthw_realtec_reset;
}
/* Radica mapper, based on DevSter's info
* http://devster.monkeeh.com/sega/radica/
*/
static unsigned int carthw_radica_baddr = 0;
static carthw_state_chunk carthw_radica_state[] =
{
{ CHUNK_CARTHW, sizeof(carthw_radica_baddr), &carthw_radica_baddr },
{ 0, 0, NULL }
};
static unsigned int carthw_radica_read16(unsigned int a, int realsize)
{
if ((a & 0xffff80) != 0xa13000) {
elprintf(EL_UIO, "radica: r16 %06x", a);
return 0;
}
carthw_radica_baddr = a;
a = (a & 0x7e) << 15;
if (a >= Pico.romsize) {
elprintf(EL_ANOMALY|EL_STATUS, "radica: missing bank @ %06x", a);
return 0;
}
memcpy(Pico.rom, Pico.rom + Pico.romsize + a, Pico.romsize - a);
return 0;
}
static void carthw_radica_statef(void)
{
carthw_radica_read16(carthw_radica_baddr, 0);
}
static void carthw_radica_reset(void)
{
memcpy(Pico.rom, Pico.rom + Pico.romsize, Pico.romsize);
}
void carthw_radica_startup(void)
{
void *tmp;
elprintf(EL_STATUS, "Radica mapper detected");
tmp = realloc(Pico.rom, Pico.romsize * 2);
if (tmp == NULL)
{
elprintf(EL_STATUS, "OOM");
return;
}
Pico.rom = tmp;
memcpy(Pico.rom + Pico.romsize, Pico.rom, Pico.romsize);
PicoRead16Hook = carthw_radica_read16;
PicoResetHook = carthw_radica_reset;
PicoLoadStateHook = carthw_radica_statef;
carthw_chunks = carthw_radica_state;
}

23
pico/carthw/carthw.h Normal file
View file

@ -0,0 +1,23 @@
/* svp */
#include "svp/ssp16.h"
typedef struct {
unsigned char iram_rom[0x20000]; // IRAM (0-0x7ff) and program ROM (0x800-0x1ffff)
unsigned char dram[0x20000];
ssp1601_t ssp1601;
} svp_t;
extern svp_t *svp;
void PicoSVPInit(void);
void PicoSVPStartup(void);
unsigned int PicoSVPRead16(unsigned int a, int realsize);
void PicoSVPWrite8 (unsigned int a, unsigned int d, int realsize);
void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize);
/* misc */
void carthw_12in1_startup(void);
void carthw_realtec_startup(void);
void carthw_radica_startup(void);

1850
pico/carthw/svp/compiler.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
#define SSP_TCACHE_SIZE (512*1024)
#define SSP_BLOCKTAB_SIZE (0x5090/2*4)
#define SSP_BLOCKTAB_IRAM_SIZE (15*0x800/2*4)
#define SSP_BLOCKTAB_ALIGN_SIZE 3808
#define SSP_DRC_SIZE (SSP_TCACHE_SIZE + SSP_BLOCKTAB_SIZE + SSP_BLOCKTAB_IRAM_SIZE + SSP_BLOCKTAB_ALIGN_SIZE)
extern unsigned int tcache[SSP_TCACHE_SIZE/4];
extern unsigned int *ssp_block_table[0x5090/2];
extern unsigned int *ssp_block_table_iram[15][0x800/2];
int ssp_drc_entry(int cycles);
void ssp_drc_next(void);
void ssp_drc_next_patch(void);
void ssp_drc_end(void);
void ssp_hle_800(void);
void ssp_hle_902(void);
void ssp_hle_07_6d6(void);
void ssp_hle_07_030(void);
void ssp_hle_07_036(void);
void ssp_hle_11_12c(void);
void ssp_hle_11_384(void);
void ssp_hle_11_38a(void);
int ssp1601_dyn_startup(void);
void ssp1601_dyn_reset(ssp1601_t *ssp);
void ssp1601_dyn_run(int cycles);

234
pico/carthw/svp/gen_arm.c Normal file
View file

@ -0,0 +1,234 @@
// Basic macros to emit ARM instructions and some utils
// (c) Copyright 2008, Grazvydas "notaz" Ignotas
// Free for non-commercial use.
#define EMIT(x) *tcache_ptr++ = x
#define A_R4M (1 << 4)
#define A_R5M (1 << 5)
#define A_R6M (1 << 6)
#define A_R7M (1 << 7)
#define A_R8M (1 << 8)
#define A_R9M (1 << 9)
#define A_R10M (1 << 10)
#define A_R11M (1 << 11)
#define A_R14M (1 << 14)
#define A_COND_AL 0xe
#define A_COND_EQ 0x0
#define A_COND_NE 0x1
#define A_COND_MI 0x4
#define A_COND_PL 0x5
#define A_COND_LE 0xd
/* addressing mode 1 */
#define A_AM1_LSL 0
#define A_AM1_LSR 1
#define A_AM1_ASR 2
#define A_AM1_ROR 3
#define A_AM1_IMM(ror2,imm8) (((ror2)<<8) | (imm8) | 0x02000000)
#define A_AM1_REG_XIMM(shift_imm,shift_op,rm) (((shift_imm)<<7) | ((shift_op)<<5) | (rm))
#define A_AM1_REG_XREG(rs,shift_op,rm) (((rs)<<8) | ((shift_op)<<5) | 0x10 | (rm))
/* data processing op */
#define A_OP_AND 0x0
#define A_OP_EOR 0x1
#define A_OP_SUB 0x2
#define A_OP_RSB 0x3
#define A_OP_ADD 0x4
#define A_OP_TST 0x8
#define A_OP_CMP 0xa
#define A_OP_ORR 0xc
#define A_OP_MOV 0xd
#define A_OP_BIC 0xe
#define EOP_C_DOP_X(cond,op,s,rn,rd,shifter_op) \
EMIT(((cond)<<28) | ((op)<< 21) | ((s)<<20) | ((rn)<<16) | ((rd)<<12) | (shifter_op))
#define EOP_C_DOP_IMM( cond,op,s,rn,rd,ror2,imm8) EOP_C_DOP_X(cond,op,s,rn,rd,A_AM1_IMM(ror2,imm8))
#define EOP_C_DOP_REG_XIMM(cond,op,s,rn,rd,shift_imm,shift_op,rm) EOP_C_DOP_X(cond,op,s,rn,rd,A_AM1_REG_XIMM(shift_imm,shift_op,rm))
#define EOP_C_DOP_REG_XREG(cond,op,s,rn,rd,rs, shift_op,rm) EOP_C_DOP_X(cond,op,s,rn,rd,A_AM1_REG_XREG(rs, shift_op,rm))
#define EOP_MOV_IMM(rd, ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_MOV,0, 0,rd,ror2,imm8)
#define EOP_ORR_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_ORR,0,rn,rd,ror2,imm8)
#define EOP_ADD_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_ADD,0,rn,rd,ror2,imm8)
#define EOP_BIC_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_BIC,0,rn,rd,ror2,imm8)
#define EOP_AND_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_AND,0,rn,rd,ror2,imm8)
#define EOP_SUB_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_SUB,0,rn,rd,ror2,imm8)
#define EOP_TST_IMM( rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_TST,1,rn, 0,ror2,imm8)
#define EOP_CMP_IMM( rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_CMP,1,rn, 0,ror2,imm8)
#define EOP_RSB_IMM(rd,rn,ror2,imm8) EOP_C_DOP_IMM(A_COND_AL,A_OP_RSB,0,rn,rd,ror2,imm8)
#define EOP_MOV_REG(s, rd,shift_imm,shift_op,rm) EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_MOV,s, 0,rd,shift_imm,shift_op,rm)
#define EOP_ORR_REG(s,rn,rd,shift_imm,shift_op,rm) EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_ORR,s,rn,rd,shift_imm,shift_op,rm)
#define EOP_ADD_REG(s,rn,rd,shift_imm,shift_op,rm) EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_ADD,s,rn,rd,shift_imm,shift_op,rm)
#define EOP_TST_REG( rn, shift_imm,shift_op,rm) EOP_C_DOP_REG_XIMM(A_COND_AL,A_OP_TST,1,rn, 0,shift_imm,shift_op,rm)
#define EOP_MOV_REG2(s, rd,rs,shift_op,rm) EOP_C_DOP_REG_XREG(A_COND_AL,A_OP_MOV,s, 0,rd,rs,shift_op,rm)
#define EOP_ADD_REG2(s,rn,rd,rs,shift_op,rm) EOP_C_DOP_REG_XREG(A_COND_AL,A_OP_ADD,s,rn,rd,rs,shift_op,rm)
#define EOP_SUB_REG2(s,rn,rd,rs,shift_op,rm) EOP_C_DOP_REG_XREG(A_COND_AL,A_OP_SUB,s,rn,rd,rs,shift_op,rm)
#define EOP_MOV_REG_SIMPLE(rd,rm) EOP_MOV_REG(0,rd,0,A_AM1_LSL,rm)
#define EOP_MOV_REG_LSL(rd, rm,shift_imm) EOP_MOV_REG(0,rd,shift_imm,A_AM1_LSL,rm)
#define EOP_MOV_REG_LSR(rd, rm,shift_imm) EOP_MOV_REG(0,rd,shift_imm,A_AM1_LSR,rm)
#define EOP_MOV_REG_ASR(rd, rm,shift_imm) EOP_MOV_REG(0,rd,shift_imm,A_AM1_ASR,rm)
#define EOP_MOV_REG_ROR(rd, rm,shift_imm) EOP_MOV_REG(0,rd,shift_imm,A_AM1_ROR,rm)
#define EOP_ORR_REG_SIMPLE(rd,rm) EOP_ORR_REG(0,rd,rd,0,A_AM1_LSL,rm)
#define EOP_ORR_REG_LSL(rd,rn,rm,shift_imm) EOP_ORR_REG(0,rn,rd,shift_imm,A_AM1_LSL,rm)
#define EOP_ORR_REG_LSR(rd,rn,rm,shift_imm) EOP_ORR_REG(0,rn,rd,shift_imm,A_AM1_LSR,rm)
#define EOP_ORR_REG_ASR(rd,rn,rm,shift_imm) EOP_ORR_REG(0,rn,rd,shift_imm,A_AM1_ASR,rm)
#define EOP_ORR_REG_ROR(rd,rn,rm,shift_imm) EOP_ORR_REG(0,rn,rd,shift_imm,A_AM1_ROR,rm)
#define EOP_ADD_REG_SIMPLE(rd,rm) EOP_ADD_REG(0,rd,rd,0,A_AM1_LSL,rm)
#define EOP_ADD_REG_LSL(rd,rn,rm,shift_imm) EOP_ADD_REG(0,rn,rd,shift_imm,A_AM1_LSL,rm)
#define EOP_ADD_REG_LSR(rd,rn,rm,shift_imm) EOP_ADD_REG(0,rn,rd,shift_imm,A_AM1_LSR,rm)
#define EOP_TST_REG_SIMPLE(rn,rm) EOP_TST_REG( rn, 0,A_AM1_LSL,rm)
#define EOP_MOV_REG2_LSL(rd, rm,rs) EOP_MOV_REG2(0, rd,rs,A_AM1_LSL,rm)
#define EOP_MOV_REG2_ROR(rd, rm,rs) EOP_MOV_REG2(0, rd,rs,A_AM1_ROR,rm)
#define EOP_ADD_REG2_LSL(rd,rn,rm,rs) EOP_ADD_REG2(0,rn,rd,rs,A_AM1_LSL,rm)
#define EOP_SUB_REG2_LSL(rd,rn,rm,rs) EOP_SUB_REG2(0,rn,rd,rs,A_AM1_LSL,rm)
/* addressing mode 2 */
#define EOP_C_AM2_IMM(cond,u,b,l,rn,rd,offset_12) \
EMIT(((cond)<<28) | 0x05000000 | ((u)<<23) | ((b)<<22) | ((l)<<20) | ((rn)<<16) | ((rd)<<12) | (offset_12))
/* addressing mode 3 */
#define EOP_C_AM3(cond,u,r,l,rn,rd,s,h,immed_reg) \
EMIT(((cond)<<28) | 0x01000090 | ((u)<<23) | ((r)<<22) | ((l)<<20) | ((rn)<<16) | ((rd)<<12) | \
((s)<<6) | ((h)<<5) | (immed_reg))
#define EOP_C_AM3_IMM(cond,u,l,rn,rd,s,h,offset_8) EOP_C_AM3(cond,u,1,l,rn,rd,s,h,(((offset_8)&0xf0)<<4)|((offset_8)&0xf))
#define EOP_C_AM3_REG(cond,u,l,rn,rd,s,h,rm) EOP_C_AM3(cond,u,0,l,rn,rd,s,h,rm)
/* ldr and str */
#define EOP_LDR_IMM( rd,rn,offset_12) EOP_C_AM2_IMM(A_COND_AL,1,0,1,rn,rd,offset_12)
#define EOP_LDR_NEGIMM(rd,rn,offset_12) EOP_C_AM2_IMM(A_COND_AL,0,0,1,rn,rd,offset_12)
#define EOP_LDR_SIMPLE(rd,rn) EOP_C_AM2_IMM(A_COND_AL,1,0,1,rn,rd,0)
#define EOP_STR_IMM( rd,rn,offset_12) EOP_C_AM2_IMM(A_COND_AL,1,0,0,rn,rd,offset_12)
#define EOP_STR_SIMPLE(rd,rn) EOP_C_AM2_IMM(A_COND_AL,1,0,0,rn,rd,0)
#define EOP_LDRH_IMM( rd,rn,offset_8) EOP_C_AM3_IMM(A_COND_AL,1,1,rn,rd,0,1,offset_8)
#define EOP_LDRH_SIMPLE(rd,rn) EOP_C_AM3_IMM(A_COND_AL,1,1,rn,rd,0,1,0)
#define EOP_LDRH_REG( rd,rn,rm) EOP_C_AM3_REG(A_COND_AL,1,1,rn,rd,0,1,rm)
#define EOP_STRH_IMM( rd,rn,offset_8) EOP_C_AM3_IMM(A_COND_AL,1,0,rn,rd,0,1,offset_8)
#define EOP_STRH_SIMPLE(rd,rn) EOP_C_AM3_IMM(A_COND_AL,1,0,rn,rd,0,1,0)
#define EOP_STRH_REG( rd,rn,rm) EOP_C_AM3_REG(A_COND_AL,1,0,rn,rd,0,1,rm)
/* ldm and stm */
#define EOP_XXM(cond,p,u,s,w,l,rn,list) \
EMIT(((cond)<<28) | (1<<27) | ((p)<<24) | ((u)<<23) | ((s)<<22) | ((w)<<21) | ((l)<<20) | ((rn)<<16) | (list))
#define EOP_STMFD_ST(list) EOP_XXM(A_COND_AL,1,0,0,1,0,13,list)
#define EOP_LDMFD_ST(list) EOP_XXM(A_COND_AL,0,1,0,1,1,13,list)
/* branches */
#define EOP_C_BX(cond,rm) \
EMIT(((cond)<<28) | 0x012fff10 | (rm))
#define EOP_BX(rm) EOP_C_BX(A_COND_AL,rm)
#define EOP_C_B(cond,l,signed_immed_24) \
EMIT(((cond)<<28) | 0x0a000000 | ((l)<<24) | (signed_immed_24))
#define EOP_B( signed_immed_24) EOP_C_B(A_COND_AL,0,signed_immed_24)
#define EOP_BL(signed_immed_24) EOP_C_B(A_COND_AL,1,signed_immed_24)
/* misc */
#define EOP_C_MUL(cond,s,rd,rs,rm) \
EMIT(((cond)<<28) | ((s)<<20) | ((rd)<<16) | ((rs)<<8) | 0x90 | (rm))
#define EOP_MUL(rd,rm,rs) EOP_C_MUL(A_COND_AL,0,rd,rs,rm) // note: rd != rm
#define EOP_C_MRS(cond,rd) \
EMIT(((cond)<<28) | 0x010f0000 | ((rd)<<12))
#define EOP_C_MSR_IMM(cond,ror2,imm) \
EMIT(((cond)<<28) | 0x0328f000 | ((ror2)<<8) | (imm)) // cpsr_f
#define EOP_C_MSR_REG(cond,rm) \
EMIT(((cond)<<28) | 0x0128f000 | (rm)) // cpsr_f
#define EOP_MRS(rd) EOP_C_MRS(A_COND_AL,rd)
#define EOP_MSR_IMM(ror2,imm) EOP_C_MSR_IMM(A_COND_AL,ror2,imm)
#define EOP_MSR_REG(rm) EOP_C_MSR_REG(A_COND_AL,rm)
static void emit_mov_const(int cond, int d, unsigned int val)
{
int need_or = 0;
if (val & 0xff000000) {
EOP_C_DOP_IMM(cond, A_OP_MOV, 0, 0, d, 8/2, (val>>24)&0xff);
need_or = 1;
}
if (val & 0x00ff0000) {
EOP_C_DOP_IMM(cond, need_or ? A_OP_ORR : A_OP_MOV, 0, need_or ? d : 0, d, 16/2, (val>>16)&0xff);
need_or = 1;
}
if (val & 0x0000ff00) {
EOP_C_DOP_IMM(cond, need_or ? A_OP_ORR : A_OP_MOV, 0, need_or ? d : 0, d, 24/2, (val>>8)&0xff);
need_or = 1;
}
if ((val &0x000000ff) || !need_or)
EOP_C_DOP_IMM(cond, need_or ? A_OP_ORR : A_OP_MOV, 0, need_or ? d : 0, d, 0, val&0xff);
}
static int is_offset_24(int val)
{
if (val >= (int)0xff000000 && val <= 0x00ffffff) return 1;
return 0;
}
static int emit_xbranch(int cond, void *target, int is_call)
{
int val = (unsigned int *)target - tcache_ptr - 2;
int direct = is_offset_24(val);
u32 *start_ptr = tcache_ptr;
if (direct)
{
EOP_C_B(cond,is_call,val & 0xffffff); // b, bl target
}
else
{
#ifdef __EPOC32__
// elprintf(EL_SVP, "emitting indirect jmp %08x->%08x", tcache_ptr, target);
if (is_call)
EOP_ADD_IMM(14,15,0,8); // add lr,pc,#8
EOP_C_AM2_IMM(cond,1,0,1,15,15,0); // ldrcc pc,[pc]
EOP_MOV_REG_SIMPLE(15,15); // mov pc, pc
EMIT((u32)target);
#else
// should never happen
elprintf(EL_STATUS|EL_SVP|EL_ANOMALY, "indirect jmp %08x->%08x", target, tcache_ptr);
exit(1);
#endif
}
return tcache_ptr - start_ptr;
}
static int emit_call(int cond, void *target)
{
return emit_xbranch(cond, target, 1);
}
static int emit_jump(int cond, void *target)
{
return emit_xbranch(cond, target, 0);
}
static void handle_caches(void)
{
#ifdef ARM
extern void cache_flush_d_inval_i(const void *start_addr, const void *end_addr);
cache_flush_d_inval_i(tcache, tcache_ptr);
#endif
}

View file

@ -0,0 +1,67 @@
vscroll: 1 (0); 209 (26) - alternates every 4 frames
vram range for patterns: 0000-999f (low scr 0000-395f,72e0-999f; high 3980-999f)
name table address: c000
seen DMAs (in order): [300002-3026c3]->[0020-26e1] len 4961
[3026c2-303943]->[26e0-3961] len 2369
[303942-306003]->[72e0-99a1] len 4961
---
[306002-3086c3]->[3980-6041] len 4961
[3086c2-309943]->[6040-72c1] len 2369
[309942-30c003]->[72e0-99a2] len 4961
tile arrangement:
000: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
001: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
002: 001 003 005 007 009 00b 00d 00f 011 013 015 017 019 01b 01d 01f 021 023 025 027 029 02b 02d 02f 031 033 035 037 039 03b 03d 03f
003: 002 004 006 008 00a 00c 00e 010 012 014 016 018 01a 01c 01e 020 022 024 026 028 02a 02c 02e 030 032 034 036 038 03a 03c 03e 040
004: 041 043 045 047 049 04b 04d 04f 051 053 055 057 059 05b 05d 05f 061 063 065 067 069 06b 06d 06f 071 073 075 077 079 07b 07d 07f
005: 042 044 046 048 04a 04c 04e 050 052 054 056 058 05a 05c 05e 060 062 064 066 068 06a 06c 06e 070 072 074 076 078 07a 07c 07e 080
006: 081 083 085 087 089 08b 08d 08f 091 093 095 097 099 09b 09d 09f 0a1 0a3 0a5 0a7 0a9 0ab 0ad 0af 0b1 0b3 0b5 0b7 0b9 0bb 0bd 0bf
007: 082 084 086 088 08a 08c 08e 090 092 094 096 098 09a 09c 09e 0a0 0a2 0a4 0a6 0a8 0aa 0ac 0ae 0b0 0b2 0b4 0b6 0b8 0ba 0bc 0be 0c0
008: 0c1 0c3 0c5 0c7 0c9 0cb 0cd 0cf 0d1 0d3 0d5 0d7 0d9 0db 0dd 0df 0e1 0e3 0e5 0e7 0e9 0eb 0ed 0ef 0f1 0f3 0f5 0f7 0f9 0fb 0fd 0ff
009: 0c2 0c4 0c6 0c8 0ca 0cc 0ce 0d0 0d2 0d4 0d6 0d8 0da 0dc 0de 0e0 0e2 0e4 0e6 0e8 0ea 0ec 0ee 0f0 0f2 0f4 0f6 0f8 0fa 0fc 0fe 100
010: 101 103 105 107 109 10b 10d 10f 111 113 115 117 119 11b 11d 11f 121 123 125 127 129 12b 12d 12f 131 133 135 137 139 13b 13d 13f
011: 102 104 106 108 10a 10c 10e 110 112 114 116 118 11a 11c 11e 120 122 124 126 128 12a 12c 12e 130 132 134 136 138 13a 13c 13e 140
012: 141 143 145 147 149 14b 14d 14f 151 153 155 157 159 15b 15d 15f 161 163 165 167 169 16b 16d 16f 171 173 175 177 179 17b 17d 17f
013: 142 144 146 148 14a 14c 14e 150 152 154 156 158 15a 15c 15e 160 162 164 166 168 16a 16c 16e 170 172 174 176 178 17a 17c 17e 180
014: 181 183 185 187 189 18b 18d 18f 191 193 195 197 199 19b 19d 19f 1a1 1a3 1a5 1a7 1a9 1ab 1ad 1af 1b1 1b3 1b5 1b7 1b9 1bb 1bd 1bf
015: 182 184 186 188 18a 18c 18e 190 192 194 196 198 19a 19c 19e 1a0 1a2 1a4 1a6 1a8 1aa 1ac 1ae 1b0 1b2 1b4 1b6 1b8 1ba 1bc 1be 1c0
016: 1c1 1c3 1c5 1c7 1c9 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
017: 1c2 1c4 1c6 1c8 1ca 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
018: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
019: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
020: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
021: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
022: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
023: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
024: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
025: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
026: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
027: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
028: 1cc 1ce 1d0 1d2 1d4 1d6 1d8 1da 1dc 1de 1e0 1e2 1e4 1e6 1e8 1ea 1ec 1ee 1f0 1f2 1f4 1f6 1f8 1fa 1fc 1fe 200 202 204 206 208 20a
029: 1cd 1cf 1d1 1d3 1d5 1d7 1d9 1db 1dd 1df 1e1 1e3 1e5 1e7 1e9 1eb 1ed 1ef 1f1 1f3 1f5 1f7 1f9 1fb 1fd 1ff 201 203 205 207 209 20b
030: 20c 20e 210 212 214 216 218 21a 21c 21e 220 222 224 226 228 22a 22c 22e 230 232 234 236 238 23a 23c 23e 240 242 244 246 248 24a
031: 20d 20f 211 213 215 217 219 21b 21d 21f 221 223 225 227 229 22b 22d 22f 231 233 235 237 239 23b 23d 23f 241 243 245 247 249 24b
032: 24c 24e 250 252 254 256 258 25a 25c 25e 260 262 264 266 268 26a 26c 26e 270 272 274 276 278 27a 27c 27e 280 282 284 286 288 28a
033: 24d 24f 251 253 255 257 259 25b 25d 25f 261 263 265 267 269 26b 26d 26f 271 273 275 277 279 27b 27d 27f 281 283 285 287 289 28b
034: 28c 28e 290 292 294 296 298 29a 29c 29e 2a0 2a2 2a4 2a6 2a8 2aa 2ac 2ae 2b0 2b2 2b4 2b6 2b8 2ba 2bc 2be 2c0 2c2 2c4 2c6 2c8 2ca
035: 28d 28f 291 293 295 297 299 29b 29d 29f 2a1 2a3 2a5 2a7 2a9 2ab 2ad 2af 2b1 2b3 2b5 2b7 2b9 2bb 2bd 2bf 2c1 2c3 2c5 2c7 2c9 2cb
036: 2cc 2ce 2d0 2d2 2d4 2d6 2d8 2da 2dc 2de 2e0 2e2 2e4 2e6 2e8 2ea 2ec 2ee 2f0 2f2 2f4 2f6 2f8 2fa 2fc 2fe 300 302 304 306 308 30a
037: 2cd 2cf 2d1 2d3 2d5 2d7 2d9 2db 2dd 2df 2e1 2e3 2e5 2e7 2e9 2eb 2ed 2ef 2f1 2f3 2f5 2f7 2f9 2fb 2fd 2ff 301 303 305 307 309 30b
038: 30c 30e 310 312 314 316 318 31a 31c 31e 320 322 324 326 328 32a 32c 32e 330 332 334 336 338 33a 33c 33e 340 342 344 346 348 34a
039: 30d 30f 311 313 315 317 319 31b 31d 31f 321 323 325 327 329 32b 32d 32f 331 333 335 337 339 33b 33d 33f 341 343 345 347 349 34b
040: 34c 34e 350 352 354 356 358 35a 35c 35e 360 362 364 366 368 36a 36c 36e 370 372 374 376 378 37a 37c 37e 380 382 384 386 388 38a
041: 34d 34f 351 353 355 357 359 35b 35d 35f 361 363 365 367 369 36b 36d 36f 371 373 375 377 379 37b 37d 37f 381 383 385 387 389 38b
042: 38c 38e 390 392 394 397 399 39b 39d 39f 3a1 3a3 3a5 3a7 3a9 3ab 3ad 3af 3b1 3b3 3b5 3b7 3b9 3bb 3bd 3bf 3c1 3c3 3c5 3c7 3c9 3cb
043: 38d 38f 391 393 395 398 39a 39c 39e 3a0 3a2 3a4 3a6 3a8 3aa 3ac 3ae 3b0 3b2 3b4 3b6 3b8 3ba 3bc 3be 3c0 3c2 3c4 3c6 3c8 3ca 3cc
044: 3cd 3cf 3d1 3d3 3d5 3d7 3d9 3db 3dd 3df 3e1 3e3 3e5 3e7 3e9 3eb 3ed 3ef 3f1 3f3 3f5 3f7 3f9 3fb 3fd 3ff 401 403 405 407 409 40b
045: 3ce 3d0 3d2 3d4 3d6 3d8 3da 3dc 3de 3e0 3e2 3e4 3e6 3e8 3ea 3ec 3ee 3f0 3f2 3f4 3f6 3f8 3fa 3fc 3fe 400 402 404 406 408 40a 40c
046: 40d 40f 411 413 415 417 419 41b 41d 41f 421 423 425 427 429 42b 42d 42f 431 433 435 437 439 43b 43d 43f 441 443 445 447 449 44b
047: 40e 410 412 414 416 418 41a 41c 41e 420 422 424 426 428 42a 42c 42e 430 432 434 436 438 43a 43c 43e 440 442 444 446 448 44a 44c
048: 44d 44f 451 453 455 457 459 45b 45d 45f 461 463 465 467 469 46b 46d 46f 471 473 475 477 479 47b 47d 47f 481 483 485 487 489 48b
049: 44e 450 452 454 456 458 45a 45c 45e 460 462 464 466 468 46a 46c 46e 470 472 474 476 478 47a 47c 47e 480 482 484 486 488 48a 48c
050: 48d 48f 491 493 495 497 499 49b 49d 49f 4a1 4a3 4a5 4a7 4a9 4ab 4ad 4af 4b1 4b3 4b5 4b7 4b9 4bb 4bd 4bf 4c1 4c3 4c5 4c7 4c9 4cb
051: 48e 490 492 494 496 498 49a 49c 49e 4a0 4a2 4a4 4a6 4a8 4aa 4ac 4ae 4b0 4b2 4b4 4b6 4b8 4ba 4bc 4be 4c0 4c2 4c4 4c6 4c8 4ca 4cc
052: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
053: 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

129
pico/carthw/svp/memory.c Normal file
View file

@ -0,0 +1,129 @@
// The SVP chip emulator, mem I/O stuff
// (c) Copyright 2008, Grazvydas "notaz" Ignotas
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include "../../pico_int.h"
#ifndef UTYPES_DEFINED
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
#define UTYPES_DEFINED
#endif
#define CLEAR_DETECT(pc_start,pc_end,text) \
if (d == 0 && SekPc >= pc_start && SekPc < pc_end) \
{ \
if (!clearing_ram) \
elprintf(EL_SVP, text); \
clearing_ram = 1; \
return; \
}
unsigned int PicoSVPRead16(unsigned int a, int realsize)
{
unsigned int d = 0;
static int a15004_looping = 0;
// dram: 300000-31ffff
if ((a & 0xfe0000) == 0x300000)
d = *(u16 *)(svp->dram + (a&0x1fffe));
// "cell arrange" 1: 390000-39ffff
else if ((a & 0xff0000) == 0x390000) {
// this is rewritten 68k code
unsigned int a1 = a >> 1;
a1 = (a1 & 0x7001) | ((a1 & 0x3e) << 6) | ((a1 & 0xfc0) >> 5);
d = ((u16 *)svp->dram)[a1];
}
// "cell arrange" 2: 3a0000-3affff
else if ((a & 0xff0000) == 0x3a0000) {
// this is rewritten 68k code
unsigned int a1 = a >> 1;
a1 = (a1 & 0x7801) | ((a1 & 0x1e) << 6) | ((a1 & 0x7e0) >> 4);
d = ((u16 *)svp->dram)[a1];
}
// regs
else if ((a & 0xfffff0) == 0xa15000) {
switch (a & 0xf) {
case 0:
case 2:
d = svp->ssp1601.gr[SSP_XST].h;
break;
case 4:
d = svp->ssp1601.gr[SSP_PM0].h;
svp->ssp1601.gr[SSP_PM0].h &= ~1;
if (d&1) a15004_looping = 0;
break;
}
}
else
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "SVP FIXME: unhandled r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
if (!a15004_looping)
elprintf(EL_SVP, "SVP r%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
if (a == 0xa15004 && !(d&1)) {
if (!a15004_looping)
elprintf(EL_SVP, "SVP det TIGHT loop: a15004");
a15004_looping = 1;
}
else a15004_looping = 0;
//if (a == 0x30fe02 && d == 0)
// elprintf(EL_ANOMALY, "SVP lag?");
return d;
}
void PicoSVPWrite8(unsigned int a, unsigned int d, int realsize)
{
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "!!! SVP w%i: [%06x], %08x @%06x", realsize, a&0xffffff, d, SekPc);
}
void PicoSVPWrite16(unsigned int a, unsigned int d, int realsize)
{
static int clearing_ram = 0;
// DRAM
if ((a & 0xfe0000) == 0x300000)
*(u16 *)(svp->dram + (a&0x1fffe)) = d;
// regs
else if ((a & 0xfffff0) == 0xa15000) {
if (a == 0xa15000 || a == 0xa15002) {
// just guessing here
svp->ssp1601.gr[SSP_XST].h = d;
svp->ssp1601.gr[SSP_PM0].h |= 2;
svp->ssp1601.emu_status &= ~SSP_WAIT_PM0;
}
//else if (a == 0xa15006) svp->ssp1601.gr[SSP_PM0].h = d | (d << 1);
// 0xa15006 probably has 'halt'
}
else
elprintf(EL_UIO|EL_SVP|EL_ANOMALY, "SVP FIXME: unhandled w%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
if (a == 0x30fe06 && d != 0)
svp->ssp1601.emu_status &= ~SSP_WAIT_30FE06;
if (a == 0x30fe08 && d != 0)
svp->ssp1601.emu_status &= ~SSP_WAIT_30FE08;
// debug: detect RAM clears..
CLEAR_DETECT(0x0221dc, 0x0221f0, "SVP RAM CLEAR (full) @ 0221C2");
CLEAR_DETECT(0x02204c, 0x022068, "SVP RAM CLEAR 300000-31ffbf (1) @ 022032");
CLEAR_DETECT(0x021900, 0x021ff0, "SVP RAM CLEAR 300000-305fff");
CLEAR_DETECT(0x0220b0, 0x0220cc, "SVP RAM CLEAR 300000-31ffbf (2) @ 022096");
clearing_ram = 0;
elprintf(EL_SVP, "SVP w%i: [%06x] %04x @%06x", realsize, a&0xffffff, d, SekPc);
}

1224
pico/carthw/svp/ssp16.c Normal file

File diff suppressed because it is too large Load diff

72
pico/carthw/svp/ssp16.h Normal file
View file

@ -0,0 +1,72 @@
// basic, incomplete SSP160x (SSP1601?) interpreter
// (c) Copyright 2008, Grazvydas "notaz" Ignotas
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
// register names
enum {
SSP_GR0, SSP_X, SSP_Y, SSP_A,
SSP_ST, SSP_STACK, SSP_PC, SSP_P,
SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
};
typedef union
{
unsigned int v;
struct {
unsigned short l;
unsigned short h;
};
} ssp_reg_t;
typedef struct
{
union {
unsigned short RAM[256*2]; // 000 2 internal RAM banks
struct {
unsigned short RAM0[256];
unsigned short RAM1[256];
};
};
ssp_reg_t gr[16]; // 400 general registers
union {
unsigned char r[8]; // 440 BANK pointers
struct {
unsigned char r0[4];
unsigned char r1[4];
};
};
unsigned short stack[6]; // 448
unsigned int pmac_read[6]; // 454 read modes/addrs for PM0-PM5
unsigned int pmac_write[6]; // 46c write ...
//
#define SSP_PMC_HAVE_ADDR 0x0001 // address written to PMAC, waiting for mode
#define SSP_PMC_SET 0x0002 // PMAC is set
#define SSP_WAIT_PM0 0x2000 // bit1 in PM0
#define SSP_WAIT_30FE06 0x4000 // ssp tight loops on 30FE06 to become non-zero
#define SSP_WAIT_30FE08 0x8000 // same for 30FE06
#define SSP_WAIT_MASK 0xe000
unsigned int emu_status; // 484
/* used by recompiler only: */
struct {
unsigned int ptr_rom; // 488
unsigned int ptr_iram_rom; // 48c
unsigned int ptr_dram; // 490
unsigned int iram_dirty; // 494
unsigned int iram_context; // 498
unsigned int ptr_btable; // 49c
unsigned int ptr_btable_iram; // 4a0
unsigned int tmp0; // 4a4
unsigned int tmp1; // 4a8
unsigned int tmp2; // 4ac
} drc;
} ssp1601_t;
void ssp1601_reset(ssp1601_t *ssp);
void ssp1601_run(int cycles);

640
pico/carthw/svp/stub_arm.S Normal file
View file

@ -0,0 +1,640 @@
@ vim:filetype=armasm
@ Compiler helper functions and some SVP HLE code
@ (c) Copyright 2008, Grazvydas "notaz" Ignotas
@ Free for non-commercial use.
.if 0
#include "compiler.h"
.endif
.global tcache
.global ssp_block_table
.global ssp_block_table_iram
.global ssp_drc_entry
.global ssp_drc_next
.global ssp_drc_next_patch
.global ssp_drc_end
.global ssp_hle_800
.global ssp_hle_902
.global ssp_hle_07_030
.global ssp_hle_07_036
.global ssp_hle_07_6d6
.global ssp_hle_11_12c
.global ssp_hle_11_384
.global ssp_hle_11_38a
@ translation cache buffer + pointer table
.data
.align 12 @ 4096
@.size tcache, SSP_TCACHE_SIZE
@.size ssp_block_table, SSP_BLOCKTAB_SIZE
@.size ssp_block_table_iram, SSP_BLOCKTAB_IRAM_SIZE
tcache:
.space SSP_TCACHE_SIZE
ssp_block_table:
.space SSP_BLOCKTAB_SIZE
ssp_block_table_iram:
.space SSP_BLOCKTAB_IRAM_SIZE
.space SSP_BLOCKTAB_ALIGN_SIZE
.text
.align 2
@ SSP_GR0, SSP_X, SSP_Y, SSP_A,
@ SSP_ST, SSP_STACK, SSP_PC, SSP_P,
@ SSP_PM0, SSP_PM1, SSP_PM2, SSP_XST,
@ SSP_PM4, SSP_gr13, SSP_PMC, SSP_AL
@ register map:
@ r4: XXYY
@ r5: A
@ r6: STACK and emu flags: sss0 * .uu. .lll NZCV (NZCV is PSR bits from ARM)
@ r7: SSP context
@ r8: r0-r2 (.210)
@ r9: r4-r6 (.654)
@ r10: P
@ r11: cycles
@ r12: tmp
#define SSP_OFFS_GR 0x400
#define SSP_PC 6
#define SSP_P 7
#define SSP_PM0 8
#define SSP_PMC 14
#define SSP_OFFS_PM_WRITE 0x46c // pmac_write[]
#define SSP_OFFS_EMUSTAT 0x484 // emu_status
#define SSP_OFFS_IRAM_ROM 0x48c // ptr_iram_rom
#define SSP_OFFS_DRAM 0x490 // ptr_dram
#define SSP_OFFS_IRAM_DIRTY 0x494
#define SSP_OFFS_IRAM_CTX 0x498 // iram_context
#define SSP_OFFS_BLTAB 0x49c // block_table
#define SSP_OFFS_BLTAB_IRAM 0x4a0
#define SSP_OFFS_TMP0 0x4a4 // for entry PC
#define SSP_OFFS_TMP1 0x4a8
#define SSP_OFFS_TMP2 0x4ac
#define SSP_WAIT_PM0 0x2000
.macro ssp_drc_do_next patch_jump=0
.if \patch_jump
str lr, [r7, #SSP_OFFS_TMP2] @ jump instr. (actually call) address + 4
.endif
mov r0, r0, lsl #16
mov r0, r0, lsr #16
str r0, [r7, #SSP_OFFS_TMP0]
cmp r0, #0x400
blt 0f @ ssp_de_iram
ldr r2, [r7, #SSP_OFFS_BLTAB]
ldr r2, [r2, r0, lsl #2]
tst r2, r2
.if \patch_jump
bne ssp_drc_do_patch
.else
bxne r2
.endif
bl ssp_translate_block
mov r2, r0
ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC
ldr r1, [r7, #SSP_OFFS_BLTAB]
str r2, [r1, r0, lsl #2]
.if \patch_jump
b ssp_drc_do_patch
.else
bx r2
.endif
0: @ ssp_de_iram:
ldr r1, [r7, #SSP_OFFS_IRAM_DIRTY]
tst r1, r1
ldreq r1, [r7, #SSP_OFFS_IRAM_CTX]
beq 1f @ ssp_de_iram_ctx
bl ssp_get_iram_context
mov r1, #0
str r1, [r7, #SSP_OFFS_IRAM_DIRTY]
mov r1, r0
str r1, [r7, #SSP_OFFS_IRAM_CTX]
ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC
1: @ ssp_de_iram_ctx:
ldr r2, [r7, #SSP_OFFS_BLTAB_IRAM]
add r2, r2, r1, lsl #12 @ block_tab_iram + iram_context * 0x800/2*4
add r1, r2, r0, lsl #2
ldr r2, [r1]
tst r2, r2
.if \patch_jump
bne ssp_drc_do_patch
.else
bxne r2
.endif
str r1, [r7, #SSP_OFFS_TMP1]
bl ssp_translate_block
mov r2, r0
ldr r0, [r7, #SSP_OFFS_TMP0] @ entry PC
ldr r1, [r7, #SSP_OFFS_TMP1] @ &block_table_iram[iram_context][rPC]
str r2, [r1]
.if \patch_jump
b ssp_drc_do_patch
.else
bx r2
.endif
.endm @ ssp_drc_do_next
ssp_drc_entry:
stmfd sp!, {r4-r11, lr}
mov r11, r0
ssp_regfile_load:
ldr r7, =ssp
ldr r7, [r7]
add r2, r7, #0x400
add r2, r2, #4
ldmia r2, {r3,r4,r5,r6,r8}
mov r3, r3, lsr #16
mov r3, r3, lsl #16
orr r4, r3, r4, lsr #16 @ XXYY
and r8, r8, #0x0f0000
mov r8, r8, lsl #13 @ sss0 *
and r9, r6, #0x670000
tst r6, #0x80000000
orrne r8, r8, #0x8
tst r6, #0x20000000
orrne r8, r8, #0x4 @ sss0 * NZ..
orr r6, r8, r9, lsr #12 @ sss0 * .uu. .lll NZ..
ldr r8, [r7, #0x440] @ r0-r2
ldr r9, [r7, #0x444] @ r4-r6
ldr r10,[r7, #(0x400+SSP_P*4)] @ P
ldr r0, [r7, #(SSP_OFFS_GR+SSP_PC*4)]
mov r0, r0, lsr #16
ssp_drc_next:
ssp_drc_do_next 0
ssp_drc_next_patch:
ssp_drc_do_next 1
ssp_drc_do_patch:
ldr r1, [r7, #SSP_OFFS_TMP2] @ jump instr. (actually call) address + 4
subs r12,r2, r1
moveq r3, #0xe1000000
orreq r3, r3, #0x00a00000 @ nop
streq r3, [r1, #-4]
beq ssp_drc_dp_end
cmp r12,#4
ldreq r3, [r1]
addeq r3, r3, #1
streq r3, [r1, #-4] @ move the other cond up
moveq r3, #0xe1000000
orreq r3, r3, #0x00a00000
streq r3, [r1] @ fill it's place with nop
beq ssp_drc_dp_end
ldr r3, [r1, #-4]
sub r12,r12,#4
mov r3, r3, lsr #24
bic r3, r3, #1 @ L bit
orr r3, r3, r12,lsl #6
mov r3, r3, ror #8 @ patched branch instruction
str r3, [r1, #-4] @ patch the bl/b to jump directly to another handler
ssp_drc_dp_end:
str r2, [r7, #SSP_OFFS_TMP1]
sub r0, r1, #4
add r1, r1, #4
bl cache_flush_d_inval_i
ldr r2, [r7, #SSP_OFFS_TMP1]
ldr r0, [r7, #SSP_OFFS_TMP0]
bx r2
ssp_drc_end:
mov r0, r0, lsl #16
str r0, [r7, #(SSP_OFFS_GR+SSP_PC*4)]
ssp_regfile_store:
str r10,[r7, #(0x400+SSP_P*4)] @ P
str r8, [r7, #0x440] @ r0-r2
str r9, [r7, #0x444] @ r4-r6
mov r9, r6, lsr #13
and r9, r9, #(7<<16) @ STACK
mov r3, r6, lsl #28
msr cpsr_flg, r3 @ to to ARM PSR
and r6, r6, #0x670
mov r6, r6, lsl #12
orrmi r6, r6, #0x80000000 @ N
orreq r6, r6, #0x20000000 @ Z
mov r3, r4, lsl #16 @ Y
mov r2, r4, lsr #16
mov r2, r2, lsl #16 @ X
add r8, r7, #0x400
add r8, r8, #4
stmia r8, {r2,r3,r5,r6,r9}
mov r0, r11
ldmfd sp!, {r4-r11, lr}
bx lr
@ ld A, PM0
@ andi 2
@ bra z=1, gloc_0800
ssp_hle_800:
ldr r0, [r7, #(SSP_OFFS_GR+SSP_PM0*4)]
ldr r1, [r7, #SSP_OFFS_EMUSTAT]
tst r0, #0x20000
orreq r1, r1, #SSP_WAIT_PM0
subeq r11,r11, #1024
streq r1, [r7, #SSP_OFFS_EMUSTAT]
mov r0, #0x400
beq ssp_drc_end
orrne r0, r0, #0x004
b ssp_drc_next
.macro hle_flushflags
bic r6, r6, #0xf
mrs r1, cpsr
orr r6, r6, r1, lsr #28
.endm
.macro hle_popstack
sub r6, r6, #0x20000000
add r1, r7, #0x400
add r1, r1, #0x048 @ stack
add r1, r1, r6, lsr #28
ldrh r0, [r1]
.endm
ssp_hle_902:
cmp r11, #0
ble ssp_drc_end
add r1, r7, #0x200
ldrh r0, [r1]
ldr r3, [r7, #SSP_OFFS_IRAM_ROM]
add r2, r3, r0, lsl #1 @ (r7|00)
ldrh r0, [r2], #2
mov r5, r5, lsl #16
mov r5, r5, lsr #16
bic r0, r0, #0xfc00
add r3, r3, r0, lsl #1 @ IRAM dest
ldrh r12,[r2], #2 @ length
bic r3, r3, #3 @ always seen aligned
@ orr r5, r5, #0x08000000
@ orr r5, r5, #0x00880000
@ sub r5, r5, r12, lsl #16
bic r6, r6, #0xf
add r12,r12,#1
mov r0, #1
str r0, [r7, #SSP_OFFS_IRAM_DIRTY]
sub r11,r11,r12,lsl #1
sub r11,r11,r12 @ -= length*3
ssp_hle_902_loop:
ldrh r0, [r2], #2
ldrh r1, [r2], #2
subs r12,r12,#2
orr r0, r0, r1, lsl #16
str r0, [r3], #4
bgt ssp_hle_902_loop
tst r12, #1
ldrneh r0, [r2], #2
strneh r0, [r3], #2
ldr r0, [r7, #SSP_OFFS_IRAM_ROM]
add r1, r7, #0x200
sub r2, r2, r0
mov r2, r2, lsr #1
strh r2, [r1] @ (r7|00)
sub r0, r3, r0
mov r0, r0, lsr #1
orr r0, r0, #0x08000000
orr r0, r0, #0x001c8000
str r0, [r7, #(SSP_OFFS_GR+SSP_PMC*4)]
str r0, [r7, #(SSP_OFFS_PM_WRITE+4*4)]
hle_popstack
subs r11,r11,#16 @ timeslice is likely to end
ble ssp_drc_end
b ssp_drc_next
@ this one is car rendering related
.macro hle_11_12c_mla offs_in
ldrsh r5, [r7, #(\offs_in+0)]
ldrsh r0, [r7, #(\offs_in+2)]
ldrsh r1, [r7, #(\offs_in+4)]
mul r5, r2, r5
ldrsh r12,[r7, #(\offs_in+6)]
mla r5, r3, r0, r5
mla r5, r4, r1, r5
add r5, r5, r12,lsl #11
movs r5, r5, lsr #13
add r1, r7, r8, lsr #23
strh r5, [r1]
add r8, r8, #(1<<24)
.endm
ssp_hle_11_12c:
cmp r11, #0
ble ssp_drc_end
mov r0, #0
bl ssp_pm_read
mov r4, r0
mov r0, #0
bl ssp_pm_read
mov r5, r0
mov r0, #0
bl ssp_pm_read
mov r2, r4, lsl #16
mov r2, r2, asr #15 @ (r7|00) << 1
mov r3, r5, lsl #16
mov r3, r3, asr #15 @ (r7|01) << 1
mov r4, r0, lsl #16
mov r4, r4, asr #15 @ (r7|10) << 1
bic r8, r8, #0xff
mov r8, r8, ror #16
hle_11_12c_mla 0x20
hle_11_12c_mla 0x28
hle_11_12c_mla 0x30
mov r8, r8, ror #16
orr r8, r8, #0x1c
@ hle_flushflags
hle_popstack
sub r11,r11,#33
b ssp_drc_next
ssp_hle_11_384:
mov r3, #2
b ssp_hle_11_38x
ssp_hle_11_38a:
mov r3, #3 @ r5
ssp_hle_11_38x:
cmp r11, #0
ble ssp_drc_end
mov r2, #0 @ EFh, EEh
mov r1, #1 @ r4
add r0, r7, #0x1c0 @ r0 (based)
ssp_hle_11_38x_loop:
ldrh r5, [r0], #2
ldr r12,[r7, #0x224]
mov r5, r5, lsl #16
eor r5, r5, r5, asr #31
add r5, r5, r5, lsr #31 @ abs(r5)
cmp r5, r12,lsl #16
orrpl r2, r2, r1,lsl #16 @ EFh |= r4
ldrh r5, [r0, #2]!
ldr r12,[r7, #0x220]
cmp r5, r12,lsr #16
orrpl r2, r2, r1,lsl #16 @ EFh |= r4
ldr r12,[r7, #0x1e8]
add r0, r0, #2
mov r12,r12,lsl #16
cmp r5, r12,lsr #16
orrmi r2, r2, r1
mov r1, r1, lsl #1
subs r3, r3, #1
bpl ssp_hle_11_38x_loop
str r2, [r7, #0x1dc]
sub r0, r0, r7
bic r8, r8, #0xff
orr r8, r8, r0, lsr #1
bic r9, r9, #0xff
orr r9, r9, r1
@ hle_flushflags
hle_popstack
sub r11,r11,#(9+30*4)
b ssp_drc_next
ssp_hle_07_6d6:
cmp r11, #0
ble ssp_drc_end
ldr r1, [r7, #0x20c]
and r0, r8, #0xff @ assuming alignment
add r0, r7, r0, lsl #1
mov r2, r1, lsr #16
mov r1, r1, lsl #16 @ 106h << 16
mov r2, r2, lsl #16 @ 107h << 16
ssp_hle_07_6d6_loop:
ldr r5, [r0], #4
tst r5, r5
bmi ssp_hle_07_6d6_end
mov r5, r5, lsl #16
cmp r5, r1
movmi r1, r5
cmp r5, r2
sub r11,r11,#16
bmi ssp_hle_07_6d6_loop
mov r2, r5
b ssp_hle_07_6d6_loop
ssp_hle_07_6d6_end:
sub r0, r0, r7
mov r0, r0, lsr #1
bic r8, r8, #0xff
orr r8, r8, r0
orr r1, r2, r1, lsr #16
str r1, [r7, #0x20c]
hle_popstack
sub r11,r11,#6
b ssp_drc_next
ssp_hle_07_030:
ldrh r0, [r7]
mov r0, r0, lsl #4
orr r0, r0, r0, lsr #16
strh r0, [r7]
sub r11,r11,#3
ssp_hle_07_036:
ldr r1, [r7, #0x1e0] @ F1h F0h
rsb r5, r1, r1, lsr #16
mov r5, r5, lsl #16 @ AL not needed
cmp r5, #(4<<16)
sub r11,r11,#5
bmi hle_07_036_ending2
ldr r1, [r7, #0x1dc] @ EEh
cmp r5, r1, lsl #16
sub r11,r11,#5
bpl hle_07_036_ret
mov r0, r5, lsr #16
add r1, r7, #0x100
strh r0, [r1, #0xea] @ F5h
ldr r0, [r7, #0x1e0] @ F0h
and r0, r0, #3
strh r0, [r1, #0xf0] @ F8h
add r2, r0, #0xc0 @ r2
add r2, r7, r2, lsl #1
ldrh r2, [r2]
ldr r0, [r7]
mov r1, #4
and r0, r0, r2
bl ssp_pm_write
@ will handle PMC later
ldr r0, [r7, #0x1e8] @ F5h << 16
ldr r1, [r7, #0x1f0] @ F8h
ldr r2, [r7, #0x1d4] @ EAh
sub r0, r0, #(3<<16)
add r0, r0, r1, lsl #16
sub r0, r2, r0, asr #18
and r0, r0, #0x7f
rsbs r0, r0, #0x78 @ length
ble hle_07_036_ending1
sub r11,r11,r0
@ copy part
ldr r1, [r7, #(SSP_OFFS_GR+SSP_PMC*4)]
ldr r2, [r7, #SSP_OFFS_DRAM]
mov r1, r1, lsl #16
add r1, r2, r1, lsr #15 @ addr (based)
ldrh r2, [r7, #0] @ pattern
ldrh r3, [r7, #6] @ mode
mov r12, #0x4000
orr r12,r12,#0x0018
subs r12,r3, r12
subnes r12,r12,#0x0400
blne tr_unhandled
orr r2, r2, r2, lsl #16
tst r3, #0x400
bne hle_07_036_ovrwr
hle_07_036_no_ovrwr:
tst r1, #2
strneh r2, [r1], #0x3e @ align
subne r0, r0, #1
subs r0, r0, #4
blt hle_07_036_l2
hle_07_036_l1:
subs r0, r0, #4
str r2, [r1], #0x40
str r2, [r1], #0x40
bge hle_07_036_l1
hle_07_036_l2:
tst r0, #2
strne r2, [r1], #0x40
tst r0, #1
strneh r2, [r1], #2
b hle_07_036_end_copy
hle_07_036_ovrwr:
tst r2, #0x000f
orreq r12,r12,#0x000f
tst r2, #0x00f0
orreq r12,r12,#0x00f0
tst r2, #0x0f00
orreq r12,r12,#0x0f00
tst r2, #0xf000
orreq r12,r12,#0xf000
orrs r12,r12,r12,lsl #16
beq hle_07_036_no_ovrwr
tst r1, #2
beq hle_07_036_ol0
ldrh r3, [r1]
and r3, r3, r12
orr r3, r3, r2
strh r3, [r1], #0x3e @ align
sub r0, r0, #1
hle_07_036_ol0:
subs r0, r0, #2
blt hle_07_036_ol2
hle_07_036_ol1:
subs r0, r0, #2
ldr r3, [r1]
and r3, r3, r12
orr r3, r3, r2
str r3, [r1], #0x40
bge hle_07_036_ol1
hle_07_036_ol2:
tst r0, #1
ldrneh r3, [r1]
andne r3, r3, r12
orrne r3, r3, r2
strneh r3, [r1], #2
hle_07_036_end_copy:
ldr r2, [r7, #SSP_OFFS_DRAM]
add r3, r7, #0x400
sub r0, r1, r2 @ new addr
mov r0, r0, lsr #1
strh r0, [r3, #(0x6c+4*4)] @ SSP_OFFS_PM_WRITE+4*4 (low)
hle_07_036_ending1:
ldr r0, [r7, #0x1e0] @ F1h << 16
add r0, r0, #(1<<16)
and r0, r0, #(3<<16)
add r0, r0, #(0xc4<<16)
bic r8, r8, #0xff0000
orr r8, r8, r0 @ r2
add r0, r7, r0, lsr #15
ldrh r0, [r0]
ldr r2, [r7]
and r0, r0, r2
movs r5, r0, lsl #16
ldr r1, [r7, #4] @ new mode
add r2, r7, #0x400
strh r1, [r2, #(0x6c+4*4+2)] @ SSP_OFFS_PM_WRITE+4*4 (high)
mov r1, #4
bl ssp_pm_write
sub r11,r11,#35
hle_07_036_ret:
hle_popstack
b ssp_drc_next
hle_07_036_ending2:
sub r11,r11,#3
movs r5, r5, lsl #1
bmi hle_07_036_ret
mov r0, #0x87
b ssp_drc_next @ let the dispatcher finish this

169
pico/carthw/svp/svp.c Normal file
View file

@ -0,0 +1,169 @@
// The SVP chip emulator
// (c) Copyright 2008, Grazvydas "notaz" Ignotas
// Free for non-commercial use.
// For commercial use, separate licencing terms must be obtained.
#include "../../pico_int.h"
#include "compiler.h"
#ifdef __GP2X__
#include <sys/mman.h>
#endif
svp_t *svp = NULL;
int PicoSVPCycles = 850; // cycles/line, just a guess
static int svp_dyn_ready = 0;
/* save state stuff */
typedef enum {
CHUNK_IRAM = CHUNK_CARTHW,
CHUNK_DRAM,
CHUNK_SSP
} chunk_name_e;
static carthw_state_chunk svp_states[] =
{
{ CHUNK_IRAM, 0x800, NULL },
{ CHUNK_DRAM, sizeof(svp->dram), NULL },
{ CHUNK_SSP, sizeof(svp->ssp1601) - sizeof(svp->ssp1601.drc), NULL },
{ 0, 0, NULL }
};
static void PicoSVPReset(void)
{
elprintf(EL_SVP, "SVP reset");
memcpy(svp->iram_rom + 0x800, Pico.rom + 0x800, 0x20000 - 0x800);
ssp1601_reset(&svp->ssp1601);
#ifndef PSP
if ((PicoOpt&POPT_EN_SVP_DRC) && svp_dyn_ready)
ssp1601_dyn_reset(&svp->ssp1601);
#endif
}
static void PicoSVPLine(void)
{
int count = 1;
#if defined(ARM) || defined(PSP)
// performance hack
static int delay_lines = 0;
delay_lines++;
if ((Pico.m.scanline&0xf) != 0xf && Pico.m.scanline != 261 && Pico.m.scanline != 311)
return;
count = delay_lines;
delay_lines = 0;
#endif
#ifndef PSP
if ((PicoOpt&POPT_EN_SVP_DRC) && svp_dyn_ready)
ssp1601_dyn_run(PicoSVPCycles * count);
else
#endif
{
ssp1601_run(PicoSVPCycles * count);
svp_dyn_ready = 0; // just in case
}
// test mode
//if (Pico.m.frame_count == 13) PicoPad[0] |= 0xff;
}
static int PicoSVPDma(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp)
{
if (source < Pico.romsize) // Rom
{
source -= 2;
*srcp = (unsigned short *)(Pico.rom + (source&~1));
*limitp = (unsigned short *)(Pico.rom + Pico.romsize);
return 1;
}
else if ((source & 0xfe0000) == 0x300000)
{
elprintf(EL_VDPDMA|EL_SVP, "SVP DmaSlow from %06x, len=%i", source, len);
source &= 0x1fffe;
source -= 2;
*srcp = (unsigned short *)(svp->dram + source);
*limitp = (unsigned short *)(svp->dram + sizeof(svp->dram));
return 1;
}
else
elprintf(EL_VDPDMA|EL_SVP|EL_ANOMALY, "SVP FIXME unhandled DmaSlow from %06x, len=%i", source, len);
return 0;
}
void PicoSVPInit(void)
{
#ifdef __GP2X__
int ret;
ret = munmap(tcache, SSP_DRC_SIZE);
printf("munmap tcache: %i\n", ret);
#endif
}
static void PicoSVPShutdown(void)
{
#ifdef __GP2X__
// also unmap tcache
PicoSVPInit();
#endif
}
void PicoSVPStartup(void)
{
void *tmp;
elprintf(EL_SVP, "SVP init");
tmp = realloc(Pico.rom, 0x200000 + sizeof(*svp));
if (tmp == NULL)
{
elprintf(EL_STATUS|EL_SVP, "OOM for SVP data");
return;
}
//PicoOpt &= ~0x20000;
Pico.rom = tmp;
svp = (void *) ((char *)tmp + 0x200000);
memset(svp, 0, sizeof(*svp));
#ifdef __GP2X__
tmp = mmap(tcache, SSP_DRC_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
printf("mmap tcache: %p, asked %p\n", tmp, tcache);
#endif
// init SVP compiler
svp_dyn_ready = 0;
#ifndef PSP
if (PicoOpt&POPT_EN_SVP_DRC) {
if (ssp1601_dyn_startup()) return;
svp_dyn_ready = 1;
}
#endif
// init ok, setup hooks..
PicoRead16Hook = PicoSVPRead16;
PicoWrite8Hook = PicoSVPWrite8;
PicoWrite16Hook = PicoSVPWrite16;
PicoDmaHook = PicoSVPDma;
PicoResetHook = PicoSVPReset;
PicoLineHook = PicoSVPLine;
PicoCartUnloadHook = PicoSVPShutdown;
// save state stuff
svp_states[0].ptr = svp->iram_rom;
svp_states[1].ptr = svp->dram;
svp_states[2].ptr = &svp->ssp1601;
carthw_chunks = svp_states;
PicoAHW |= PAHW_SVP;
}