📄 mips_stub.s
字号:
# gameplaySP## Copyright (C) 2006 Exophase <exophase@gmail.com>## This program is free software; you can redistribute it and/or# modify it under the terms of the GNU General Public License as# published by the Free Software Foundation; either version 2 of# the License, or (at your option) any later version.## This program is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU# General Public License for more details.## You should have received a copy of the GNU General Public License# along with this program; if not, write to the Free Software# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.align 4.global mips_update_gba.global mips_indirect_branch_arm.global mips_indirect_branch_thumb.global mips_indirect_branch_dual.global execute_load_u8.global execute_load_u16.global execute_load_u32.global execute_load_s8.global execute_load_s16.global execute_store_u8.global execute_store_u16.global execute_store_u32.global execute_aligned_load32.global execute_aligned_store32.global execute_read_cpsr.global execute_read_spsr.global execute_swi.global execute_spsr_restore.global execute_store_cpsr.global execute_store_spsr.global execute_lsl_flags_reg.global execute_lsr_flags_reg.global execute_asr_flags_reg.global execute_ror_flags_reg.global execute_arm_translate.global invalidate_icache_region.global step_debug_mips.global reg_check.global memory_map_read.global memory_map_write.global reg.extern reg.extern spsr# MIPS register layout:# $0 - constant zero# $1 - temporary# $2 - temporary / return value# $3 - ARM r0 (not saved)# $4 - temporary / function argument 0# $5 - temporary / function argument 1# $6 - temporary / function argument 2# $7 - ARM r1 (not saved)# $8 - ARM r2 (not saved)# $9 - ARM r3 (not saved)# $10 - ARM r4 (not saved)# $11 - ARM r5 (not saved)# $12 - ARM r6 (not saved)# $13 - ARM r7 (not saved)# $14 - ARM r8 (not saved)# $15 - ARM r9 (not saved)# $16 - ARM machine state pointer (saved)# $17 - cycle counter (saved)# $18 - ARM r10 (saved)# $19 - block start address (roughly r15) (saved)# $20 - ARM negative register (saved)# $21 - ARM zero register (saved)# $22 - ARM carry register (saved)# $23 - ARM overflow register (saved)# $24 - ARM r11 (not saved)# $25 - ARM r12 (not saved)# $26 - kernel temporary 0# $27 - kernel temporary 1# $28 - ARM r13 (saved)# $29 - stack pointer# $30 - ARM r14 (saved)# $31 - return address.equ REG_R0, (0 * 4).equ REG_R1, (1 * 4).equ REG_R2, (2 * 4).equ REG_R3, (3 * 4).equ REG_R4, (4 * 4).equ REG_R5, (5 * 4).equ REG_R6, (6 * 4).equ REG_R7, (7 * 4).equ REG_R8, (8 * 4).equ REG_R9, (9 * 4).equ REG_R10, (10 * 4).equ REG_R11, (11 * 4).equ REG_R12, (12 * 4).equ REG_R13, (13 * 4).equ REG_R14, (14 * 4).equ REG_PC, (15 * 4).equ REG_LR, (14 * 4).equ REG_N_FLAG, (16 * 4).equ REG_Z_FLAG, (17 * 4).equ REG_C_FLAG, (18 * 4).equ REG_V_FLAG, (19 * 4).equ REG_CPSR, (20 * 4).equ REG_SAVE, (21 * 4).equ REG_SAVE2, (22 * 4).equ REG_SAVE3, (23 * 4).equ CPU_MODE, (29 * 4).equ CPU_HALT_STATE, (30 * 4).equ CHANGED_PC_STATUS, (31 * 4).equ GP_SAVE, (32 * 4).equ SUPERVISOR_LR, (reg_mode + (3 * (7 * 4)) + (6 * 4)).equ SUPERVISOR_SPSR, (spsr + (3 * 4)).set noat.set noreorder# make sure $16 has the register base for these macros.macro collapse_flag flag_reg, shift ins $2, $\flag_reg, \shift, 1 # insert flag into CPSR.endm.macro collapse_flags lw $2, REG_CPSR($16) # load CPSR andi $2, $2, 0xFF # isolate lower 8bits collapse_flag 20, 31 # store flags collapse_flag 21, 30 collapse_flag 22, 29 collapse_flag 23, 28 sw $2, REG_CPSR($16) # store CPSR.endm.macro extract_flag shift, flag_reg ext $\flag_reg, $1, \shift, 1 # extract flag from CPSR.endm.macro extract_flags_body # extract flags from $1 extract_flag 31, 20 # load flags extract_flag 30, 21 extract_flag 29, 22 extract_flag 28, 23.endm.macro extract_flags lw $1, REG_CPSR($16) # load CPSR extract_flags_body.endm.macro save_registers sw $3, REG_R0($16) sw $7, REG_R1($16) sw $8, REG_R2($16) sw $9, REG_R3($16) sw $10, REG_R4($16) sw $11, REG_R5($16) sw $12, REG_R6($16) sw $13, REG_R7($16) sw $14, REG_R8($16) sw $15, REG_R9($16) sw $24, REG_R11($16) sw $25, REG_R12($16) sw $18, REG_R10($16) sw $28, REG_R13($16) sw $30, REG_R14($16) lw $28, GP_SAVE($16).endm.macro restore_registers lw $3, REG_R0($16) lw $7, REG_R1($16) lw $8, REG_R2($16) lw $9, REG_R3($16) lw $10, REG_R4($16) lw $11, REG_R5($16) lw $12, REG_R6($16) lw $13, REG_R7($16) lw $14, REG_R8($16) lw $15, REG_R9($16) lw $24, REG_R11($16) lw $25, REG_R12($16) lw $18, REG_R10($16) lw $28, REG_R13($16) lw $30, REG_R14($16).endm# Process a hardware event. Since an interrupt might be# raised we have to check if the PC has changed.# $4: next address# $16: register base# $17: cycle counter.balign 64mips_update_gba: sw $4, REG_PC($16) # current PC = $4 addiu $sp, $sp, -4 # make room on the stack sw $ra,($sp) # save return address collapse_flags # update cpsr save_registers # save registers jal update_gba # process the next event sw $0, CHANGED_PC_STATUS($16) lw $ra, ($sp) # restore return address addiu $sp, $sp, 4 # fix stack lw $1, CHANGED_PC_STATUS($16) bne $1, $0, lookup_pc addu $17, $2, $0 # $17 = new cycle count (delay slot) restore_registers jr $ra # if not, go back to caller nop# Perform an indirect branch.# $4: GBA address to branch tomips_indirect_branch_arm: save_registers jal block_lookup_address_arm # $2 = MIPS address to jump to nop restore_registers jr $2 # jump to it nopmips_indirect_branch_thumb: save_registers jal block_lookup_address_thumb # $2 = MIPS address to jump to nop restore_registers jr $2 # jump to it nopmips_indirect_branch_dual: save_registers jal block_lookup_address_dual # $2 = MIPS address to jump to nop restore_registers jr $2 # jump to it nop# $4: address to write to# $5: current PC# Will patch the return address with a call to the correct handler as# listed in the given table.# Value will be set to force_open if it's open.macro patch_handler ftable, force_open srl $1, $4, 24 # $1 = address region sltu $2, $1, 0x0F # check if the value is open bne $2, $0, 1f sll $1, $1, 2 # make address word indexed (delay) addiu $1, $0, (\force_open * 4)1: lui $2, %hi(\ftable) addu $2, $2, $1 lw $2, %lo(\ftable)($2) # new function handler is in $2 srl $2, $2, 2 # remove lower two bits lui $1, %hi(3 << 26) # $1 = 3 (JAL opcode) ins $1, $2, 0, 26 # insert offset into jal addiu $ra, $ra, -8 # rewind return address to function call sw $1, ($ra) # modify to call new handler cache 0x1a, ($ra) # writeback dcache line cache 0x8, ($ra) # invalidate icache line cache 0x1a, ($ra) # do it again for good luck :P cache 0x8, ($ra) jr $ra # return nop # wary of putting cache here.endm# Like the above, but will use the table of the proper alignment,# The tables should be ordered by alignment.macro patch_handler_align ftable, alignment srl $1, $4, 24 # $1 = address region sltu $2, $1, 0x0F # check if the value is open bne $2, $0, 1f sll $1, $1, 2 # make address word indexed (delay) addiu $1, $0, 4 # force address to 0x1 (open)1: ins $1, $4, 6, \alignment # place alignment bits into offset lui $2, %hi(\ftable) addu $2, $2, $1 lw $2, %lo(\ftable)($2) # new function handler is in $2 srl $2, $2, 2 # remove lower two bits lui $1, %hi(3 << 26) # $1 = 3 (JAL opcode) ins $1, $2, 0, 26 # insert offset into jal addiu $ra, $ra, -8 # rewind return address to function call sw $1, ($ra) # modify to call new handler cache 0x1a, ($ra) # writeback dcache line cache 0x8, ($ra) # invalidate icache line cache 0x1a, ($ra) # do it again for good luck :P cache 0x8, ($ra) jr $ra # return nop # wary of putting cache here.endm.macro region_check region, patch_handler srl $1, $4, 24 # check upper 8bits of address xor $1, $1, \region # see if it is the given region bne $1, $0, \patch_handler # if not repatch/try again.endm.macro region_check_open patch_handler srl $1, $4, 24 # check upper 8bits of address sltiu $2, $1, 0x0F # true if it is a low address addiu $1, $1, -1 # non-zero if it is not a low open sltu $1, $0, $1 # true if lower bits != 1 and $1, $1, $2 # true if low address and not open bne $1, $0, \patch_handler # if above is true, patch.endm.macro region_check_align region, align_bits, alignment, patch_handler srl $1, $4, 24 # check upper 8bits of address ins $1, $4, 8, \align_bits # look at lower bits of address too # See if it is the given region and alignment xori $1, $1, (\region | (\alignment << 8)) bne $1, $0, \patch_handler # if not repatch/try again.endm.macro region_check_open_align align_bits, alignment, patch_handler srl $1, $4, 24 # check upper 8bits of address sltiu $2, $1, 0x0F # true if it is a low address addiu $1, $1, -1 # non-zero if it is not a low open sltu $1, $0, $1 # true if $1 != 0 and $1, $1, $2 # true if low address and not open ext $2, $4, 0, \align_bits # $2 = low bits of 4 xori $2, $2, \alignment # true if alignment doesn't match or $1, $1, $2 # align failure will trigger too bne $1, $0, \patch_handler # if above is true, patch.endm.macro ignore_region region, patch_handler region_check \region, \patch_handler nop jr $ra nop.endm.macro ignore_high patch_handler srl $1, $4, 24 # check upper 8bits of address sltiu $1, $1, 0x0F # see if it is not high bne $1, $0, \patch_handler # if not repatch/try again nop jr $ra nop.endm.macro translate_region_core base, size lui $2, %hi(\base) # generate upper address andi $4, $4, \size # generate offset addu $2, $2, $4 # add ptr upper and offset.endm.macro translate_region region, patch_handler, base, size region_check \region, \patch_handler translate_region_core \base, \size.endm# I refuse to have > 80 char lines, and GAS has a problem with the param# list spilling over (grumble).macro translate_region_align region, a_b, alignment, p_h, base, size region_check_align \region, \a_b, \alignment, \p_h translate_region_core \base, \size.endm.macro translate_region_ewram_core mask lui $2, %hi(ewram + 0x8000) # generate upper address (delay) andi $1, $4, \mask # generate 15bit offset ext $4, $4, 15, 3 # isolate top 3 bits of offset ins $1, $4, 16, 3 # reinsert into top 4 bits addu $2, $2, $1.endm.macro translate_region_ewram patch_handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -