drc: rework block tracking
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm64.S
... / ...
CommitLineData
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * linkage_arm.s for PCSX *
3 * Copyright (C) 2009-2011 Ari64 *
4 * Copyright (C) 2021 notaz *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22#include "arm_features.h"
23#include "new_dynarec_config.h"
24#include "assem_arm64.h"
25#include "linkage_offsets.h"
26
27#if (LO_mem_wtab & 7)
28#error misligned pointers
29#endif
30
31.bss
32 .align 4
33 .global dynarec_local
34 .type dynarec_local, %object
35 .size dynarec_local, LO_dynarec_local_size
36dynarec_local:
37 .space LO_dynarec_local_size
38
39#define DRC_VAR_(name, vname, size_) \
40 vname = dynarec_local + LO_##name; \
41 .global vname; \
42 .type vname, %object; \
43 .size vname, size_
44
45#define DRC_VAR(name, size_) \
46 DRC_VAR_(name, ESYM(name), size_)
47
48DRC_VAR(next_interupt, 4)
49DRC_VAR(cycle_count, 4)
50DRC_VAR(last_count, 4)
51DRC_VAR(pending_exception, 4)
52DRC_VAR(stop, 4)
53DRC_VAR(branch_target, 4)
54DRC_VAR(address, 4)
55DRC_VAR(hack_addr, 4)
56DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
57
58/* psxRegs */
59#DRC_VAR(reg, 128)
60DRC_VAR(lo, 4)
61DRC_VAR(hi, 4)
62DRC_VAR(reg_cop0, 128)
63DRC_VAR(reg_cop2d, 128)
64DRC_VAR(reg_cop2c, 128)
65DRC_VAR(pcaddr, 4)
66#DRC_VAR(code, 4)
67#DRC_VAR(cycle, 4)
68#DRC_VAR(interrupt, 4)
69#DRC_VAR(intCycle, 256)
70
71DRC_VAR(rcnts, 7*4*4)
72DRC_VAR(inv_code_start, 4)
73DRC_VAR(inv_code_end, 4)
74DRC_VAR(mem_rtab, 8)
75DRC_VAR(mem_wtab, 8)
76DRC_VAR(psxH_ptr, 8)
77DRC_VAR(invc_ptr, 8)
78DRC_VAR(zeromem_ptr, 8)
79DRC_VAR(scratch_buf_ptr, 8)
80DRC_VAR(ram_offset, 8)
81DRC_VAR(mini_ht, 256)
82
83
84 .text
85 .align 2
86
87FUNCTION(dyna_linker):
88 /* r0 = virtual target address */
89 /* r1 = instruction to patch */
90 bl ndrc_get_addr_ht
91 br x0
92 .size dyna_linker, .-dyna_linker
93
94 .align 2
95FUNCTION(cc_interrupt):
96 ldr w0, [rFP, #LO_last_count]
97 add rCC, w0, rCC
98 str wzr, [rFP, #LO_pending_exception]
99 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
100# str rCC, [rFP, #LO_reg_cop0+36] /* Count */
101 mov x21, lr
1021:
103 bl gen_interupt
104 mov lr, x21
105 ldr rCC, [rFP, #LO_cycle]
106 ldr w0, [rFP, #LO_next_interupt]
107 ldr w1, [rFP, #LO_pending_exception]
108 ldr w2, [rFP, #LO_stop]
109 str w0, [rFP, #LO_last_count]
110 sub rCC, rCC, w0
111 cbnz w2, new_dyna_leave
112 cbnz w1, 2f
113 ret
1142:
115 ldr w0, [rFP, #LO_pcaddr]
116 bl ndrc_get_addr_ht
117 br x0
118 .size cc_interrupt, .-cc_interrupt
119
120 .align 2
121FUNCTION(fp_exception):
122 mov w2, #0x10000000
1230:
124 ldr w1, [rFP, #LO_reg_cop0+48] /* Status */
125 mov w3, #0x80000000
126 str w0, [rFP, #LO_reg_cop0+56] /* EPC */
127 orr w1, w1, #2
128 add w2, w2, #0x2c
129 str w1, [rFP, #LO_reg_cop0+48] /* Status */
130 str w2, [rFP, #LO_reg_cop0+52] /* Cause */
131 add w0, w3, #0x80
132 bl ndrc_get_addr_ht
133 br x0
134 .size fp_exception, .-fp_exception
135 .align 2
136FUNCTION(fp_exception_ds):
137 mov w2, #0x90000000 /* Set high bit if delay slot */
138 b 0b
139 .size fp_exception_ds, .-fp_exception_ds
140
141 .align 2
142FUNCTION(jump_break_ds):
143 mov w0, #0x24
144 mov w1, #1
145 b call_psxException
146FUNCTION(jump_break):
147 mov w0, #0x24
148 mov w1, #0
149 b call_psxException
150FUNCTION(jump_syscall_ds):
151 mov w0, #0x20
152 mov w1, #1
153 b call_psxException
154FUNCTION(jump_syscall):
155 mov w0, #0x20
156 mov w1, #0
157
158call_psxException:
159 ldr w3, [rFP, #LO_last_count]
160 str w2, [rFP, #LO_pcaddr]
161 add rCC, w3, rCC
162 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
163 bl psxException
164
165 /* note: psxException might do recursive recompiler call from it's HLE code,
166 * so be ready for this */
167FUNCTION(jump_to_new_pc):
168 ldr w1, [rFP, #LO_next_interupt]
169 ldr rCC, [rFP, #LO_cycle]
170 ldr w0, [rFP, #LO_pcaddr]
171 sub rCC, rCC, w1
172 str w1, [rFP, #LO_last_count]
173 bl ndrc_get_addr_ht
174 br x0
175 .size jump_to_new_pc, .-jump_to_new_pc
176
177 /* stack must be aligned by 16, and include space for save_regs() use */
178 .align 2
179FUNCTION(new_dyna_start):
180 stp x29, x30, [sp, #-SSP_ALL]!
181 ldr w1, [x0, #LO_next_interupt]
182 ldr w2, [x0, #LO_cycle]
183 stp x19, x20, [sp, #16*1]
184 stp x21, x22, [sp, #16*2]
185 stp x23, x24, [sp, #16*3]
186 stp x25, x26, [sp, #16*4]
187 stp x27, x28, [sp, #16*5]
188 mov rFP, x0
189 ldr w0, [rFP, #LO_pcaddr]
190 str w1, [rFP, #LO_last_count]
191 sub rCC, w2, w1
192 bl ndrc_get_addr_ht
193 br x0
194 .size new_dyna_start, .-new_dyna_start
195
196 .align 2
197FUNCTION(new_dyna_leave):
198 ldr w0, [rFP, #LO_last_count]
199 add rCC, rCC, w0
200 str rCC, [rFP, #LO_cycle]
201 ldp x19, x20, [sp, #16*1]
202 ldp x21, x22, [sp, #16*2]
203 ldp x23, x24, [sp, #16*3]
204 ldp x25, x26, [sp, #16*4]
205 ldp x27, x28, [sp, #16*5]
206 ldp x29, x30, [sp], #SSP_ALL
207 ret
208 .size new_dyna_leave, .-new_dyna_leave
209
210/* --------------------------------------- */
211
212.align 2
213
214.macro memhandler_pre
215 /* w0 = adddr/data, x1 = rhandler, w2 = cycles, x3 = whandler */
216 ldr w4, [rFP, #LO_last_count]
217 add w4, w4, w2
218 str w4, [rFP, #LO_cycle]
219.endm
220
221.macro memhandler_post
222 ldr w0, [rFP, #LO_next_interupt]
223 ldr w2, [rFP, #LO_cycle] // memhandlers can modify cc, like dma
224 str w0, [rFP, #LO_last_count]
225 sub w0, w2, w0
226.endm
227
228FUNCTION(do_memhandler_pre):
229 memhandler_pre
230 ret
231
232FUNCTION(do_memhandler_post):
233 memhandler_post
234 ret
235
236.macro pcsx_read_mem readop tab_shift
237 /* w0 = address, x1 = handler_tab, w2 = cycles */
238 ubfm w4, w0, #\tab_shift, #11
239 ldr x3, [x1, w4, uxtw #3]
240 adds x3, x3, x3
241 bcs 0f
242 \readop w0, [x3, w4, uxtw #\tab_shift]
243 ret
2440:
245 stp xzr, x30, [sp, #-16]!
246 memhandler_pre
247 blr x3
248.endm
249
250FUNCTION(jump_handler_read8):
251 add x1, x1, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
252 pcsx_read_mem ldrb, 0
253 b handler_read_end
254
255FUNCTION(jump_handler_read16):
256 add x1, x1, #0x1000/4*8 /* shift to r16 part */
257 pcsx_read_mem ldrh, 1
258 b handler_read_end
259
260FUNCTION(jump_handler_read32):
261 pcsx_read_mem ldr, 2
262
263handler_read_end:
264 ldp xzr, x30, [sp], #16
265 ret
266
267.macro pcsx_write_mem wrtop movop tab_shift
268 /* w0 = address, w1 = data, w2 = cycles, x3 = handler_tab */
269 ubfm w4, w0, #\tab_shift, #11
270 ldr x3, [x3, w4, uxtw #3]
271 adds x3, x3, x3
272 bcs 0f
273 mov w0, w2 /* cycle return */
274 \wrtop w1, [x3, w4, uxtw #\tab_shift]
275 ret
2760:
277 stp xzr, x30, [sp, #-16]!
278 str w0, [rFP, #LO_address] /* some handlers still need it... */
279 \movop w0, w1
280 memhandler_pre
281 blr x3
282.endm
283
284FUNCTION(jump_handler_write8):
285 add x3, x3, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
286 pcsx_write_mem strb uxtb 0
287 b handler_write_end
288
289FUNCTION(jump_handler_write16):
290 add x3, x3, #0x1000/4*8 /* shift to r16 part */
291 pcsx_write_mem strh uxth 1
292 b handler_write_end
293
294FUNCTION(jump_handler_write32):
295 pcsx_write_mem str mov 2
296
297handler_write_end:
298 memhandler_post
299 ldp xzr, x30, [sp], #16
300 ret
301
302FUNCTION(jump_handle_swl):
303 /* w0 = address, w1 = data, w2 = cycles */
304 ldr x3, [rFP, #LO_mem_wtab]
305 orr w4, wzr, w0, lsr #12
306 ldr x3, [x3, w4, uxtw #3]
307 adds x3, x3, x3
308 bcs 4f
309 add x3, x0, x3
310 mov w0, w2
311 tbz x3, #1, 10f // & 2
312 tbz x3, #0, 2f // & 1
3133:
314 stur w1, [x3, #-3]
315 ret
3162:
317 lsr w2, w1, #8
318 lsr w1, w1, #24
319 sturh w2, [x3, #-2]
320 strb w1, [x3]
321 ret
32210:
323 tbz x3, #0, 0f // & 1
3241:
325 lsr w1, w1, #16
326 sturh w1, [x3, #-1]
327 ret
3280:
329 lsr w2, w1, #24
330 strb w2, [x3]
331 ret
3324:
333 mov w0, w2 // todo
334 bl abort
335 ret
336
337FUNCTION(jump_handle_swr):
338 /* w0 = address, w1 = data, w2 = cycles */
339 ldr x3, [rFP, #LO_mem_wtab]
340 orr w4, wzr, w0, lsr #12
341 ldr x3, [x3, w4, uxtw #3]
342 adds x3, x3, x3
343 bcs 4f
344 add x3, x0, x3
345 mov w0, w2
346 tbz x3, #1, 10f // & 2
347 tbz x3, #0, 2f // & 1
3483:
349 strb w1, [x3]
350 ret
3512:
352 strh w1, [x3]
353 ret
35410:
355 tbz x3, #0, 0f // & 1
3561:
357 lsr w2, w1, #8
358 strb w1, [x3]
359 sturh w2, [x3, #1]
360 ret
3610:
362 str w1, [x3]
363 ret
3644:
365 mov w0, w2 // todo
366 bl abort
367 ret
368
369FUNCTION(call_gteStall):
370 /* w0 = op_cycles, w1 = cycles */
371 ldr w2, [rFP, #LO_last_count]
372 str lr, [rFP, #LO_saved_lr]
373 add w1, w1, w2
374 str w1, [rFP, #LO_cycle]
375 add x1, rFP, #LO_psxRegs
376 bl gteCheckStallRaw
377 ldr lr, [rFP, #LO_saved_lr]
378 add rCC, rCC, w0
379 ret
380