cdrom: adjust pause behavior
[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
be516ebe 87FUNCTION(dyna_linker):
88 /* r0 = virtual target address */
89 /* r1 = instruction to patch */
104df9d3 90 bl ndrc_get_addr_ht
4bdc30ab 91 br x0
be516ebe 92 .size dyna_linker, .-dyna_linker
93
be516ebe 94 .align 2
95FUNCTION(cc_interrupt):
d1e4ebd9 96 ldr w0, [rFP, #LO_last_count]
d1e4ebd9 97 add rCC, w0, rCC
98 str wzr, [rFP, #LO_pending_exception]
d1e4ebd9 99 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
d1e4ebd9 100 mov x21, lr
d1e4ebd9 1011:
de6dbc52 102 add x0, rFP, #LO_reg_cop0 /* CP0 */
d1e4ebd9 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]
104df9d3 116 bl ndrc_get_addr_ht
d1e4ebd9 117 br x0
be516ebe 118 .size cc_interrupt, .-cc_interrupt
119
be516ebe 120 .align 2
277718fa 121FUNCTION(jump_addrerror_ds): /* R3000E_AdEL / R3000E_AdES in w0 */
122 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
123 mov w1, #1
124 b call_psxException
125FUNCTION(jump_addrerror):
126 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
127 mov w1, #0
128 b call_psxException
a5cd72d0 129FUNCTION(jump_overflow_ds):
130 mov w0, #(12<<2) /* R3000E_Ov */
131 mov w1, #1
132 b call_psxException
133FUNCTION(jump_overflow):
134 mov w0, #(12<<2)
135 mov w1, #0
136 b call_psxException
d1150cd6 137FUNCTION(jump_break_ds):
a5cd72d0 138 mov w0, #(9<<2) /* R3000E_Bp */
d1150cd6 139 mov w1, #1
140 b call_psxException
141FUNCTION(jump_break):
a5cd72d0 142 mov w0, #(9<<2)
d1150cd6 143 mov w1, #0
144 b call_psxException
145FUNCTION(jump_syscall_ds):
a5cd72d0 146 mov w0, #(8<<2) /* R3000E_Syscall */
bc7c5acb 147 mov w1, #2
d1150cd6 148 b call_psxException
be516ebe 149FUNCTION(jump_syscall):
a5cd72d0 150 mov w0, #(8<<2)
d1150cd6 151 mov w1, #0
152
153call_psxException:
154 ldr w3, [rFP, #LO_last_count]
155 str w2, [rFP, #LO_pcaddr]
156 add rCC, w3, rCC
6d75addf 157 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
de6dbc52 158 add x2, rFP, #LO_reg_cop0 /* CP0 */
d1150cd6 159 bl psxException
be516ebe 160
be516ebe 161 /* note: psxException might do recursive recompiler call from it's HLE code,
162 * so be ready for this */
3968e69e 163FUNCTION(jump_to_new_pc):
dc4fa8bc 164 ldr w2, [rFP, #LO_stop]
81dbbf4c 165 ldr w1, [rFP, #LO_next_interupt]
166 ldr rCC, [rFP, #LO_cycle]
167 ldr w0, [rFP, #LO_pcaddr]
3968e69e 168 sub rCC, rCC, w1
81dbbf4c 169 str w1, [rFP, #LO_last_count]
dc4fa8bc 170 cbnz w2, new_dyna_leave
104df9d3 171 bl ndrc_get_addr_ht
be516ebe 172 br x0
3968e69e 173 .size jump_to_new_pc, .-jump_to_new_pc
be516ebe 174
687b4580 175 /* stack must be aligned by 16, and include space for save_regs() use */
be516ebe 176 .align 2
177FUNCTION(new_dyna_start):
687b4580 178 stp x29, x30, [sp, #-SSP_ALL]!
be516ebe 179 ldr w1, [x0, #LO_next_interupt]
180 ldr w2, [x0, #LO_cycle]
181 stp x19, x20, [sp, #16*1]
182 stp x21, x22, [sp, #16*2]
183 stp x23, x24, [sp, #16*3]
184 stp x25, x26, [sp, #16*4]
185 stp x27, x28, [sp, #16*5]
186 mov rFP, x0
187 ldr w0, [rFP, #LO_pcaddr]
188 str w1, [rFP, #LO_last_count]
189 sub rCC, w2, w1
104df9d3 190 bl ndrc_get_addr_ht
be516ebe 191 br x0
192 .size new_dyna_start, .-new_dyna_start
193
194 .align 2
195FUNCTION(new_dyna_leave):
196 ldr w0, [rFP, #LO_last_count]
197 add rCC, rCC, w0
198 str rCC, [rFP, #LO_cycle]
199 ldp x19, x20, [sp, #16*1]
200 ldp x21, x22, [sp, #16*2]
201 ldp x23, x24, [sp, #16*3]
202 ldp x25, x26, [sp, #16*4]
203 ldp x27, x28, [sp, #16*5]
687b4580 204 ldp x29, x30, [sp], #SSP_ALL
be516ebe 205 ret
206 .size new_dyna_leave, .-new_dyna_leave
207
208/* --------------------------------------- */
209
210.align 2
211
d1e4ebd9 212.macro memhandler_pre
eb38e4a2 213 /* w0 = addr/data, x1 = rhandler, w2 = cycles, x3 = whandler */
d1e4ebd9 214 ldr w4, [rFP, #LO_last_count]
215 add w4, w4, w2
216 str w4, [rFP, #LO_cycle]
217.endm
218
219.macro memhandler_post
9b9af0d1 220 ldr w0, [rFP, #LO_next_interupt]
221 ldr w2, [rFP, #LO_cycle] // memhandlers can modify cc, like dma
222 str w0, [rFP, #LO_last_count]
223 sub w0, w2, w0
d1e4ebd9 224.endm
225
226FUNCTION(do_memhandler_pre):
227 memhandler_pre
228 ret
229
230FUNCTION(do_memhandler_post):
231 memhandler_post
232 ret
233
234.macro pcsx_read_mem readop tab_shift
235 /* w0 = address, x1 = handler_tab, w2 = cycles */
d1e4ebd9 236 ubfm w4, w0, #\tab_shift, #11
237 ldr x3, [x1, w4, uxtw #3]
238 adds x3, x3, x3
239 bcs 0f
240 \readop w0, [x3, w4, uxtw #\tab_shift]
241 ret
2420:
3968e69e 243 stp xzr, x30, [sp, #-16]!
d1e4ebd9 244 memhandler_pre
245 blr x3
246.endm
247
be516ebe 248FUNCTION(jump_handler_read8):
3968e69e 249 add x1, x1, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
d1e4ebd9 250 pcsx_read_mem ldrb, 0
251 b handler_read_end
be516ebe 252
253FUNCTION(jump_handler_read16):
3968e69e 254 add x1, x1, #0x1000/4*8 /* shift to r16 part */
d1e4ebd9 255 pcsx_read_mem ldrh, 1
256 b handler_read_end
be516ebe 257
258FUNCTION(jump_handler_read32):
d1e4ebd9 259 pcsx_read_mem ldr, 2
260
261handler_read_end:
262 ldp xzr, x30, [sp], #16
263 ret
264
265.macro pcsx_write_mem wrtop movop tab_shift
266 /* w0 = address, w1 = data, w2 = cycles, x3 = handler_tab */
d1e4ebd9 267 ubfm w4, w0, #\tab_shift, #11
268 ldr x3, [x3, w4, uxtw #3]
d1e4ebd9 269 adds x3, x3, x3
d1e4ebd9 270 bcs 0f
271 mov w0, w2 /* cycle return */
272 \wrtop w1, [x3, w4, uxtw #\tab_shift]
273 ret
2740:
3968e69e 275 stp xzr, x30, [sp, #-16]!
276 str w0, [rFP, #LO_address] /* some handlers still need it... */
d1e4ebd9 277 \movop w0, w1
278 memhandler_pre
279 blr x3
280.endm
be516ebe 281
282FUNCTION(jump_handler_write8):
3968e69e 283 add x3, x3, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
d1e4ebd9 284 pcsx_write_mem strb uxtb 0
285 b handler_write_end
be516ebe 286
287FUNCTION(jump_handler_write16):
3968e69e 288 add x3, x3, #0x1000/4*8 /* shift to r16 part */
d1e4ebd9 289 pcsx_write_mem strh uxth 1
290 b handler_write_end
be516ebe 291
292FUNCTION(jump_handler_write32):
d1e4ebd9 293 pcsx_write_mem str mov 2
be516ebe 294
d1e4ebd9 295handler_write_end:
296 memhandler_post
297 ldp xzr, x30, [sp], #16
298 ret
be516ebe 299
300FUNCTION(jump_handle_swl):
3968e69e 301 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 302 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 303 orr w4, wzr, w0, lsr #12
3968e69e 304 ldr x3, [x3, w4, uxtw #3]
305 adds x3, x3, x3
de6dbc52 306 bcs jump_handle_swx_interp
3968e69e 307 add x3, x0, x3
308 mov w0, w2
309 tbz x3, #1, 10f // & 2
310 tbz x3, #0, 2f // & 1
3113:
312 stur w1, [x3, #-3]
313 ret
3142:
315 lsr w2, w1, #8
316 lsr w1, w1, #24
317 sturh w2, [x3, #-2]
318 strb w1, [x3]
319 ret
32010:
321 tbz x3, #0, 0f // & 1
3221:
323 lsr w1, w1, #16
324 sturh w1, [x3, #-1]
325 ret
3260:
327 lsr w2, w1, #24
328 strb w2, [x3]
329 ret
be516ebe 330
331FUNCTION(jump_handle_swr):
3968e69e 332 /* w0 = address, w1 = data, w2 = cycles */
81dbbf4c 333 ldr x3, [rFP, #LO_mem_wtab]
48ce2528 334 orr w4, wzr, w0, lsr #12
3968e69e 335 ldr x3, [x3, w4, uxtw #3]
336 adds x3, x3, x3
de6dbc52 337 bcs jump_handle_swx_interp
3968e69e 338 add x3, x0, x3
339 mov w0, w2
340 tbz x3, #1, 10f // & 2
341 tbz x3, #0, 2f // & 1
3423:
343 strb w1, [x3]
344 ret
3452:
346 strh w1, [x3]
347 ret
34810:
349 tbz x3, #0, 0f // & 1
3501:
351 lsr w2, w1, #8
352 strb w1, [x3]
353 sturh w2, [x3, #1]
354 ret
3550:
356 str w1, [x3]
357 ret
de6dbc52 358
359jump_handle_swx_interp: /* almost never happens */
360 ldr w3, [rFP, #LO_last_count]
361 add x0, rFP, #LO_psxRegs
362 add w2, w3, w2
363 str w2, [rFP, #LO_cycle] /* PCSX cycles */
364 bl execI
365 b jump_to_new_pc
be516ebe 366
81dbbf4c 367FUNCTION(call_gteStall):
368 /* w0 = op_cycles, w1 = cycles */
369 ldr w2, [rFP, #LO_last_count]
370 str lr, [rFP, #LO_saved_lr]
371 add w1, w1, w2
372 str w1, [rFP, #LO_cycle]
373 add x1, rFP, #LO_psxRegs
374 bl gteCheckStallRaw
375 ldr lr, [rFP, #LO_saved_lr]
376 add rCC, rCC, w0
377 ret
378
33a1eda1 379#ifdef DRC_DBG
380#undef do_insn_cmp
381FUNCTION(do_insn_cmp_arm64):
382 stp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
383 stp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
384 stp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
385 stp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
386 stp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
387 stp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
388 stp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
389 stp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
390 stp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]
391 bl do_insn_cmp
392 ldp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
393 ldp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
394 ldp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
395 ldp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
396 ldp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
397 ldp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
398 ldp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
399 ldp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
400 ldp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]
401 ret
402#endif