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