drc: restore all block entry points at once
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm64.S
CommitLineData
be516ebe 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
39b71d9a 27#if (LO_mem_wtab & 7)
28#error misligned pointers
29#endif
30
be516ebe 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)
687b4580 53DRC_VAR(branch_target, 4)
be516ebe 54DRC_VAR(address, 4)
7f94b097 55DRC_VAR(hack_addr, 4)
be516ebe 56DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
57
58/* psxRegs */
7c3a5182 59#DRC_VAR(reg, 128)
be516ebe 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)
be516ebe 72DRC_VAR(inv_code_start, 4)
73DRC_VAR(inv_code_end, 4)
687b4580 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)
37387d8b 80DRC_VAR(ram_offset, 8)
be516ebe 81DRC_VAR(mini_ht, 256)
be516ebe 82
83
84 .text
85 .align 2
86
87/* r0 = virtual target address */
88/* r1 = instruction to patch */
89.macro dyna_linker_main
d1e4ebd9 90 /* XXX TODO: should be able to do better than this... */
be516ebe 91 bl get_addr_ht
92 br x0
93.endm
94
95
96FUNCTION(dyna_linker):
97 /* r0 = virtual target address */
98 /* r1 = instruction to patch */
99 dyna_linker_main
100 .size dyna_linker, .-dyna_linker
101
102FUNCTION(exec_pagefault):
103 /* r0 = instruction pointer */
104 /* r1 = fault address */
105 /* r2 = cause */
106 bl abort
107 .size exec_pagefault, .-exec_pagefault
108
109/* Special dynamic linker for the case where a page fault
110 may occur in a branch delay slot */
111FUNCTION(dyna_linker_ds):
112 /* r0 = virtual target address */
113 /* r1 = instruction to patch */
114 dyna_linker_main
115 .size dyna_linker_ds, .-dyna_linker_ds
116
be516ebe 117 .align 2
118FUNCTION(cc_interrupt):
d1e4ebd9 119 ldr w0, [rFP, #LO_last_count]
d1e4ebd9 120 add rCC, w0, rCC
121 str wzr, [rFP, #LO_pending_exception]
d1e4ebd9 122 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
123# str rCC, [rFP, #LO_reg_cop0+36] /* Count */
d1e4ebd9 124 mov x21, lr
d1e4ebd9 1251:
126 bl gen_interupt
127 mov lr, x21
128 ldr rCC, [rFP, #LO_cycle]
129 ldr w0, [rFP, #LO_next_interupt]
130 ldr w1, [rFP, #LO_pending_exception]
131 ldr w2, [rFP, #LO_stop]
132 str w0, [rFP, #LO_last_count]
133 sub rCC, rCC, w0
134 cbnz w2, new_dyna_leave
135 cbnz w1, 2f
136 ret
1372:
138 ldr w0, [rFP, #LO_pcaddr]
139 bl get_addr_ht
140 br x0
be516ebe 141 .size cc_interrupt, .-cc_interrupt
142
be516ebe 143 .align 2
144FUNCTION(fp_exception):
145 mov w2, #0x10000000
1460:
81dbbf4c 147 ldr w1, [rFP, #LO_reg_cop0+48] /* Status */
be516ebe 148 mov w3, #0x80000000
81dbbf4c 149 str w0, [rFP, #LO_reg_cop0+56] /* EPC */
be516ebe 150 orr w1, w1, #2
151 add w2, w2, #0x2c
81dbbf4c 152 str w1, [rFP, #LO_reg_cop0+48] /* Status */
153 str w2, [rFP, #LO_reg_cop0+52] /* Cause */
be516ebe 154 add w0, w3, #0x80
155 bl get_addr_ht
156 br x0
157 .size fp_exception, .-fp_exception
158 .align 2
159FUNCTION(fp_exception_ds):
160 mov w2, #0x90000000 /* Set high bit if delay slot */
161 b 0b
162 .size fp_exception_ds, .-fp_exception_ds
163
164 .align 2
d1150cd6 165FUNCTION(jump_break_ds):
166 mov w0, #0x24
167 mov w1, #1
168 b call_psxException
169FUNCTION(jump_break):
170 mov w0, #0x24
171 mov w1, #0
172 b call_psxException
173FUNCTION(jump_syscall_ds):
174 mov w0, #0x20
175 mov w1, #1
176 b call_psxException
be516ebe 177FUNCTION(jump_syscall):
d1150cd6 178 mov w0, #0x20
179 mov w1, #0
180
181call_psxException:
182 ldr w3, [rFP, #LO_last_count]
183 str w2, [rFP, #LO_pcaddr]
184 add rCC, w3, rCC
185 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
186 bl psxException
be516ebe 187
be516ebe 188 /* note: psxException might do recursive recompiler call from it's HLE code,
189 * so be ready for this */
3968e69e 190FUNCTION(jump_to_new_pc):
81dbbf4c 191 ldr w1, [rFP, #LO_next_interupt]
192 ldr rCC, [rFP, #LO_cycle]
193 ldr w0, [rFP, #LO_pcaddr]
3968e69e 194 sub rCC, rCC, w1
81dbbf4c 195 str w1, [rFP, #LO_last_count]
be516ebe 196 bl get_addr_ht
197 br x0
3968e69e 198 .size jump_to_new_pc, .-jump_to_new_pc
be516ebe 199
687b4580 200 /* stack must be aligned by 16, and include space for save_regs() use */
be516ebe 201 .align 2
202FUNCTION(new_dyna_start):
687b4580 203 stp x29, x30, [sp, #-SSP_ALL]!
be516ebe 204 ldr w1, [x0, #LO_next_interupt]
205 ldr w2, [x0, #LO_cycle]
206 stp x19, x20, [sp, #16*1]
207 stp x21, x22, [sp, #16*2]
208 stp x23, x24, [sp, #16*3]
209 stp x25, x26, [sp, #16*4]
210 stp x27, x28, [sp, #16*5]
211 mov rFP, x0
212 ldr w0, [rFP, #LO_pcaddr]
213 str w1, [rFP, #LO_last_count]
214 sub rCC, w2, w1
215 bl get_addr_ht
216 br x0
217 .size new_dyna_start, .-new_dyna_start
218
219 .align 2
220FUNCTION(new_dyna_leave):
221 ldr w0, [rFP, #LO_last_count]
222 add rCC, rCC, w0
223 str rCC, [rFP, #LO_cycle]
224 ldp x19, x20, [sp, #16*1]
225 ldp x21, x22, [sp, #16*2]
226 ldp x23, x24, [sp, #16*3]
227 ldp x25, x26, [sp, #16*4]
228 ldp x27, x28, [sp, #16*5]
687b4580 229 ldp x29, x30, [sp], #SSP_ALL
be516ebe 230 ret
231 .size new_dyna_leave, .-new_dyna_leave
232
233/* --------------------------------------- */
234
235.align 2
236
d1e4ebd9 237.macro memhandler_pre
238 /* w0 = adddr/data, x1 = rhandler, w2 = cycles, x3 = whandler */
239 ldr w4, [rFP, #LO_last_count]
240 add w4, w4, w2
241 str w4, [rFP, #LO_cycle]
242.endm
243
244.macro memhandler_post
9b9af0d1 245 ldr w0, [rFP, #LO_next_interupt]
246 ldr w2, [rFP, #LO_cycle] // memhandlers can modify cc, like dma
247 str w0, [rFP, #LO_last_count]
248 sub w0, w2, w0
d1e4ebd9 249.endm
250
251FUNCTION(do_memhandler_pre):
252 memhandler_pre
253 ret
254
255FUNCTION(do_memhandler_post):
256 memhandler_post
257 ret
258
259.macro pcsx_read_mem readop tab_shift
260 /* w0 = address, x1 = handler_tab, w2 = cycles */
d1e4ebd9 261 ubfm w4, w0, #\tab_shift, #11
262 ldr x3, [x1, w4, uxtw #3]
263 adds x3, x3, x3
264 bcs 0f
265 \readop w0, [x3, w4, uxtw #\tab_shift]
266 ret
2670:
3968e69e 268 stp xzr, x30, [sp, #-16]!
d1e4ebd9 269 memhandler_pre
270 blr x3
271.endm
272
be516ebe 273FUNCTION(jump_handler_read8):
3968e69e 274 add x1, x1, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
d1e4ebd9 275 pcsx_read_mem ldrb, 0
276 b handler_read_end
be516ebe 277
278FUNCTION(jump_handler_read16):
3968e69e 279 add x1, x1, #0x1000/4*8 /* shift to r16 part */
d1e4ebd9 280 pcsx_read_mem ldrh, 1
281 b handler_read_end
be516ebe 282
283FUNCTION(jump_handler_read32):
d1e4ebd9 284 pcsx_read_mem ldr, 2
285
286handler_read_end:
287 ldp xzr, x30, [sp], #16
288 ret
289
290.macro pcsx_write_mem wrtop movop tab_shift
291 /* w0 = address, w1 = data, w2 = cycles, x3 = handler_tab */
d1e4ebd9 292 ubfm w4, w0, #\tab_shift, #11
293 ldr x3, [x3, w4, uxtw #3]
d1e4ebd9 294 adds x3, x3, x3
d1e4ebd9 295 bcs 0f
296 mov w0, w2 /* cycle return */
297 \wrtop w1, [x3, w4, uxtw #\tab_shift]
298 ret
2990:
3968e69e 300 stp xzr, x30, [sp, #-16]!
301 str w0, [rFP, #LO_address] /* some handlers still need it... */
d1e4ebd9 302 \movop w0, w1
303 memhandler_pre
304 blr x3
305.endm
be516ebe 306
307FUNCTION(jump_handler_write8):
3968e69e 308 add x3, x3, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
d1e4ebd9 309 pcsx_write_mem strb uxtb 0
310 b handler_write_end
be516ebe 311
312FUNCTION(jump_handler_write16):
3968e69e 313 add x3, x3, #0x1000/4*8 /* shift to r16 part */
d1e4ebd9 314 pcsx_write_mem strh uxth 1
315 b handler_write_end
be516ebe 316
317FUNCTION(jump_handler_write32):
d1e4ebd9 318 pcsx_write_mem str mov 2
be516ebe 319
d1e4ebd9 320handler_write_end:
321 memhandler_post
322 ldp xzr, x30, [sp], #16
323 ret
be516ebe 324
325FUNCTION(jump_handle_swl):
3968e69e 326 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 327 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 328 orr w4, wzr, w0, lsr #12
3968e69e 329 ldr x3, [x3, w4, uxtw #3]
330 adds x3, x3, x3
331 bcs 4f
332 add x3, x0, x3
333 mov w0, w2
334 tbz x3, #1, 10f // & 2
335 tbz x3, #0, 2f // & 1
3363:
337 stur w1, [x3, #-3]
338 ret
3392:
340 lsr w2, w1, #8
341 lsr w1, w1, #24
342 sturh w2, [x3, #-2]
343 strb w1, [x3]
344 ret
34510:
346 tbz x3, #0, 0f // & 1
3471:
348 lsr w1, w1, #16
349 sturh w1, [x3, #-1]
350 ret
3510:
352 lsr w2, w1, #24
353 strb w2, [x3]
354 ret
3554:
356 mov w0, w2 // todo
be516ebe 357 bl abort
3968e69e 358 ret
be516ebe 359
360FUNCTION(jump_handle_swr):
3968e69e 361 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 362 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 363 orr w4, wzr, w0, lsr #12
3968e69e 364 ldr x3, [x3, w4, uxtw #3]
365 adds x3, x3, x3
366 bcs 4f
367 add x3, x0, x3
368 mov w0, w2
369 tbz x3, #1, 10f // & 2
370 tbz x3, #0, 2f // & 1
3713:
372 strb w1, [x3]
373 ret
3742:
375 strh w1, [x3]
376 ret
37710:
378 tbz x3, #0, 0f // & 1
3791:
380 lsr w2, w1, #8
381 strb w1, [x3]
382 sturh w2, [x3, #1]
383 ret
3840:
385 str w1, [x3]
386 ret
3874:
388 mov w0, w2 // todo
be516ebe 389 bl abort
3968e69e 390 ret
be516ebe 391
81dbbf4c 392FUNCTION(call_gteStall):
393 /* w0 = op_cycles, w1 = cycles */
394 ldr w2, [rFP, #LO_last_count]
395 str lr, [rFP, #LO_saved_lr]
396 add w1, w1, w2
397 str w1, [rFP, #LO_cycle]
398 add x1, rFP, #LO_psxRegs
399 bl gteCheckStallRaw
400 ldr lr, [rFP, #LO_saved_lr]
401 add rCC, rCC, w0
402 ret
403