2823a4c8 |
1 | # gameplaySP |
2 | # |
3 | # Copyright (C) 2006 Exophase <exophase@gmail.com> |
4 | # |
5 | # This program is free software; you can redistribute it and/or |
6 | # modify it under the terms of the GNU General Public License as |
7 | # published by the Free Software Foundation; either version 2 of |
8 | # the License, or (at your option) any later version. |
9 | # |
10 | # This program is distributed in the hope that it will be useful, |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | # General Public License for more details. |
14 | # |
15 | # You should have received a copy of the GNU General Public License |
16 | # along with this program; if not, write to the Free Software |
17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | |
19 | .align 4 |
20 | |
21 | .global mips_update_gba |
22 | .global mips_indirect_branch_arm |
23 | .global mips_indirect_branch_thumb |
24 | .global mips_indirect_branch_dual |
25 | .global execute_load_u8 |
26 | .global execute_load_u16 |
27 | .global execute_load_u32 |
28 | .global execute_load_s8 |
29 | .global execute_load_s16 |
30 | .global execute_store_u8 |
31 | .global execute_store_u16 |
32 | .global execute_store_u32 |
33 | .global execute_aligned_load32 |
34 | .global execute_aligned_store32 |
35 | .global execute_read_cpsr |
36 | .global execute_read_spsr |
37 | .global execute_swi |
38 | .global execute_spsr_restore |
39 | .global execute_store_cpsr |
40 | .global execute_store_spsr |
41 | .global execute_lsl_flags_reg |
42 | .global execute_lsr_flags_reg |
43 | .global execute_asr_flags_reg |
44 | .global execute_ror_flags_reg |
45 | .global execute_arm_translate |
46 | .global invalidate_icache_region |
47 | .global invalidate_all_cache |
48 | .global step_debug_mips |
49 | .global reg_check |
50 | |
51 | .global memory_map_read |
52 | .global memory_map_write |
53 | .global reg |
54 | |
55 | .extern reg |
56 | .extern spsr |
57 | |
58 | # MIPS register layout: |
59 | |
60 | # $0 - constant zero |
61 | # $1 - temporary |
62 | # $2 - temporary / return value |
63 | # $3 - ARM r0 (not saved) |
64 | # $4 - temporary / function argument 0 |
65 | # $5 - temporary / function argument 1 |
66 | # $6 - temporary / function argument 2 |
67 | # $7 - ARM r1 (not saved) |
68 | # $8 - ARM r2 (not saved) |
69 | # $9 - ARM r3 (not saved) |
70 | # $10 - ARM r4 (not saved) |
71 | # $11 - ARM r5 (not saved) |
72 | # $12 - ARM r6 (not saved) |
73 | # $13 - ARM r7 (not saved) |
74 | # $14 - ARM r8 (not saved) |
75 | # $15 - ARM r9 (not saved) |
76 | # $16 - ARM machine state pointer (saved) |
77 | # $17 - cycle counter (saved) |
78 | # $18 - ARM r10 (saved) |
79 | # $19 - block start address (roughly r15) (saved) |
80 | # $20 - ARM negative register (saved) |
81 | # $21 - ARM zero register (saved) |
82 | # $22 - ARM carry register (saved) |
83 | # $23 - ARM overflow register (saved) |
84 | # $24 - ARM r11 (not saved) |
85 | # $25 - ARM r12 (not saved) |
86 | # $26 - kernel temporary 0 |
87 | # $27 - kernel temporary 1 |
88 | # $28 - ARM r13 (saved) |
89 | # $29 - stack pointer |
90 | # $30 - ARM r14 (saved) |
91 | # $31 - return address |
92 | |
93 | .equ REG_R0, (0 * 4) |
94 | .equ REG_R1, (1 * 4) |
95 | .equ REG_R2, (2 * 4) |
96 | .equ REG_R3, (3 * 4) |
97 | .equ REG_R4, (4 * 4) |
98 | .equ REG_R5, (5 * 4) |
99 | .equ REG_R6, (6 * 4) |
100 | .equ REG_R7, (7 * 4) |
101 | .equ REG_R8, (8 * 4) |
102 | .equ REG_R9, (9 * 4) |
103 | .equ REG_R10, (10 * 4) |
104 | .equ REG_R11, (11 * 4) |
105 | .equ REG_R12, (12 * 4) |
106 | .equ REG_R13, (13 * 4) |
107 | .equ REG_R14, (14 * 4) |
108 | .equ REG_LR, (14 * 4) |
109 | .equ REG_PC, (15 * 4) |
110 | .equ REG_N_FLAG, (16 * 4) |
111 | .equ REG_Z_FLAG, (17 * 4) |
112 | .equ REG_C_FLAG, (18 * 4) |
113 | .equ REG_V_FLAG, (19 * 4) |
114 | .equ REG_CPSR, (20 * 4) |
115 | .equ REG_SAVE, (21 * 4) |
116 | .equ REG_SAVE2, (22 * 4) |
117 | .equ REG_SAVE3, (23 * 4) |
118 | .equ CPU_MODE, (29 * 4) |
119 | .equ CPU_HALT_STATE, (30 * 4) |
120 | .equ CHANGED_PC_STATUS, (31 * 4) |
121 | .equ GP_SAVE, (32 * 4) |
122 | |
123 | .equ SUPERVISOR_LR, (reg_mode + (3 * (7 * 4)) + (6 * 4)) |
124 | .equ SUPERVISOR_SPSR, (spsr + (3 * 4)) |
125 | |
126 | .set noat |
127 | .set noreorder |
128 | |
129 | # make sure $16 has the register base for these macros |
130 | |
131 | .macro collapse_flag flag_reg, shift |
132 | ins $2, $\flag_reg, \shift, 1 # insert flag into CPSR |
133 | .endm |
134 | |
135 | .macro collapse_flags |
136 | lw $2, REG_CPSR($16) # load CPSR |
137 | andi $2, $2, 0xFF # isolate lower 8bits |
138 | collapse_flag 20, 31 # store flags |
139 | collapse_flag 21, 30 |
140 | collapse_flag 22, 29 |
141 | collapse_flag 23, 28 |
142 | sw $2, REG_CPSR($16) # store CPSR |
143 | .endm |
144 | |
145 | .macro extract_flag shift, flag_reg |
146 | ext $\flag_reg, $1, \shift, 1 # extract flag from CPSR |
147 | .endm |
148 | |
149 | .macro extract_flags_body # extract flags from $1 |
150 | extract_flag 31, 20 # load flags |
151 | extract_flag 30, 21 |
152 | extract_flag 29, 22 |
153 | extract_flag 28, 23 |
154 | .endm |
155 | |
156 | .macro extract_flags |
157 | lw $1, REG_CPSR($16) # load CPSR |
158 | extract_flags_body |
159 | .endm |
160 | |
161 | .macro save_registers |
162 | sw $3, REG_R0($16) |
163 | sw $7, REG_R1($16) |
164 | sw $8, REG_R2($16) |
165 | sw $9, REG_R3($16) |
166 | sw $10, REG_R4($16) |
167 | sw $11, REG_R5($16) |
168 | sw $12, REG_R6($16) |
169 | sw $13, REG_R7($16) |
170 | sw $14, REG_R8($16) |
171 | sw $15, REG_R9($16) |
172 | sw $24, REG_R11($16) |
173 | sw $25, REG_R12($16) |
174 | |
175 | sw $18, REG_R10($16) |
176 | sw $28, REG_R13($16) |
177 | sw $30, REG_R14($16) |
178 | |
179 | lw $28, GP_SAVE($16) |
180 | .endm |
181 | |
182 | .macro restore_registers |
183 | lw $3, REG_R0($16) |
184 | lw $7, REG_R1($16) |
185 | lw $8, REG_R2($16) |
186 | lw $9, REG_R3($16) |
187 | lw $10, REG_R4($16) |
188 | lw $11, REG_R5($16) |
189 | lw $12, REG_R6($16) |
190 | lw $13, REG_R7($16) |
191 | lw $14, REG_R8($16) |
192 | lw $15, REG_R9($16) |
193 | lw $24, REG_R11($16) |
194 | lw $25, REG_R12($16) |
195 | |
196 | lw $18, REG_R10($16) |
197 | lw $28, REG_R13($16) |
198 | lw $30, REG_R14($16) |
199 | .endm |
200 | |
201 | # Process a hardware event. Since an interrupt might be |
202 | # raised we have to check if the PC has changed. |
203 | |
204 | # $4: next address |
205 | # $16: register base |
206 | # $17: cycle counter |
207 | |
208 | .balign 64 |
209 | |
210 | mips_update_gba: |
211 | sw $4, REG_PC($16) # current PC = $4 |
212 | |
213 | addiu $sp, $sp, -4 # make room on the stack |
214 | sw $ra,($sp) # save return address |
215 | collapse_flags # update cpsr |
216 | save_registers # save registers |
217 | jal update_gba # process the next event |
218 | sw $0, CHANGED_PC_STATUS($16) |
219 | |
220 | lw $ra, ($sp) # restore return address |
221 | addiu $sp, $sp, 4 # fix stack |
222 | |
223 | lw $1, CHANGED_PC_STATUS($16) |
224 | bne $1, $0, lookup_pc |
225 | addu $17, $2, $0 # $17 = new cycle count (delay slot) |
226 | |
227 | restore_registers |
228 | |
229 | jr $ra # if not, go back to caller |
230 | nop |
231 | |
232 | # Perform an indirect branch. |
233 | |
234 | # $4: GBA address to branch to |
235 | |
236 | mips_indirect_branch_arm: |
237 | save_registers |
238 | jal block_lookup_address_arm # $2 = MIPS address to jump to |
239 | nop |
240 | restore_registers |
241 | jr $2 # jump to it |
242 | nop |
243 | |
244 | mips_indirect_branch_thumb: |
245 | save_registers |
246 | jal block_lookup_address_thumb # $2 = MIPS address to jump to |
247 | nop |
248 | restore_registers |
249 | jr $2 # jump to it |
250 | nop |
251 | |
252 | mips_indirect_branch_dual: |
253 | save_registers |
254 | jal block_lookup_address_dual # $2 = MIPS address to jump to |
255 | nop |
256 | restore_registers |
257 | jr $2 # jump to it |
258 | nop |
259 | |
260 | |
261 | # $4: address to write to |
262 | # $5: current PC |
263 | |
264 | # Will patch the return address with a call to the correct handler as |
265 | # listed in the given table. |
266 | |
267 | # Value will be set to force_open if it's open |
268 | |
269 | .macro patch_handler ftable, force_open |
270 | srl $1, $4, 24 # $1 = address region |
271 | sltu $2, $1, 0x0F # check if the value is open |
272 | bne $2, $0, 1f |
273 | sll $1, $1, 2 # make address word indexed (delay) |
274 | |
275 | addiu $1, $0, (\force_open * 4) |
276 | |
277 | 1: |
278 | lui $2, %hi(\ftable) |
279 | addu $2, $2, $1 |
280 | lw $2, %lo(\ftable)($2) # new function handler is in $2 |
281 | srl $2, $2, 2 # remove lower two bits |
282 | |
283 | lui $1, %hi(3 << 26) # $1 = 3 (JAL opcode) |
284 | ins $1, $2, 0, 26 # insert offset into jal |
285 | |
286 | addiu $ra, $ra, -8 # rewind return address to function call |
287 | sw $1, ($ra) # modify to call new handler |
288 | |
289 | cache 0x1a, ($ra) # hit writeback dcache line |
290 | cache 0x08, ($ra) # hit invalidate icache line |
291 | |
292 | jr $ra # return |
293 | nop # wary of putting cache here |
294 | .endm |
295 | |
296 | |
297 | # Like the above, but will use the table of the proper alignment, |
298 | # The tables should be ordered by alignment |
299 | |
300 | .macro patch_handler_align ftable, alignment |
301 | srl $1, $4, 24 # $1 = address region |
302 | sltu $2, $1, 0x0F # check if the value is open |
303 | bne $2, $0, 1f |
304 | sll $1, $1, 2 # make address word indexed (delay) |
305 | |
306 | addiu $1, $0, 4 # force address to 0x1 (open) |
307 | |
308 | 1: |
309 | ins $1, $4, 6, \alignment # place alignment bits into offset |
310 | lui $2, %hi(\ftable) |
311 | |
312 | addu $2, $2, $1 |
313 | lw $2, %lo(\ftable)($2) # new function handler is in $2 |
314 | |
315 | srl $2, $2, 2 # remove lower two bits |
316 | |
317 | lui $1, %hi(3 << 26) # $1 = 3 (JAL opcode) |
318 | ins $1, $2, 0, 26 # insert offset into jal |
319 | |
320 | addiu $ra, $ra, -8 # rewind return address to function call |
321 | sw $1, ($ra) # modify to call new handler |
322 | |
323 | cache 0x1a, ($ra) # hit writeback dcache line |
324 | cache 0x08, ($ra) # hit invalidate icache line |
325 | |
326 | jr $ra # return |
327 | nop # wary of putting cache here |
328 | .endm |
329 | |
330 | |
331 | .macro region_check region, patch_handler |
332 | srl $1, $4, 24 # check upper 8bits of address |
333 | xor $1, $1, \region # see if it is the given region |
334 | bne $1, $0, \patch_handler # if not repatch/try again |
335 | .endm |
336 | |
337 | .macro region_check_open patch_handler |
338 | srl $1, $4, 24 # check upper 8bits of address |
339 | sltiu $2, $1, 0x0F # true if it is a low address |
340 | addiu $1, $1, -1 # non-zero if it is not a low open |
341 | sltu $1, $0, $1 # true if lower bits != 1 |
342 | and $1, $1, $2 # true if low address and not open |
343 | bne $1, $0, \patch_handler # if above is true, patch |
344 | .endm |
345 | |
346 | |
347 | .macro region_check_align region, align_bits, alignment, patch_handler |
348 | srl $1, $4, 24 # check upper 8bits of address |
349 | ins $1, $4, 8, \align_bits # look at lower bits of address too |
350 | # See if it is the given region and alignment |
351 | xori $1, $1, (\region | (\alignment << 8)) |
352 | bne $1, $0, \patch_handler # if not repatch/try again |
353 | .endm |
354 | |
355 | .macro region_check_open_align align_bits, alignment, patch_handler |
356 | srl $1, $4, 24 # check upper 8bits of address |
357 | sltiu $2, $1, 0x0F # true if it is a low address |
358 | addiu $1, $1, -1 # non-zero if it is not a low open |
359 | sltu $1, $0, $1 # true if $1 != 0 |
360 | and $1, $1, $2 # true if low address and not open |
361 | ext $2, $4, 0, \align_bits # $2 = low bits of 4 |
362 | xori $2, $2, \alignment # true if alignment doesn't match |
363 | or $1, $1, $2 # align failure will trigger too |
364 | bne $1, $0, \patch_handler # if above is true, patch |
365 | .endm |
366 | |
367 | |
368 | .macro ignore_region region, patch_handler |
369 | region_check \region, \patch_handler |
370 | nop |
371 | jr $ra |
372 | nop |
373 | .endm |
374 | |
375 | .macro ignore_high patch_handler |
376 | srl $1, $4, 24 # check upper 8bits of address |
377 | sltiu $1, $1, 0x0F # see if it is not high |
378 | bne $1, $0, \patch_handler # if not repatch/try again |
379 | nop |
380 | jr $ra |
381 | nop |
382 | .endm |
383 | |
384 | |
385 | .macro translate_region_core base, size |
386 | lui $2, %hi(\base) # generate upper address |
387 | andi $4, $4, \size # generate offset |
388 | addu $2, $2, $4 # add ptr upper and offset |
389 | .endm |
390 | |
391 | .macro translate_region region, patch_handler, base, size |
392 | region_check \region, \patch_handler |
393 | translate_region_core \base, \size |
394 | .endm |
395 | |
396 | # I refuse to have > 80 char lines, and GAS has a problem with the param |
397 | # list spilling over (grumble) |
398 | |
399 | .macro translate_region_align region, a_b, alignment, p_h, base, size |
400 | region_check_align \region, \a_b, \alignment, \p_h |
401 | translate_region_core \base, \size |
402 | .endm |
403 | |
404 | |
405 | .macro translate_region_ewram_core mask |
406 | lui $2, %hi(ewram + 0x8000) # generate upper address (delay) |
407 | andi $1, $4, \mask # generate 15bit offset |
408 | ext $4, $4, 15, 3 # isolate top 3 bits of offset |
409 | ins $1, $4, 16, 3 # reinsert into top 4 bits |
410 | addu $2, $2, $1 |
411 | .endm |
412 | |
413 | .macro translate_region_ewram patch_handler |
414 | region_check 2, \patch_handler |
415 | translate_region_ewram_core 0x7FFF |
416 | .endm |
417 | |
418 | .macro translate_region_ewram_load_align align_bits, alignment, patch_handler |
419 | region_check_align 2, \align_bits, \alignment, \patch_handler |
420 | translate_region_ewram_core 0x7FFF |
421 | .endm |
422 | |
423 | .macro translate_region_ewram_load_align16 align_bits, alignment, patch_handler |
424 | region_check_align 2, \align_bits, \alignment, \patch_handler |
425 | translate_region_ewram_core 0x7FFE |
426 | .endm |
427 | |
428 | .macro translate_region_ewram_load_align32 align_bits, alignment, patch_handler |
429 | region_check_align 2, \align_bits, \alignment, \patch_handler |
430 | translate_region_ewram_core 0x7FFC |
431 | .endm |
432 | |
433 | .macro translate_region_ewram_store_align16 patch_handler |
434 | region_check 2, \patch_handler |
435 | translate_region_ewram_core 0x7FFE |
436 | .endm |
437 | |
438 | .macro translate_region_ewram_store_align32 patch_handler |
439 | region_check 2, \patch_handler |
440 | translate_region_ewram_core 0x7FFC |
441 | .endm |
442 | |
443 | |
444 | .macro translate_region_vram_core |
445 | addiu $2, $2, -3 # see if it's 3 |
446 | ext $4, $4, 0, 17 # generate 17bit offset |
447 | bne $2, $0, 1f |
448 | lui $1, %hi(vram) # start loading vram address (delay) |
449 | |
450 | addiu $4, $4, -0x8000 # move address into VRAM region |
451 | |
452 | 1: |
453 | addu $2, $1, $4 # $2 = (hi)vram + address |
454 | .endm |
455 | |
456 | .macro translate_region_vram patch_handler |
457 | region_check 6, \patch_handler |
458 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
459 | translate_region_vram_core |
460 | .endm |
461 | |
462 | .macro translate_region_vram_load_align align_bits, alignment, patch_handler |
463 | region_check_align 6, \align_bits, \alignment, \patch_handler |
464 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
465 | translate_region_vram_core |
466 | .endm |
467 | |
468 | .macro translate_region_vram_load_align16 align_bits, alignment, patch_handler |
469 | region_check_align 6, \align_bits, \alignment, \patch_handler |
470 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
471 | ins $4, $0, 0, 1 # mask out lower bit of address |
472 | translate_region_vram_core |
473 | .endm |
474 | |
475 | .macro translate_region_vram_load_align32 align_bits, alignment, patch_handler |
476 | region_check_align 6, \align_bits, \alignment, \patch_handler |
477 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
478 | ins $4, $0, 0, 2 # mask out lower two bits of address |
479 | translate_region_vram_core |
480 | .endm |
481 | |
482 | .macro translate_region_vram_store_align16 patch_handler |
483 | region_check 6, \patch_handler |
484 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
485 | ins $4, $0, 0, 1 # mask out lower bit of address |
486 | translate_region_vram_core |
487 | .endm |
488 | |
489 | .macro translate_region_vram_store_align32 patch_handler |
490 | region_check 6, \patch_handler |
491 | ext $2, $4, 15, 2 # $2 = bits 15 and 16 of address (delay) |
492 | ins $4, $0, 0, 2 # mask out lower two bits of address |
493 | translate_region_vram_core |
494 | .endm |
495 | |
496 | |
497 | |
498 | .macro translate_region_gamepak_core mask |
499 | srl $2, $4, 15 # $2 = page number of address (delay) |
500 | sll $2, $2, 2 # adjust to word index |
501 | addu $2, $2, $16 # $2 = memory_map_read[address >> 15] |
502 | lw $2, -32768($2) |
503 | bne $2, $0, 1f # if it's non-NULL continue |
504 | andi $1, $4, \mask # $1 = low 15bits of address (delay slot) |
505 | |
506 | sw $ra, REG_SAVE2($16) # save return address |
507 | |
508 | save_registers # save the registers |
509 | ext $4, $4, 15, 10 # $4 = (address >> 15) & 0x3FF |
510 | |
511 | jal load_gamepak_page # get page in $2 |
512 | sw $1, REG_SAVE($16) # save offset (delay) |
513 | lw $1, REG_SAVE($16) # restore offset (delay) |
514 | |
515 | restore_registers # restore the other registers |
516 | |
517 | lw $ra, REG_SAVE2($16) # restore return address |
518 | |
519 | 1: |
520 | addu $2, $2, $1 # add the memory map offset |
521 | .endm |
522 | |
523 | .macro translate_region_gamepak region, patch_handler |
524 | region_check \region, \patch_handler |
525 | translate_region_gamepak_core 0x7FFF |
526 | .endm |
527 | |
528 | .macro translate_region_gamepak_align region, a_b, alignment, patch_handler |
529 | region_check_align \region, \a_b, \alignment, \patch_handler |
530 | translate_region_gamepak_core 0x7FFF |
531 | .endm |
532 | |
533 | .macro translate_region_gamepak_align16 region, a_b, alignment, patch_handler |
534 | region_check_align \region, \a_b, \alignment, \patch_handler |
535 | translate_region_gamepak_core 0x7FFE |
536 | .endm |
537 | |
538 | .macro translate_region_gamepak_align32 region, a_b, alignment, patch_handler |
539 | region_check_align \region, \a_b, \alignment, \patch_handler |
540 | translate_region_gamepak_core 0x7FFC |
541 | .endm |
542 | |
543 | |
544 | .macro translate_region_gamepak_a region, patch_handler |
545 | region_check \region, \patch_handler |
546 | srl $2, $4, 15 # $2 = page number of address (delay) |
547 | sll $2, $2, 2 # adjust to word index |
548 | addu $2, $2, $16 # $2 = memory_map_read[address >> 15] |
549 | lw $2, -32768($2) |
550 | bne $2, $0, 1f # if it's non-NULL continue |
551 | andi $1, $4, 0x7FFF # $1 = low 15bits of address (delay slot) |
552 | |
553 | sw $ra, REG_SAVE2($16) # save return address |
554 | sw $6, REG_SAVE3($16) # save a2 |
555 | |
556 | save_registers # save the registers |
557 | ext $4, $4, 15, 10 # $4 = (address >> 15) & 0x3FF |
558 | |
559 | jal load_gamepak_page # get page in $2 |
560 | sw $1, REG_SAVE($16) # save offset (delay) |
561 | lw $1, REG_SAVE($16) # restore offset (delay) |
562 | |
563 | restore_registers # restore the other registers |
564 | |
565 | lw $ra, REG_SAVE2($16) # restore return address |
566 | lw $6, REG_SAVE3($16) # restore a2 |
567 | |
568 | 1: |
569 | addu $2, $2, $1 # add the memory map offset |
570 | .endm |
571 | |
572 | |
573 | .macro eeprom_load_a patch_handler |
574 | region_check 0xD, \patch_handler |
575 | |
576 | sw $ra, REG_SAVE($16) # save the return address (delay) |
577 | sw $6, REG_SAVE2($16) # save a2 |
578 | |
579 | save_registers # save the registers |
580 | |
581 | jal read_eeprom # get eeprom value in $2 |
582 | nop |
583 | |
584 | restore_registers # restore the other registers |
585 | |
586 | lw $ra, REG_SAVE($16) # restore return address |
587 | jr $ra # return |
588 | lw $6, REG_SAVE2($16) # restore a2 |
589 | .endm |
590 | |
591 | |
592 | .macro eeprom_load_core |
593 | sw $ra, REG_SAVE($16) # save the return address (delay) |
594 | |
595 | save_registers # save the registers |
596 | |
597 | jal read_eeprom # get eeprom value in $2 |
598 | nop |
599 | |
600 | restore_registers # restore the other registers |
601 | |
602 | lw $ra, REG_SAVE($16) # restore return address |
603 | jr $ra # return |
604 | nop |
605 | .endm |
606 | |
607 | .macro eeprom_load patch_handler |
608 | region_check 0xD, \patch_handler |
609 | eeprom_load_core |
610 | .endm |
611 | |
612 | .macro eeprom_load_align align_bits, alignment, patch_handler |
613 | region_check_align 0xD, \align_bits, \alignment, \patch_handler |
614 | eeprom_load_core |
615 | .endm |
616 | |
617 | .macro eeprom_load_align16 align_bits, alignment, patch_handler |
618 | eeprom_load_align \align_bits, \alignment, \patch_handler |
619 | .endm |
620 | |
621 | .macro eeprom_load_align32 align_bits, alignment, patch_handler |
622 | eeprom_load_align \align_bits, \alignment, \patch_handler |
623 | .endm |
624 | |
625 | |
626 | .macro backup_load_core |
627 | save_registers # save the registers |
628 | |
629 | jal read_backup # get backup value in $2 |
630 | ext $4, $4, 0, 16 # address &= 0xFFFF |
631 | |
632 | restore_registers # restore the other registers |
633 | |
634 | lw $ra, REG_SAVE($16) # restore return address |
635 | jr $ra # return |
636 | .endm |
637 | |
638 | .macro backup_load_a patch_handler |
639 | region_check 0xE, \patch_handler |
640 | sw $ra, REG_SAVE($16) # save return address (delay) |
641 | sw $6, REG_SAVE2($16) # save a2 |
642 | |
643 | save_registers # save the registers |
644 | |
645 | jal read_backup # get backup value in $2 |
646 | ext $4, $4, 0, 16 # address &= 0xFFFF |
647 | |
648 | restore_registers # restore the other registers |
649 | |
650 | lw $ra, REG_SAVE($16) # restore return address |
651 | jr $ra # return |
652 | lw $6, REG_SAVE2($16) # restore a2 |
653 | .endm |
654 | |
655 | |
656 | .macro backup_load patch_handler |
657 | region_check 0xE, \patch_handler |
658 | sw $ra, REG_SAVE($16) # save the return address (delay) |
659 | backup_load_core |
660 | .endm |
661 | |
662 | .macro backup_load_align align_bits, alignment, patch_handler |
663 | region_check_align 0xE, \align_bits, \alignment, \patch_handler |
664 | sw $ra, REG_SAVE($16) # save the return address (delay) |
665 | backup_load_core |
666 | .endm |
667 | |
668 | .macro backup_load_align16 align_bits, alignment, patch_handler |
669 | region_check_align 0xE, \align_bits, \alignment, \patch_handler |
670 | sw $ra, REG_SAVE($16) # save the return address (delay) |
671 | ins $4, $0, 0, 1 # mask out lower bit |
672 | backup_load_core |
673 | .endm |
674 | |
675 | .macro backup_load_align32 align_bits, alignment, patch_handler |
676 | region_check_align 0xE, \align_bits, \alignment, \patch_handler |
677 | sw $ra, REG_SAVE($16) # save the return address (delay) |
678 | ins $4, $0, 0, 2 # mask out lower two bits |
679 | backup_load_core |
680 | .endm |
681 | |
682 | |
683 | .macro open_load8_core |
684 | lw $2, REG_CPSR($16) # $2 = CPSR (delay) |
685 | andi $2, $2, 0x20 # test T bit |
686 | beq $2, $0, 1f # branch if ARM mode |
687 | andi $4, $4, 0x03 # isolate lower 3bits from address (delay) |
688 | |
689 | andi $4, $4, 0x01 # in Thumb mode, isolate one more bit |
690 | |
691 | 1: |
692 | sw $ra, REG_SAVE($16) # save the return address (delay) |
693 | save_registers # save the registers |
694 | |
695 | jal read_memory8 # get instruction at PC |
696 | addu $4, $5, $4 # a0 = PC + low bits of address |
697 | |
698 | restore_registers # restore the other registers |
699 | |
700 | lw $ra, REG_SAVE($16) # restore return address |
701 | jr $ra # return |
702 | .endm |
703 | |
704 | .macro open_load8 patch_handler |
705 | region_check_open \patch_handler |
706 | open_load8_core |
707 | .endm |
708 | |
709 | |
710 | |
711 | .macro open_load16_core |
712 | lw $2, REG_CPSR($16) # $2 = CPSR (delay) |
713 | andi $2, $2, 0x20 # test T bit |
714 | beq $2, $0, 1f # branch if ARM mode |
715 | andi $4, $4, 0x02 # isolate bit 1 from address (delay) |
716 | |
717 | addu $4, $0, $0 # zero out address bit |
718 | |
719 | 1: |
720 | sw $ra, REG_SAVE($16) # save the return address (delay) |
721 | save_registers # save the registers |
722 | |
723 | jal read_memory16 # get instruction at PC |
724 | addu $4, $5, $4 # a0 = PC + low bits of address |
725 | |
726 | restore_registers # restore the other registers |
727 | |
728 | lw $ra, REG_SAVE($16) # restore return address |
729 | jr $ra # return |
730 | .endm |
731 | |
732 | .macro open_load16_align align_bits, alignment, patch_handler |
733 | region_check_open_align \align_bits, \alignment, \patch_handler |
734 | open_load16_core |
735 | .endm |
736 | |
737 | .macro open_load16_align16 align_bits, alignment, patch_handler |
738 | open_load16_align \align_bits, \alignment, \patch_handler |
739 | .endm |
740 | |
741 | |
742 | |
743 | .macro open_load32_core |
744 | lw $2, REG_CPSR($16) # $2 = CPSR (delay) |
745 | andi $2, $2, 0x20 # test T bit |
746 | |
747 | save_registers # save the registers |
748 | |
749 | beq $2, $0, 1f # branch if ARM mode |
750 | sw $ra, REG_SAVE($16) # save the return address (delay) |
751 | |
752 | jal read_memory16 # get instruction at PC |
753 | addu $4, $5, $0 # a0 = PC |
754 | |
755 | j 2f |
756 | ins $2, $2, 16, 16 # result = (result << 16) | result (delay) |
757 | |
758 | 1: |
759 | jal read_memory32 # get instruction at PC |
760 | addu $4, $5, $4 # a0 = PC |
761 | |
762 | 2: # join point |
763 | restore_registers # restore the other registers |
764 | |
765 | lw $ra, REG_SAVE($16) # restore return address |
766 | jr $ra # return |
767 | .endm |
768 | |
769 | .macro open_load32_a patch_handler |
770 | region_check_open \patch_handler |
771 | |
772 | lw $2, REG_CPSR($16) # $2 = CPSR (delay) |
773 | andi $2, $2, 0x20 # test T bit |
774 | |
775 | save_registers # save the registers |
776 | sw $6, REG_SAVE2($16) # save a2 |
777 | |
778 | beq $2, $0, 1f # branch if ARM mode |
779 | sw $ra, REG_SAVE($16) # save the return address (delay) |
780 | |
781 | jal read_memory16 # get instruction at PC |
782 | addu $4, $5, $0 # a0 = PC |
783 | |
784 | j 2f |
785 | ins $2, $2, 16, 16 # result = (result << 16) | result (delay) |
786 | |
787 | 1: |
788 | jal read_memory32 # get instruction at PC |
789 | addu $4, $5, $4 # a0 = PC |
790 | |
791 | 2: |
792 | restore_registers # restore the other registers |
793 | |
794 | lw $ra, REG_SAVE($16) # restore return address |
795 | jr $ra # return |
796 | lw $6, REG_SAVE2($16) # restore a2 (delay) |
797 | .endm |
798 | |
799 | .macro open_load32_align align_bits, alignment, patch_handler |
800 | region_check_open_align \align_bits, \alignment, \patch_handler |
801 | open_load32_core |
802 | .endm |
803 | |
804 | .macro open_load32_align32 align_bits, alignment, patch_handler |
805 | open_load32_align \align_bits, \alignment, \patch_handler |
806 | .endm |
807 | |
808 | |
809 | .macro store_function function, region, patch_handler, mask |
810 | region_check \region, \patch_handler |
811 | sw $ra, REG_SAVE($16) # save the return address (delay) |
812 | |
813 | save_registers # save the registers |
814 | |
815 | jal \function # store value out |
816 | andi $4, $4, \mask # mask address |
817 | |
818 | restore_registers # restore the other registers |
819 | |
820 | lw $ra, REG_SAVE($16) # restore return address |
821 | jr $ra # return |
822 | nop |
823 | .endm |
824 | |
825 | |
826 | .macro store_function_a function, region, patch_handler, mask |
827 | region_check \region, \patch_handler |
828 | sw $ra, REG_SAVE($16) # save the return address (delay) |
829 | |
830 | save_registers # save the registers |
831 | |
832 | jal \function # store value out |
833 | andi $4, $4, \mask # mask address |
834 | |
835 | restore_registers # restore the other registers |
836 | |
837 | lw $ra, REG_SAVE($16) # restore return address |
838 | jr $ra # return |
839 | nop |
840 | .endm |
841 | |
842 | |
843 | |
844 | .macro load_u8 base |
845 | jr $ra # return |
846 | lbu $2, %lo(\base)($2) # return base[offset] |
847 | .endm |
848 | |
849 | .macro load_s8 base |
850 | jr $ra # return |
851 | lb $2, %lo(\base)($2) # return base[offset] |
852 | .endm |
853 | |
854 | .macro load_u16 base |
855 | jr $ra # return |
856 | lhu $2, %lo(\base)($2) # return base[offset] |
857 | .endm |
858 | |
859 | .macro load_s16 base |
860 | jr $ra # return |
861 | lh $2, %lo(\base)($2) # return base[offset] |
862 | .endm |
863 | |
864 | .macro load_u32 base |
865 | jr $ra # return |
866 | lw $2, %lo(\base)($2) # return base[offset] |
867 | .endm |
868 | |
869 | |
870 | # 16bit unaligned load will always have a 1 in the LSB; |
871 | # should have already been taken care of in indexing. |
872 | |
873 | .macro load_u16_unaligned base |
874 | lhu $2, %lo(\base)($2) # load base[offset] |
875 | jr $ra # return |
876 | ror $2, $2, 8 # rotate value by 8bits |
877 | .endm |
878 | |
879 | # This is technically the same as load_s8, but kept to |
880 | # avoid confusion. |
881 | |
882 | .macro load_s16_unaligned base |
883 | jr $ra # return |
884 | lb $2, %lo(\base)($2) # return base[offset] |
885 | .endm |
886 | |
887 | # Unalignment must be known statically (use the tables to |
888 | # patch correctly) |
889 | |
890 | .macro load_u32_unaligned base, alignment |
891 | lw $2, %lo(\base)($2) # load base[offset] |
892 | jr $ra # return |
893 | ror $2, $2, (\alignment * 8) # rotate value by 8bits |
894 | .endm |
895 | |
896 | |
897 | .macro store_u8 base |
898 | jr $ra # return |
899 | sb $5, %lo(\base)($2) # store value at base[offset] |
900 | .endm |
901 | |
902 | .macro store_u16 base |
903 | jr $ra # return |
904 | sh $5, %lo(\base)($2) # store value at base[offset] |
905 | .endm |
906 | |
907 | .macro store_u32 base |
908 | jr $ra # return |
909 | sw $5, %lo(\base)($2) # store value at base[offset] |
910 | .endm |
911 | |
912 | |
913 | # Store the value double mirrored (u16) |
914 | |
915 | .macro store_u8_double base |
916 | ins $5, $5, 8, 8 # value = (value << 8) | value |
917 | jr $ra # return |
918 | sh $5, %lo(\base)($2) # store value at base[offset] |
919 | .endm |
920 | |
921 | |
922 | # Store the values and check if it overwrote code there |
923 | |
924 | .macro store_u8_smc base |
925 | addiu $2, $2, %lo(\base) # offset the address |
926 | lb $1, -32768($2) # load the SMC status |
927 | bne $1, $0, smc_write # is there code there? |
928 | sb $5, ($2) # store value at base[offset] (delay) |
929 | jr $ra # return |
930 | nop |
931 | .endm |
932 | |
933 | .macro store_u16_smc base |
934 | addiu $2, $2, %lo(\base) # offset the address |
935 | lh $1, -32768($2) # load the SMC status |
936 | bne $1, $0, smc_write # is there code there? |
937 | sh $5, ($2) # store value at base[offset] (delay) |
938 | jr $ra # return |
939 | nop |
940 | .endm |
941 | |
942 | .macro store_u32_smc base |
943 | addiu $2, $2, %lo(\base) # offset the address |
944 | lw $1, -32768($2) # load the SMC status |
945 | bne $1, $0, smc_write # is there code there? |
946 | sw $5, ($2) # store value at base[offset] (delay) |
947 | jr $ra # return |
948 | nop |
949 | .endm |
950 | |
951 | |
952 | |
953 | # Unsigned 8bit load handlers |
954 | |
955 | execute_load_bios_u8: |
956 | region_check 0, patch_load_u8 |
957 | srl $2, $4, 14 # check if address is in BIOS region |
958 | bne $2, $0, 2f # if not, perform open read |
959 | srl $1, $5, 14 # check if PC is in BIOS region |
960 | bne $1, $0, 1f # if not, perform BIOS protected read |
961 | lui $2, %hi(bios_rom) # generate upper address (delay) |
962 | |
963 | andi $4, $4, 0x3FFF # generate offset |
964 | addu $2, $2, $4 |
965 | load_u8 bios_rom |
966 | |
967 | 1: |
968 | lui $2, %hi(bios_read_protect) # generate upper address |
969 | ins $2, $4, 0, 2 # lower 2 bits address contributes |
970 | load_u8 bios_read_protect |
971 | |
972 | 2: |
973 | open_load8_core |
974 | nop |
975 | |
976 | |
977 | execute_load_ewram_u8: |
978 | translate_region_ewram patch_load_u8 |
979 | load_u8 (ewram + 0x8000) |
980 | |
981 | # Put the generic address over the handler you want to be default |
982 | # IWRAM is typically the most frequently read and written to. |
983 | |
984 | execute_load_u8: |
985 | execute_load_iwram_u8: |
986 | translate_region 3, patch_load_u8, (iwram + 0x8000), 0x7FFF |
987 | load_u8 (iwram + 0x8000) |
988 | |
989 | execute_load_io_u8: |
990 | translate_region 4, patch_load_u8, io_registers, 0x3FF |
991 | load_u8 io_registers |
992 | |
993 | execute_load_palette_u8: |
994 | translate_region 5, patch_load_u8, palette_ram, 0x3FF |
995 | load_u8 palette_ram |
996 | |
997 | execute_load_vram_u8: |
998 | translate_region_vram patch_load_u8 |
999 | load_u8 vram |
1000 | |
1001 | execute_load_oam_u8: |
1002 | translate_region 7, patch_load_u8, oam_ram, 0x3FF |
1003 | load_u8 oam_ram |
1004 | |
1005 | execute_load_gamepak8_u8: |
1006 | translate_region_gamepak 8, patch_load_u8 |
1007 | load_u8 0 |
1008 | |
1009 | execute_load_gamepak9_u8: |
1010 | translate_region_gamepak 9, patch_load_u8 |
1011 | load_u8 0 |
1012 | |
1013 | execute_load_gamepakA_u8: |
1014 | translate_region_gamepak 10, patch_load_u8 |
1015 | load_u8 0 |
1016 | |
1017 | execute_load_gamepakB_u8: |
1018 | translate_region_gamepak 11, patch_load_u8 |
1019 | load_u8 0 |
1020 | |
1021 | execute_load_gamepakC_u8: |
1022 | translate_region_gamepak 12, patch_load_u8 |
1023 | load_u8 0 |
1024 | |
1025 | execute_load_eeprom_u8: |
1026 | eeprom_load patch_load_u8 |
1027 | |
1028 | execute_load_backup_u8: |
1029 | backup_load patch_load_u8 |
1030 | nop |
1031 | |
1032 | execute_load_open_u8: |
1033 | open_load8 patch_load_u8 |
1034 | nop |
1035 | |
1036 | load_u8_ftable: |
1037 | .long execute_load_bios_u8 # 0x00 BIOS |
1038 | .long execute_load_open_u8 # 0x01 open address |
1039 | .long execute_load_ewram_u8 # 0x02 EWRAM |
1040 | .long execute_load_iwram_u8 # 0x03 IWRAM |
1041 | .long execute_load_io_u8 # 0x04 I/O registers |
1042 | .long execute_load_palette_u8 # 0x05 Palette RAM |
1043 | .long execute_load_vram_u8 # 0x06 VRAM |
1044 | .long execute_load_oam_u8 # 0x07 OAM RAM |
1045 | .long execute_load_gamepak8_u8 # 0x08 gamepak |
1046 | .long execute_load_gamepak9_u8 # 0x09 gamepak |
1047 | .long execute_load_gamepakA_u8 # 0x0A gamepak |
1048 | .long execute_load_gamepakB_u8 # 0x0B gamepak |
1049 | .long execute_load_gamepakC_u8 # 0x0C gamepak |
1050 | .long execute_load_eeprom_u8 # 0x0D gamepak/eeprom |
1051 | .long execute_load_backup_u8 # 0x0E Flash ROM/SRAM |
1052 | .long execute_load_open_u8 # 0x0F open address |
1053 | |
1054 | patch_load_u8: |
1055 | patch_handler load_u8_ftable, 0x01 |
1056 | |
1057 | |
1058 | |
1059 | # Signed 8bit load handlers |
1060 | |
1061 | execute_load_bios_s8: |
1062 | region_check 0, patch_load_s8 |
1063 | srl $2, $4, 14 # check if address is in BIOS region |
1064 | bne $2, $0, 2f |
1065 | srl $1, $5, 14 # check if PC is in BIOS region |
1066 | bne $1, $0, 1f # if not, perform BIOS protected read |
1067 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1068 | |
1069 | andi $4, $4, 0x3FFF # generate offset |
1070 | addu $2, $2, $4 |
1071 | load_s8 bios_rom |
1072 | |
1073 | 1: |
1074 | lui $2, %hi(bios_read_protect) # generate upper address |
1075 | ins $2, $4, 0, 2 # lower 2 bits contribute |
1076 | load_s8 bios_read_protect |
1077 | |
1078 | 2: |
1079 | open_load8_core |
1080 | seb $2, $2 |
1081 | |
1082 | |
1083 | execute_load_ewram_s8: |
1084 | translate_region_ewram patch_load_s8 |
1085 | load_s8 (ewram + 0x8000) |
1086 | |
1087 | execute_load_s8: |
1088 | execute_load_iwram_s8: |
1089 | translate_region 3, patch_load_s8, (iwram + 0x8000), 0x7FFF |
1090 | load_s8 (iwram + 0x8000) |
1091 | |
1092 | execute_load_io_s8: |
1093 | translate_region 4, patch_load_s8, io_registers, 0x3FF |
1094 | load_s8 io_registers |
1095 | |
1096 | execute_load_palette_s8: |
1097 | translate_region 5, patch_load_s8, palette_ram, 0x3FF |
1098 | load_s8 palette_ram |
1099 | |
1100 | execute_load_vram_s8: |
1101 | translate_region_vram patch_load_s8 |
1102 | load_s8 vram |
1103 | |
1104 | execute_load_oam_s8: |
1105 | translate_region 7, patch_load_s8, oam_ram, 0x3FF |
1106 | load_s8 oam_ram |
1107 | |
1108 | execute_load_gamepak8_s8: |
1109 | translate_region_gamepak 8, patch_load_s8 |
1110 | load_s8 0 |
1111 | |
1112 | execute_load_gamepak9_s8: |
1113 | translate_region_gamepak 9, patch_load_s8 |
1114 | load_s8 0 |
1115 | |
1116 | execute_load_gamepakA_s8: |
1117 | translate_region_gamepak 10, patch_load_s8 |
1118 | load_s8 0 |
1119 | |
1120 | execute_load_gamepakB_s8: |
1121 | translate_region_gamepak 11, patch_load_s8 |
1122 | load_s8 0 |
1123 | |
1124 | execute_load_gamepakC_s8: |
1125 | translate_region_gamepak 12, patch_load_s8 |
1126 | load_s8 0 |
1127 | |
1128 | execute_load_eeprom_s8: |
1129 | eeprom_load patch_load_s8 |
1130 | |
1131 | execute_load_backup_s8: |
1132 | backup_load patch_load_s8 |
1133 | seb $2, $2 # sign extend result (delay) |
1134 | |
1135 | execute_load_open_s8: |
1136 | open_load8 patch_load_s8 |
1137 | seb $2, $2 # sign extend result (delay) |
1138 | |
1139 | load_s8_ftable: |
1140 | .long execute_load_bios_s8 # 0x00 BIOS |
1141 | .long execute_load_open_s8 # 0x01 open address |
1142 | .long execute_load_ewram_s8 # 0x02 EWRAM |
1143 | .long execute_load_iwram_s8 # 0x03 IWRAM |
1144 | .long execute_load_io_s8 # 0x04 I/O registers |
1145 | .long execute_load_palette_s8 # 0x05 Palette RAM |
1146 | .long execute_load_vram_s8 # 0x06 VRAM |
1147 | .long execute_load_oam_s8 # 0x07 OAM RAM |
1148 | .long execute_load_gamepak8_s8 # 0x08 gamepak |
1149 | .long execute_load_gamepak9_s8 # 0x09 gamepak |
1150 | .long execute_load_gamepakA_s8 # 0x0A gamepak |
1151 | .long execute_load_gamepakB_s8 # 0x0B gamepak |
1152 | .long execute_load_gamepakC_s8 # 0x0C gamepak |
1153 | .long execute_load_eeprom_s8 # 0x0D gamepak/eeprom |
1154 | .long execute_load_backup_s8 # 0x0E Flash ROM/SRAM |
1155 | .long execute_load_open_s8 # 0x0F open address |
1156 | |
1157 | patch_load_s8: |
1158 | patch_handler load_s8_ftable, 1 |
1159 | |
1160 | |
1161 | |
1162 | # Unsigned aligned 16bit load handlers |
1163 | |
1164 | execute_load_bios_u16: |
1165 | region_check_align 0, 1, 0, patch_load_u16 |
1166 | srl $2, $4, 14 # check if address is in BIOS region |
1167 | bne $2, $0, 2f # if not, perform open read |
1168 | srl $1, $5, 14 # check if PC is in BIOS region |
1169 | bne $1, $0, 1f # if not, perform BIOS protected read |
1170 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1171 | |
1172 | andi $4, $4, 0x3FFF # generate offset |
1173 | addu $2, $2, $4 |
1174 | load_u16 bios_rom |
1175 | |
1176 | 1: |
1177 | lui $2, %hi(bios_read_protect) # generate upper address |
1178 | ins $2, $4, 0, 2 # bit 1 contributes |
1179 | load_u16 bios_read_protect |
1180 | |
1181 | 2: |
1182 | open_load16_core |
1183 | nop |
1184 | |
1185 | execute_load_ewram_u16: |
1186 | translate_region_ewram_load_align 1, 0, patch_load_u16 |
1187 | load_u16 (ewram + 0x8000) |
1188 | |
1189 | execute_load_u16: |
1190 | execute_load_iwram_u16: |
1191 | translate_region_align 3, 1, 0, patch_load_u16, (iwram + 0x8000), 0x7FFF |
1192 | load_u16 (iwram + 0x8000) |
1193 | |
1194 | execute_load_io_u16: |
1195 | translate_region_align 4, 1, 0, patch_load_u16, io_registers, 0x3FF |
1196 | load_u16 io_registers |
1197 | |
1198 | execute_load_palette_u16: |
1199 | translate_region_align 5, 1, 0, patch_load_u16, palette_ram, 0x3FF |
1200 | load_u16 palette_ram |
1201 | |
1202 | execute_load_vram_u16: |
1203 | translate_region_vram_load_align 1, 0, patch_load_u16 |
1204 | load_u16 vram |
1205 | |
1206 | execute_load_oam_u16: |
1207 | translate_region_align 7, 1, 0, patch_load_u16, oam_ram, 0x3FF |
1208 | load_u16 oam_ram |
1209 | |
1210 | execute_load_gamepak8_u16: |
1211 | translate_region_gamepak_align 8, 1, 0, patch_load_u16 |
1212 | load_u16 0 |
1213 | |
1214 | execute_load_gamepak9_u16: |
1215 | translate_region_gamepak_align 9, 1, 0, patch_load_u16 |
1216 | load_u16 0 |
1217 | |
1218 | execute_load_gamepakA_u16: |
1219 | translate_region_gamepak_align 10, 1, 0, patch_load_u16 |
1220 | load_u16 0 |
1221 | |
1222 | execute_load_gamepakB_u16: |
1223 | translate_region_gamepak_align 11, 1, 0, patch_load_u16 |
1224 | load_u16 0 |
1225 | |
1226 | execute_load_gamepakC_u16: |
1227 | translate_region_gamepak_align 12, 1, 0, patch_load_u16 |
1228 | load_u16 0 |
1229 | |
1230 | execute_load_eeprom_u16: |
1231 | eeprom_load_align 1, 0, patch_load_u16 |
1232 | |
1233 | execute_load_backup_u16: |
1234 | backup_load_align 1, 0, patch_load_u16 |
1235 | nop |
1236 | |
1237 | execute_load_open_u16: |
1238 | open_load16_align 1, 0, patch_load_u16 |
1239 | nop |
1240 | |
1241 | |
1242 | # Unsigned unaligned 16bit load handlers |
1243 | |
1244 | execute_load_bios_u16u: |
1245 | region_check_align 0, 1, 1, patch_load_u16 |
1246 | srl $2, $4, 14 # check if address is in BIOS region |
1247 | bne $2, $0, 2f # if not, perform open read |
1248 | srl $1, $5, 14 # check if PC is in BIOS region |
1249 | bne $1, $0, 1f # if not, perform BIOS protected read |
1250 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1251 | |
1252 | andi $4, $4, 0x3FFE # generate offset |
1253 | addu $2, $2, $4 |
1254 | load_u16_unaligned bios_rom |
1255 | |
1256 | 1: |
1257 | lui $2, %hi(bios_read_protect) # generate upper address |
1258 | ext $1, $4, 1, 1 |
1259 | ins $2, $1, 1, 1 # bit 1 contributes |
1260 | load_u16_unaligned bios_read_protect |
1261 | |
1262 | 2: |
1263 | open_load16_core |
1264 | ror $2, $2, 8 |
1265 | |
1266 | |
1267 | execute_load_ewram_u16u: |
1268 | translate_region_ewram_load_align16 1, 1, patch_load_u16 |
1269 | load_u16_unaligned (ewram + 0x8000) |
1270 | |
1271 | execute_load_iwram_u16u: |
1272 | translate_region_align 3, 1, 1, patch_load_u16, (iwram + 0x8000), 0x7FFE |
1273 | load_u16_unaligned (iwram + 0x8000) |
1274 | |
1275 | execute_load_io_u16u: |
1276 | translate_region_align 4, 1, 1, patch_load_u16, io_registers, 0x3FE |
1277 | load_u16_unaligned io_registers |
1278 | |
1279 | execute_load_palette_u16u: |
1280 | translate_region_align 5, 1, 1, patch_load_u16, palette_ram, 0x3FE |
1281 | load_u16_unaligned palette_ram |
1282 | |
1283 | execute_load_vram_u16u: |
1284 | translate_region_vram_load_align16 1, 1, patch_load_u16 |
1285 | load_u16_unaligned vram |
1286 | |
1287 | execute_load_oam_u16u: |
1288 | translate_region_align 7, 1, 1, patch_load_u16, oam_ram, 0x3FE |
1289 | load_u16_unaligned oam_ram |
1290 | |
1291 | execute_load_gamepak8_u16u: |
1292 | translate_region_gamepak_align16 8, 1, 1, patch_load_u16 |
1293 | load_u16_unaligned 0 |
1294 | |
1295 | execute_load_gamepak9_u16u: |
1296 | translate_region_gamepak_align16 9, 1, 1, patch_load_u16 |
1297 | load_u16_unaligned 0 |
1298 | |
1299 | execute_load_gamepakA_u16u: |
1300 | translate_region_gamepak_align16 10, 1, 1, patch_load_u16 |
1301 | load_u16_unaligned 0 |
1302 | |
1303 | execute_load_gamepakB_u16u: |
1304 | translate_region_gamepak_align16 11, 1, 1, patch_load_u16 |
1305 | load_u16_unaligned 0 |
1306 | |
1307 | execute_load_gamepakC_u16u: |
1308 | translate_region_gamepak_align16 12, 1, 1, patch_load_u16 |
1309 | load_u16_unaligned 0 |
1310 | |
1311 | execute_load_eeprom_u16u: |
1312 | eeprom_load_align16 1, 1, patch_load_u16 |
1313 | |
1314 | execute_load_backup_u16u: |
1315 | backup_load_align16 1, 1, patch_load_u16 |
1316 | ror $2, $2, 8 # rotate value by 8bits |
1317 | |
1318 | execute_load_open_u16u: |
1319 | open_load16_align16 1, 1, patch_load_u16 |
1320 | ror $2, $2, 8 # rotate value by 8bits |
1321 | |
1322 | load_u16_ftable: |
1323 | # .long execute_load_full_u16 |
1324 | .long execute_load_bios_u16 # 0x00 BIOS |
1325 | .long execute_load_open_u16 # 0x01 open address |
1326 | .long execute_load_ewram_u16 # 0x02 EWRAM |
1327 | .long execute_load_iwram_u16 # 0x03 IWRAM |
1328 | .long execute_load_io_u16 # 0x04 I/O registers |
1329 | .long execute_load_palette_u16 # 0x05 Palette RAM |
1330 | .long execute_load_vram_u16 # 0x06 VRAM |
1331 | .long execute_load_oam_u16 # 0x07 OAM RAM |
1332 | .long execute_load_gamepak8_u16 # 0x08 gamepak |
1333 | .long execute_load_gamepak9_u16 # 0x09 gamepak |
1334 | .long execute_load_gamepakA_u16 # 0x0A gamepak |
1335 | .long execute_load_gamepakB_u16 # 0x0B gamepak |
1336 | .long execute_load_gamepakC_u16 # 0x0C gamepak |
1337 | |
1338 | .long execute_load_eeprom_u16 # 0x0D gamepak/eeprom |
1339 | .long execute_load_backup_u16 # 0x0E Flash ROM/SRAM |
1340 | .long execute_load_open_u16 # 0x0F open |
1341 | |
1342 | .long execute_load_bios_u16u # 0x00 BIOS unaligned |
1343 | .long execute_load_open_u16u # 0x01 open address unaligned |
1344 | .long execute_load_ewram_u16u # 0x02 EWRAM unaligned |
1345 | .long execute_load_iwram_u16u # 0x03 IWRAM unaligned |
1346 | .long execute_load_io_u16u # 0x04 I/O registers unaligned |
1347 | .long execute_load_palette_u16u # 0x05 Palette RAM unaligned |
1348 | .long execute_load_vram_u16u # 0x06 VRAM unaligned |
1349 | .long execute_load_oam_u16u # 0x07 OAM RAM unaligned |
1350 | .long execute_load_gamepak8_u16u# 0x08 gamepak unaligned |
1351 | .long execute_load_gamepak9_u16u# 0x09 gamepak unaligned |
1352 | .long execute_load_gamepakA_u16u# 0x0A gamepak unaligned |
1353 | .long execute_load_gamepakB_u16u# 0x0B gamepak unaligned |
1354 | .long execute_load_gamepakC_u16u# 0x0C gamepak unaligned |
1355 | .long execute_load_eeprom_u16u # 0x0D gamepak/eeprom unaligned |
1356 | .long execute_load_backup_u16u # 0x0E Flash ROM/SRAM unaligned |
1357 | .long execute_load_open_u16u # 0x0F open unaligned |
1358 | |
1359 | |
1360 | .long execute_load_full_u16 |
1361 | .long execute_load_full_u16 |
1362 | .long execute_load_full_u16 |
1363 | .long execute_load_full_u16 |
1364 | .long execute_load_full_u16 |
1365 | .long execute_load_full_u16 |
1366 | .long execute_load_full_u16 |
1367 | .long execute_load_full_u16 |
1368 | .long execute_load_full_u16 |
1369 | .long execute_load_full_u16 |
1370 | .long execute_load_full_u16 |
1371 | .long execute_load_full_u16 |
1372 | .long execute_load_full_u16 |
1373 | .long execute_load_full_u16 |
1374 | .long execute_load_full_u16 |
1375 | |
1376 | .long execute_load_full_u16 |
1377 | .long execute_load_full_u16 |
1378 | .long execute_load_full_u16 |
1379 | .long execute_load_full_u16 |
1380 | .long execute_load_full_u16 |
1381 | .long execute_load_full_u16 |
1382 | .long execute_load_full_u16 |
1383 | .long execute_load_full_u16 |
1384 | .long execute_load_full_u16 |
1385 | .long execute_load_full_u16 |
1386 | .long execute_load_full_u16 |
1387 | .long execute_load_full_u16 |
1388 | .long execute_load_full_u16 |
1389 | .long execute_load_full_u16 |
1390 | .long execute_load_full_u16 |
1391 | .long execute_load_full_u16 |
1392 | |
1393 | |
1394 | |
1395 | patch_load_u16: |
1396 | patch_handler_align load_u16_ftable, 1 |
1397 | |
1398 | # Signed aligned 16bit load handlers |
1399 | |
1400 | execute_load_bios_s16: |
1401 | region_check_align 0, 1, 0, patch_load_s16 |
1402 | srl $2, $4, 14 # check if address is in BIOS region |
1403 | bne $2, $0, 2f # if not, perform open read |
1404 | srl $1, $5, 14 # check if PC is in BIOS region |
1405 | bne $1, $0, 1f # if not, perform BIOS protected read |
1406 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1407 | |
1408 | andi $4, $4, 0x3FFF # generate offset |
1409 | addu $2, $2, $4 |
1410 | load_s16 bios_rom |
1411 | |
1412 | 1: |
1413 | lui $2, %hi(bios_read_protect) # generate upper address |
1414 | ins $2, $4, 0, 2 # bit 1 contributes |
1415 | load_s16 bios_read_protect |
1416 | |
1417 | 2: |
1418 | open_load16_core |
1419 | seh $2, $2 |
1420 | |
1421 | |
1422 | execute_load_ewram_s16: |
1423 | translate_region_ewram_load_align 1, 0, patch_load_s16 |
1424 | load_s16 (ewram + 0x8000) |
1425 | |
1426 | execute_load_s16: |
1427 | execute_load_iwram_s16: |
1428 | translate_region_align 3, 1, 0, patch_load_s16, (iwram + 0x8000), 0x7FFF |
1429 | load_s16 (iwram + 0x8000) |
1430 | |
1431 | execute_load_io_s16: |
1432 | translate_region_align 4, 1, 0, patch_load_s16, io_registers, 0x3FF |
1433 | load_s16 io_registers |
1434 | |
1435 | execute_load_palette_s16: |
1436 | translate_region_align 5, 1, 0, patch_load_s16, palette_ram, 0x3FF |
1437 | load_s16 palette_ram |
1438 | |
1439 | execute_load_vram_s16: |
1440 | translate_region_vram_load_align 1, 0, patch_load_s16 |
1441 | load_s16 vram |
1442 | |
1443 | execute_load_oam_s16: |
1444 | translate_region_align 7, 1, 0, patch_load_s16, oam_ram, 0x3FF |
1445 | load_s16 oam_ram |
1446 | |
1447 | execute_load_gamepak8_s16: |
1448 | translate_region_gamepak_align 8, 1, 0, patch_load_s16 |
1449 | load_s16 0 |
1450 | |
1451 | execute_load_gamepak9_s16: |
1452 | translate_region_gamepak_align 9, 1, 0, patch_load_s16 |
1453 | load_s16 0 |
1454 | |
1455 | execute_load_gamepakA_s16: |
1456 | translate_region_gamepak_align 10, 1, 0, patch_load_s16 |
1457 | load_s16 0 |
1458 | |
1459 | execute_load_gamepakB_s16: |
1460 | translate_region_gamepak_align 11, 1, 0, patch_load_s16 |
1461 | load_s16 0 |
1462 | |
1463 | execute_load_gamepakC_s16: |
1464 | translate_region_gamepak_align 12, 1, 0, patch_load_s16 |
1465 | load_s16 0 |
1466 | |
1467 | execute_load_eeprom_s16: |
1468 | eeprom_load_align 1, 0, patch_load_s16 |
1469 | |
1470 | execute_load_backup_s16: |
1471 | backup_load_align 1, 0, patch_load_s16 |
1472 | nop |
1473 | |
1474 | execute_load_open_s16: |
1475 | open_load16_align 1, 0, patch_load_s16 |
1476 | nop |
1477 | |
1478 | |
1479 | # Signed unaligned 16bit load handlers |
1480 | |
1481 | execute_load_bios_s16u: |
1482 | region_check_align 0, 1, 1, patch_load_s16 |
1483 | srl $2, $4, 14 # check if address is in BIOS region |
1484 | bne $2, $0, 2f # if not, perform open read |
1485 | srl $1, $5, 14 # check if PC is in BIOS region |
1486 | bne $1, $0, 1f # if not, perform BIOS protected read |
1487 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1488 | |
1489 | andi $4, $4, 0x3FFE # generate offset |
1490 | addu $2, $1, $4 |
1491 | load_s16_unaligned bios_rom |
1492 | |
1493 | 1: |
1494 | lui $2, %hi(bios_read_protect) # generate upper address |
1495 | ext $1, $4, 1, 1 |
1496 | ins $2, $1, 1, 1 # bit 1 contributes |
1497 | load_s16_unaligned bios_read_protect |
1498 | |
1499 | 2: |
1500 | open_load16_core |
1501 | seb $2, $2 |
1502 | |
1503 | execute_load_ewram_s16u: |
1504 | translate_region_ewram_load_align16 1, 1, patch_load_s16 |
1505 | load_s16_unaligned (ewram + 0x8000) |
1506 | |
1507 | execute_load_iwram_s16u: |
1508 | translate_region_align 3, 1, 1, patch_load_s16, (iwram + 0x8000), 0x7FFE |
1509 | load_s16_unaligned (iwram + 0x8000) |
1510 | |
1511 | execute_load_io_s16u: |
1512 | translate_region_align 4, 1, 1, patch_load_s16, io_registers, 0x3FE |
1513 | load_s16_unaligned io_registers |
1514 | |
1515 | execute_load_palette_s16u: |
1516 | translate_region_align 5, 1, 1, patch_load_s16, palette_ram, 0x3FE |
1517 | load_s16_unaligned palette_ram |
1518 | |
1519 | execute_load_vram_s16u: |
1520 | translate_region_vram_load_align16 1, 1, patch_load_s16 |
1521 | load_s16_unaligned vram |
1522 | |
1523 | execute_load_oam_s16u: |
1524 | translate_region_align 7, 1, 1, patch_load_s16, oam_ram, 0x3FE |
1525 | load_s16_unaligned oam_ram |
1526 | |
1527 | execute_load_gamepak8_s16u: |
1528 | translate_region_gamepak_align16 8, 1, 1, patch_load_s16 |
1529 | load_s16_unaligned 0 |
1530 | |
1531 | execute_load_gamepak9_s16u: |
1532 | translate_region_gamepak_align16 9, 1, 1, patch_load_s16 |
1533 | load_s16_unaligned 0 |
1534 | |
1535 | execute_load_gamepakA_s16u: |
1536 | translate_region_gamepak_align16 10, 1, 1, patch_load_s16 |
1537 | load_s16_unaligned 0 |
1538 | |
1539 | execute_load_gamepakB_s16u: |
1540 | translate_region_gamepak_align16 11, 1, 1, patch_load_s16 |
1541 | load_s16_unaligned 0 |
1542 | |
1543 | execute_load_gamepakC_s16u: |
1544 | translate_region_gamepak_align16 12, 1, 1, patch_load_s16 |
1545 | load_s16_unaligned 0 |
1546 | |
1547 | execute_load_eeprom_s16u: |
1548 | eeprom_load_align 1, 1, patch_load_s16 |
1549 | |
1550 | execute_load_backup_s16u: |
1551 | backup_load_align 1, 1, patch_load_s16 |
1552 | seb $2, $2 # sign extend result from 8bits |
1553 | |
1554 | execute_load_open_s16u: |
1555 | open_load16_align 1, 1, patch_load_s16 |
1556 | seb $2, $2 # sign extend result from 8bits |
1557 | |
1558 | load_s16_ftable: |
1559 | .long execute_load_bios_s16 # 0x00 BIOS |
1560 | .long execute_load_open_s16 # 0x01 open address |
1561 | .long execute_load_ewram_s16 # 0x02 EWRAM |
1562 | .long execute_load_iwram_s16 # 0x03 IWRAM |
1563 | .long execute_load_io_s16 # 0x04 I/O registers |
1564 | .long execute_load_palette_s16 # 0x05 Palette RAM |
1565 | .long execute_load_vram_s16 # 0x06 VRAM |
1566 | .long execute_load_oam_s16 # 0x07 OAM RAM |
1567 | .long execute_load_gamepak8_s16 # 0x08 gamepak |
1568 | .long execute_load_gamepak9_s16 # 0x09 gamepak |
1569 | .long execute_load_gamepakA_s16 # 0x0A gamepak |
1570 | .long execute_load_gamepakB_s16 # 0x0B gamepak |
1571 | .long execute_load_gamepakC_s16 # 0x0C gamepak |
1572 | .long execute_load_eeprom_s16 # 0x0D gamepak/eeprom |
1573 | .long execute_load_backup_s16 # 0x0E Flash ROM/SRAM |
1574 | .long execute_load_open_s16 # 0x0F open unaligned |
1575 | |
1576 | .long execute_load_bios_s16u # 0x00 BIOS unaligned |
1577 | .long execute_load_open_s16u # 0x01 open address unaligned |
1578 | .long execute_load_ewram_s16u # 0x02 EWRAM unaligned |
1579 | .long execute_load_iwram_s16u # 0x03 IWRAM unaligned |
1580 | .long execute_load_io_s16u # 0x04 I/O registers unaligned |
1581 | .long execute_load_palette_s16u # 0x05 Palette RAM unaligned |
1582 | .long execute_load_vram_s16u # 0x06 VRAM unaligned |
1583 | .long execute_load_oam_s16u # 0x07 OAM RAM unaligned |
1584 | .long execute_load_gamepak8_s16u# 0x08 gamepak unaligned |
1585 | .long execute_load_gamepak9_s16u# 0x09 gamepak unaligned |
1586 | .long execute_load_gamepakA_s16u# 0x0A gamepak unaligned |
1587 | .long execute_load_gamepakB_s16u# 0x0B gamepak unaligned |
1588 | .long execute_load_gamepakC_s16u# 0x0C gamepak unaligned |
1589 | .long execute_load_eeprom_s16u # 0x0D gamepak/eeprom unaligned |
1590 | .long execute_load_backup_s16u # 0x0E Flash ROM/SRAM unaligned |
1591 | .long execute_load_open_s16u # 0x0F open unaligned |
1592 | |
1593 | patch_load_s16: |
1594 | patch_handler_align load_s16_ftable, 1 |
1595 | |
1596 | |
1597 | |
1598 | # Unsigned aligned 32bit load handlers |
1599 | |
1600 | execute_load_bios_u32: |
1601 | region_check_align 0, 2, 0, patch_load_u32 |
1602 | srl $2, $4, 14 # check if address is in BIOS region |
1603 | bne $2, $0, 2f # if not, perform open read |
1604 | srl $1, $5, 14 # check if PC is in BIOS region |
1605 | bne $1, $0, 1f # if not, perform BIOS protected read |
1606 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1607 | |
1608 | andi $4, $4, 0x3FFF # generate offset |
1609 | addu $2, $2, $4 |
1610 | load_u32 bios_rom |
1611 | |
1612 | 1: |
1613 | lui $2, %hi(bios_read_protect) # generate upper address |
1614 | load_u32 bios_read_protect |
1615 | |
1616 | 2: |
1617 | open_load32_core |
1618 | nop |
1619 | |
1620 | |
1621 | execute_load_ewram_u32: |
1622 | translate_region_ewram_load_align 2, 0, patch_load_u32 |
1623 | load_u32 (ewram + 0x8000) |
1624 | |
1625 | execute_load_u32: |
1626 | execute_load_iwram_u32: |
1627 | translate_region_align 3, 2, 0, patch_load_u32, (iwram + 0x8000), 0x7FFF |
1628 | load_u32 (iwram + 0x8000) |
1629 | |
1630 | execute_load_io_u32: |
1631 | translate_region_align 4, 2, 0, patch_load_u32, io_registers, 0x3FF |
1632 | load_u32 io_registers |
1633 | |
1634 | execute_load_palette_u32: |
1635 | translate_region_align 5, 2, 0, patch_load_u32, palette_ram, 0x3FF |
1636 | load_u32 palette_ram |
1637 | |
1638 | execute_load_vram_u32: |
1639 | translate_region_vram_load_align 2, 0, patch_load_u32 |
1640 | load_u32 vram |
1641 | |
1642 | execute_load_oam_u32: |
1643 | translate_region_align 7, 2, 0, patch_load_u32, oam_ram, 0x3FF |
1644 | load_u32 oam_ram |
1645 | |
1646 | execute_load_gamepak8_u32: |
1647 | translate_region_gamepak_align 8, 2, 0, patch_load_u32 |
1648 | load_u32 0 |
1649 | |
1650 | execute_load_gamepak9_u32: |
1651 | translate_region_gamepak_align 9, 2, 0, patch_load_u32 |
1652 | load_u32 0 |
1653 | |
1654 | execute_load_gamepakA_u32: |
1655 | translate_region_gamepak_align 10, 2, 0, patch_load_u32 |
1656 | load_u32 0 |
1657 | |
1658 | execute_load_gamepakB_u32: |
1659 | translate_region_gamepak_align 11, 2, 0, patch_load_u32 |
1660 | load_u32 0 |
1661 | |
1662 | execute_load_gamepakC_u32: |
1663 | translate_region_gamepak_align 12, 2, 0, patch_load_u32 |
1664 | load_u32 0 |
1665 | |
1666 | execute_load_eeprom_u32: |
1667 | eeprom_load_align 2, 0, patch_load_u32 |
1668 | |
1669 | execute_load_backup_u32: |
1670 | backup_load_align 2, 0, patch_load_u32 |
1671 | nop |
1672 | |
1673 | execute_load_open_u32: |
1674 | open_load32_align 2, 0, patch_load_u32 |
1675 | nop |
1676 | |
1677 | |
1678 | # Unsigned unaligned (by 1) 32bit load handlers |
1679 | |
1680 | execute_load_bios_u32u1: |
1681 | region_check_align 0, 2, 1, patch_load_u32 |
1682 | srl $2, $4, 14 # check if address is in BIOS region |
1683 | bne $2, $0, 2f # if not, perform open read |
1684 | srl $1, $5, 14 # check if PC is in BIOS region |
1685 | bne $1, $0, 1f # if not, perform BIOS protected read |
1686 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1687 | |
1688 | andi $4, $4, 0x3FFC # generate offset |
1689 | addu $2, $2, $4 |
1690 | load_u32_unaligned bios_rom, 1 |
1691 | |
1692 | 1: |
1693 | lui $2, %hi(bios_read_protect) # generate upper address |
1694 | load_u32_unaligned bios_read_protect, 1 |
1695 | |
1696 | 2: |
1697 | open_load32_core |
1698 | ror $2, $2, 8 |
1699 | |
1700 | execute_load_ewram_u32u1: |
1701 | translate_region_ewram_load_align32 2, 1, patch_load_u32 |
1702 | load_u32_unaligned (ewram + 0x8000), 1 |
1703 | |
1704 | execute_load_iwram_u32u1: |
1705 | translate_region_align 3, 2, 1, patch_load_u32, (iwram + 0x8000), 0x7FFC |
1706 | load_u32_unaligned (iwram + 0x8000), 1 |
1707 | |
1708 | execute_load_io_u32u1: |
1709 | translate_region_align 4, 2, 1, patch_load_u32, io_registers, 0x3FC |
1710 | load_u32_unaligned io_registers, 1 |
1711 | |
1712 | execute_load_palette_u32u1: |
1713 | translate_region_align 5, 2, 1, patch_load_u32, palette_ram, 0x3FC |
1714 | load_u32_unaligned palette_ram, 1 |
1715 | |
1716 | execute_load_vram_u32u1: |
1717 | translate_region_vram_load_align32 2, 1, patch_load_u32 |
1718 | load_u32_unaligned vram, 1 |
1719 | |
1720 | execute_load_oam_u32u1: |
1721 | translate_region_align 7, 2, 1, patch_load_u32, oam_ram, 0x3FC |
1722 | load_u32_unaligned oam_ram, 1 |
1723 | |
1724 | execute_load_gamepak8_u32u1: |
1725 | translate_region_gamepak_align32 8, 2, 1, patch_load_u32 |
1726 | load_u32_unaligned 0, 1 |
1727 | |
1728 | execute_load_gamepak9_u32u1: |
1729 | translate_region_gamepak_align32 9, 2, 1, patch_load_u32 |
1730 | load_u32_unaligned 0, 1 |
1731 | |
1732 | execute_load_gamepakA_u32u1: |
1733 | translate_region_gamepak_align32 10, 2, 1, patch_load_u32 |
1734 | load_u32_unaligned 0, 1 |
1735 | |
1736 | execute_load_gamepakB_u32u1: |
1737 | translate_region_gamepak_align32 11, 2, 1, patch_load_u32 |
1738 | load_u32_unaligned 0, 1 |
1739 | |
1740 | execute_load_gamepakC_u32u1: |
1741 | translate_region_gamepak_align32 12, 2, 1, patch_load_u32 |
1742 | load_u32_unaligned 0, 1 |
1743 | |
1744 | execute_load_eeprom_u32u1: |
1745 | eeprom_load_align32 2, 1, patch_load_u32 |
1746 | |
1747 | execute_load_backup_u32u1: |
1748 | backup_load_align32 2, 1, patch_load_u32 |
1749 | ror $2, $2, 8 # rotate value by 8bits |
1750 | |
1751 | execute_load_open_u32u1: |
1752 | open_load32_align32 2, 1, patch_load_u32 |
1753 | ror $2, $2, 8 # rotate value by 8bits |
1754 | |
1755 | |
1756 | # Unsigned unaligned (by 2) 32bit load handlers |
1757 | |
1758 | execute_load_bios_u32u2: |
1759 | region_check_align 0, 2, 2, patch_load_u32 |
1760 | srl $2, $4, 14 # check if address is in BIOS region |
1761 | bne $2, $0, 2f # if not, perform open read |
1762 | srl $1, $5, 14 # check if PC is in BIOS region |
1763 | bne $1, $0, 1f # if not, perform BIOS protected read |
1764 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1765 | |
1766 | andi $4, $4, 0x3FFC # generate offset |
1767 | addu $2, $2, $4 |
1768 | load_u32_unaligned bios_rom, 2 |
1769 | |
1770 | 1: |
1771 | lui $2, %hi(bios_read_protect) # generate upper address |
1772 | load_u32_unaligned bios_read_protect, 2 |
1773 | |
1774 | 2: |
1775 | open_load32_core |
1776 | ror $2, $2, 16 |
1777 | |
1778 | execute_load_ewram_u32u2: |
1779 | translate_region_ewram_load_align32 2, 2, patch_load_u32 |
1780 | load_u32_unaligned (ewram + 0x8000), 2 |
1781 | |
1782 | execute_load_iwram_u32u2: |
1783 | translate_region_align 3, 2, 2, patch_load_u32, (iwram + 0x8000), 0x7FFC |
1784 | load_u32_unaligned (iwram + 0x8000), 2 |
1785 | |
1786 | execute_load_io_u32u2: |
1787 | translate_region_align 4, 2, 2, patch_load_u32, io_registers, 0x3FC |
1788 | load_u32_unaligned io_registers, 2 |
1789 | |
1790 | execute_load_palette_u32u2: |
1791 | translate_region_align 5, 2, 2, patch_load_u32, palette_ram, 0x3FC |
1792 | load_u32_unaligned palette_ram, 2 |
1793 | |
1794 | execute_load_vram_u32u2: |
1795 | translate_region_vram_load_align32 2, 2, patch_load_u32 |
1796 | load_u32_unaligned vram, 2 |
1797 | |
1798 | execute_load_oam_u32u2: |
1799 | translate_region_align 7, 2, 2, patch_load_u32, oam_ram, 0x3FC |
1800 | load_u32_unaligned oam_ram, 2 |
1801 | |
1802 | execute_load_gamepak8_u32u2: |
1803 | translate_region_gamepak_align32 8, 2, 2, patch_load_u32 |
1804 | load_u32_unaligned 0, 2 |
1805 | |
1806 | execute_load_gamepak9_u32u2: |
1807 | translate_region_gamepak_align32 9, 2, 2, patch_load_u32 |
1808 | load_u32_unaligned 0, 2 |
1809 | |
1810 | execute_load_gamepakA_u32u2: |
1811 | translate_region_gamepak_align32 10, 2, 2, patch_load_u32 |
1812 | load_u32_unaligned 0, 2 |
1813 | |
1814 | execute_load_gamepakB_u32u2: |
1815 | translate_region_gamepak_align32 11, 2, 2, patch_load_u32 |
1816 | load_u32_unaligned 0, 2 |
1817 | |
1818 | execute_load_gamepakC_u32u2: |
1819 | translate_region_gamepak_align32 12, 2, 2, patch_load_u32 |
1820 | load_u32_unaligned 0, 2 |
1821 | |
1822 | execute_load_eeprom_u32u2: |
1823 | eeprom_load_align32 2, 2, patch_load_u32 |
1824 | |
1825 | execute_load_backup_u32u2: |
1826 | backup_load_align32 2, 2, patch_load_u32 |
1827 | ror $2, $2, 16 # rotate value by 16bits |
1828 | |
1829 | execute_load_open_u32u2: |
1830 | open_load32_align32 2, 2, patch_load_u32 |
1831 | ror $2, $2, 16 # rotate value by 16bits |
1832 | |
1833 | # Unsigned unaligned (by 1) 32bit load handlers |
1834 | |
1835 | execute_load_bios_u32u3: |
1836 | region_check_align 0, 2, 3, patch_load_u32 |
1837 | srl $2, $4, 14 # check if address is in BIOS region |
1838 | bne $2, $0, 2f # if not, perform open read |
1839 | srl $1, $5, 14 # check if PC is in BIOS region |
1840 | bne $1, $0, 1f # if not, perform BIOS protected read |
1841 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1842 | |
1843 | andi $4, $4, 0x3FFC # generate offset |
1844 | addu $2, $2, $4 |
1845 | load_u32_unaligned bios_rom, 3 |
1846 | |
1847 | 1: |
1848 | lui $2, %hi(bios_read_protect) # generate upper address |
1849 | load_u32_unaligned bios_read_protect, 3 |
1850 | |
1851 | 2: |
1852 | open_load32_core |
1853 | ror $2, $2, 24 |
1854 | |
1855 | execute_load_ewram_u32u3: |
1856 | translate_region_ewram_load_align32 2, 3, patch_load_u32 |
1857 | load_u32_unaligned (ewram + 0x8000), 3 |
1858 | |
1859 | execute_load_iwram_u32u3: |
1860 | translate_region_align 3, 2, 3, patch_load_u32, (iwram + 0x8000), 0x7FFC |
1861 | load_u32_unaligned (iwram + 0x8000), 3 |
1862 | |
1863 | execute_load_io_u32u3: |
1864 | translate_region_align 4, 2, 3, patch_load_u32, io_registers, 0x3FC |
1865 | load_u32_unaligned io_registers, 3 |
1866 | |
1867 | execute_load_palette_u32u3: |
1868 | translate_region_align 5, 2, 3, patch_load_u32, palette_ram, 0x3FC |
1869 | load_u32_unaligned palette_ram, 3 |
1870 | |
1871 | execute_load_vram_u32u3: |
1872 | translate_region_vram_load_align32 2, 3, patch_load_u32 |
1873 | load_u32_unaligned vram, 3 |
1874 | |
1875 | execute_load_oam_u32u3: |
1876 | translate_region_align 7, 2, 3, patch_load_u32, oam_ram, 0x3FC |
1877 | load_u32_unaligned oam_ram, 3 |
1878 | |
1879 | execute_load_gamepak8_u32u3: |
1880 | translate_region_gamepak_align32 8, 2, 3, patch_load_u32 |
1881 | load_u32_unaligned 0, 3 |
1882 | |
1883 | execute_load_gamepak9_u32u3: |
1884 | translate_region_gamepak_align32 9, 2, 3, patch_load_u32 |
1885 | load_u32_unaligned 0, 3 |
1886 | |
1887 | execute_load_gamepakA_u32u3: |
1888 | translate_region_gamepak_align32 10, 2, 3, patch_load_u32 |
1889 | load_u32_unaligned 0, 3 |
1890 | |
1891 | execute_load_gamepakB_u32u3: |
1892 | translate_region_gamepak_align32 11, 2, 3, patch_load_u32 |
1893 | load_u32_unaligned 0, 3 |
1894 | |
1895 | execute_load_gamepakC_u32u3: |
1896 | translate_region_gamepak_align32 12, 2, 3, patch_load_u32 |
1897 | load_u32_unaligned 0, 3 |
1898 | |
1899 | execute_load_eeprom_u32u3: |
1900 | eeprom_load_align32 2, 3, patch_load_u32 |
1901 | |
1902 | execute_load_backup_u32u3: |
1903 | backup_load_align32 2, 3, patch_load_u32 |
1904 | ror $2, $2, 24 # rotate value by 24bits |
1905 | |
1906 | execute_load_open_u32u3: |
1907 | open_load32_align32 2, 3, patch_load_u32 |
1908 | ror $2, $2, 24 # rotate value by 24bits |
1909 | |
1910 | |
1911 | load_u32_ftable: |
1912 | .long execute_load_bios_u32 # 0x00 BIOS |
1913 | .long execute_load_open_u32 # 0x01 open address |
1914 | .long execute_load_ewram_u32 # 0x02 EWRAM |
1915 | .long execute_load_iwram_u32 # 0x03 IWRAM |
1916 | .long execute_load_io_u32 # 0x04 I/O registers |
1917 | .long execute_load_palette_u32 # 0x05 Palette RAM |
1918 | .long execute_load_vram_u32 # 0x06 VRAM |
1919 | .long execute_load_oam_u32 # 0x07 OAM RAM |
1920 | .long execute_load_gamepak8_u32 # 0x08 gamepak |
1921 | .long execute_load_gamepak9_u32 # 0x09 gamepak |
1922 | .long execute_load_gamepakA_u32 # 0x0A gamepak |
1923 | .long execute_load_gamepakB_u32 # 0x0B gamepak |
1924 | .long execute_load_gamepakC_u32 # 0x0C gamepak |
1925 | |
1926 | .long execute_load_eeprom_u32 # 0x0D gamepak/eeprom |
1927 | .long execute_load_backup_u32 # 0x0E Flash ROM/SRAM |
1928 | .long execute_load_open_u32 # 0x0F open |
1929 | |
1930 | .long execute_load_bios_u32u1 # 0x00 BIOS unaligned (1b) |
1931 | .long execute_load_open_u32u1 # 0x01 open address unaligned (1b) |
1932 | .long execute_load_ewram_u32u1 # 0x02 EWRAM unaligned (1b) |
1933 | .long execute_load_iwram_u32u1 # 0x03 IWRAM unaligned (1b) |
1934 | .long execute_load_io_u32u1 # 0x04 I/O registers unaligned (1b) |
1935 | .long execute_load_palette_u32u1 # 0x05 Palette RAM unaligned (1b) |
1936 | .long execute_load_vram_u32u1 # 0x06 VRAM unaligned (1b) |
1937 | .long execute_load_oam_u32u1 # 0x07 OAM RAM unaligned (1b) |
1938 | .long execute_load_gamepak8_u32u1 # 0x08 gamepak unaligned (1b) |
1939 | .long execute_load_gamepak9_u32u1 # 0x09 gamepak unaligned (1b) |
1940 | .long execute_load_gamepakA_u32u1 # 0x0A gamepak unaligned (1b) |
1941 | .long execute_load_gamepakB_u32u1 # 0x0B gamepak unaligned (1b) |
1942 | .long execute_load_gamepakC_u32u1 # 0x0C gamepak unaligned (1b) |
1943 | .long execute_load_eeprom_u32u1 # 0x0D gamepak/eeprom unaligned (1b) |
1944 | .long execute_load_backup_u32u1 # 0x0E Flash ROM/SRAM unaligned (1b) |
1945 | .long execute_load_open_u32u1 # 0x0F open unaligned (1b) |
1946 | |
1947 | .long execute_load_bios_u32u2 # 0x00 BIOS unaligned (2b) |
1948 | .long execute_load_open_u32u2 # 0x01 open address unaligned (2b) |
1949 | .long execute_load_ewram_u32u2 # 0x02 EWRAM unaligned (2b) |
1950 | .long execute_load_iwram_u32u2 # 0x03 IWRAM unaligned (2b) |
1951 | .long execute_load_io_u32u2 # 0x04 I/O registers unaligned (2b) |
1952 | .long execute_load_palette_u32u2 # 0x05 Palette RAM unaligned (2b) |
1953 | .long execute_load_vram_u32u2 # 0x06 VRAM unaligned (2b) |
1954 | .long execute_load_oam_u32u2 # 0x07 OAM RAM unaligned (2b) |
1955 | .long execute_load_gamepak8_u32u2 # 0x08 gamepak unaligned (2b) |
1956 | .long execute_load_gamepak9_u32u2 # 0x09 gamepak unaligned (2b) |
1957 | .long execute_load_gamepakA_u32u2 # 0x0A gamepak unaligned (2b) |
1958 | .long execute_load_gamepakB_u32u2 # 0x0B gamepak unaligned (2b) |
1959 | .long execute_load_gamepakC_u32u2 # 0x0C gamepak unaligned (2b) |
1960 | .long execute_load_eeprom_u32u2 # 0x0D gamepak/eeprom unaligned (2b) |
1961 | .long execute_load_backup_u32u2 # 0x0E Flash ROM/SRAM unaligned (2b) |
1962 | .long execute_load_open_u32u2 # 0x0F open unaligned (2b) |
1963 | |
1964 | .long execute_load_bios_u32u3 # 0x00 BIOS unaligned (3b) |
1965 | .long execute_load_open_u32u3 # 0x01 open address unaligned (3b) |
1966 | .long execute_load_ewram_u32u3 # 0x02 EWRAM unaligned (3b) |
1967 | .long execute_load_iwram_u32u3 # 0x03 IWRAM unaligned (3b) |
1968 | .long execute_load_io_u32u3 # 0x04 I/O registers unaligned (3b) |
1969 | .long execute_load_palette_u32u3 # 0x05 Palette RAM unaligned (3b) |
1970 | .long execute_load_vram_u32u3 # 0x06 VRAM unaligned (3b) |
1971 | .long execute_load_oam_u32u3 # 0x07 OAM RAM unaligned (3b) |
1972 | .long execute_load_gamepak8_u32u3 # 0x08 gamepak unaligned (3b) |
1973 | .long execute_load_gamepak9_u32u3 # 0x09 gamepak unaligned (3b) |
1974 | .long execute_load_gamepakA_u32u3 # 0x0A gamepak unaligned (3b) |
1975 | .long execute_load_gamepakB_u32u3 # 0x0B gamepak unaligned (3b) |
1976 | .long execute_load_gamepakC_u32u3 # 0x0C gamepak unaligned (3b) |
1977 | .long execute_load_eeprom_u32u3 # 0x0D gamepak/eeprom unaligned (3b) |
1978 | .long execute_load_backup_u32u3 # 0x0E Flash ROM/SRAM unaligned (3b) |
1979 | .long execute_load_open_u32u3 # 0x0F open unaligned (3b) |
1980 | |
1981 | patch_load_u32: |
1982 | patch_handler_align load_u32_ftable, 2 |
1983 | |
1984 | |
1985 | |
1986 | # Unsigned always aligned 32bit load handlers |
1987 | |
1988 | execute_load_bios_u32a: |
1989 | region_check 0, patch_load_u32a |
1990 | srl $2, $4, 14 # check if address is in BIOS region |
1991 | bne $2, $0, 2f # if not, perform open read |
1992 | srl $1, $5, 14 # check if PC is in BIOS region |
1993 | bne $1, $0, 1f # if not, perform BIOS protected read |
1994 | lui $2, %hi(bios_rom) # generate upper address (delay) |
1995 | |
1996 | andi $4, $4, 0x3FFF # generate offset |
1997 | addu $2, $2, $4 |
1998 | load_u32 bios_rom |
1999 | |
2000 | 1: |
2001 | lui $2, %hi(bios_read_protect) # generate upper address |
2002 | load_u32 bios_read_protect |
2003 | |
2004 | 2: |
2005 | open_load32_a |
2006 | nop |
2007 | |
2008 | execute_load_ewram_u32a: |
2009 | translate_region_ewram patch_load_u32a |
2010 | load_u32 (ewram + 0x8000) |
2011 | |
2012 | execute_aligned_load32: |
2013 | execute_load_iwram_u32a: |
2014 | translate_region 3, patch_load_u32a, (iwram + 0x8000), 0x7FFF |
2015 | load_u32 (iwram + 0x8000) |
2016 | |
2017 | execute_load_io_u32a: |
2018 | translate_region 4, patch_load_u32a, io_registers, 0x3FF |
2019 | load_u32 io_registers |
2020 | |
2021 | execute_load_palette_u32a: |
2022 | translate_region 5, patch_load_u32a, palette_ram, 0x3FF |
2023 | load_u32 palette_ram |
2024 | |
2025 | execute_load_vram_u32a: |
2026 | translate_region_vram patch_load_u32a |
2027 | load_u32 vram |
2028 | |
2029 | execute_load_oam_u32a: |
2030 | translate_region 7, patch_load_u32a, oam_ram, 0x3FF |
2031 | load_u32 oam_ram |
2032 | |
2033 | execute_load_gamepak8_u32a: |
2034 | translate_region_gamepak_a 8, patch_load_u32a |
2035 | load_u32 0 |
2036 | |
2037 | execute_load_gamepak9_u32a: |
2038 | translate_region_gamepak_a 9, patch_load_u32a |
2039 | load_u32 0 |
2040 | |
2041 | execute_load_gamepakA_u32a: |
2042 | translate_region_gamepak_a 10, patch_load_u32a |
2043 | load_u32 0 |
2044 | |
2045 | execute_load_gamepakB_u32a: |
2046 | translate_region_gamepak_a 11, patch_load_u32a |
2047 | load_u32 0 |
2048 | |
2049 | execute_load_gamepakC_u32a: |
2050 | translate_region_gamepak_a 12, patch_load_u32a |
2051 | load_u32 0 |
2052 | |
2053 | execute_load_eeprom_u32a: |
2054 | eeprom_load_a patch_load_u32a |
2055 | |
2056 | execute_load_backup_u32a: |
2057 | backup_load_a patch_load_u32a |
2058 | nop |
2059 | |
2060 | execute_load_open_u32a: |
2061 | open_load32_a patch_load_u32a |
2062 | |
2063 | load_u32a_ftable: |
2064 | .long execute_load_bios_u32a # 0x00 BIOS unaligned (3b) |
2065 | .long execute_load_open_u32a # 0x01 open address unaligned (3b) |
2066 | .long execute_load_ewram_u32a # 0x02 EWRAM unaligned (3b) |
2067 | .long execute_load_iwram_u32a # 0x03 IWRAM unaligned (3b) |
2068 | .long execute_load_io_u32a # 0x04 I/O registers unaligned (3b) |
2069 | .long execute_load_palette_u32a # 0x05 Palette RAM unaligned (3b) |
2070 | .long execute_load_vram_u32a # 0x06 VRAM unaligned (3b) |
2071 | .long execute_load_oam_u32a # 0x07 OAM RAM unaligned (3b) |
2072 | .long execute_load_gamepak8_u32a # 0x08 gamepak unaligned (3b) |
2073 | .long execute_load_gamepak9_u32a # 0x09 gamepak unaligned (3b) |
2074 | .long execute_load_gamepakA_u32a # 0x0A gamepak unaligned (3b) |
2075 | .long execute_load_gamepakB_u32a # 0x0B gamepak unaligned (3b) |
2076 | .long execute_load_gamepakC_u32a # 0x0C gamepak unaligned (3b) |
2077 | .long execute_load_eeprom_u32a # 0x0D gamepak/eeprom unaligned (3b) |
2078 | .long execute_load_backup_u32a # 0x0E Flash ROM/SRAM unaligned (3b) |
2079 | .long execute_load_open_u32a # 0x0F open unaligned (3b) |
2080 | |
2081 | patch_load_u32a: |
2082 | patch_handler load_u32a_ftable, 1 |
2083 | |
2084 | |
2085 | # Unsigned 8bit store handlers |
2086 | |
2087 | execute_store_ignore0_u8: |
2088 | ignore_region 0, patch_store_u8 |
2089 | |
2090 | execute_store_ignore1_u8: |
2091 | ignore_region 1, patch_store_u8 |
2092 | |
2093 | execute_store_ewram_u8: |
2094 | translate_region_ewram patch_store_u8 |
2095 | store_u8_smc (ewram + 0x8000) |
2096 | |
2097 | execute_store_u8: |
2098 | execute_store_iwram_u8: |
2099 | translate_region 3, patch_store_u8, (iwram + 0x8000), 0x7FFF |
2100 | store_u8_smc (iwram + 0x8000) |
2101 | |
2102 | execute_store_io_u8: |
2103 | region_check 4, patch_store_u8 |
2104 | andi $5, $5, 0xFF # make value 8bit |
2105 | andi $4, $4, 0x3FF # wrap around address |
2106 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2107 | sw $ra, ($sp) |
2108 | |
2109 | save_registers |
2110 | jal write_io_register8 # write the value out |
2111 | sw $6, REG_PC($16) # save the PC (delay slot) |
2112 | j write_io_epilogue # handle any state changes |
2113 | nop |
2114 | |
2115 | execute_store_palette_u8: |
2116 | region_check 5, patch_store_u8 |
2117 | lui $2, %hi(palette_ram) # start loading palette_ram address (delay) |
2118 | ins $5, $5, 8, 8 # double value |
2119 | andi $4, $4, 0x3FE # align palette address |
2120 | addu $2, $2, $4 |
2121 | sh $5, %lo(palette_ram)($2) # palette_ram[address] = value |
2122 | sll $1, $5, 1 # make green 6bits |
2123 | ins $1, $0, 0, 6 # make bottom bit 0 |
2124 | ins $1, $5, 0, 5 # insert red channel into $1 |
2125 | lui $2, %hi(palette_ram_converted) |
2126 | addu $2, $2, $4 |
2127 | jr $ra # return |
2128 | sh $1, %lo(palette_ram_converted)($2) |
2129 | |
2130 | execute_store_vram_u8: |
2131 | translate_region_vram_store_align16 patch_store_u8 |
2132 | store_u8_double vram |
2133 | |
2134 | execute_store_oam_u8: |
2135 | translate_region 7, patch_store_u8, oam_ram, 0x3FE |
2136 | lui $1, %hi(oam_update) # write non-zero to oam_update |
2137 | sw $1, %lo(oam_update)($1) # cheap, but this is non-zero |
2138 | store_u8_double oam_ram |
2139 | |
2140 | execute_store_ignore8_u8: |
2141 | ignore_region 8, patch_store_u8 |
2142 | |
2143 | execute_store_ignore9_u8: |
2144 | ignore_region 9, patch_store_u8 |
2145 | |
2146 | execute_store_ignoreA_u8: |
2147 | ignore_region 10, patch_store_u8 |
2148 | |
2149 | execute_store_ignoreB_u8: |
2150 | ignore_region 11, patch_store_u8 |
2151 | |
2152 | execute_store_ignoreC_u8: |
2153 | ignore_region 12, patch_store_u8 |
2154 | |
2155 | execute_store_eeprom_u8: |
2156 | store_function write_eeprom, 13, patch_store_u8, 0x3FF |
2157 | |
2158 | execute_store_backup_u8: |
2159 | store_function write_backup, 14, patch_store_u8, 0xFFFF |
2160 | |
2161 | execute_store_ignoreF_u8: |
2162 | ignore_high patch_store_u8 |
2163 | |
2164 | store_u8_ftable: |
2165 | .long execute_store_ignore0_u8 # 0x00 BIOS |
2166 | .long execute_store_ignore1_u8 # 0x01 open address |
2167 | .long execute_store_ewram_u8 # 0x02 EWRAM |
2168 | .long execute_store_iwram_u8 # 0x03 IWRAM |
2169 | .long execute_store_io_u8 # 0x04 I/O registers |
2170 | .long execute_store_palette_u8 # 0x05 Palette RAM |
2171 | .long execute_store_vram_u8 # 0x06 VRAM |
2172 | .long execute_store_oam_u8 # 0x07 OAM RAM |
2173 | .long execute_store_ignore8_u8 # 0x08 gamepak |
2174 | .long execute_store_ignore9_u8 # 0x09 gamepak |
2175 | .long execute_store_ignoreA_u8 # 0x0A gamepak |
2176 | .long execute_store_ignoreB_u8 # 0x0B gamepak |
2177 | .long execute_store_ignoreC_u8 # 0x0C gamepak |
2178 | .long execute_store_eeprom_u8 # 0x0D gamepak/eeprom |
2179 | .long execute_store_backup_u8 # 0x0E Flash ROM/SRAM |
2180 | .long execute_store_ignoreF_u8 # 0x0F open address |
2181 | |
2182 | patch_store_u8: |
2183 | patch_handler store_u8_ftable, 0x0F |
2184 | |
2185 | |
2186 | # Unsigned 16bit store handlers |
2187 | |
2188 | execute_store_ignore0_u16: |
2189 | ignore_region 0, patch_store_u16 |
2190 | |
2191 | execute_store_ignore1_u16: |
2192 | ignore_region 1, patch_store_u16 |
2193 | |
2194 | execute_store_ewram_u16: |
2195 | translate_region_ewram_store_align16 patch_store_u16 |
2196 | store_u16_smc (ewram + 0x8000) |
2197 | |
2198 | execute_store_u16: |
2199 | execute_store_iwram_u16: |
2200 | translate_region 3, patch_store_u16, (iwram + 0x8000), 0x7FFE |
2201 | store_u16_smc (iwram + 0x8000) |
2202 | |
2203 | execute_store_io_u16: |
2204 | region_check 4, patch_store_u16 |
2205 | andi $5, $5, 0xFFFF # make value 16bit |
2206 | andi $4, $4, 0x3FE # wrap around/align address |
2207 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2208 | sw $ra, ($sp) |
2209 | |
2210 | save_registers |
2211 | jal write_io_register16 # write the value out |
2212 | sw $6, REG_PC($16) # save the PC (delay slot) |
2213 | j write_io_epilogue # handle any state changes |
2214 | nop |
2215 | |
2216 | execute_store_palette_u16: |
2217 | region_check 5, patch_store_u16 |
2218 | lui $2, %hi(palette_ram) # start loading palette_ram address (delay) |
2219 | andi $4, $4, 0x3FE # wrap/align palette address |
2220 | addu $2, $2, $4 |
2221 | sh $5, %lo(palette_ram)($2) # palette_ram[address] = value |
2222 | sll $1, $5, 1 # make green 6bits |
2223 | ins $1, $0, 0, 6 # make bottom bit 0 |
2224 | ins $1, $5, 0, 5 # insert red channel into $1 |
2225 | lui $2, %hi(palette_ram_converted) |
2226 | addu $2, $2, $4 |
2227 | jr $ra # return |
2228 | sh $1, %lo(palette_ram_converted)($2) |
2229 | |
2230 | execute_store_vram_u16: |
2231 | translate_region_vram_store_align16 patch_store_u16 |
2232 | store_u16 vram |
2233 | |
2234 | execute_store_oam_u16: |
2235 | translate_region 7, patch_store_u16, oam_ram, 0x3FE |
2236 | lui $1, %hi(oam_update) # write non-zero to oam_update |
2237 | sw $1, %lo(oam_update)($1) # cheap, but this is non-zero |
2238 | store_u16 oam_ram |
2239 | |
2240 | execute_store_rtc_u16: |
2241 | store_function write_rtc, 8, patch_store_u16, 0xFE |
2242 | |
2243 | execute_store_ignore9_u16: |
2244 | ignore_region 9, patch_store_u16 |
2245 | |
2246 | execute_store_ignoreA_u16: |
2247 | ignore_region 10, patch_store_u16 |
2248 | |
2249 | execute_store_ignoreB_u16: |
2250 | ignore_region 11, patch_store_u16 |
2251 | |
2252 | execute_store_ignoreC_u16: |
2253 | ignore_region 12, patch_store_u16 |
2254 | |
2255 | execute_store_eeprom_u16: |
2256 | store_function write_eeprom, 13, patch_store_u16, 0x3FE |
2257 | |
2258 | execute_store_ignoreE_u16: |
2259 | ignore_region 14, patch_store_u16 |
2260 | |
2261 | execute_store_ignoreF_u16: |
2262 | ignore_high patch_store_u16 |
2263 | |
2264 | store_u16_ftable: |
2265 | .long execute_store_ignore0_u16 # 0x00 BIOS |
2266 | .long execute_store_ignore1_u16 # 0x01 open address |
2267 | .long execute_store_ewram_u16 # 0x02 EWRAM |
2268 | .long execute_store_iwram_u16 # 0x03 IWRAM |
2269 | .long execute_store_io_u16 # 0x04 I/O registers |
2270 | .long execute_store_palette_u16 # 0x05 Palette RAM |
2271 | .long execute_store_vram_u16 # 0x06 VRAM |
2272 | .long execute_store_oam_u16 # 0x07 OAM RAM |
2273 | .long execute_store_rtc_u16 # 0x08 gamepak |
2274 | .long execute_store_ignore9_u16 # 0x09 gamepak |
2275 | .long execute_store_ignoreA_u16 # 0x0A gamepak |
2276 | .long execute_store_ignoreB_u16 # 0x0B gamepak |
2277 | .long execute_store_ignoreC_u16 # 0x0C gamepak |
2278 | .long execute_store_eeprom_u16 # 0x0D gamepak/eeprom |
2279 | .long execute_store_ignoreE_u16 # 0x0E Flash ROM/SRAM |
2280 | .long execute_store_ignoreF_u16 # 0x0F open address |
2281 | |
2282 | |
2283 | patch_store_u16: |
2284 | patch_handler store_u16_ftable, 0x0F |
2285 | |
2286 | |
2287 | |
2288 | |
2289 | # Unsigned 32bit store handlers |
2290 | |
2291 | execute_store_ignore0_u32: |
2292 | ignore_region 0, patch_store_u32 |
2293 | |
2294 | execute_store_ignore1_u32: |
2295 | ignore_region 1, patch_store_u32 |
2296 | |
2297 | execute_store_ewram_u32: |
2298 | translate_region_ewram_store_align32 patch_store_u32 |
2299 | store_u32_smc (ewram + 0x8000) |
2300 | |
2301 | execute_store_u32: |
2302 | execute_store_iwram_u32: |
2303 | translate_region 3, patch_store_u32, (iwram + 0x8000), 0x7FFC |
2304 | store_u32_smc (iwram + 0x8000) |
2305 | |
2306 | execute_store_io_u32: |
2307 | region_check 4, patch_store_u32 |
2308 | nop |
2309 | andi $4, $4, 0x3FC # wrap around/align address |
2310 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2311 | sw $ra, ($sp) |
2312 | |
2313 | save_registers |
2314 | jal write_io_register32 # write the value out |
2315 | sw $6, REG_PC($16) # save the PC (delay slot) |
2316 | j write_io_epilogue # handle any state changes |
2317 | nop |
2318 | |
2319 | execute_store_palette_u32: |
2320 | region_check 5, patch_store_u32 |
2321 | lui $2, %hi(palette_ram) # start loading palette_ram address (delay) |
2322 | andi $4, $4, 0x3FC # wrap/align palette address |
2323 | addu $2, $2, $4 |
2324 | sw $5, %lo(palette_ram)($2) # palette_ram[address] = value |
2325 | |
2326 | sll $1, $5, 1 # make green 6bits |
2327 | ins $1, $0, 0, 6 # make bottom bit 0 |
2328 | ins $1, $5, 0, 5 # insert red channel into $1 |
2329 | lui $2, %hi(palette_ram_converted) |
2330 | addu $2, $2, $4 |
2331 | addiu $2, $2, %lo(palette_ram_converted) |
2332 | sh $1, ($2) |
2333 | |
2334 | srl $5, $5, 16 # shift down to next palette value |
2335 | sll $1, $5, 1 # make green 6bits |
2336 | ins $1, $0, 0, 6 # make bottom bit 0 |
2337 | ins $1, $5, 0, 5 # insert red channel into $1 |
2338 | |
2339 | jr $ra # return |
2340 | sh $1, 2($2) |
2341 | |
2342 | execute_store_vram_u32: |
2343 | translate_region_vram_store_align32 patch_store_u32 |
2344 | store_u32 vram |
2345 | |
2346 | execute_store_oam_u32: |
2347 | translate_region 7, patch_store_u32, oam_ram, 0x3FC |
2348 | lui $1, %hi(oam_update) # write non-zero to oam_update |
2349 | sw $1, %lo(oam_update)($1) # cheap, but this is non-zero |
2350 | store_u32 oam_ram |
2351 | |
2352 | execute_store_ignore8_u32: |
2353 | ignore_region 8, patch_store_u32 |
2354 | |
2355 | execute_store_ignore9_u32: |
2356 | ignore_region 9, patch_store_u32 |
2357 | |
2358 | execute_store_ignoreA_u32: |
2359 | ignore_region 10, patch_store_u32 |
2360 | |
2361 | execute_store_ignoreB_u32: |
2362 | ignore_region 11, patch_store_u32 |
2363 | |
2364 | execute_store_ignoreC_u32: |
2365 | ignore_region 12, patch_store_u32 |
2366 | |
2367 | execute_store_eeprom_u32: |
2368 | store_function write_eeprom, 13, patch_store_u32, 0x3FC |
2369 | |
2370 | execute_store_ignoreE_u32: |
2371 | ignore_region 14, patch_store_u32 |
2372 | |
2373 | execute_store_ignoreF_u32: |
2374 | ignore_high patch_store_u32 |
2375 | |
2376 | store_u32_ftable: |
2377 | .long execute_store_ignore0_u32 # 0x00 BIOS |
2378 | .long execute_store_ignore1_u32 # 0x01 open address |
2379 | .long execute_store_ewram_u32 # 0x02 EWRAM |
2380 | .long execute_store_iwram_u32 # 0x03 IWRAM |
2381 | .long execute_store_io_u32 # 0x04 I/O registers |
2382 | .long execute_store_palette_u32 # 0x05 Palette RAM |
2383 | .long execute_store_vram_u32 # 0x06 VRAM |
2384 | .long execute_store_oam_u32 # 0x07 OAM RAM |
2385 | .long execute_store_ignore8_u32 # 0x08 gamepak |
2386 | .long execute_store_ignore9_u32 # 0x09 gamepak |
2387 | .long execute_store_ignoreA_u32 # 0x0A gamepak |
2388 | .long execute_store_ignoreB_u32 # 0x0B gamepak |
2389 | .long execute_store_ignoreC_u32 # 0x0C gamepak |
2390 | .long execute_store_eeprom_u32 # 0x0D gamepak/eeprom |
2391 | .long execute_store_ignoreE_u32 # 0x0E Flash ROM/SRAM |
2392 | .long execute_store_ignoreF_u32 # 0x0F open address |
2393 | |
2394 | |
2395 | patch_store_u32: |
2396 | patch_handler store_u32_ftable, 0x0F |
2397 | |
2398 | |
2399 | |
2400 | # Unsigned always aligned, a2 safe 32bit store handlers |
2401 | |
2402 | execute_store_ignore0_u32a: |
2403 | ignore_region 0, patch_store_u32a |
2404 | |
2405 | execute_store_ignore1_u32a: |
2406 | ignore_region 1, patch_store_u32a |
2407 | |
2408 | execute_store_ewram_u32a: |
2409 | translate_region_ewram_store_align32 patch_store_u32a |
2410 | store_u32 (ewram + 0x8000) |
2411 | |
2412 | execute_aligned_store32: |
2413 | execute_store_iwram_u32a: |
2414 | translate_region 3, patch_store_u32a, (iwram + 0x8000), 0x7FFC |
2415 | store_u32 (iwram + 0x8000) |
2416 | |
2417 | execute_store_io_u32a: |
2418 | region_check 4, patch_store_u32a |
2419 | nop |
2420 | sw $6, REG_SAVE($16) # save a2 |
2421 | sw $ra, REG_SAVE2($16) # save ra |
2422 | |
2423 | andi $4, $4, 0x3FC # wrap around/align address |
2424 | |
2425 | save_registers |
2426 | jal write_io_register32 # write the value out |
2427 | nop |
2428 | |
2429 | restore_registers |
2430 | |
2431 | lw $ra, REG_SAVE2($16) # restore ra |
2432 | jr $ra |
2433 | lw $6, REG_SAVE($16) # restore a2 |
2434 | |
2435 | execute_store_palette_u32a: |
2436 | region_check 5, patch_store_u32a |
2437 | lui $2, %hi(palette_ram) # start loading palette_ram address (delay) |
2438 | andi $4, $4, 0x3FC # wrap/align palette address |
2439 | addu $2, $2, $4 |
2440 | sw $5, %lo(palette_ram)($2) # palette_ram[address] = value |
2441 | |
2442 | sll $1, $5, 1 # make green 6bits |
2443 | ins $1, $0, 0, 6 # make bottom bit 0 |
2444 | ins $1, $5, 0, 5 # insert red channel into $1 |
2445 | lui $2, %hi(palette_ram_converted) |
2446 | addu $2, $2, $4 |
2447 | addiu $2, $2, %lo(palette_ram_converted) |
2448 | sh $1, ($2) |
2449 | |
2450 | srl $5, $5, 16 # shift down to next palette value |
2451 | sll $1, $5, 1 # make green 6bits |
2452 | ins $1, $0, 0, 6 # make bottom bit 0 |
2453 | ins $1, $5, 0, 5 # insert red channel into $1 |
2454 | |
2455 | jr $ra # return |
2456 | sh $1, 2($2) |
2457 | |
2458 | execute_store_vram_u32a: |
2459 | translate_region_vram_store_align32 patch_store_u32a |
2460 | store_u32 vram |
2461 | |
2462 | execute_store_oam_u32a: |
2463 | translate_region 7, patch_store_u32a, oam_ram, 0x3FC |
2464 | lui $1, %hi(oam_update) # write non-zero to oam_update |
2465 | sw $1, %lo(oam_update)($1) # cheap, but this is non-zero |
2466 | store_u32 oam_ram |
2467 | |
2468 | execute_store_ignore8_u32a: |
2469 | ignore_region 8, patch_store_u32a |
2470 | |
2471 | execute_store_ignore9_u32a: |
2472 | ignore_region 9, patch_store_u32a |
2473 | |
2474 | execute_store_ignoreA_u32a: |
2475 | ignore_region 10, patch_store_u32a |
2476 | |
2477 | execute_store_ignoreB_u32a: |
2478 | ignore_region 11, patch_store_u32a |
2479 | |
2480 | execute_store_ignoreC_u32a: |
2481 | ignore_region 12, patch_store_u32a |
2482 | |
2483 | execute_store_eeprom_u32a: |
2484 | store_function_a write_eeprom, 13, patch_store_u32a, 0x3FC |
2485 | |
2486 | execute_store_ignoreE_u32a: |
2487 | ignore_region 14, patch_store_u32a |
2488 | |
2489 | execute_store_ignoreF_u32a: |
2490 | ignore_high patch_store_u32a |
2491 | |
2492 | store_u32a_ftable: |
2493 | .long execute_store_ignore0_u32a# 0x00 BIOS |
2494 | .long execute_store_ignore1_u32a# 0x01 open address |
2495 | .long execute_store_ewram_u32a # 0x02 EWRAM |
2496 | .long execute_store_iwram_u32a # 0x03 IWRAM |
2497 | .long execute_store_io_u32a # 0x04 I/O registers |
2498 | .long execute_store_palette_u32a# 0x05 Palette RAM |
2499 | .long execute_store_vram_u32a # 0x06 VRAM |
2500 | .long execute_store_oam_u32a # 0x07 OAM RAM |
2501 | .long execute_store_ignore8_u32a# 0x08 gamepak |
2502 | .long execute_store_ignore9_u32a# 0x09 gamepak |
2503 | .long execute_store_ignoreA_u32a# 0x0A gamepak |
2504 | .long execute_store_ignoreB_u32a# 0x0B gamepak |
2505 | .long execute_store_ignoreC_u32a# 0x0C gamepak |
2506 | .long execute_store_eeprom_u32a # 0x0D gamepak/eeprom |
2507 | .long execute_store_ignoreE_u32a# 0x0E Flash ROM/SRAM |
2508 | .long execute_store_ignoreF_u32a# 0x0F open address |
2509 | |
2510 | patch_store_u32a: |
2511 | patch_handler store_u32a_ftable, 0x0F |
2512 | |
2513 | |
2514 | |
2515 | #execute_load_u8: |
2516 | execute_load_full_u8: |
2517 | srl $1, $4, 28 # check if the address is out of range |
2518 | bne $1, $0, ext_load_u8 # if it is, perform an extended read |
2519 | srl $2, $4, 15 # $1 = page number of address |
2520 | sll $2, $2, 2 # adjust to word index |
2521 | addu $2, $2, $16 # $1 = memory_map_read[address >> 15] |
2522 | lw $1, -32768($2) |
2523 | beq $1, $0, ext_load_u8 # if it's NULL perform an extended read |
2524 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2525 | addu $1, $1, $2 # add the memory map offset |
2526 | jr $ra # return |
2527 | lbu $2, ($1) # read the value |
2528 | |
2529 | ext_load_u8: |
2530 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2531 | sw $ra, ($sp) # store return address |
2532 | save_registers |
2533 | jal read_memory8 # read the value |
2534 | nop |
2535 | restore_registers |
2536 | lw $ra, ($sp) # restore return address |
2537 | jr $ra # return |
2538 | addiu $sp, $sp, 4 # fix stack (delay slot) |
2539 | |
2540 | #execute_load_s8: |
2541 | execute_load_full_s8: |
2542 | srl $1, $4, 28 # check if the address is out of range |
2543 | bne $1, $0, ext_load_s8 # if it is, perform an extended read |
2544 | srl $2, $4, 15 # $1 = page number of address |
2545 | sll $2, $2, 2 # adjust to word index |
2546 | addu $2, $2, $16 # $1 = memory_map_read[address >> 15] |
2547 | lw $1, -32768($2) |
2548 | beq $1, $0, ext_load_s8 # if it's NULL perform an extended read |
2549 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2550 | addu $1, $1, $2 # add the memory map offset |
2551 | jr $ra # return |
2552 | lb $2, ($1) # read the value |
2553 | |
2554 | ext_load_s8: |
2555 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2556 | sw $ra, ($sp) # store return address |
2557 | save_registers |
2558 | jal read_memory8 # read the value |
2559 | nop |
2560 | restore_registers |
2561 | seb $2, $2 # sign extend the read value |
2562 | lw $ra, ($sp) # restore return address |
2563 | jr $ra # return |
2564 | addiu $sp, $sp, 4 # fix stack (delay slot) |
2565 | |
2566 | #execute_load_u16: |
2567 | execute_load_full_u16: |
2568 | srl $1, $4, 28 # check if the address is out of range |
2569 | ins $1, $4, 4, 1 # or unaligned (bottom bit) |
2570 | bne $1, $0, ext_load_u16 # if it is, perform an extended read |
2571 | srl $2, $4, 15 # $1 = page number of address |
2572 | sll $2, $2, 2 # adjust to word index |
2573 | addu $2, $2, $16 # $1 = memory_map_read[address >> 15] |
2574 | lw $1, -32768($2) |
2575 | beq $1, $0, ext_load_u16 # if it's NULL perform an extended read |
2576 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2577 | addu $1, $1, $2 # add the memory map offset |
2578 | jr $ra # return |
2579 | lhu $2, ($1) # read the value |
2580 | |
2581 | ext_load_u16: |
2582 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2583 | sw $ra, ($sp) # store return address |
2584 | save_registers |
2585 | jal read_memory16 # read the value |
2586 | nop |
2587 | restore_registers |
2588 | lw $ra, ($sp) # restore return address |
2589 | jr $ra # return |
2590 | addiu $sp, $sp, 4 # fix stack (delay slot) |
2591 | |
2592 | #execute_load_s16: |
2593 | execute_load_full_s16: |
2594 | srl $1, $4, 28 # check if the address is out of range |
2595 | ins $1, $4, 4, 1 # or unaligned (bottom bit) |
2596 | bne $1, $0, ext_load_s16 # if it is, perform an extended read |
2597 | srl $2, $4, 15 # $1 = page number of address |
2598 | sll $2, $2, 2 # adjust to word index |
2599 | addu $2, $2, $16 # $1 = memory_map_read[address >> 15] |
2600 | lw $1, -32768($2) |
2601 | beq $1, $0, ext_load_s16 # if it's NULL perform an extended read |
2602 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2603 | addu $1, $1, $2 # add the memory map offset |
2604 | jr $ra # return |
2605 | lh $2, ($1) # read the value |
2606 | |
2607 | ext_load_s16: |
2608 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2609 | sw $ra, ($sp) # store return address |
2610 | save_registers |
2611 | jal read_memory16_signed # read the value |
2612 | nop |
2613 | restore_registers |
2614 | seh $2, $2 # sign extend the return value |
2615 | lw $ra, ($sp) # restore return address |
2616 | jr $ra # return |
2617 | addiu $sp, $sp, 4 # fix stack (delay slot) |
2618 | |
2619 | #execute_load_u32: |
2620 | execute_load_full_u32: |
2621 | srl $1, $4, 28 # check if the address is out of range |
2622 | ins $1, $4, 4, 2 # or unaligned (bottom two bits) |
2623 | bne $1, $0, ext_load_u32 # if it is, perform an extended read |
2624 | srl $2, $4, 15 # $1 = page number of address |
2625 | sll $2, $2, 2 # adjust to word index |
2626 | addu $2, $2, $16 # $1 = memory_map_read[address >> 15] |
2627 | lw $1, -32768($2) |
2628 | beq $1, $0, ext_load_u32 # if it's NULL perform an extended read |
2629 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2630 | addu $1, $1, $2 # add the memory map offset |
2631 | jr $ra # return |
2632 | lw $2, ($1) # read the value |
2633 | |
2634 | ext_load_u32: |
2635 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2636 | sw $ra, ($sp) # store return address |
2637 | save_registers |
2638 | jal read_memory32 # read the value |
2639 | nop |
2640 | restore_registers |
2641 | lw $ra, ($sp) # restore return address |
2642 | jr $ra # return |
2643 | addiu $sp, $sp, 4 # fix stack (delay slot) |
2644 | |
2645 | #execute_aligned_load32: |
2646 | srl $2, $4, 28 # check if the address is out of range |
2647 | bne $2, $0, ext_aligned_load32 # if it is, perform an extended load |
2648 | srl $1, $4, 15 # $1 = page number of address |
2649 | sll $1, $1, 2 # adjust to word index |
2650 | addu $1, $1, $16 # $1 = memory_map_read[address >> 15] |
2651 | lw $1, -32768($1) |
2652 | beq $1, $0, ext_aligned_load32 # if it's NULL perform an extended read |
2653 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2654 | addu $1, $1, $2 # add the memory map offset |
2655 | jr $ra # return |
2656 | lw $2, ($1) # read the value |
2657 | |
2658 | ext_aligned_load32: |
2659 | addiu $sp, $sp, -8 # make room on the stack for $ra |
2660 | sw $6, 4($sp) |
2661 | sw $ra, ($sp) # store return address |
2662 | save_registers |
2663 | jal read_memory32 # read the value |
2664 | nop |
2665 | restore_registers |
2666 | lw $6, 4($sp) |
2667 | lw $ra, ($sp) # restore return address |
2668 | jr $ra # return |
2669 | addiu $sp, $sp, 8 # fix stack (delay slot) |
2670 | |
2671 | # General ext memory routines |
2672 | |
2673 | ext_store_ignore: |
2674 | jr $ra # ignore these writes |
2675 | nop |
2676 | |
2677 | write_io_epilogue: |
2678 | beq $2, $0, no_alert # 0 means nothing happened |
2679 | addiu $4, $2, -2 # see if return value is 2 (delay slot) |
2680 | beq $4, $0, smc_dma # is it an SMC alert? (return value = 2) |
2681 | nop |
2682 | addiu $4, $2, -3 # see if return value is 3 |
2683 | beq $4, $0, irq_alert # is it an IRQ alert? (return value = 3) |
2684 | nop |
2685 | collapse_flags # make sure flags are good for update_gba |
2686 | |
2687 | alert_loop: |
2688 | jal update_gba # process the next event |
2689 | nop |
2690 | lw $1, CPU_HALT_STATE($16) # check if CPU is sleeping |
2691 | bne $1, $0, alert_loop # see if it hasn't changed |
2692 | nop |
2693 | |
2694 | addu $17, $2, $0 # $17 = new cycle counter |
2695 | lw $4, REG_PC($16) # $4 = new PC |
2696 | |
2697 | j lookup_pc |
2698 | addiu $sp, $sp, 4 # fix the stack (delay slot) |
2699 | |
2700 | irq_alert: |
2701 | restore_registers |
2702 | j lookup_pc # PC has changed, get a new one |
2703 | addiu $sp, $sp, 4 # fix the stack |
2704 | |
2705 | no_alert: |
2706 | restore_registers |
2707 | lw $ra, ($sp) # restore return address |
2708 | jr $ra # we can return |
2709 | addiu $sp, $sp, 4 # fix the stack |
2710 | |
2711 | smc_dma: |
2712 | addiu $sp, $sp, 4 # fix the stack |
2713 | jal flush_translation_cache_ram # flush translation cache |
2714 | nop |
2715 | j lookup_pc |
2716 | nop |
2717 | |
2718 | |
2719 | ext_store_eeprom: |
2720 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2721 | sw $ra, ($sp) |
2722 | save_registers |
2723 | jal write_eeprom # write the value out |
2724 | sw $6, REG_PC($16) # save the PC (delay slot) |
2725 | restore_registers |
2726 | lw $ra, ($sp) # restore return address |
2727 | jr $ra # we can return |
2728 | addiu $sp, $sp, 4 # fix the stack |
2729 | |
2730 | |
2731 | # 8bit ext memory routines |
2732 | |
2733 | ext_store_io8: |
2734 | andi $5, $5, 0xFF # make value 8bit |
2735 | andi $4, $4, 0x3FF # wrap around address |
2736 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2737 | sw $ra, ($sp) |
2738 | save_registers |
2739 | jal write_io_register8 # write the value out |
2740 | sw $6, REG_PC($16) # save the PC (delay slot) |
2741 | j write_io_epilogue # handle any state changes |
2742 | nop |
2743 | |
2744 | ext_store_palette8: |
2745 | j ext_store_palette16b # perform 16bit palette write |
2746 | andi $4, $4, 0x3FE # wrap + align (delay) |
2747 | |
2748 | ext_store_vram8: |
2749 | ins $5, $5, 8, 8 # value = (value << 8) | value |
2750 | ext $4, $4, 0, 17 # address = adress & 0x1FFFF |
2751 | ins $4, $0, 0, 1 # align out bottom bit |
2752 | lui $1, %hi(0x18000) # $1 = 0x18000 |
2753 | sltu $1, $4, $1 # see if address < 0x18000 |
2754 | bne $1, $0, ext_store_vram8b |
2755 | lui $2, %hi(vram) # start loading vram address (delay) |
2756 | |
2757 | addiu $4, $4, -0x8000 # move address into VRAM region |
2758 | |
2759 | ext_store_vram8b: |
2760 | addu $2, $2, $4 # $2 = (hi)vram + address |
2761 | jr $ra # return |
2762 | sh $5, %lo(vram)($2) # vram[address] = value (delay) |
2763 | |
2764 | ext_store_oam8: |
2765 | lui $1, %hi(oam_update) # $1 = oam_update |
2766 | addiu $1, %lo(oam_update) |
2767 | li $2, 1 # $2 = 1 |
2768 | sw $2, ($1) # *oam_update = 1 |
2769 | andi $4, $4, 0x3FE # wrap around address and align to 16bits |
2770 | ins $5, $5, 8, 8 # value = (value << 8) | value |
2771 | lui $1, %hi(oam_ram) # $1 = (hi)oam_ram |
2772 | addu $1, $1, $4 # $1 = (hi)oam_ram + address |
2773 | jr $ra # return |
2774 | sh $5, %lo(oam_ram)($1) # oam_ram[address] = value (delay) |
2775 | |
2776 | ext_store_backup: |
2777 | andi $5, $5, 0xFF # make value 8bit |
2778 | andi $4, $4, 0xFFFF # mask value |
2779 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2780 | sw $ra, ($sp) |
2781 | save_registers |
2782 | jal write_backup # write the value out |
2783 | sw $6, REG_PC($16) # save the PC (delay slot) |
2784 | restore_registers |
2785 | lw $ra, ($sp) # restore return address |
2786 | jr $ra # we can return |
2787 | addiu $sp, $sp, 4 # fix the stack |
2788 | |
2789 | ext_store_u8_jtable: |
2790 | .long ext_store_ignore # 0x00 BIOS |
2791 | .long ext_store_ignore # 0x01 invalid |
2792 | .long ext_store_ignore # 0x02 EWRAM |
2793 | .long ext_store_ignore # 0x03 IWRAM |
2794 | .long ext_store_io8 # 0x04 I/O registers |
2795 | .long ext_store_palette8 # 0x05 Palette RAM |
2796 | .long ext_store_vram8 # 0x06 VRAM |
2797 | .long ext_store_oam8 # 0x07 OAM RAM |
2798 | .long ext_store_ignore # 0x08 gamepak (no RTC accepted in 8bit) |
2799 | .long ext_store_ignore # 0x09 gamepak, ignore |
2800 | .long ext_store_ignore # 0x0A gamepak, ignore |
2801 | .long ext_store_ignore # 0x0B gamepak, ignore |
2802 | .long ext_store_ignore # 0x0C gamepak, ignore |
2803 | .long ext_store_eeprom # 0x0D EEPROM (possibly) |
2804 | .long ext_store_backup # 0x0E Flash ROM/SRAM |
2805 | .long ext_store_ignore # 0x0F invalid |
2806 | |
2807 | |
2808 | |
2809 | ext_store_u8: |
2810 | srl $1, $4, 24 # $1 = address >> 24 |
2811 | sltu $2, $1, 16 # check if the value is out of range |
2812 | beq $2, $0, ext_store_ignore |
2813 | sll $1, $1, 2 # make address word indexed (delay) |
2814 | lui $2, %hi(ext_store_u8_jtable) |
2815 | addu $2, $2, $1 |
2816 | # $2 = ext_store_u8_jtable[address >> 24] |
2817 | lw $2, %lo(ext_store_u8_jtable)($2) |
2818 | jr $2 # jump to table location |
2819 | nop |
2820 | |
2821 | # $4: address to write to |
2822 | # $5: value to write |
2823 | # $6: current PC |
2824 | |
2825 | #execute_store_u8: |
2826 | srl $1, $4, 28 # check if the address is out of range |
2827 | bne $1, $0, ext_store_u8 # if it is, perform an extended write |
2828 | srl $2, $4, 15 # $1 = page number of address (delay slot) |
2829 | sll $2, $2, 2 # adjust to word index |
2830 | addu $2, $2, $16 |
2831 | lw $1, 256($2) # $1 = memory_map_write[address >> 15] |
2832 | beq $1, $0, ext_store_u8 # if it's NULL perform an extended write |
2833 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
2834 | addu $1, $1, $2 # add the memory map offset |
2835 | lb $2, -32768($1) # load the SMC status |
2836 | bne $2, $0, smc_write # is there code there? |
2837 | sb $5, ($1) # store the value (delay slot) |
2838 | jr $ra # return |
2839 | nop |
2840 | |
2841 | # 16bit ext memory routines |
2842 | |
2843 | ext_store_io16: |
2844 | andi $4, $4, 0x3FF # wrap around address |
2845 | andi $5, $5, 0xFFFF # make value 16bit |
2846 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2847 | sw $ra, ($sp) |
2848 | save_registers |
2849 | jal write_io_register16 # write the value out |
2850 | sw $6, REG_PC($16) # save the PC (delay slot) |
2851 | j write_io_epilogue # handle any state changes |
2852 | nop |
2853 | |
2854 | ext_store_palette16: |
2855 | andi $4, 0x3FF # wrap address |
2856 | |
2857 | ext_store_palette16b: |
2858 | lui $2, %hi(palette_ram) |
2859 | addu $2, $2, $4 |
2860 | sh $5, %lo(palette_ram)($2) # palette_ram[address] = value |
2861 | sll $1, $5, 1 # make green 6bits |
2862 | ins $1, $0, 0, 6 # make bottom bit 0 |
2863 | ins $1, $5, 0, 5 # insert red channel into $1 |
2864 | lui $2, %hi(palette_ram_converted) |
2865 | addu $2, $2, $4 |
2866 | jr $ra # return |
2867 | sh $1, %lo(palette_ram_converted)($2) |
2868 | |
2869 | ext_store_vram16: |
2870 | ext $4, $4, 0, 17 # address = adress & 0x1FFFF |
2871 | lui $1, %hi(0x18000) # $1 = 0x18000 |
2872 | sltu $1, $4, $1 # see if address < 0x18000 |
2873 | bne $1, $0, ext_store_vram16b |
2874 | lui $2, %hi(vram) # start loading vram address (delay) |
2875 | |
2876 | addiu $4, $4, -0x8000 # move address into VRAM region |
2877 | |
2878 | ext_store_vram16b: |
2879 | addu $2, $2, $4 # $2 = (hi)vram + address |
2880 | jr $ra # return |
2881 | sh $5, %lo(vram)($2) # vram[address] = value (delay) |
2882 | |
2883 | ext_store_oam16: |
2884 | lui $1, %hi(oam_update) # $1 = oam_update |
2885 | addiu $1, %lo(oam_update) |
2886 | li $2, 1 # $2 = 1 |
2887 | sw $2, ($1) # *oam_update = 1 |
2888 | andi $4, $4, 0x3FF # wrap around address |
2889 | lui $1, %hi(oam_ram) # $1 = (hi)oam_ram |
2890 | addu $1, $1, $4 # $1 = (hi)oam_ram + address |
2891 | jr $ra # return |
2892 | sh $5, %lo(oam_ram)($1) # oam_ram[address] = value (delay) |
2893 | |
2894 | ext_store_rtc: |
2895 | andi $5, $5, 0xFFFF # make value 16bit |
2896 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2897 | sw $ra, ($sp) |
2898 | save_registers |
2899 | jal write_rtc # write the value out |
2900 | sw $6, REG_PC($16) # save the PC (delay slot) |
2901 | restore_registers |
2902 | lw $ra, ($sp) # restore return address |
2903 | jr $ra # we can return |
2904 | addiu $sp, $sp, 4 # fix the stack |
2905 | |
2906 | ext_store_u16_jtable: |
2907 | .long ext_store_ignore # 0x00 BIOS, ignore |
2908 | .long ext_store_ignore # 0x01 invalid, ignore |
2909 | .long ext_store_ignore # 0x02 EWRAM, should have been hit already |
2910 | .long ext_store_ignore # 0x03 IWRAM, should have been hit already |
2911 | .long ext_store_io16 # 0x04 I/O registers |
2912 | .long ext_store_palette16 # 0x05 Palette RAM |
2913 | .long ext_store_vram16 # 0x06 VRAM |
2914 | .long ext_store_oam16 # 0x07 OAM RAM |
2915 | .long ext_store_rtc # 0x08 gamepak, RTC |
2916 | .long ext_store_ignore # 0x09 gamepak, ignore |
2917 | .long ext_store_ignore # 0x0A gamepak, ignore |
2918 | .long ext_store_ignore # 0x0B gamepak, ignore |
2919 | .long ext_store_ignore # 0x0C gamepak, ignore |
2920 | .long ext_store_eeprom # 0x0D EEPROM (possibly) |
2921 | .long ext_store_ignore # 0x0E Flash ROM/SRAM |
2922 | |
2923 | ext_store_u16: |
2924 | srl $1, $4, 24 # $1 = address >> 24 |
2925 | sltu $2, $1, 16 # check if the value is out of range |
2926 | beq $2, $0, ext_store_ignore |
2927 | sll $1, $1, 2 # make address word indexed (delay) |
2928 | lui $2, %hi(ext_store_u16_jtable) |
2929 | addu $2, $2, $1 |
2930 | # $2 = ext_store_u16_jtable[address >> 24] |
2931 | lw $2, %lo(ext_store_u16_jtable)($2) |
2932 | jr $2 # jump to table location |
2933 | nop |
2934 | |
2935 | |
2936 | #execute_store_u16: |
2937 | srl $1, $4, 28 # check if the address is out of range |
2938 | bne $1, $0, ext_store_u16 # if it is, perform an extended write |
2939 | srl $2, $4, 15 # $1 = page number of address (delay slot) |
2940 | sll $2, $2, 2 # adjust to word index |
2941 | addu $2, $2, $16 |
2942 | lw $1, 256($2) # $1 = memory_map_write[address >> 15] |
2943 | beq $1, $0, ext_store_u16 # if it's NULL perform an extended write |
2944 | andi $2, $4, 0x7FFE # $2 = low 15bits of address (delay slot) |
2945 | addu $1, $1, $2 # add the memory map offset |
2946 | lh $2, -32768($1) # load the SMC status |
2947 | bne $2, $0, smc_write # is there code there? |
2948 | sh $5, ($1) # store the value (delay slot) |
2949 | jr $ra # return |
2950 | nop |
2951 | |
2952 | |
2953 | |
2954 | |
2955 | |
2956 | |
2957 | |
2958 | |
2959 | # 32bit ext memory routines |
2960 | |
2961 | ext_store_io32: |
2962 | andi $4, $4, 0x3FF # wrap around address |
2963 | addiu $sp, $sp, -4 # make room on the stack for $ra |
2964 | sw $ra, ($sp) |
2965 | save_registers |
2966 | jal write_io_register32 # write the value out |
2967 | sw $6, REG_PC($16) # save the PC (delay slot) |
2968 | j write_io_epilogue # handle any state changes |
2969 | nop |
2970 | |
2971 | ext_store_palette32: |
2972 | addu $6, $ra, $0 # save return address in $6 |
2973 | jal ext_store_palette16b # write out palette entry |
2974 | andi $4, 0x3FF # wrap address (delay) |
2975 | addiu $4, $4, 2 # go to next location |
2976 | srl $5, $5, 16 # shift to next 16bit value |
2977 | j ext_store_palette16b # write out next palette entry |
2978 | addu $ra, $6, $0 # restore return address (delay) |
2979 | |
2980 | ext_store_vram32: |
2981 | ext $4, $4, 0, 17 # address = adress & 0x1FFFF |
2982 | lui $1, %hi(0x18000) # $1 = 0x18000 |
2983 | sltu $1, $4, $1 # see if address < 0x18000 |
2984 | bne $1, $0, ext_store_vram32b |
2985 | lui $2, %hi(vram) # start loading vram address (delay) |
2986 | |
2987 | addiu $4, $4, -0x8000 # move address into VRAM region |
2988 | |
2989 | ext_store_vram32b: |
2990 | addu $2, $2, $4 # $2 = (hi)vram + address |
2991 | jr $ra # return |
2992 | sw $5, %lo(vram)($2) # vram[address] = value (delay) |
2993 | |
2994 | ext_store_oam32: |
2995 | lui $1, %hi(oam_update) # $1 = oam_update |
2996 | addiu $1, %lo(oam_update) |
2997 | li $2, 1 # $2 = 1 |
2998 | sw $2, ($1) # *oam_update = 1 |
2999 | andi $4, $4, 0x3FF # wrap around address |
3000 | lui $1, %hi(oam_ram) # $1 = (hi)oam_ram |
3001 | addu $1, $1, $4 # $1 = (hi)oam_ram + address |
3002 | jr $ra # return |
3003 | sw $5, %lo(oam_ram)($1) # oam_ram[address] = value (delay) |
3004 | |
3005 | ext_store_u32_jtable: |
3006 | .long ext_store_ignore # 0x00 BIOS, ignore |
3007 | .long ext_store_ignore # 0x01 invalid, ignore |
3008 | .long ext_store_ignore # 0x02 EWRAM, should have been hit already |
3009 | .long ext_store_ignore # 0x03 IWRAM, should have been hit already |
3010 | .long ext_store_io32 # 0x04 I/O registers |
3011 | .long ext_store_palette32 # 0x05 Palette RAM |
3012 | .long ext_store_vram32 # 0x06 VRAM |
3013 | .long ext_store_oam32 # 0x07 OAM RAM |
3014 | .long ext_store_ignore # 0x08 gamepak, ignore |
3015 | .long ext_store_ignore # 0x09 gamepak, ignore |
3016 | .long ext_store_ignore # 0x0A gamepak, ignore |
3017 | .long ext_store_ignore # 0x0B gamepak, ignore |
3018 | .long ext_store_ignore # 0x0C gamepak, ignore |
3019 | .long ext_store_eeprom # 0x0D EEPROM (possibly) |
3020 | .long ext_store_ignore # 0x0E Flash ROM/SRAM |
3021 | |
3022 | ext_store_u32: |
3023 | srl $1, $4, 24 # $1 = address >> 24 |
3024 | sltu $2, $1, 16 # check if the value is out of range |
3025 | beq $2, $0, ext_store_ignore |
3026 | sll $1, $1, 2 # make address word indexed (delay) |
3027 | lui $2, %hi(ext_store_u32_jtable) |
3028 | addu $2, $2, $1 |
3029 | # $2 = ext_store_u32_jtable[address >> 24] |
3030 | lw $2, %lo(ext_store_u32_jtable)($2) |
3031 | jr $2 # jump to table location |
3032 | nop |
3033 | |
3034 | #execute_store_u32: |
3035 | execute_store_full_u32: |
3036 | srl $1, $4, 28 # check if the address is out of range |
3037 | bne $1, $0, ext_store_u32 # if it is, perform an extended write |
3038 | srl $2, $4, 15 # $1 = page number of address (delay slot) |
3039 | sll $2, $2, 2 # adjust to word index |
3040 | addu $2, $2, $16 |
3041 | lw $1, 256($2) # $1 = memory_map_write[address >> 15] |
3042 | beq $1, $0, ext_store_u32 # if it's NULL perform an extended write |
3043 | andi $2, $4, 0x7FFC # $2 = low 15bits of address (delay slot) |
3044 | addu $1, $1, $2 # add the memory map offset |
3045 | lw $2, -32768($1) # load the SMC status |
3046 | bne $2, $0, smc_write # is there code there? |
3047 | sw $5, ($1) # store the value (delay slot) |
3048 | jr $ra # return |
3049 | nop |
3050 | |
3051 | |
3052 | # 32bit ext aligned, non a2 destroying routines |
3053 | |
3054 | ext_store_io32a: |
3055 | andi $4, $4, 0x3FF # wrap around address |
3056 | addiu $sp, $sp, -4 # make room on the stack for $ra |
3057 | sw $ra, ($sp) |
3058 | save_registers |
3059 | jal write_io_register32 # write the value out |
3060 | sw $6, REG_SAVE($16) # save a2 |
3061 | lw $6, REG_SAVE($16) # restore a2 |
3062 | j write_io_epilogue # handle any state changes |
3063 | nop |
3064 | |
3065 | ext_store_palette32a: |
3066 | sw $ra, REG_SAVE($16) # save return address |
3067 | jal ext_store_palette16b # write out palette entry |
3068 | andi $4, 0x3FF # wrap address (delay) |
3069 | addiu $4, $4, 2 # go to next location |
3070 | srl $5, $5, 16 # shift to next 16bit value |
3071 | j ext_store_palette16b # write out next palette entry |
3072 | lw $ra, REG_SAVE($16) # restore return address (delay) |
3073 | |
3074 | ext_store_u32a_jtable: |
3075 | .long ext_store_ignore # 0x00 BIOS, ignore |
3076 | .long ext_store_ignore # 0x01 invalid, ignore |
3077 | .long ext_store_ignore # 0x02 EWRAM, should have been hit already |
3078 | .long ext_store_ignore # 0x03 IWRAM, should have been hit already |
3079 | .long ext_store_io32a # 0x04 I/O registers |
3080 | .long ext_store_palette32a # 0x05 Palette RAM |
3081 | .long ext_store_vram32 # 0x06 VRAM |
3082 | .long ext_store_oam32 # 0x07 OAM RAM |
3083 | .long ext_store_ignore # 0x08 gamepak, ignore |
3084 | .long ext_store_ignore # 0x09 gamepak, ignore |
3085 | .long ext_store_ignore # 0x0A gamepak, ignore |
3086 | .long ext_store_ignore # 0x0B gamepak, ignore |
3087 | .long ext_store_ignore # 0x0C gamepak, ignore |
3088 | .long ext_store_ignore # 0x0D EEPROM (nothing will write this) |
3089 | .long ext_store_ignore # 0x0E Flash ROM/SRAM |
3090 | |
3091 | ext_aligned_store32: |
3092 | srl $1, $4, 24 # $1 = address >> 24 |
3093 | sltu $2, $1, 16 # check if the value is out of range |
3094 | beq $2, $0, ext_store_ignore |
3095 | sll $1, $1, 2 # make address word indexed (delay) |
3096 | lui $2, %hi(ext_store_u32a_jtable) |
3097 | addu $2, $2, $1 |
3098 | # $2 = ext_store_u32a_jtable[address >> 24] |
3099 | lw $2, %lo(ext_store_u32a_jtable)($2) |
3100 | jr $2 # jump to table location |
3101 | nop |
3102 | |
3103 | #execute_aligned_store32: |
3104 | srl $2, $4, 28 # check if the address is out of range |
3105 | bne $2, $0, ext_aligned_store32 # if it is, perform an extended load |
3106 | srl $1, $4, 15 # $1 = page number of address |
3107 | sll $1, $1, 2 # adjust to word index |
3108 | addu $1, $1, $16 # $1 = memory_map_write[address >> 15] |
3109 | lw $1, 256($1) |
3110 | beq $1, $0, ext_aligned_store32 # if it's NULL perform an extended write |
3111 | andi $2, $4, 0x7FFF # $2 = low 15bits of address (delay slot) |
3112 | addu $1, $1, $2 # add the memory map offset |
3113 | jr $ra # return |
3114 | sw $5, ($1) # write the value |
3115 | |
3116 | smc_write: |
3117 | save_registers |
3118 | jal flush_translation_cache_ram # flush translation cache |
3119 | sw $6, REG_PC($16) # save PC (delay slot) |
3120 | |
3121 | lookup_pc: |
3122 | lw $2, REG_CPSR($16) # $2 = cpsr |
3123 | andi $2, $2, 0x20 # isolate mode bit |
3124 | beq $2, $0, lookup_pc_arm # if T bit is zero use arm handler |
3125 | nop |
3126 | |
3127 | lookup_pc_thumb: |
3128 | jal block_lookup_address_thumb # get Thumb address |
3129 | lw $4, REG_PC($16) # load PC as arg 0 (delay slot) |
3130 | restore_registers |
3131 | jr $2 # jump to result |
3132 | nop |
3133 | |
3134 | lookup_pc_arm: |
3135 | jal block_lookup_address_arm # get ARM address |
3136 | lw $4, REG_PC($16) # load PC as arg 0 (delay slot) |
3137 | restore_registers |
3138 | jr $2 # jump to result |
3139 | nop |
3140 | |
3141 | # Return the current cpsr |
3142 | |
3143 | execute_read_cpsr: |
3144 | collapse_flags # fold flags into cpsr, put cpsr into $2 |
3145 | jr $ra # return |
3146 | nop |
3147 | |
3148 | # Return the current spsr |
3149 | |
3150 | execute_read_spsr: |
3151 | lw $1, CPU_MODE($16) # $1 = cpu_mode |
3152 | lui $2, %hi(spsr) |
3153 | sll $1, $1, 2 # adjust to word offset size |
3154 | addu $2, $2, $1 |
3155 | jr $ra # return |
3156 | lw $2, %lo(spsr)($2) # $2 = spsr[cpu_mode] (delay slot) |
3157 | |
3158 | # Switch into SWI, has to collapse flags |
3159 | # $4: Current pc |
3160 | |
3161 | execute_swi: |
3162 | add $sp, $sp, -4 # push $ra |
3163 | sw $ra, ($sp) |
3164 | lui $1, %hi(SUPERVISOR_LR) |
3165 | sw $4, %lo(SUPERVISOR_LR)($1) # store next PC in the supervisor's LR |
3166 | collapse_flags # get cpsr in $2 |
3167 | lui $5, %hi(SUPERVISOR_SPSR) |
3168 | sw $2, %lo(SUPERVISOR_SPSR)($5) # save cpsr in SUPERVISOR_CPSR |
3169 | ins $2, $0, 0, 6 # zero out bottom 6 bits of CPSR |
3170 | ori $2, 0x13 # set mode to supervisor |
3171 | sw $2, REG_CPSR($16) # write back CPSR |
3172 | save_registers |
3173 | jal set_cpu_mode # set the CPU mode to supervisor |
3174 | li $4, 3 # 3 is supervisor mode (delay slot) |
3175 | restore_registers |
3176 | lw $ra, ($sp) # pop $ra |
3177 | jr $ra # return |
3178 | add $sp, $sp, 4 # fix stack (delay slot) |
3179 | |
3180 | # $4: pc to restore to |
3181 | # returns in $4 |
3182 | |
3183 | execute_spsr_restore: |
3184 | lw $1, CPU_MODE($16) # $1 = cpu_mode |
3185 | |
3186 | beq $1, $0, no_spsr_restore # only restore if the cpu isn't usermode |
3187 | lui $2, %hi(spsr) # start loading SPSR (delay) |
3188 | |
3189 | sll $1, $1, 2 # adjust to word offset size |
3190 | addu $2, $2, $1 |
3191 | lw $1, %lo(spsr)($2) # $1 = spsr[cpu_mode] |
3192 | sw $1, REG_CPSR($16) # cpsr = spsr[cpu_mode] |
3193 | extract_flags_body # extract flags from $1 |
3194 | addiu $sp, $sp, -4 |
3195 | sw $ra, ($sp) |
3196 | save_registers |
3197 | jal execute_spsr_restore_body # do the dirty work in this C function |
3198 | nop |
3199 | restore_registers |
3200 | addu $4, $2, $0 # move return value to $4 |
3201 | lw $ra, ($sp) |
3202 | jr $ra |
3203 | addiu $sp, $sp, 4 |
3204 | |
3205 | no_spsr_restore: |
3206 | jr $ra |
3207 | nop |
3208 | |
3209 | # $4: new cpsr |
3210 | # $5: store mask |
3211 | # $6: current PC |
3212 | |
3213 | execute_store_cpsr: |
3214 | and $1, $4, $5 # $1 = new_cpsr & store_mask |
3215 | lw $2, REG_CPSR($16) # $2 = current cpsr |
3216 | nor $4, $5, $0 # $4 = ~store_mask |
3217 | and $2, $2, $4 # $2 = (cpsr & (~store_mask)) |
3218 | or $1, $1, $2 # $1 = new cpsr combined with old |
3219 | extract_flags_body # extract flags from $1 |
3220 | addiu $sp, $sp, -4 |
3221 | sw $ra, ($sp) |
3222 | save_registers |
3223 | jal execute_store_cpsr_body # do the dirty work in this C function |
3224 | addu $4, $1, $0 # load the new CPSR (delay slot) |
3225 | |
3226 | bne $2, $0, changed_pc_cpsr # this could have changed the pc |
3227 | nop |
3228 | |
3229 | restore_registers |
3230 | |
3231 | lw $ra, ($sp) |
3232 | jr $ra |
3233 | addiu $sp, $sp, 4 |
3234 | |
3235 | changed_pc_cpsr: |
3236 | jal block_lookup_address_arm # GBA address is in $4 |
3237 | addu $4, $2, $0 # load new address in $4 (delay slot) |
3238 | restore_registers # restore registers |
3239 | jr $2 # jump to the new address |
3240 | addiu $sp, $sp, 4 # get rid of the old ra (delay slot) |
3241 | |
3242 | |
3243 | # $4: new spsr |
3244 | # $5: store mask |
3245 | |
3246 | execute_store_spsr: |
3247 | lw $1, CPU_MODE($16) # $1 = cpu_mode |
3248 | lui $2, %hi(spsr) |
3249 | sll $1, $1, 2 # adjust to word offset size |
3250 | addu $1, $2, $1 |
3251 | lw $2, %lo(spsr)($1) # $2 = spsr[cpu_mode] |
3252 | and $4, $4, $5 # $4 = new_spsr & store_mask |
3253 | nor $5, $5, $0 # $5 = ~store_mask |
3254 | and $2, $2, $5 # $2 = (spsr & (~store_mask)) |
3255 | or $4, $4, $2 # $4 = new spsr combined with old |
3256 | jr $ra # return |
3257 | sw $4, %lo(spsr)($1) # spsr[cpu_mode] = $4 (delay slot) |
3258 | |
3259 | # $4: value |
3260 | # $5: shift |
3261 | |
3262 | execute_lsl_flags_reg: |
3263 | beq $5, $0, lsl_shift_zero # is the shift zero? |
3264 | sltiu $1, $5, 32 # $1 = (shift < 32) (delay) |
3265 | beq $1, $0, lsl_shift_high # is the shift >= 32? |
3266 | li $2, 32 |
3267 | |
3268 | subu $2, $2, $5 # $2 = (32 - shift) |
3269 | srlv $2, $4, $2 # $2 = (value >> (32 - shift)) |
3270 | andi $22, $2, 1 # c flag = (value >> (32 - shift)) & 0x01 |
3271 | |
3272 | lsl_shift_zero: |
3273 | jr $ra # return |
3274 | sllv $4, $4, $5 # return (value << shift) (delay) |
3275 | |
3276 | lsl_shift_high: |
3277 | sltiu $1, $5, 33 # $1 = (shift < 33) (delay) |
3278 | bne $1, $0, lsl_shift_done # jump if shift == 32 |
3279 | andi $22, $4, 1 # c flag = value & 0x01 (delay) |
3280 | |
3281 | add $22, $0, $0 # c flag = 0 otherwise |
3282 | |
3283 | lsl_shift_done: |
3284 | jr $ra # return |
3285 | add $4, $0, $0 # value = 0 no matter what |
3286 | |
3287 | |
3288 | execute_lsr_flags_reg: |
3289 | beq $5, $0, lsr_shift_zero # is the shift zero? |
3290 | sltiu $1, $5, 32 # $1 = (shift < 32) (delay) |
3291 | beq $1, $0, lsr_shift_high # is the shift >= 32? |
3292 | addiu $2, $5, -1 # $2 = shift - 1 (delay) |
3293 | |
3294 | srlv $2, $4, $2 # $2 = (value >> (shift - 1)) |
3295 | andi $22, $2, 1 # c flag = (value >> (32 - shift)) & 0x01 |
3296 | |
3297 | lsr_shift_zero: |
3298 | jr $ra # return |
3299 | srlv $4, $4, $5 # return (value >> shift) (delay) |
3300 | |
3301 | lsr_shift_high: |
3302 | sltiu $1, $5, 33 # $1 = (shift < 33) (delay) |
3303 | bne $1, $0, lsr_shift_done # jump if shift == 32 |
3304 | srl $22, $4, 31 # c flag = value >> 31 (delay) |
3305 | |
3306 | add $22, $0, $0 # c flag = 0 otherwise |
3307 | |
3308 | lsr_shift_done: |
3309 | jr $ra # return |
3310 | add $4, $0, $0 # value = 0 no matter what |
3311 | |
3312 | |
3313 | execute_asr_flags_reg: |
3314 | beq $5, $0, asr_shift_zero # is the shift zero? |
3315 | sltiu $1, $5, 32 # $1 = (shift < 32) (delay) |
3316 | beq $1, $0, asr_shift_high # is the shift >= 32? |
3317 | addiu $2, $5, -1 # $2 = shift - 1 (delay) |
3318 | |
3319 | srlv $2, $4, $2 # $2 = (value >> (shift - 1)) |
3320 | andi $22, $2, 1 # c flag = (value >> (32 - shift)) & 0x01 |
3321 | |
3322 | asr_shift_zero: |
3323 | jr $ra # return |
3324 | srav $4, $4, $5 # return (value >> shift) (delay) |
3325 | |
3326 | asr_shift_high: |
3327 | sra $4, $4, 31 # value >>= 31 |
3328 | jr $ra # return |
3329 | andi $22, $4, 1 # c flag = value & 0x01 |
3330 | |
3331 | |
3332 | execute_ror_flags_reg: |
3333 | beq $5, $0, ror_zero_shift # is the shift zero? |
3334 | addiu $1, $5, -1 # $1 = (shift - 1) (delay) |
3335 | |
3336 | srav $1, $4, $1 # $1 = (value >> (shift - 1)) |
3337 | andi $22, $1, 1 # c flag = $1 & 1 |
3338 | |
3339 | ror_zero_shift: |
3340 | jr $ra # return |
3341 | rotrv $4, $4, $5 # return (value ror shift) delay |
3342 | |
3343 | # $4: cycle counter argument |
3344 | |
3345 | execute_arm_translate: |
3346 | addu $17, $4, $0 # load cycle counter register |
3347 | lui $16, %hi(reg) # load base register |
3348 | addiu $16, %lo(reg) |
3349 | extract_flags # load flag variables |
3350 | |
3351 | and $1, $1, 0x20 # see if Thumb bit is set in flags |
3352 | |
3353 | bne $1, $0, 1f |
3354 | lw $4, REG_PC($16) # load PC into $4 (delay) |
3355 | |
3356 | jal block_lookup_address_arm # lookup initial jump address |
3357 | nop |
3358 | restore_registers # load initial register values |
3359 | jr $2 # jump to return |
3360 | nop |
3361 | |
3362 | 1: |
3363 | jal block_lookup_address_thumb # lookup initial jump address |
3364 | nop |
3365 | restore_registers # load initial register values |
3366 | jr $2 # jump to return |
3367 | nop |
3368 | |
3369 | # sceKernelInvalidateIcacheRange gives me problems, trying this instead |
3370 | # Invalidates an n byte region starting at the start address |
3371 | # $4: start location |
3372 | # $5: length |
3373 | |
3374 | invalidate_icache_region: |
3375 | ins $4, $0, 0, 6 # align to 64 bytes |
3376 | addiu $2, $5, 63 # align up to 64 bytes |
3377 | srl $2, $2, 6 # divide by 64 |
3378 | beq $2, $0, done # exit early on 0 |
3379 | nop |
3380 | |
3381 | iir_loop: |
3382 | cache 0x08, ($4) # hit invalidate icache line |
3383 | addiu $2, $2, -1 # next loop iteration |
3384 | bne $2, $0, iir_loop # loop |
3385 | addiu $4, $4, 64 # go to next cache line (delay slot) |
3386 | |
3387 | done: |
3388 | jr $ra # return |
3389 | nop |
3390 | |
3391 | # Writes back dcache and invalidates icache. |
3392 | |
3393 | invalidate_all_cache: |
3394 | addu $4, $0, $0 # $4 = 0 |
3395 | addiu $5, $0, 0x4000 # $5 = 0x4000 |
3396 | |
3397 | iac_loop: |
3398 | cache 0x14, 0($4) # index invalidate/writeback dcache index |
3399 | addiu $4, $4, 0x40 # goto next cache line |
3400 | bne $4, $5, iac_loop # next iteration |
3401 | cache 0x04, -0x40($4) # index invalidate icache index.. maybe? |
3402 | |
3403 | jr $ra # return |
3404 | nop |
3405 | |
3406 | |
3407 | step_debug_mips: |
3408 | addiu $sp, $sp, -4 |
3409 | sw $ra, ($sp) |
3410 | collapse_flags |
3411 | save_registers |
3412 | jal step_debug |
3413 | addiu $5, $17, 0 |
3414 | restore_registers |
3415 | lw $ra, ($sp) |
3416 | jr $ra |
3417 | addiu $sp, $sp, 4 |
3418 | |
3419 | memory_map_read: |
3420 | .space 0x8000 |
3421 | |
3422 | reg: |
3423 | .space 0x100 |
3424 | |
3425 | memory_map_write: |
3426 | .space 0x8000 |
3427 | |