drc: don't delay block restoration
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / linkage_arm64.S
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
36 dynarec_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
48 DRC_VAR(next_interupt, 4)
49 DRC_VAR(cycle_count, 4)
50 DRC_VAR(last_count, 4)
51 DRC_VAR(pending_exception, 4)
52 DRC_VAR(stop, 4)
53 DRC_VAR(branch_target, 4)
54 DRC_VAR(address, 4)
55 DRC_VAR(hack_addr, 4)
56 DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
57
58 /* psxRegs */
59 #DRC_VAR(reg, 128)
60 DRC_VAR(lo, 4)
61 DRC_VAR(hi, 4)
62 DRC_VAR(reg_cop0, 128)
63 DRC_VAR(reg_cop2d, 128)
64 DRC_VAR(reg_cop2c, 128)
65 DRC_VAR(pcaddr, 4)
66 #DRC_VAR(code, 4)
67 #DRC_VAR(cycle, 4)
68 #DRC_VAR(interrupt, 4)
69 #DRC_VAR(intCycle, 256)
70
71 DRC_VAR(rcnts, 7*4*4)
72 DRC_VAR(inv_code_start, 4)
73 DRC_VAR(inv_code_end, 4)
74 DRC_VAR(mem_rtab, 8)
75 DRC_VAR(mem_wtab, 8)
76 DRC_VAR(psxH_ptr, 8)
77 DRC_VAR(invc_ptr, 8)
78 DRC_VAR(zeromem_ptr, 8)
79 DRC_VAR(scratch_buf_ptr, 8)
80 DRC_VAR(ram_offset, 8)
81 DRC_VAR(mini_ht, 256)
82
83
84         .text
85         .align  2
86
87 /* r0 = virtual target address */
88 /* r1 = instruction to patch */
89 .macro dyna_linker_main
90         /* XXX TODO: should be able to do better than this... */
91         bl      get_addr_ht
92         br      x0
93 .endm
94
95
96 FUNCTION(dyna_linker):
97         /* r0 = virtual target address */
98         /* r1 = instruction to patch */
99         dyna_linker_main
100         .size   dyna_linker, .-dyna_linker
101
102 FUNCTION(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 */
111 FUNCTION(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
117         .align  2
118 FUNCTION(cc_interrupt):
119         ldr     w0, [rFP, #LO_last_count]
120         add     rCC, w0, rCC
121         str     wzr, [rFP, #LO_pending_exception]
122         str     rCC, [rFP, #LO_cycle]           /* PCSX cycles */
123 #       str     rCC, [rFP, #LO_reg_cop0+36]     /* Count */
124         mov     x21, lr
125 1:
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
137 2:
138         ldr     w0, [rFP, #LO_pcaddr]
139         bl      get_addr_ht
140         br      x0
141         .size   cc_interrupt, .-cc_interrupt
142
143         .align  2
144 FUNCTION(fp_exception):
145         mov     w2, #0x10000000
146 0:
147         ldr     w1, [rFP, #LO_reg_cop0+48] /* Status */
148         mov     w3, #0x80000000
149         str     w0, [rFP, #LO_reg_cop0+56] /* EPC */
150         orr     w1, w1, #2
151         add     w2, w2, #0x2c
152         str     w1, [rFP, #LO_reg_cop0+48] /* Status */
153         str     w2, [rFP, #LO_reg_cop0+52] /* Cause */
154         add     w0, w3, #0x80
155         bl      get_addr_ht
156         br      x0
157         .size   fp_exception, .-fp_exception
158         .align  2
159 FUNCTION(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
165 FUNCTION(jump_break_ds):
166         mov     w0, #0x24
167         mov     w1, #1
168         b       call_psxException
169 FUNCTION(jump_break):
170         mov     w0, #0x24
171         mov     w1, #0
172         b       call_psxException
173 FUNCTION(jump_syscall_ds):
174         mov     w0, #0x20
175         mov     w1, #1
176         b       call_psxException
177 FUNCTION(jump_syscall):
178         mov     w0, #0x20
179         mov     w1, #0
180
181 call_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
187
188         /* note: psxException might do recursive recompiler call from it's HLE code,
189          * so be ready for this */
190 FUNCTION(jump_to_new_pc):
191         ldr     w1, [rFP, #LO_next_interupt]
192         ldr     rCC, [rFP, #LO_cycle]
193         ldr     w0, [rFP, #LO_pcaddr]
194         sub     rCC, rCC, w1
195         str     w1, [rFP, #LO_last_count]
196         bl      get_addr_ht
197         br      x0
198         .size   jump_to_new_pc, .-jump_to_new_pc
199
200         /* stack must be aligned by 16, and include space for save_regs() use */
201         .align  2
202 FUNCTION(new_dyna_start):
203         stp     x29, x30, [sp, #-SSP_ALL]!
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
220 FUNCTION(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]
229         ldp     x29, x30, [sp], #SSP_ALL
230         ret
231         .size   new_dyna_leave, .-new_dyna_leave
232
233 /* --------------------------------------- */
234
235 .align  2
236
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
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
249 .endm
250
251 FUNCTION(do_memhandler_pre):
252         memhandler_pre
253         ret
254
255 FUNCTION(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 */
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
267 0:
268         stp     xzr, x30, [sp, #-16]!
269         memhandler_pre
270         blr     x3
271 .endm
272
273 FUNCTION(jump_handler_read8):
274         add     x1, x1, #0x1000/4*8 + 0x1000/2*8  /* shift to r8 part */
275         pcsx_read_mem ldrb, 0
276         b       handler_read_end
277
278 FUNCTION(jump_handler_read16):
279         add     x1, x1, #0x1000/4*8               /* shift to r16 part */
280         pcsx_read_mem ldrh, 1
281         b       handler_read_end
282
283 FUNCTION(jump_handler_read32):
284         pcsx_read_mem ldr, 2
285
286 handler_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 */
292         ubfm    w4, w0, #\tab_shift, #11
293         ldr     x3, [x3, w4, uxtw #3]
294         adds    x3, x3, x3
295         bcs     0f
296         mov     w0, w2                    /* cycle return */
297         \wrtop  w1, [x3, w4, uxtw #\tab_shift]
298         ret
299 0:
300         stp     xzr, x30, [sp, #-16]!
301         str     w0, [rFP, #LO_address]    /* some handlers still need it... */
302         \movop  w0, w1
303         memhandler_pre
304         blr     x3
305 .endm
306
307 FUNCTION(jump_handler_write8):
308         add     x3, x3, #0x1000/4*8 + 0x1000/2*8  /* shift to r8 part */
309         pcsx_write_mem strb uxtb 0
310         b       handler_write_end
311
312 FUNCTION(jump_handler_write16):
313         add     x3, x3, #0x1000/4*8               /* shift to r16 part */
314         pcsx_write_mem strh uxth 1
315         b       handler_write_end
316
317 FUNCTION(jump_handler_write32):
318         pcsx_write_mem str mov 2
319
320 handler_write_end:
321         memhandler_post
322         ldp     xzr, x30, [sp], #16
323         ret
324
325 FUNCTION(jump_handle_swl):
326         /* w0 = address, w1 = data, w2 = cycles */
327         ldr     x3, [rFP, #LO_mem_wtab]
328         orr     w4, wzr, w0, lsr #12
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
336 3:
337         stur    w1, [x3, #-3]
338         ret
339 2:
340         lsr     w2, w1, #8
341         lsr     w1, w1, #24
342         sturh   w2, [x3, #-2]
343         strb    w1, [x3]
344         ret
345 10:
346         tbz     x3, #0, 0f      // & 1
347 1:
348         lsr     w1, w1, #16
349         sturh   w1, [x3, #-1]
350         ret
351 0:
352         lsr     w2, w1, #24
353         strb    w2, [x3]
354         ret
355 4:
356         mov     w0, w2          // todo
357         bl      abort
358         ret
359
360 FUNCTION(jump_handle_swr):
361         /* w0 = address, w1 = data, w2 = cycles */
362         ldr     x3, [rFP, #LO_mem_wtab]
363         orr     w4, wzr, w0, lsr #12
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
371 3:
372         strb    w1, [x3]
373         ret
374 2:
375         strh    w1, [x3]
376         ret
377 10:
378         tbz     x3, #0, 0f      // & 1
379 1:
380         lsr     w2, w1, #8
381         strb    w1, [x3]
382         sturh   w2, [x3, #1]
383         ret
384 0:
385         str     w1, [x3]
386         ret
387 4:
388         mov     w0, w2          // todo
389         bl      abort
390         ret
391
392 FUNCTION(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