X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=Pico%2Fcd%2Fpico_arm.s;fp=Pico%2Fcd%2Fpico_arm.s;h=a51590f5ce3417179d40bebf0e45cb591ecf408f;hb=efcba75f8a730340df6c1b679a207723f98d1ee6;hp=0000000000000000000000000000000000000000;hpb=6a13ef3f56a80ac698d463f5d00235ea2a090f52;p=picodrive.git diff --git a/Pico/cd/pico_arm.s b/Pico/cd/pico_arm.s new file mode 100644 index 0000000..a51590f --- /dev/null +++ b/Pico/cd/pico_arm.s @@ -0,0 +1,181 @@ +@ vim:filetype=armasm + +@ SekRunPS runs PicoCpuCM68k and PicoCpuCS68k interleaved in steps of PS_STEP_M68K +@ cycles. This is done without calling CycloneRun and jumping directly to +@ Cyclone code to avoid pushing/popping all the registers every time. + +@ (c) Copyright 2007, Grazvydas "notaz" Ignotas +@ All Rights Reserved + + +.equiv PS_STEP_M68K, ((488<<16)/20) @ ~24 + +@ .extern is ignored by gas, we add these here just to see what we depend on. +.extern CycloneJumpTab +.extern CycloneDoInterrupt +.extern PicoCpuCM68k +.extern PicoCpuCS68k +.extern SekCycleAim +.extern SekCycleCnt +.extern SekCycleAimS68k +.extern SekCycleCntS68k + + +.text +.align 4 + + +.global SekRunPS @ cyc_m68k, cyc_s68k + +SekRunPS: + stmfd sp!, {r4-r8,r10,r11,lr} + sub sp, sp, #2*4 @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt + + @ override CycloneEnd for both contexts + ldr r7, =PicoCpuCM68k + ldr lr, =PicoCpuCS68k + ldr r2, =CycloneEnd_M68k + ldr r3, =CycloneEnd_S68k + str r2, [r7,#0x98] + str r3, [lr,#0x98] + + @ update aims + ldr r8, =SekCycleAim + ldr r10,=SekCycleAimS68k + ldr r2, [r8] + ldr r3, [r10] + add r2, r2, r0 + add r3, r3, r1 + str r2, [r8] + str r3, [r10] + + ldr r6, =CycloneJumpTab + ldr r1, =SekCycleCnt + ldr r0, =((488<<16)-PS_STEP_M68K) + str r6, [r7,#0x54] + str r6, [lr,#0x54] @ make copies to avoid literal pools + + @ schedule m68k for the first time.. + ldr r1, [r1] + str r0, [sp] @ main target 'left cycle' counter + sub r1, r2, r1 + subs r5, r1, r0, asr #16 + ble schedule_s68k @ m68k has not enough cycles + + str r5, [sp,#4] @ run_cycle_cnt + b CycloneRunLocal + + + +CycloneEnd_M68k: + ldr r3, =SekCycleCnt + ldr r0, [sp,#4] @ run_cycle_cnt + ldr r1, [r3] + str r4, [r7,#0x40] ;@ Save Current PC + Memory Base + strb r10,[r7,#0x46] ;@ Save Flags (NZCV) + sub r0, r0, r5 @ subtract leftover cycles (which should be negative) + add r0, r0, r1 + str r0, [r3] + +schedule_s68k: + ldr r8, =SekCycleCntS68k + ldr r10,=SekCycleAimS68k + ldr r3, [sp] + ldr r8, [r8] + ldr r10,[r10] + + sub r0, r10, r8 + mov r2, r3 + add r3, r3, r2, asr #1 + add r3, r3, r2, asr #3 @ cycn_s68k = (cycn + cycn/2 + cycn/8) + + subs r5, r0, r3, asr #16 + ble schedule_m68k @ s68k has not enough cycles + + ldr r7, =PicoCpuCS68k + str r5, [sp,#4] @ run_cycle_cnt + b CycloneRunLocal + + + +CycloneEnd_S68k: + ldr r3, =SekCycleCntS68k + ldr r0, [sp,#4] @ run_cycle_cnt + ldr r1, [r3] + str r4, [r7,#0x40] ;@ Save Current PC + Memory Base + strb r10,[r7,#0x46] ;@ Save Flags (NZCV) + sub r0, r0, r5 @ subtract leftover cycles (should be negative) + add r0, r0, r1 + str r0, [r3] + +schedule_m68k: + ldr r1, =PS_STEP_M68K + ldr r3, [sp] @ main_cycle_cnt + ldr r8, =SekCycleCnt + ldr r10,=SekCycleAim + subs r3, r3, r1 + bmi SekRunPS_end + + ldr r8, [r8] + ldr r10,[r10] + str r3, [sp] @ update main_cycle_cnt + sub r0, r10, r8 + + subs r5, r0, r3, asr #16 + ble schedule_s68k @ m68k has not enough cycles + + ldr r7, =PicoCpuCM68k + str r5, [sp,#4] @ run_cycle_cnt + b CycloneRunLocal + + + +SekRunPS_end: + ldr r7, =PicoCpuCM68k + ldr lr, =PicoCpuCS68k + mov r0, #0 + str r0, [r7,#0x98] @ remove CycloneEnd handler + str r0, [lr,#0x98] + @ return + add sp, sp, #2*4 + ldmfd sp!, {r4-r8,r10,r11,pc} + + + +CycloneRunLocal: + ;@ r0-3 = Temporary registers + ldr r4,[r7,#0x40] ;@ r4 = Current PC + Memory Base + ;@ r5 = Cycles + ;@ r6 = Opcode Jump table + ;@ r7 = Pointer to Cpu Context + ;@ r8 = Current Opcode + ldrb r10,[r7,#0x46];@ r10 = Flags (NZCV) + ldr r1,[r7,#0x44] ;@ get SR high and IRQ level + orr r10,r10,r10,lsl #28 ;@ r10 = Flags 0xf0000000, cpsr format + +;@ CheckInterrupt: + movs r0,r1,lsr #24 ;@ Get IRQ level + beq NoIntsLocal + cmp r0,#6 ;@ irq>6 ? + andle r1,r1,#7 ;@ Get interrupt mask + cmple r0,r1 ;@ irq<=6: Is irq<=mask ? + bgt CycloneDoInterrupt +NoIntsLocal: + +;@ Check if our processor is in special state +;@ and jump to opcode handler if not + ldr r0,[r7,#0x58] ;@ state_flags + ldrh r8,[r4],#2 ;@ Fetch first opcode + tst r0,#0x03 ;@ special state? + andeq r10,r10,#0xf0000000 + ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler + +CycloneSpecial2: + tst r0,#2 ;@ tracing? + bne CycloneDoTrace +;@ stopped or halted + sub r4,r4,#2 + ldr r1,[r7,#0x98] + mov r5,#0 + bx r1 +