b1f554c5d7f04696ae08c2a75b9db007f928ac01
[picodrive.git] / Pico / cd / Pico.s
1 @ vim:filetype=armasm
2
3 @ SekRunPS runs PicoCpu and PicoCpuS68k interleaved in steps of PS_STEP_M68K
4 @ cycles. This is done without calling CycloneRun and jumping directly to
5 @ Cyclone code to avoid pushing/popping all the registers every time.
6
7 @ (c) Copyright 2007, Grazvydas "notaz" Ignotas
8 @ All Rights Reserved
9
10
11 .equiv PS_STEP_M68K, ((488<<16)/20) @ ~24
12
13 @ .extern is ignored by gas, we add these here just to see what we depend on.
14 .extern CycloneJumpTab
15 .extern CycloneDoInterrupt
16 .extern PicoCpu
17 .extern PicoCpuS68k
18 .extern SekCycleAim
19 .extern SekCycleCnt
20 .extern SekCycleAimS68k
21 .extern SekCycleCntS68k
22
23
24 .text
25 .align 4
26
27
28 .global SekRunPS @ cyc_m68k, cyc_s68k
29
30 SekRunPS:
31     stmfd   sp!, {r4-r11,lr}
32     sub     sp, sp, #2*4          @ sp[0] = main_cycle_cnt, sp[4] = run_cycle_cnt
33
34     @ override CycloneEnd for both contexts
35     ldr     r7, =PicoCpu
36     ldr     lr, =PicoCpuS68k
37     ldr     r2, =CycloneEnd_M68k
38     ldr     r3, =CycloneEnd_S68k
39     str     r2, [r7,#0x98]
40     str     r3, [lr,#0x98]
41
42     @ update aims
43     ldr     r8, =SekCycleAim
44     ldr     r9, =SekCycleAimS68k
45     ldr     r2, [r8]
46     ldr     r3, [r9]
47     add     r2, r2, r0
48     add     r3, r3, r1
49     str     r2, [r8]
50     str     r3, [r9]
51
52     ldr     r1, =SekCycleCnt
53     ldr     r0, =((488<<16)-PS_STEP_M68K)
54     ldr     r6, =CycloneJumpTab
55
56     @ schedule m68k for the first time..
57     ldr     r1, [r1]
58     str     r0, [sp]                  @ main target 'left cycle' counter
59     sub     r1, r2, r1
60     subs    r5, r1, r0, asr #16
61     ble     schedule_s68k             @ m68k has not enough cycles
62
63     str     r5, [sp,#4]               @ run_cycle_cnt
64     b       CycloneRunLocal
65
66
67
68 CycloneEnd_M68k:
69     ldr     r3, =SekCycleCnt
70     ldr     r0, [sp,#4]               @ run_cycle_cnt
71     ldr     r1, [r3]
72     str     r4, [r7,#0x40]  ;@ Save Current PC + Memory Base
73     strb    r9, [r7,#0x46]  ;@ Save Flags (NZCV)
74     sub     r0, r0, r5                @ subtract leftover cycles (which should be negative)
75     add     r0, r0, r1
76     str     r0, [r3]
77
78 schedule_s68k:
79     ldr     r8, =SekCycleCntS68k
80     ldr     r9, =SekCycleAimS68k
81     ldr     r3, [sp]
82     ldr     r8, [r8]
83     ldr     r9, [r9]
84
85     sub     r0, r9, r8
86     mov     r2, r3
87     add     r3, r3, r2, asr #1
88     add     r3, r3, r2, asr #3        @ cycn_s68k = (cycn + cycn/2 + cycn/8)
89
90     subs    r5, r0, r3, asr #16
91     ble     schedule_m68k             @ s68k has not enough cycles
92
93     ldr     r7, =PicoCpuS68k
94     str     r5, [sp,#4]               @ run_cycle_cnt
95     b       CycloneRunLocal
96
97
98
99 CycloneEnd_S68k:
100     ldr     r3, =SekCycleCntS68k
101     ldr     r0, [sp,#4]               @ run_cycle_cnt
102     ldr     r1, [r3]
103     str     r4, [r7,#0x40]  ;@ Save Current PC + Memory Base
104     strb    r9, [r7,#0x46]  ;@ Save Flags (NZCV)
105     sub     r0, r0, r5                @ subtract leftover cycles (should be negative)
106     add     r0, r0, r1
107     str     r0, [r3]
108
109 schedule_m68k:
110     ldr     r1, =PS_STEP_M68K
111     ldr     r3, [sp]                  @ main_cycle_cnt
112     ldr     r8, =SekCycleCnt
113     ldr     r9, =SekCycleAim
114     subs    r3, r3, r1
115     bmi     SekRunPS_end
116
117     ldr     r8, [r8]
118     ldr     r9, [r9]
119     str     r3, [sp]                  @ update main_cycle_cnt
120     sub     r0, r9, r8
121
122     subs    r5, r0, r3, asr #16
123     ble     schedule_s68k             @ m68k has not enough cycles
124
125     ldr     r7, =PicoCpu
126     str     r5, [sp,#4]               @ run_cycle_cnt
127     b       CycloneRunLocal
128
129
130
131 SekRunPS_end:
132     ldr     r7, =PicoCpu
133     ldr     lr, =PicoCpuS68k
134     mov     r0, #0
135     str     r0, [r7,#0x98]            @ remove CycloneEnd handler
136     str     r0, [lr,#0x98]
137     @ return
138     add     sp, sp, #2*4
139     ldmfd   sp!, {r4-r11,pc}
140
141
142
143 CycloneRunLocal:
144                      ;@ r0-3 = Temporary registers
145   ldr r4,[r7,#0x40]  ;@ r4 = Current PC + Memory Base
146                      ;@ r5 = Cycles
147                      ;@ r6 = Opcode Jump table
148                      ;@ r7 = Pointer to Cpu Context
149                      ;@ r8 = Current Opcode
150   ldrb r9,[r7,#0x46] ;@ r9 = Flags (NZCV)
151   ldr r1,[r7,#0x44]  ;@ get SR high and IRQ level
152   orr r9,r9,r9,lsl #28 ;@ r9 = Flags 0xf0000000, cpsr format
153                      ;@ r10 = Source value / Memory Base
154
155 ;@ CheckInterrupt:
156   movs r0,r1,lsr #24 ;@ Get IRQ level
157   beq NoIntsLocal
158   cmp r0,#6 ;@ irq>6 ?
159   andle r1,r1,#7 ;@ Get interrupt mask
160   cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
161   bgt CycloneDoInterrupt
162 NoIntsLocal:
163
164 ;@ Check if our processor is in special state
165 ;@ and jump to opcode handler if not
166   ldr r0,[r7,#0x58] ;@ state_flags
167   ldrh r8,[r4],#2 ;@ Fetch first opcode
168   tst r0,#0x03 ;@ special state?
169   andeq r9,r9,#0xf0000000
170   ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
171
172 CycloneSpecial2:
173   tst r0,#2 ;@ tracing?
174   bne CycloneDoTrace
175 ;@ stopped or halted
176   sub r4,r4,#2
177   ldr r1,[r7,#0x98]
178   mov r5,#0
179   bx r1
180