⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mips_stub.s

📁 psp上的GBA模拟器
💻 S
📖 第 1 页 / 共 5 页
字号:
# 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 + -