drc: implement cycle reload on read
[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
c57af5e6 27#ifdef __MACH__
28#define dynarec_local ESYM(dynarec_local)
29#define ndrc_add_jump_out ESYM(ndrc_add_jump_out)
30#define ndrc_get_addr_ht ESYM(ndrc_get_addr_ht)
31#define gen_interupt ESYM(gen_interupt)
32#define gteCheckStallRaw ESYM(gteCheckStallRaw)
33#define psxException ESYM(psxException)
34#define execI ESYM(execI)
35#endif
36
39b71d9a 37#if (LO_mem_wtab & 7)
38#error misligned pointers
39#endif
40
be516ebe 41.bss
42 .align 4
43 .global dynarec_local
c57af5e6 44 EOBJECT(dynarec_local)
45 ESIZE(dynarec_local, LO_dynarec_local_size)
be516ebe 46dynarec_local:
47 .space LO_dynarec_local_size
48
49#define DRC_VAR_(name, vname, size_) \
c57af5e6 50 vname = dynarec_local + LO_##name ASM_SEPARATOR \
51 .globl vname; \
52 EOBJECT(vname); \
53 ESIZE(vname, LO_dynarec_local_size)
be516ebe 54
55#define DRC_VAR(name, size_) \
56 DRC_VAR_(name, ESYM(name), size_)
57
58DRC_VAR(next_interupt, 4)
59DRC_VAR(cycle_count, 4)
60DRC_VAR(last_count, 4)
61DRC_VAR(pending_exception, 4)
62DRC_VAR(stop, 4)
687b4580 63DRC_VAR(branch_target, 4)
be516ebe 64DRC_VAR(address, 4)
7f94b097 65DRC_VAR(hack_addr, 4)
be516ebe 66DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
67
68/* psxRegs */
7c3a5182 69#DRC_VAR(reg, 128)
be516ebe 70DRC_VAR(lo, 4)
71DRC_VAR(hi, 4)
72DRC_VAR(reg_cop0, 128)
73DRC_VAR(reg_cop2d, 128)
74DRC_VAR(reg_cop2c, 128)
75DRC_VAR(pcaddr, 4)
76#DRC_VAR(code, 4)
77#DRC_VAR(cycle, 4)
78#DRC_VAR(interrupt, 4)
79#DRC_VAR(intCycle, 256)
80
81DRC_VAR(rcnts, 7*4*4)
be516ebe 82DRC_VAR(inv_code_start, 4)
83DRC_VAR(inv_code_end, 4)
687b4580 84DRC_VAR(mem_rtab, 8)
85DRC_VAR(mem_wtab, 8)
86DRC_VAR(psxH_ptr, 8)
87DRC_VAR(invc_ptr, 8)
88DRC_VAR(zeromem_ptr, 8)
89DRC_VAR(scratch_buf_ptr, 8)
37387d8b 90DRC_VAR(ram_offset, 8)
be516ebe 91DRC_VAR(mini_ht, 256)
be516ebe 92
93
94 .text
95 .align 2
96
be516ebe 97FUNCTION(dyna_linker):
98 /* r0 = virtual target address */
99 /* r1 = instruction to patch */
104df9d3 100 bl ndrc_get_addr_ht
4bdc30ab 101 br x0
c57af5e6 102 ESIZE(dyna_linker, .-dyna_linker)
be516ebe 103
be516ebe 104 .align 2
105FUNCTION(cc_interrupt):
d1e4ebd9 106 ldr w0, [rFP, #LO_last_count]
d1e4ebd9 107 add rCC, w0, rCC
108 str wzr, [rFP, #LO_pending_exception]
d1e4ebd9 109 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
d1e4ebd9 110 mov x21, lr
d1e4ebd9 1111:
de6dbc52 112 add x0, rFP, #LO_reg_cop0 /* CP0 */
d1e4ebd9 113 bl gen_interupt
114 mov lr, x21
115 ldr rCC, [rFP, #LO_cycle]
116 ldr w0, [rFP, #LO_next_interupt]
117 ldr w1, [rFP, #LO_pending_exception]
118 ldr w2, [rFP, #LO_stop]
119 str w0, [rFP, #LO_last_count]
120 sub rCC, rCC, w0
121 cbnz w2, new_dyna_leave
122 cbnz w1, 2f
123 ret
1242:
125 ldr w0, [rFP, #LO_pcaddr]
104df9d3 126 bl ndrc_get_addr_ht
d1e4ebd9 127 br x0
c57af5e6 128 ESIZE(cc_interrupt, .-cc_interrupt)
be516ebe 129
be516ebe 130 .align 2
277718fa 131FUNCTION(jump_addrerror_ds): /* R3000E_AdEL / R3000E_AdES in w0 */
132 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
133 mov w1, #1
134 b call_psxException
135FUNCTION(jump_addrerror):
136 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
137 mov w1, #0
138 b call_psxException
a5cd72d0 139FUNCTION(jump_overflow_ds):
140 mov w0, #(12<<2) /* R3000E_Ov */
141 mov w1, #1
142 b call_psxException
143FUNCTION(jump_overflow):
144 mov w0, #(12<<2)
145 mov w1, #0
146 b call_psxException
d1150cd6 147FUNCTION(jump_break_ds):
a5cd72d0 148 mov w0, #(9<<2) /* R3000E_Bp */
d1150cd6 149 mov w1, #1
150 b call_psxException
151FUNCTION(jump_break):
a5cd72d0 152 mov w0, #(9<<2)
d1150cd6 153 mov w1, #0
154 b call_psxException
155FUNCTION(jump_syscall_ds):
a5cd72d0 156 mov w0, #(8<<2) /* R3000E_Syscall */
bc7c5acb 157 mov w1, #2
d1150cd6 158 b call_psxException
be516ebe 159FUNCTION(jump_syscall):
a5cd72d0 160 mov w0, #(8<<2)
d1150cd6 161 mov w1, #0
162
163call_psxException:
164 ldr w3, [rFP, #LO_last_count]
165 str w2, [rFP, #LO_pcaddr]
166 add rCC, w3, rCC
6d75addf 167 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
de6dbc52 168 add x2, rFP, #LO_reg_cop0 /* CP0 */
d1150cd6 169 bl psxException
be516ebe 170
be516ebe 171 /* note: psxException might do recursive recompiler call from it's HLE code,
172 * so be ready for this */
3968e69e 173FUNCTION(jump_to_new_pc):
dc4fa8bc 174 ldr w2, [rFP, #LO_stop]
81dbbf4c 175 ldr w1, [rFP, #LO_next_interupt]
176 ldr rCC, [rFP, #LO_cycle]
177 ldr w0, [rFP, #LO_pcaddr]
3968e69e 178 sub rCC, rCC, w1
81dbbf4c 179 str w1, [rFP, #LO_last_count]
dc4fa8bc 180 cbnz w2, new_dyna_leave
104df9d3 181 bl ndrc_get_addr_ht
be516ebe 182 br x0
c57af5e6 183 ESIZE(jump_to_new_pc, .-jump_to_new_pc)
be516ebe 184
687b4580 185 /* stack must be aligned by 16, and include space for save_regs() use */
be516ebe 186 .align 2
187FUNCTION(new_dyna_start):
687b4580 188 stp x29, x30, [sp, #-SSP_ALL]!
be516ebe 189 ldr w1, [x0, #LO_next_interupt]
190 ldr w2, [x0, #LO_cycle]
191 stp x19, x20, [sp, #16*1]
192 stp x21, x22, [sp, #16*2]
193 stp x23, x24, [sp, #16*3]
194 stp x25, x26, [sp, #16*4]
195 stp x27, x28, [sp, #16*5]
196 mov rFP, x0
197 ldr w0, [rFP, #LO_pcaddr]
198 str w1, [rFP, #LO_last_count]
199 sub rCC, w2, w1
104df9d3 200 bl ndrc_get_addr_ht
be516ebe 201 br x0
c57af5e6 202 ESIZE(new_dyna_start, .-new_dyna_start)
be516ebe 203
204 .align 2
205FUNCTION(new_dyna_leave):
206 ldr w0, [rFP, #LO_last_count]
207 add rCC, rCC, w0
208 str rCC, [rFP, #LO_cycle]
209 ldp x19, x20, [sp, #16*1]
210 ldp x21, x22, [sp, #16*2]
211 ldp x23, x24, [sp, #16*3]
212 ldp x25, x26, [sp, #16*4]
213 ldp x27, x28, [sp, #16*5]
687b4580 214 ldp x29, x30, [sp], #SSP_ALL
be516ebe 215 ret
c57af5e6 216 ESIZE(new_dyna_leave, .-new_dyna_leave)
be516ebe 217
218/* --------------------------------------- */
219
220.align 2
221
d1e4ebd9 222.macro memhandler_pre
eb38e4a2 223 /* w0 = addr/data, x1 = rhandler, w2 = cycles, x3 = whandler */
d1e4ebd9 224 ldr w4, [rFP, #LO_last_count]
225 add w4, w4, w2
226 str w4, [rFP, #LO_cycle]
227.endm
228
229.macro memhandler_post
7da5c7ad 230 /* w2 = cycles_out, x3 = tmp */
231 ldr w3, [rFP, #LO_next_interupt]
9b9af0d1 232 ldr w2, [rFP, #LO_cycle] // memhandlers can modify cc, like dma
7da5c7ad 233 str w3, [rFP, #LO_last_count]
234 sub w2, w2, w3
d1e4ebd9 235.endm
236
237FUNCTION(do_memhandler_pre):
238 memhandler_pre
239 ret
240
241FUNCTION(do_memhandler_post):
242 memhandler_post
243 ret
244
245.macro pcsx_read_mem readop tab_shift
246 /* w0 = address, x1 = handler_tab, w2 = cycles */
d1e4ebd9 247 ubfm w4, w0, #\tab_shift, #11
248 ldr x3, [x1, w4, uxtw #3]
249 adds x3, x3, x3
250 bcs 0f
251 \readop w0, [x3, w4, uxtw #\tab_shift]
252 ret
2530:
3968e69e 254 stp xzr, x30, [sp, #-16]!
d1e4ebd9 255 memhandler_pre
256 blr x3
257.endm
258
be516ebe 259FUNCTION(jump_handler_read8):
3968e69e 260 add x1, x1, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
d1e4ebd9 261 pcsx_read_mem ldrb, 0
7da5c7ad 262 ldp xzr, x30, [sp], #16
263 ret
be516ebe 264
265FUNCTION(jump_handler_read16):
3968e69e 266 add x1, x1, #0x1000/4*8 /* shift to r16 part */
d1e4ebd9 267 pcsx_read_mem ldrh, 1
7da5c7ad 268 ldp xzr, x30, [sp], #16
269 ret
be516ebe 270
271FUNCTION(jump_handler_read32):
d1e4ebd9 272 pcsx_read_mem ldr, 2
7da5c7ad 273 /* memhandler_post */
d1e4ebd9 274 ldp xzr, x30, [sp], #16
275 ret
276
277.macro pcsx_write_mem wrtop movop tab_shift
278 /* w0 = address, w1 = data, w2 = cycles, x3 = handler_tab */
d1e4ebd9 279 ubfm w4, w0, #\tab_shift, #11
280 ldr x3, [x3, w4, uxtw #3]
d1e4ebd9 281 adds x3, x3, x3
d1e4ebd9 282 bcs 0f
d1e4ebd9 283 \wrtop w1, [x3, w4, uxtw #\tab_shift]
284 ret
2850:
3968e69e 286 stp xzr, x30, [sp, #-16]!
287 str w0, [rFP, #LO_address] /* some handlers still need it... */
d1e4ebd9 288 \movop w0, w1
289 memhandler_pre
290 blr x3
291.endm
be516ebe 292
293FUNCTION(jump_handler_write8):
3968e69e 294 add x3, x3, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
c57af5e6 295 pcsx_write_mem strb, uxtb, 0
d1e4ebd9 296 b handler_write_end
be516ebe 297
298FUNCTION(jump_handler_write16):
3968e69e 299 add x3, x3, #0x1000/4*8 /* shift to r16 part */
c57af5e6 300 pcsx_write_mem strh, uxth, 1
d1e4ebd9 301 b handler_write_end
be516ebe 302
303FUNCTION(jump_handler_write32):
c57af5e6 304 pcsx_write_mem str, mov, 2
be516ebe 305
d1e4ebd9 306handler_write_end:
307 memhandler_post
308 ldp xzr, x30, [sp], #16
309 ret
be516ebe 310
311FUNCTION(jump_handle_swl):
3968e69e 312 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 313 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 314 orr w4, wzr, w0, lsr #12
3968e69e 315 ldr x3, [x3, w4, uxtw #3]
316 adds x3, x3, x3
de6dbc52 317 bcs jump_handle_swx_interp
3968e69e 318 add x3, x0, x3
319 mov w0, w2
320 tbz x3, #1, 10f // & 2
321 tbz x3, #0, 2f // & 1
3223:
323 stur w1, [x3, #-3]
324 ret
3252:
326 lsr w2, w1, #8
327 lsr w1, w1, #24
328 sturh w2, [x3, #-2]
329 strb w1, [x3]
330 ret
33110:
332 tbz x3, #0, 0f // & 1
3331:
334 lsr w1, w1, #16
335 sturh w1, [x3, #-1]
336 ret
3370:
338 lsr w2, w1, #24
339 strb w2, [x3]
340 ret
be516ebe 341
342FUNCTION(jump_handle_swr):
3968e69e 343 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 344 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 345 orr w4, wzr, w0, lsr #12
3968e69e 346 ldr x3, [x3, w4, uxtw #3]
347 adds x3, x3, x3
de6dbc52 348 bcs jump_handle_swx_interp
3968e69e 349 add x3, x0, x3
350 mov w0, w2
351 tbz x3, #1, 10f // & 2
352 tbz x3, #0, 2f // & 1
3533:
354 strb w1, [x3]
355 ret
3562:
357 strh w1, [x3]
358 ret
35910:
360 tbz x3, #0, 0f // & 1
3611:
362 lsr w2, w1, #8
363 strb w1, [x3]
364 sturh w2, [x3, #1]
365 ret
3660:
367 str w1, [x3]
368 ret
de6dbc52 369
370jump_handle_swx_interp: /* almost never happens */
371 ldr w3, [rFP, #LO_last_count]
372 add x0, rFP, #LO_psxRegs
373 add w2, w3, w2
374 str w2, [rFP, #LO_cycle] /* PCSX cycles */
375 bl execI
376 b jump_to_new_pc
be516ebe 377
81dbbf4c 378FUNCTION(call_gteStall):
379 /* w0 = op_cycles, w1 = cycles */
380 ldr w2, [rFP, #LO_last_count]
381 str lr, [rFP, #LO_saved_lr]
382 add w1, w1, w2
383 str w1, [rFP, #LO_cycle]
384 add x1, rFP, #LO_psxRegs
385 bl gteCheckStallRaw
386 ldr lr, [rFP, #LO_saved_lr]
387 add rCC, rCC, w0
388 ret
389
33a1eda1 390#ifdef DRC_DBG
391#undef do_insn_cmp
392FUNCTION(do_insn_cmp_arm64):
393 stp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
394 stp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
395 stp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
396 stp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
397 stp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
398 stp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
399 stp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
400 stp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
401 stp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]
402 bl do_insn_cmp
403 ldp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
404 ldp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
405 ldp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
406 ldp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
407 ldp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
408 ldp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
409 ldp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
410 ldp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
411 ldp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]
412 ret
413#endif