summaryrefslogtreecommitdiff
path: root/psp
diff options
context:
space:
mode:
authorneonloop2021-05-05 17:12:36 +0000
committerneonloop2021-05-05 17:12:59 +0000
commit997d3f2183eb9e99a3a1578a0060cb2fcd2165a2 (patch)
tree5b2afae111495c75ddf5c2b8fd8e6699da50117e /psp
parent3aa34f7503bbb03e9bcd191f8af4fd5faac66d2e (diff)
parent52088a4d10af9a8c0e95b0eb168d4dfd0a13639f (diff)
downloadpicogpsp-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.h63
-rw-r--r--psp/mips_stub.S15
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