diff options
author | neonloop | 2021-05-05 17:12:36 +0000 |
---|---|---|
committer | neonloop | 2021-05-05 17:12:59 +0000 |
commit | 997d3f2183eb9e99a3a1578a0060cb2fcd2165a2 (patch) | |
tree | 5b2afae111495c75ddf5c2b8fd8e6699da50117e /psp | |
parent | 3aa34f7503bbb03e9bcd191f8af4fd5faac66d2e (diff) | |
parent | 52088a4d10af9a8c0e95b0eb168d4dfd0a13639f (diff) | |
download | picogpsp-997d3f2183eb9e99a3a1578a0060cb2fcd2165a2.tar.gz picogpsp-997d3f2183eb9e99a3a1578a0060cb2fcd2165a2.tar.bz2 picogpsp-997d3f2183eb9e99a3a1578a0060cb2fcd2165a2.zip |
Merge remote-tracking branch 'libretro/master' into pico-fe
Diffstat (limited to 'psp')
-rw-r--r-- | psp/mips_emit.h | 63 | ||||
-rw-r--r-- | psp/mips_stub.S | 15 |
2 files changed, 54 insertions, 24 deletions
diff --git a/psp/mips_emit.h b/psp/mips_emit.h index 818b724..12685e8 100644 --- a/psp/mips_emit.h +++ b/psp/mips_emit.h @@ -2422,6 +2422,24 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address) generate_indirect_branch_cycle_update(dual); \ } \ +#ifdef TRACE_INSTRUCTIONS + void trace_instruction(u32 pc) + { + printf("Executed %x\n", pc); + } + + #define emit_trace_instruction(pc) \ + emit_save_regs(false); \ + generate_load_imm(reg_a0, pc); \ + genccall(&trace_instruction); \ + emit_restore_regs(false) + #define emit_trace_thumb_instruction(pc) emit_trace_instruction(pc) + #define emit_trace_arm_instruction(pc) emit_trace_instruction(pc) +#else + #define emit_trace_thumb_instruction(pc) + #define emit_trace_arm_instruction(pc) +#endif + #define thumb_swi() \ generate_swi_hle_handler(opcode & 0xFF); \ generate_load_pc(reg_a0, (pc + 2)); \ @@ -2932,13 +2950,14 @@ static void emit_palette_hdl( } mips_emit_addu(reg_rv, reg_rv, reg_base); - // Store the data (delay slot from the SMC branch) + // Store the data in real palette memory if (realsize == 2) { - mips_emit_sw(reg_a1, reg_base, 0x100); + mips_emit_sw(reg_a1, reg_rv, 0x100); } else if (realsize == 1) { - mips_emit_sh(reg_a1, reg_base, 0x100); + mips_emit_sh(reg_a1, reg_rv, 0x100); } + // Convert and store in mirror memory palette_convert(); mips_emit_sh(reg_temp, reg_rv, 0x500); @@ -2965,24 +2984,23 @@ static void emit_ignorestore_stub(unsigned size, u8 **tr_ptr) { mips_emit_jr(mips_reg_ra); mips_emit_nop(); - // Region 8-B - tmemst[size][ 8] = tmemst[size][ 9] = - tmemst[size][10] = tmemst[size][11] = (u32)translation_ptr; + // Region 9-C + tmemst[size][ 9] = tmemst[size][10] = + tmemst[size][11] = tmemst[size][12] = (u32)translation_ptr; - mips_emit_srl(reg_temp, reg_a0, 26); // Check 6 MSB to be 0x02 - mips_emit_xori(reg_temp, reg_temp, 0x02); + mips_emit_srl(reg_temp, reg_a0, 24); + mips_emit_addiu(reg_temp, reg_temp, -9); + mips_emit_srl(reg_temp, reg_temp, 2); mips_emit_b(bne, reg_temp, reg_zero, st_phndlr_branch(size)); mips_emit_nop(); mips_emit_jr(mips_reg_ra); mips_emit_nop(); - // Region C or F (or bigger!) - tmemst[size][12] = tmemst[size][15] = (u32)translation_ptr; + // Region F or higher + tmemst[size][15] = (u32)translation_ptr; mips_emit_srl(reg_temp, reg_a0, 24); - mips_emit_sltiu(reg_rv, reg_temp, 0x0F); - mips_emit_b(beq, reg_rv, reg_zero, 3); // If 15 or bigger, ignore store - mips_emit_xori(reg_rv, reg_temp, 0x0C); - mips_emit_b(bne, reg_temp, reg_zero, st_phndlr_branch(size)); + mips_emit_sltiu(reg_rv, reg_temp, 0x0F); // Is < 15? + mips_emit_b(bne, reg_rv, reg_zero, st_phndlr_branch(size)); mips_emit_nop(); mips_emit_jr(mips_reg_ra); mips_emit_nop(); @@ -2990,7 +3008,7 @@ static void emit_ignorestore_stub(unsigned size, u8 **tr_ptr) { *tr_ptr = translation_ptr; } -// Stubs for regions with EEPROM or flash/SRAM +// Stubs for regions with EEPROM or flash/SRAM (also RTC) static void emit_saveaccess_stub(u8 **tr_ptr) { unsigned opt, i, strop; u8 *translation_ptr = *tr_ptr; @@ -3043,6 +3061,21 @@ static void emit_saveaccess_stub(u8 **tr_ptr) { } } + // RTC writes, only for 16 bit accesses + for (strop = 0; strop <= 3; strop++) { + tmemst[strop][8] = (u32)translation_ptr; + mips_emit_srl(reg_temp, reg_a0, 24); + mips_emit_xori(reg_rv, reg_temp, 0x08); + mips_emit_b(bne, reg_rv, reg_zero, st_phndlr_branch(strop)); + if (strop == 1) { + emit_mem_call(&write_rtc, 0xFF); // Addr + } else { + mips_emit_nop(); + mips_emit_jr(mips_reg_ra); // Do nothing + mips_emit_nop(); + } + } + // Region 4 writes // I/O writes are also a bit special, they can trigger things like DMA, IRQs... // Also: aligned (strop==3) accesses do not trigger IRQs diff --git a/psp/mips_stub.S b/psp/mips_stub.S index 62a7731..3c05f52 100644 --- a/psp/mips_stub.S +++ b/psp/mips_stub.S @@ -391,8 +391,7 @@ execute_read_spsr: # $4: Current pc execute_swi: - add $sp, $sp, -4 # push $ra - sw $ra, ($sp) + sw $ra, REG_SAVE3($16) sw $4, SUPERVISOR_LR($16) # store next PC in the supervisor's LR collapse_flags # get cpsr in $2 sw $2, SUPERVISOR_SPSR($16) # save cpsr in SUPERVISOR_CPSR @@ -402,10 +401,10 @@ execute_swi: save_registers li $4, 3 # 3 is supervisor mode cfncall set_cpu_mode, 5 # set the CPU mode to supervisor + lw $ra, REG_SAVE3($16) restore_registers - lw $ra, ($sp) # pop $ra jr $ra # return - add $sp, $sp, 4 # fix stack (delay slot) + nop # $4: pc to restore to # returns in $4 @@ -420,15 +419,13 @@ execute_spsr_restore: lw $1, SPSR_BASE($2) # $1 = spsr[cpu_mode] sw $1, REG_CPSR($16) # cpsr = spsr[cpu_mode] extract_flags_body # extract flags from $1 - addiu $sp, $sp, -4 - sw $ra, ($sp) + sw $ra, REG_SAVE3($16) save_registers cfncall execute_spsr_restore_body, 6 # do the dirty work in this C function restore_registers - addu $4, $2, $0 # move return value to $4 - lw $ra, ($sp) + lw $ra, REG_SAVE3($16) jr $ra - addiu $sp, $sp, 4 + addu $4, $2, $0 # move return value to $4 no_spsr_restore: jr $ra |