mirror of
https://github.com/RaySollium99/picodrive.git
synced 2025-09-05 15:27:46 -04:00
Cyclone: direct memhandler calls option + reset function
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@778 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
parent
5d572e5228
commit
fc1874de8a
5 changed files with 102 additions and 26 deletions
|
@ -52,6 +52,9 @@ struct Cyclone
|
||||||
// Initialize. Used only if Cyclone was compiled with compressed jumptable, see config.h
|
// Initialize. Used only if Cyclone was compiled with compressed jumptable, see config.h
|
||||||
void CycloneInit(void);
|
void CycloneInit(void);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
void CycloneReset(struct Cyclone *pcy);
|
||||||
|
|
||||||
// Run cyclone. Cycles should be specified in context (pcy->cycles)
|
// Run cyclone. Cycles should be specified in context (pcy->cycles)
|
||||||
void CycloneRun(struct Cyclone *pcy);
|
void CycloneRun(struct Cyclone *pcy);
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,32 @@ static void PrintFramework()
|
||||||
#endif
|
#endif
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
ot("CycloneReset%s\n", ms?"":":");
|
||||||
|
ot(" stmfd sp!,{r7,lr}\n");
|
||||||
|
ot(" mov r7,r0\n");
|
||||||
|
ot(" mov r0,#0\n");
|
||||||
|
ot(" str r0,[r7,#0x58] ;@ state_flags\n");
|
||||||
|
ot(" str r0,[r7,#0x48] ;@ OSP\n");
|
||||||
|
ot(" mov r1,#0x27 ;@ Supervisor mode\n");
|
||||||
|
ot(" strb r1,[r7,#0x44] ;@ set SR high\n");
|
||||||
|
ot(" strb r0,[r7,#0x47] ;@ IRQ\n");
|
||||||
|
MemHandler(0,2);
|
||||||
|
ot(" str r0,[r7,#0x3c] ;@ Stack pointer\n");
|
||||||
|
ot(" mov r0,#0\n");
|
||||||
|
ot(" str r0,[r7,#0x60] ;@ Membase\n");
|
||||||
|
ot(" mov r0,#4\n");
|
||||||
|
MemHandler(0,2);
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
|
ot(" mov lr,pc\n");
|
||||||
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
|
#endif
|
||||||
|
ot(" str r0,[r7,#0x40] ;@ PC + base\n");
|
||||||
|
ot(" ldmfd sp!,{r7,pc}\n");
|
||||||
|
ot("\n");
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
// 68k: XNZVC, ARM: NZCV
|
// 68k: XNZVC, ARM: NZCV
|
||||||
ot("CycloneSetSr%s\n", ms?"":":");
|
ot("CycloneSetSr%s\n", ms?"":":");
|
||||||
|
@ -375,9 +401,10 @@ static void PrintFramework()
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
ot("CycloneUnpack%s\n", ms?"":":");
|
ot("CycloneUnpack%s\n", ms?"":":");
|
||||||
ot(" stmfd sp!,{r4,r5,lr}\n");
|
ot(" stmfd sp!,{r5,r7,lr}\n");
|
||||||
ot(" mov r4,r0\n");
|
ot(" mov r7,r0\n");
|
||||||
ot(" mov r5,r1\n");
|
ot(" movs r5,r1\n");
|
||||||
|
ot(" beq c_unpack_do_pc\n");
|
||||||
ot(" mov r3,#16\n");
|
ot(" mov r3,#16\n");
|
||||||
ot(";@ 0x00-0x3f: DA registers\n");
|
ot(";@ 0x00-0x3f: DA registers\n");
|
||||||
ot("c_unpack_loop%s\n",ms?"":":");
|
ot("c_unpack_loop%s\n",ms?"":":");
|
||||||
|
@ -387,30 +414,37 @@ static void PrintFramework()
|
||||||
ot(" bne c_unpack_loop\n");
|
ot(" bne c_unpack_loop\n");
|
||||||
ot(";@ 0x40: PC\n");
|
ot(";@ 0x40: PC\n");
|
||||||
ot(" ldr r0,[r5],#4 ;@ PC\n");
|
ot(" ldr r0,[r5],#4 ;@ PC\n");
|
||||||
#if USE_CHECKPC_CALLBACK
|
ot(" str r0,[r7,#0x40] ;@ handle later\n");
|
||||||
ot(" mov r1,#0\n");
|
|
||||||
ot(" str r1,[r4,#0x60] ;@ Memory base\n");
|
|
||||||
ot(" mov lr,pc\n");
|
|
||||||
ot(" ldr pc,[r4,#0x64] ;@ Call checkpc()\n");
|
|
||||||
#else
|
|
||||||
ot(" ldr r1,[r4,#0x60] ;@ Memory base\n");
|
|
||||||
ot(" add r0,r0,r1 ;@ r0 = Memory Base + New PC\n");
|
|
||||||
#endif
|
|
||||||
ot(" str r0,[r4,#0x40] ;@ PC + Memory Base\n");
|
|
||||||
ot(";@ 0x44: SR\n");
|
ot(";@ 0x44: SR\n");
|
||||||
ot(" ldrh r1,[r5],#2\n");
|
ot(" ldrh r1,[r5],#2\n");
|
||||||
ot(" mov r0,r4\n");
|
ot(" mov r0,r7\n");
|
||||||
ot(" bl CycloneSetSr\n");
|
ot(" bl CycloneSetSr\n");
|
||||||
ot(";@ 0x46: IRQ level\n");
|
ot(";@ 0x46: IRQ level\n");
|
||||||
ot(" ldrb r0,[r5],#2\n");
|
ot(" ldrb r0,[r5],#2\n");
|
||||||
ot(" strb r0,[r4,#0x47]\n");
|
ot(" strb r0,[r7,#0x47]\n");
|
||||||
ot(";@ 0x48: other SP\n");
|
ot(";@ 0x48: other SP\n");
|
||||||
ot(" ldr r0,[r5],#4\n");
|
ot(" ldr r0,[r5],#4\n");
|
||||||
ot(" str r0,[r4,#0x48]\n");
|
ot(" str r0,[r7,#0x48]\n");
|
||||||
ot(";@ 0x4c: CPU state flags\n");
|
ot(";@ 0x4c: CPU state flags\n");
|
||||||
ot(" ldr r0,[r5],#4\n");
|
ot(" ldr r0,[r5],#4\n");
|
||||||
ot(" str r0,[r4,#0x58]\n");
|
ot(" str r0,[r7,#0x58]\n");
|
||||||
ot(" ldmfd sp!,{r4,r5,pc}\n");
|
ot("c_unpack_do_pc%s\n",ms?"":":");
|
||||||
|
ot(" ldr r0,[r7,#0x40] ;@ unbased PC\n");
|
||||||
|
#if USE_CHECKPC_CALLBACK
|
||||||
|
ot(" mov r1,#0\n");
|
||||||
|
ot(" str r1,[r7,#0x60] ;@ Memory base\n");
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
|
ot(" mov lr,pc\n");
|
||||||
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
ot(" ldr r1,[r7,#0x60] ;@ Memory base\n");
|
||||||
|
ot(" add r0,r0,r1 ;@ r0 = Memory Base + New PC\n");
|
||||||
|
#endif
|
||||||
|
ot(" str r0,[r7,#0x40] ;@ PC + Memory Base\n");
|
||||||
|
ot(" ldmfd sp!,{r5,r7,pc}\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
|
@ -549,12 +583,20 @@ static void PrintFramework()
|
||||||
MemHandler(0,2,0,0);
|
MemHandler(0,2,0,0);
|
||||||
ot(" tst r0,r0 ;@ uninitialized int vector?\n");
|
ot(" tst r0,r0 ;@ uninitialized int vector?\n");
|
||||||
ot(" moveq r0,#0x3c\n");
|
ot(" moveq r0,#0x3c\n");
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bleq %sread32 ;@ Call read32(r0) handler\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
ot(" moveq lr,pc\n");
|
ot(" moveq lr,pc\n");
|
||||||
ot(" ldreq pc,[r7,#0x70] ;@ Call read32(r0) handler\n");
|
ot(" ldreq pc,[r7,#0x70] ;@ Call read32(r0) handler\n");
|
||||||
|
#endif
|
||||||
#if USE_CHECKPC_CALLBACK
|
#if USE_CHECKPC_CALLBACK
|
||||||
ot(" add lr,pc,#4\n");
|
ot(" add lr,pc,#4\n");
|
||||||
ot(" add r0,r0,r11 ;@ r0 = Memory Base + New PC\n");
|
ot(" add r0,r0,r11 ;@ r0 = Memory Base + New PC\n");
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
|
#endif
|
||||||
#if EMULATE_ADDRESS_ERRORS_JUMP
|
#if EMULATE_ADDRESS_ERRORS_JUMP
|
||||||
ot(" mov r4,r0\n");
|
ot(" mov r4,r0\n");
|
||||||
#else
|
#else
|
||||||
|
@ -636,7 +678,11 @@ static void PrintFramework()
|
||||||
#if USE_CHECKPC_CALLBACK
|
#if USE_CHECKPC_CALLBACK
|
||||||
ot(" add lr,pc,#4\n");
|
ot(" add lr,pc,#4\n");
|
||||||
ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n");
|
ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n");
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
|
#endif
|
||||||
#if EMULATE_ADDRESS_ERRORS_JUMP
|
#if EMULATE_ADDRESS_ERRORS_JUMP
|
||||||
ot(" mov r4,r0\n");
|
ot(" mov r4,r0\n");
|
||||||
#else
|
#else
|
||||||
|
@ -763,7 +809,11 @@ static void PrintFramework()
|
||||||
#if USE_CHECKPC_CALLBACK
|
#if USE_CHECKPC_CALLBACK
|
||||||
ot(" add lr,pc,#4\n");
|
ot(" add lr,pc,#4\n");
|
||||||
ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n");
|
ot(" add r0,r0,r3 ;@ r0 = Memory Base + New PC\n");
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
|
#endif
|
||||||
ot(" mov r4,r0\n");
|
ot(" mov r4,r0\n");
|
||||||
#else
|
#else
|
||||||
ot(" add r4,r0,r3 ;@ r4 = Memory Base + New PC\n");
|
ot(" add r4,r0,r3 ;@ r4 = Memory Base + New PC\n");
|
||||||
|
@ -854,8 +904,8 @@ static void PrintFramework()
|
||||||
// Trashes r0-r3,r12,lr
|
// Trashes r0-r3,r12,lr
|
||||||
int MemHandler(int type,int size,int addrreg,int need_addrerr_check)
|
int MemHandler(int type,int size,int addrreg,int need_addrerr_check)
|
||||||
{
|
{
|
||||||
int func=0;
|
int func=0x68+type*0xc+(size<<2); // Find correct offset
|
||||||
func=0x68+type*0xc+(size<<2); // Find correct offset
|
char what[32];
|
||||||
|
|
||||||
#if MEMHANDLERS_NEED_FLAGS
|
#if MEMHANDLERS_NEED_FLAGS
|
||||||
ot(" mov r3,r10,lsr #28\n");
|
ot(" mov r3,r10,lsr #28\n");
|
||||||
|
@ -894,6 +944,14 @@ int MemHandler(int type,int size,int addrreg,int need_addrerr_check)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sprintf(what, "%s%d", type==0 ? "read" : (type==1 ? "write" : "fetch"), 8<<size);
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
if (addrreg != 0)
|
||||||
|
ot(" mov r0,r%i\n", addrreg);
|
||||||
|
ot(" bl %s%s ;@ Call ", MEMHANDLERS_DIRECT_PREFIX, what);
|
||||||
|
(void)func; // avoid warning
|
||||||
|
#else
|
||||||
if (addrreg != 0)
|
if (addrreg != 0)
|
||||||
{
|
{
|
||||||
ot(" add lr,pc,#4\n");
|
ot(" add lr,pc,#4\n");
|
||||||
|
@ -902,14 +960,11 @@ int MemHandler(int type,int size,int addrreg,int need_addrerr_check)
|
||||||
else
|
else
|
||||||
ot(" mov lr,pc\n");
|
ot(" mov lr,pc\n");
|
||||||
ot(" ldr pc,[r7,#0x%x] ;@ Call ",func);
|
ot(" ldr pc,[r7,#0x%x] ;@ Call ",func);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Document what we are calling:
|
// Document what we are calling:
|
||||||
if (type==0) ot("read");
|
if (type==1) ot("%s(r0,r1)",what);
|
||||||
if (type==1) ot("write");
|
else ot("%s(r0)", what);
|
||||||
if (type==2) ot("fetch");
|
|
||||||
|
|
||||||
if (type==1) ot("%d(r0,r1)",8<<size);
|
|
||||||
else ot("%d(r0)", 8<<size);
|
|
||||||
ot(" handler\n");
|
ot(" handler\n");
|
||||||
|
|
||||||
#if MEMHANDLERS_CHANGE_FLAGS
|
#if MEMHANDLERS_CHANGE_FLAGS
|
||||||
|
@ -1185,6 +1240,7 @@ static int CycloneMake()
|
||||||
|
|
||||||
ot(ms?" area |.text|, code\n":" .text\n .align 4\n\n");
|
ot(ms?" area |.text|, code\n":" .text\n .align 4\n\n");
|
||||||
ot(" %s CycloneInit\n",globl);
|
ot(" %s CycloneInit\n",globl);
|
||||||
|
ot(" %s CycloneReset\n",globl);
|
||||||
ot(" %s CycloneRun\n",globl);
|
ot(" %s CycloneRun\n",globl);
|
||||||
ot(" %s CycloneSetSr\n",globl);
|
ot(" %s CycloneSetSr\n",globl);
|
||||||
ot(" %s CycloneGetSr\n",globl);
|
ot(" %s CycloneGetSr\n",globl);
|
||||||
|
|
|
@ -5,10 +5,14 @@
|
||||||
static void CheckPc(void)
|
static void CheckPc(void)
|
||||||
{
|
{
|
||||||
#if USE_CHECKPC_CALLBACK
|
#if USE_CHECKPC_CALLBACK
|
||||||
|
#ifdef MEMHANDLERS_DIRECT_PREFIX
|
||||||
|
ot(" bl %scheckpc ;@ Call checkpc()\n", MEMHANDLERS_DIRECT_PREFIX);
|
||||||
|
#else
|
||||||
ot(";@ Check Memory Base+pc\n");
|
ot(";@ Check Memory Base+pc\n");
|
||||||
ot(" mov lr,pc\n");
|
ot(" mov lr,pc\n");
|
||||||
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
ot(" ldr pc,[r7,#0x64] ;@ Call checkpc()\n");
|
||||||
ot("\n");
|
ot("\n");
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,17 @@
|
||||||
#define MEMHANDLERS_CHANGE_FLAGS 0
|
#define MEMHANDLERS_CHANGE_FLAGS 0
|
||||||
#define MEMHANDLERS_CHANGE_CYCLES 0
|
#define MEMHANDLERS_CHANGE_CYCLES 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the following macro is defined, Cyclone no longer calls read*, write*,
|
||||||
|
* fetch* and checkpc from it's context, it calls these functions directly
|
||||||
|
* instead, prefixed with prefix selected below. For example, if
|
||||||
|
* MEMHANDLERS_DIRECT_PREFIX is set to cyclone_, it will call cyclone_read8
|
||||||
|
* on byte reads.
|
||||||
|
* This is to avoid indirect jumps, which are slower. It also saves one ARM
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
/* MEMHANDLERS_DIRECT_PREFIX "cyclone_" */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If enabled, Cyclone will call .IrqCallback routine from it's context whenever it
|
* If enabled, Cyclone will call .IrqCallback routine from it's context whenever it
|
||||||
* acknowledges an IRQ. IRQ level (.irq) is not cleared automatically, do this in your
|
* acknowledges an IRQ. IRQ level (.irq) is not cleared automatically, do this in your
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#define MEMHANDLERS_CHANGE_FLAGS 0
|
#define MEMHANDLERS_CHANGE_FLAGS 0
|
||||||
#define MEMHANDLERS_CHANGE_CYCLES 0
|
#define MEMHANDLERS_CHANGE_CYCLES 0
|
||||||
|
|
||||||
|
#define MEMHANDLERS_DIRECT_PREFIX "cyclone_"
|
||||||
|
|
||||||
#define USE_INT_ACK_CALLBACK 1
|
#define USE_INT_ACK_CALLBACK 1
|
||||||
|
|
||||||
#define INT_ACK_NEEDS_STUFF 0
|
#define INT_ACK_NEEDS_STUFF 0
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue