1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * linkage_arm.s for PCSX *
3 * Copyright (C) 2009-2011 Ari64 *
4 * Copyright (C) 2021 notaz *
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. *
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. *
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 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22 #include "arm_features.h"
23 #include "new_dynarec_config.h"
24 #include "assem_arm64.h"
25 #include "linkage_offsets.h"
28 #define dynarec_local ESYM(dynarec_local)
29 #define ndrc_patch_link ESYM(ndrc_patch_link)
30 #define ndrc_get_addr_ht ESYM(ndrc_get_addr_ht)
31 #define ndrc_get_addr_ht_param ESYM(ndrc_get_addr_ht_param)
32 #define gen_interupt ESYM(gen_interupt)
33 #define psxException ESYM(psxException)
34 #define execI ESYM(execI)
38 #error misligned pointers
44 EOBJECT(dynarec_local)
45 ESIZE(dynarec_local, LO_dynarec_local_size)
47 .space LO_dynarec_local_size
49 #define DRC_VAR_(name, vname, size_) \
50 vname = dynarec_local + LO_##name ASM_SEPARATOR \
53 ESIZE(vname, LO_dynarec_local_size)
55 #define DRC_VAR(name, size_) \
56 DRC_VAR_(name, ESYM(name), size_)
58 #DRC_VAR(next_interupt, 4)
59 DRC_VAR(cycle_count, 4)
60 DRC_VAR(last_count, 4)
64 DRC_VAR(psxRegs, LO_psxRegs_end - LO_psxRegs)
69 DRC_VAR(reg_cop2d, 128)
70 DRC_VAR(reg_cop2c, 128)
73 #DRC_VAR(interrupt, 4)
74 #DRC_VAR(intCycle, 256)
77 DRC_VAR(inv_code_start, 4)
78 DRC_VAR(inv_code_end, 4)
83 DRC_VAR(zeromem_ptr, 8)
84 DRC_VAR(scratch_buf_ptr, 8)
85 DRC_VAR(ram_offset, 8)
86 DRC_VAR(hash_table_ptr, 8)
93 FUNCTION(dyna_linker):
94 /* w0 = virtual target address */
95 /* x1 = instruction to patch */
99 /* must not compile - that might expire the caller block */
100 ldr x0, [rFP, #LO_hash_table_ptr]
102 mov w2, #0 /* ndrc_compile_mode=ndrc_cm_no_compile */
103 bl ndrc_get_addr_ht_param
118 ldr x1, [rFP, #LO_hash_table_ptr]
121 ESIZE(dyna_linker, .-dyna_linker)
124 FUNCTION(cc_interrupt):
125 ldr w0, [rFP, #LO_last_count]
126 ldr w22, [rFP, #LO_pcaddr]
128 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
131 add x0, rFP, #LO_reg_cop0 /* CP0 */
134 ldr rCC, [rFP, #LO_cycle]
135 ldr w0, [rFP, #LO_pcaddr]
136 ldr w1, [rFP, #LO_next_interupt]
137 ldrb w2, [rFP, #LO_stop]
138 str w1, [rFP, #LO_last_count]
140 cbnz w2, new_dyna_leave
145 ldr x1, [rFP, #LO_hash_table_ptr]
148 ESIZE(cc_interrupt, .-cc_interrupt)
151 FUNCTION(jump_addrerror_ds): /* R3000E_AdEL / R3000E_AdES in w0 */
152 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
155 FUNCTION(jump_addrerror):
156 str w1, [rFP, #(LO_psxRegs + (34+8)*4)] /* BadVaddr */
159 FUNCTION(jump_overflow_ds):
160 mov w0, #(12<<2) /* R3000E_Ov */
163 FUNCTION(jump_overflow):
167 FUNCTION(jump_break_ds):
168 mov w0, #(9<<2) /* R3000E_Bp */
171 FUNCTION(jump_break):
175 FUNCTION(jump_syscall_ds):
176 mov w0, #(8<<2) /* R3000E_Syscall */
179 FUNCTION(jump_syscall):
184 ldr w3, [rFP, #LO_last_count]
185 str w2, [rFP, #LO_pcaddr]
187 str rCC, [rFP, #LO_cycle] /* PCSX cycles */
188 add x2, rFP, #LO_reg_cop0 /* CP0 */
191 /* note: psxException might do recursive recompiler call from it's HLE code,
192 * so be ready for this */
193 FUNCTION(jump_to_new_pc):
194 ldrb w2, [rFP, #LO_stop]
195 ldr w1, [rFP, #LO_next_interupt]
196 ldr rCC, [rFP, #LO_cycle]
197 ldr w0, [rFP, #LO_pcaddr]
199 str w1, [rFP, #LO_last_count]
200 cbnz w2, new_dyna_leave
201 ldr x1, [rFP, #LO_hash_table_ptr]
204 ESIZE(jump_to_new_pc, .-jump_to_new_pc)
206 /* stack must be aligned by 16, and include space for save_regs() use */
208 FUNCTION(new_dyna_start_at):
209 stp x29, x30, [sp, #-SSP_ALL]!
211 b new_dyna_start_at_e
213 FUNCTION(new_dyna_start):
214 stp x29, x30, [sp, #-SSP_ALL]!
216 ldr w0, [rFP, #LO_pcaddr]
217 ldr x1, [rFP, #LO_hash_table_ptr]
221 ldr w3, [rFP, #LO_next_interupt]
222 ldr w2, [rFP, #LO_cycle]
223 stp x19, x20, [sp, #16*1]
224 stp x21, x22, [sp, #16*2]
225 stp x23, x24, [sp, #16*3]
226 stp x25, x26, [sp, #16*4]
227 stp x27, x28, [sp, #16*5]
228 str w3, [rFP, #LO_last_count]
231 ESIZE(new_dyna_start, .-new_dyna_start)
234 FUNCTION(new_dyna_leave):
235 ldr w0, [rFP, #LO_last_count]
237 str rCC, [rFP, #LO_cycle]
238 ldp x19, x20, [sp, #16*1]
239 ldp x21, x22, [sp, #16*2]
240 ldp x23, x24, [sp, #16*3]
241 ldp x25, x26, [sp, #16*4]
242 ldp x27, x28, [sp, #16*5]
243 ldp x29, x30, [sp], #SSP_ALL
245 ESIZE(new_dyna_leave, .-new_dyna_leave)
247 /* --------------------------------------- */
251 .macro memhandler_pre
252 /* w0 = addr/data, x1 = rhandler, w2 = cycles, x3 = whandler */
253 ldr w4, [rFP, #LO_last_count]
255 str w4, [rFP, #LO_cycle]
258 .macro memhandler_post
259 /* w2 = cycles_out, x3 = tmp */
260 ldr w3, [rFP, #LO_next_interupt]
261 ldr w2, [rFP, #LO_cycle] // memhandlers can modify cc, like dma
262 str w3, [rFP, #LO_last_count]
266 FUNCTION(do_memhandler_pre):
270 FUNCTION(do_memhandler_post):
274 .macro pcsx_read_mem readop tab_shift
275 /* w0 = address, x1 = handler_tab, w2 = cycles */
276 ubfm w4, w0, #\tab_shift, #11
277 ldr x3, [x1, w4, uxtw #3]
280 \readop w0, [x3, w4, uxtw #\tab_shift]
283 stp xzr, x30, [sp, #-16]!
288 FUNCTION(jump_handler_read8):
289 add x1, x1, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
290 pcsx_read_mem ldrb, 0
291 ldp xzr, x30, [sp], #16
294 FUNCTION(jump_handler_read16):
295 add x1, x1, #0x1000/4*8 /* shift to r16 part */
296 pcsx_read_mem ldrh, 1
297 ldp xzr, x30, [sp], #16
300 FUNCTION(jump_handler_read32):
302 /* memhandler_post */
303 ldp xzr, x30, [sp], #16
306 .macro pcsx_write_mem wrtop movop tab_shift
307 /* w0 = address, w1 = data, w2 = cycles, x3 = handler_tab */
308 ubfm w4, w0, #\tab_shift, #11
309 ldr x3, [x3, w4, uxtw #3]
312 \wrtop w1, [x3, w4, uxtw #\tab_shift]
315 stp xzr, x30, [sp, #-16]!
316 str w0, [rFP, #LO_address] /* some handlers still need it... */
322 FUNCTION(jump_handler_write8):
323 add x3, x3, #0x1000/4*8 + 0x1000/2*8 /* shift to r8 part */
324 pcsx_write_mem strb, uxtb, 0
327 FUNCTION(jump_handler_write16):
328 add x3, x3, #0x1000/4*8 /* shift to r16 part */
329 pcsx_write_mem strh, uxth, 1
332 FUNCTION(jump_handler_write32):
333 pcsx_write_mem str, mov, 2
337 ldp xzr, x30, [sp], #16
340 FUNCTION(jump_handle_swl):
341 /* w0 = address, w1 = data, w2 = cycles */
342 ldr x3, [rFP, #LO_mem_wtab]
343 orr w4, wzr, w0, lsr #12
344 ldr x3, [x3, w4, uxtw #3]
346 bcs jump_handle_swx_interp
349 tbz x3, #1, 10f // & 2
350 tbz x3, #0, 2f // & 1
361 tbz x3, #0, 0f // & 1
371 FUNCTION(jump_handle_swr):
372 /* w0 = address, w1 = data, w2 = cycles */
373 ldr x3, [rFP, #LO_mem_wtab]
374 orr w4, wzr, w0, lsr #12
375 ldr x3, [x3, w4, uxtw #3]
377 bcs jump_handle_swx_interp
380 tbz x3, #1, 10f // & 2
381 tbz x3, #0, 2f // & 1
389 tbz x3, #0, 0f // & 1
399 jump_handle_swx_interp: /* almost never happens */
400 ldr w3, [rFP, #LO_last_count]
401 add x0, rFP, #LO_psxRegs
403 str w2, [rFP, #LO_cycle] /* PCSX cycles */
409 FUNCTION(do_insn_cmp_arm64):
410 stp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
411 stp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
412 stp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
413 stp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
414 stp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
415 stp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
416 stp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
417 stp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
418 stp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]
420 ldp x2, x3, [sp, #(SSP_CALLEE_REGS + 2*8)]
421 ldp x4, x5, [sp, #(SSP_CALLEE_REGS + 4*8)]
422 ldp x6, x7, [sp, #(SSP_CALLEE_REGS + 6*8)]
423 ldp x8, x9, [sp, #(SSP_CALLEE_REGS + 8*8)]
424 ldp x10, x11, [sp, #(SSP_CALLEE_REGS + 10*8)]
425 ldp x12, x13, [sp, #(SSP_CALLEE_REGS + 12*8)]
426 ldp x14, x15, [sp, #(SSP_CALLEE_REGS + 14*8)]
427 ldp x16, x17, [sp, #(SSP_CALLEE_REGS + 16*8)]
428 ldp x18, x30, [sp, #(SSP_CALLEE_REGS + 18*8)]