mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
276 lines
No EOL
6.8 KiB
ArmAsm
276 lines
No EOL
6.8 KiB
ArmAsm
.arm
|
|
|
|
//The top two defines needs to be adjusted depending on how gCPUState struct is formated in CPU.h!! //Corn
|
|
//
|
|
#define _C0_Count (0x100 + 9 * 4) //CPU_Control_base + 9*8(64bit regs) or 9*4(32bit regs)
|
|
#define _AuxBase 0x280 //Base pointer to Aux regs
|
|
#define _CurrentPC (_AuxBase + 0x00)
|
|
#define _TargetPC (_AuxBase + 0x04)
|
|
#define _Delay (_AuxBase + 0x08)
|
|
#define _StuffToDo (_AuxBase + 0x0c)
|
|
#define _Temp1 (_AuxBase + 0x20)
|
|
#define _Temp2 (_AuxBase + 0x24)
|
|
#define _Temp3 (_AuxBase + 0x28)
|
|
#define _Temp4 (_AuxBase + 0x2C)
|
|
#define _Events (_AuxBase + 0x30)
|
|
|
|
.extern CPU_UpdateCounter
|
|
.extern CPU_HANDLE_COUNT_INTERRUPT
|
|
.extern g_MemoryLookupTableRead
|
|
.extern g_MemoryLookupTableWrite
|
|
.extern HandleException_extern
|
|
.extern Write32BitsForDynaRec
|
|
.extern Write16BitsForDynaRec
|
|
.extern Write8BitsForDynaRec
|
|
|
|
.align 4
|
|
.global _EnterDynaRec
|
|
.global _DirectExitCheckNoDelay
|
|
.global _DirectExitCheckDelay
|
|
.global _IndirectExitCheck
|
|
|
|
.global _ReadBitsDirect_u8
|
|
.global _ReadBitsDirect_s8
|
|
.global _ReadBitsDirect_u16
|
|
.global _ReadBitsDirect_s16
|
|
.global _ReadBitsDirect_u32
|
|
|
|
.global _ReadBitsDirectBD_u8
|
|
.global _ReadBitsDirectBD_s8
|
|
.global _ReadBitsDirectBD_u16
|
|
.global _ReadBitsDirectBD_s16
|
|
.global _ReadBitsDirectBD_u32
|
|
|
|
.global _WriteBitsDirect_u32
|
|
.global _WriteBitsDirect_u16
|
|
.global _WriteBitsDirect_u8
|
|
.global _WriteBitsDirectBD_u32
|
|
.global _WriteBitsDirectBD_u16
|
|
.global _WriteBitsDirectBD_u8
|
|
|
|
|
|
.type _EnterDynaRec, %function
|
|
.type _DirectExitCheckNoDelay, %function
|
|
.type _DirectExitCheckDelay, %function
|
|
.type _IndirectExitCheck, %function
|
|
|
|
_DirectExitCheckNoDelay:
|
|
ldr r4, [r12, #_C0_Count] // COUNT register
|
|
ldr r5, [r12, #_Events] // Events[0].mCount
|
|
|
|
add r4, r4, r0 // COUNT + ops_executed
|
|
str r4, [r12, #_C0_Count] // COUNT = COUNT + ops_executed
|
|
|
|
str r1, [r12, #_CurrentPC] // Current PC
|
|
mov r1, #0
|
|
str r1, [r12, #_Delay] // Delay = NO_DELAY
|
|
|
|
sub r5, r5, r0 // Events[0].mCount - ops_executed
|
|
cmp r5, #0
|
|
str r5, [r12, #_Events]
|
|
ble _DirectExitCheckCheckCount
|
|
bx lr
|
|
|
|
_DirectExitCheckDelay:
|
|
ldr r4, [r12, #_C0_Count] // COUNT register
|
|
ldr r5, [r12, #_Events] // Events[0].mCount
|
|
|
|
add r4, r4, r0 // COUNT + ops_executed
|
|
str r4, [r12, #_C0_Count] // COUNT = COUNT + ops_executed
|
|
|
|
str r1, [r12, #_CurrentPC] // Current PC
|
|
str r2, [r12, #_TargetPC] // Target PC
|
|
mov r1, #1 // EXEC_DELAY
|
|
str r1, [r12, #_Delay] // Delay = NO_DELAY
|
|
|
|
sub r5, r5, r0 // Events[0].mCount - ops_executed
|
|
cmp r5, #0
|
|
str r5, [r12, #_Events]
|
|
ble _DirectExitCheckCheckCount
|
|
bx lr
|
|
|
|
#######################################################################################
|
|
# Utility routine for _DirectExitCheckXX.
|
|
#
|
|
_DirectExitCheckCheckCount:
|
|
mov r4, lr // Keep track of return addresss
|
|
mov r5, r12
|
|
bl CPU_HANDLE_COUNT_INTERRUPT
|
|
mov lr, r4
|
|
mov r12, r5
|
|
ldr r0, [r12, #_StuffToDo] // StuffToDo
|
|
cmp r0, #0
|
|
popne {r4-r12, pc} // Exit the DynaRec
|
|
bx lr // Return back to caller
|
|
|
|
#######################################################################################
|
|
# Update counter. If StuffToDo flags is clear on return,
|
|
# r0 - instructions executed
|
|
# r1 - CIndirectExitMap pointer
|
|
# r2 - exit pc (exit delay is always NO_DELAY)
|
|
_IndirectExitCheck:
|
|
mov r4, r1 // Keep track of map pointer
|
|
mov r5, r2 // and the exit pc
|
|
mov r6, r12
|
|
# Can avoid these until Return From DynaRec (pop)?
|
|
str r2, [r12,#_CurrentPC] // CurrentPC
|
|
bl CPU_UpdateCounter // a0 holds instructions executed
|
|
mov r0, #0
|
|
str r0, [r6, #_Delay] // Delay (NO_DELAY)
|
|
|
|
ldr r0, [r6, #_StuffToDo] // StuffToDo
|
|
cmp r0, #0
|
|
popne {r4-r12,pc} // Exit the DynaRec
|
|
|
|
mov r0, r4 // p_map
|
|
mov r1, r5 // exit_pc
|
|
bl IndirectExitMap_Lookup
|
|
|
|
|
|
# r0 holds pointer to indirect target. If it's 0, it means it's not compiled yet
|
|
cmp r0, #0
|
|
popeq {r4-r12,pc} // Exit the DynaRec
|
|
mov r12,r6 // Restore the CPUState pointer
|
|
bx r0 // branch to the looked up fragment
|
|
|
|
_ReturnFromDynaRecAndHandleException:
|
|
bl HandleException_extern
|
|
pop {r4-r12,pc}
|
|
|
|
.macro READ_BITS function, load_instruction
|
|
\function:
|
|
// look up memread function
|
|
lsr r2, r0, #0x12
|
|
ldr r3, =g_MemoryLookupTableRead
|
|
add r2, r3, r2, lsl #3 // * 8 to index the two pointer struct
|
|
ldr r2, [r2,#4] //offset 4 to get the second pointer
|
|
|
|
str r1, [r12,#_CurrentPC] // CurrentPC
|
|
|
|
// execute memread function
|
|
mov r5, r12
|
|
mov r6, lr
|
|
blx r2
|
|
mov lr, r6
|
|
mov r12, r5
|
|
|
|
// check exceptions
|
|
ldr r1, [r12, #_StuffToDo]
|
|
cmp r1, #0
|
|
bne _ReturnFromDynaRecAndHandleException
|
|
|
|
//execute the load
|
|
\load_instruction r0, [r0] // e.g. lbu, lhu, lw etc
|
|
|
|
// return
|
|
bx lr
|
|
.endm
|
|
|
|
.macro READ_BITS_BD function, load_instruction
|
|
\function:
|
|
// look up memread function
|
|
lsr r2, r0, #0x12
|
|
ldr r3, =g_MemoryLookupTableRead
|
|
add r2, r3, r2, lsl #3 // * 8 to index the two pointer struct
|
|
ldr r2, [r2,#4] //offset 4 to get the second pointer
|
|
|
|
str r1, [r12,#_CurrentPC] // CurrentPC
|
|
|
|
mov r3, #1 // EXEC_DELAY
|
|
str r3, [r12, #_Delay]
|
|
|
|
// execute memread function
|
|
mov r5, r12
|
|
mov r6, lr
|
|
blx r2
|
|
mov lr, r6
|
|
mov r12, r5
|
|
|
|
// check exceptions
|
|
ldr r1, [r12, #_StuffToDo]
|
|
cmp r1, #0
|
|
bne _ReturnFromDynaRecAndHandleException
|
|
|
|
mov r1, #0
|
|
str r1, [r12, #_Delay]
|
|
|
|
// execute the load
|
|
\load_instruction r0, [r0] // e.g. lbu, lhu, lw etc
|
|
|
|
// return
|
|
bx lr
|
|
.endm
|
|
|
|
READ_BITS _ReadBitsDirect_u8, ldrb
|
|
READ_BITS _ReadBitsDirect_s8, ldrsb
|
|
READ_BITS _ReadBitsDirect_u16, ldrh
|
|
READ_BITS _ReadBitsDirect_s16, ldrsh
|
|
READ_BITS _ReadBitsDirect_u32, ldr
|
|
|
|
READ_BITS_BD _ReadBitsDirectBD_u8, ldrb
|
|
READ_BITS_BD _ReadBitsDirectBD_s8, ldrsb
|
|
READ_BITS_BD _ReadBitsDirectBD_u16, ldrh
|
|
READ_BITS_BD _ReadBitsDirectBD_s16, ldrsh
|
|
READ_BITS_BD _ReadBitsDirectBD_u32, ldr
|
|
|
|
.macro WRITE_BITS function, store_func
|
|
\function:
|
|
str r2, [r12,#_CurrentPC] // CurrentPC
|
|
|
|
// do the write
|
|
mov r5, r12
|
|
mov r6, lr
|
|
bl \store_func
|
|
mov lr, r6
|
|
mov r12, r5
|
|
|
|
// check exceptions
|
|
ldr r1, [r12, #_StuffToDo]
|
|
cmp r1, #0
|
|
bne _ReturnFromDynaRecAndHandleException
|
|
|
|
bx lr
|
|
.endm
|
|
|
|
.macro WRITE_BITS_BD function, store_func
|
|
\function:
|
|
str r2, [r12,#_CurrentPC] // CurrentPC
|
|
|
|
mov r2, #1 // EXEC_DELAY
|
|
str r2, [r12, #_Delay]
|
|
|
|
// do the write
|
|
mov r5, r12
|
|
mov r6, lr
|
|
bl \store_func
|
|
mov lr, r6
|
|
mov r12, r5
|
|
|
|
|
|
// check exceptions
|
|
ldr r1, [r12, #_StuffToDo]
|
|
cmp r1, #0
|
|
bne _ReturnFromDynaRecAndHandleException
|
|
|
|
mov r0, #0
|
|
str r0, [r12, #_Delay]
|
|
|
|
bx lr
|
|
.endm
|
|
|
|
|
|
|
|
WRITE_BITS _WriteBitsDirect_u8, Write8BitsForDynaRec
|
|
WRITE_BITS _WriteBitsDirect_u16, Write16BitsForDynaRec
|
|
WRITE_BITS _WriteBitsDirect_u32, Write32BitsForDynaRec
|
|
|
|
WRITE_BITS_BD _WriteBitsDirectBD_u8, Write8BitsForDynaRec
|
|
WRITE_BITS_BD _WriteBitsDirectBD_u16, Write16BitsForDynaRec
|
|
WRITE_BITS_BD _WriteBitsDirectBD_u32, Write32BitsForDynaRec
|
|
|
|
_EnterDynaRec:
|
|
push {r4-r12, lr}
|
|
mov r12, r1
|
|
mov r10, r2
|
|
mov r9, r3
|
|
bx r0 |