a51590f5ce3417179d40bebf0e45cb591ecf408f
[picodrive.git] / pico_arm.s
1 @ vim:filetype=armasm
2
3 @ SekRunPS runs PicoCpuCM68k and PicoCpuCS68k 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 PicoCpuCM68k
17 .extern PicoCpuCS68k
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-r8,r10,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, =PicoCpuCM68k
36     ldr     lr, =PicoCpuCS68k
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     r10,=SekCycleAimS68k
45     ldr     r2, [r8]
46     ldr     r3, [r10]
47     add     r2, r2, r0
48     add     r3, r3, r1
49     str     r2, [r8]
50     str     r3, [r10]
51
52     ldr     r6, =CycloneJumpTab
53     ldr     r1, =SekCycleCnt
54     ldr     r0, =((488<<16)-PS_STEP_M68K)
55     str     r6, [r7,#0x54]
56     str     r6, [lr,#0x54]            @ make copies to avoid literal pools
57
58     @ schedule m68k for the first time..
59     ldr     r1, [r1]
60     str     r0, [sp]                  @ main target 'left cycle' counter
61     sub     r1, r2, r1
62     subs    r5, r1, r0, asr #16
63     ble     schedule_s68k             @ m68k has not enough cycles
64
65     str     r5, [sp,#4]               @ run_cycle_cnt
66     b       CycloneRunLocal
67
68
69
70 CycloneEnd_M68k:
71     ldr     r3, =SekCycleCnt
72     ldr     r0, [sp,#4]               @ run_cycle_cnt
73     ldr     r1, [r3]
74     str     r4, [r7,#0x40]  ;@ Save Current PC + Memory Base
75     strb    r10,[r7,#0x46]  ;@ Save Flags (NZCV)
76     sub     r0, r0, r5                @ subtract leftover cycles (which should be negative)
77     add     r0, r0, r1
78     str     r0, [r3]
79
80 schedule_s68k:
81     ldr     r8, =SekCycleCntS68k
82     ldr     r10,=SekCycleAimS68k
83     ldr     r3, [sp]
84     ldr     r8, [r8]
85     ldr     r10,[r10]
86
87     sub     r0, r10, r8
88     mov     r2, r3
89     add     r3, r3, r2, asr #1
90     add     r3, r3, r2, asr #3        @ cycn_s68k = (cycn + cycn/2 + cycn/8)
91
92     subs    r5, r0, r3, asr #16
93     ble     schedule_m68k             @ s68k has not enough cycles
94
95     ldr     r7, =PicoCpuCS68k
96     str     r5, [sp,#4]               @ run_cycle_cnt
97     b       CycloneRunLocal
98
99
100
101 CycloneEnd_S68k:
102     ldr     r3, =SekCycleCntS68k
103     ldr     r0, [sp,#4]               @ run_cycle_cnt
104     ldr     r1, [r3]
105     str     r4, [r7,#0x40]  ;@ Save Current PC + Memory Base
106     strb    r10,[r7,#0x46]  ;@ Save Flags (NZCV)
107     sub     r0, r0, r5                @ subtract leftover cycles (should be negative)
108     add     r0, r0, r1
109     str     r0, [r3]
110
111 schedule_m68k:
112     ldr     r1, =PS_STEP_M68K
113     ldr     r3, [sp]                  @ main_cycle_cnt
114     ldr     r8, =SekCycleCnt
115     ldr     r10,=SekCycleAim
116     subs    r3, r3, r1
117     bmi     SekRunPS_end
118
119     ldr     r8, [r8]
120     ldr     r10,[r10]
121     str     r3, [sp]                  @ update main_cycle_cnt
122     sub     r0, r10, r8
123
124     subs    r5, r0, r3, asr #16
125     ble     schedule_s68k             @ m68k has not enough cycles
126
127     ldr     r7, =PicoCpuCM68k
128     str     r5, [sp,#4]               @ run_cycle_cnt
129     b       CycloneRunLocal
130
131
132
133 SekRunPS_end:
134     ldr     r7, =PicoCpuCM68k
135     ldr     lr, =PicoCpuCS68k
136     mov     r0, #0
137     str     r0, [r7,#0x98]            @ remove CycloneEnd handler
138     str     r0, [lr,#0x98]
139     @ return
140     add     sp, sp, #2*4
141     ldmfd   sp!, {r4-r8,r10,r11,pc}
142
143
144
145 CycloneRunLocal:
146                      ;@ r0-3 = Temporary registers
147   ldr r4,[r7,#0x40]  ;@ r4 = Current PC + Memory Base
148                      ;@ r5 = Cycles
149                      ;@ r6 = Opcode Jump table
150                      ;@ r7 = Pointer to Cpu Context
151                      ;@ r8 = Current Opcode
152   ldrb r10,[r7,#0x46];@ r10 = Flags (NZCV)
153   ldr r1,[r7,#0x44]  ;@ get SR high and IRQ level
154   orr r10,r10,r10,lsl #28 ;@ r10 = Flags 0xf0000000, cpsr format
155
156 ;@ CheckInterrupt:
157   movs r0,r1,lsr #24 ;@ Get IRQ level
158   beq NoIntsLocal
159   cmp r0,#6 ;@ irq>6 ?
160   andle r1,r1,#7 ;@ Get interrupt mask
161   cmple r0,r1 ;@ irq<=6: Is irq<=mask ?
162   bgt CycloneDoInterrupt
163 NoIntsLocal:
164
165 ;@ Check if our processor is in special state
166 ;@ and jump to opcode handler if not
167   ldr r0,[r7,#0x58] ;@ state_flags
168   ldrh r8,[r4],#2 ;@ Fetch first opcode
169   tst r0,#0x03 ;@ special state?
170   andeq r10,r10,#0xf0000000
171   ldreq pc,[r6,r8,asl #2] ;@ Jump to opcode handler
172
173 CycloneSpecial2:
174   tst r0,#2 ;@ tracing?
175   bne CycloneDoTrace
176 ;@ stopped or halted
177   sub r4,r4,#2
178   ldr r1,[r7,#0x98]
179   mov r5,#0
180   bx r1
181