OBJS += libpcsxcore/new_dynarec/pcsxmem.o
endif
OBJS += libpcsxcore/new_dynarec/emu_if.o
-libpcsxcore/new_dynarec/new_dynarec.o: libpcsxcore/new_dynarec/assem_arm.c
+libpcsxcore/new_dynarec/new_dynarec.o: libpcsxcore/new_dynarec/assem_arm.c \
+ libpcsxcore/new_dynarec/pcsxmem_inline.c
libpcsxcore/new_dynarec/new_dynarec.o: CFLAGS += -Wno-all -Wno-pointer-sign
ifdef DRC_DBG
libpcsxcore/new_dynarec/emu_if.o: CFLAGS += -D_FILE_OFFSET_BITS=64
mee_onoff_h ("Disable CD Audio", 0, Config.Cdda, 1, h_cfg_cdda),
mee_onoff_h ("SIO IRQ Always Enabled", 0, Config.Sio, 1, h_cfg_sio),
mee_onoff_h ("SPU IRQ Always Enabled", 0, Config.SpuIrq, 1, h_cfg_spuirq),
- mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1),
+ //mee_onoff_h ("Rootcounter hack", 0, Config.RCntFix, 1, h_cfg_rcnt1),
mee_onoff_h ("Rootcounter hack 2", 0, Config.VSyncWA, 1, h_cfg_rcnt2),
mee_enum_h ("CD read reschedule hack",0, Config.CdrReschedule, men_cfg_cdrr, h_cfg_cdrr),
mee_range_h ("PSX CPU clock, %%", 0, psx_clock, 1, 500, h_cfg_psxclk),
output_w32(0x31a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
}
+void emit_shrne_imm(int rs,u_int imm,int rt)
+{
+ assert(imm>0);
+ assert(imm<32);
+ assem_debug("lsrne %s,%s,#%d\n",regname[rt],regname[rs],imm);
+ output_w32(0x11a00000|rd_rn_rm(rt,0,rs)|0x20|(imm<<7));
+}
+
void emit_negmi(int rs, int rt)
{
assem_debug("rsbmi %s,%s,#0\n",regname[rt],regname[rs]);
}
}
+static void mov_loadtype_adj(int type,int rs,int rt)
+{
+ switch(type) {
+ case LOADB_STUB: emit_signextend8(rs,rt); break;
+ case LOADBU_STUB: emit_andimm(rs,0xff,rt); break;
+ case LOADH_STUB: emit_signextend16(rs,rt); break;
+ case LOADHU_STUB: emit_andimm(rs,0xffff,rt); break;
+ case LOADW_STUB: if(rs!=rt) emit_mov(rs,rt); break;
+ default: assert(0);
+ }
+}
+
+#ifdef PCSX
+#include "pcsxmem.h"
+#include "pcsxmem_inline.c"
+#endif
+
do_readstub(int n)
{
assem_debug("do_readstub %x\n",start+stubs[n][3]*4);
emit_addimm(cc<0?2:cc,CLOCK_ADJUST((int)stubs[n][6]+1),2);
emit_call(handler);
if(itype[i]==C1LS||itype[i]==C2LS||(rt>=0&&rt1[i]!=0)) {
- switch(type) {
- case LOADB_STUB: emit_signextend8(0,rt); break;
- case LOADBU_STUB: emit_andimm(0,0xff,rt); break;
- case LOADH_STUB: emit_signextend16(0,rt); break;
- case LOADHU_STUB: emit_andimm(0,0xffff,rt); break;
- case LOADW_STUB: if(rt!=0) emit_mov(0,rt); break;
- }
+ mov_loadtype_adj(type,0,rt);
}
if(restore_jump)
set_jump_target(restore_jump,(int)out);
if(rs<0) rs=get_reg(regmap,-1);
assert(rs>=0);
#ifdef PCSX
- u_int handler,host_addr=0;
+ u_int handler,host_addr=0,is_dynamic,far_call=0;
+ int cc=get_reg(regmap,CCREG);
+ if(pcsx_direct_read(type,addr,CLOCK_ADJUST(adj+1),cc,target?rs:-1,rt))
+ return;
handler=get_direct_memhandler(mem_rtab,addr,type,&host_addr);
if (handler==0) {
if(rt<0)
}
return;
}
+ is_dynamic=pcsxmem_is_handler_dynamic(addr);
+ if(is_dynamic) {
+ if(type==LOADB_STUB||type==LOADBU_STUB)
+ handler=(int)jump_handler_read8;
+ if(type==LOADH_STUB||type==LOADHU_STUB)
+ handler=(int)jump_handler_read16;
+ if(type==LOADW_STUB)
+ handler=(int)jump_handler_read32;
+ }
// call a memhandler
if(rt>=0)
emit_movimm(addr,0);
else if(rs!=0)
emit_mov(rs,0);
- int cc=get_reg(regmap,CCREG);
- if(cc<0)
- emit_loadreg(CCREG,2);
- emit_readword((int)&last_count,3);
- emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
- emit_add(2,3,3);
- emit_writeword(3,(int)&Count);
-
int offset=(int)handler-(int)out-8;
if(offset<-33554432||offset>=33554432) {
// unreachable memhandler, a plugin func perhaps
- emit_movimm(handler,1);
- emit_callreg(1);
+ emit_movimm(handler,12);
+ far_call=1;
+ }
+ if(cc<0)
+ emit_loadreg(CCREG,2);
+ if(is_dynamic) {
+ emit_movimm(((u_int *)mem_rtab)[addr>>12]<<1,1);
+ emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
}
+ else {
+ emit_readword((int)&last_count,3);
+ emit_addimm(cc<0?2:cc,CLOCK_ADJUST(adj+1),2);
+ emit_add(2,3,2);
+ emit_writeword(2,(int)&Count);
+ }
+
+ if(far_call)
+ emit_callreg(12);
else
emit_call(handler);
+
if(rt>=0) {
switch(type) {
case LOADB_STUB: emit_signextend8(0,rt); break;
int i;
for (i = 0; i < PSXINT_COUNT; i++)
event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
+
+ new_dyna_pcsx_mem_load_state();
}
void *gte_handlers[64];
void invalidate_block(unsigned int block) {}
void new_dyna_pcsx_mem_init(void) {}
void new_dyna_pcsx_mem_reset(void) {}
+void new_dyna_pcsx_mem_load_state(void) {}
#endif
#ifdef DRC_DBG
void jump_handler_write_h(u32 addr, u32 data, u32 cycles, void *handler);
void jump_handle_swl(u32 addr, u32 data, u32 cycles);
void jump_handle_swr(u32 addr, u32 data, u32 cycles);
+void rcnt0_read_count_m0(u32 addr, u32, u32 cycles);
+void rcnt0_read_count_m1(u32 addr, u32, u32 cycles);
+void rcnt1_read_count_m0(u32 addr, u32, u32 cycles);
+void rcnt1_read_count_m1(u32 addr, u32, u32 cycles);
+void rcnt2_read_count_m0(u32 addr, u32, u32 cycles);
+void rcnt2_read_count_m1(u32 addr, u32, u32 cycles);
extern unsigned int address;
extern void *psxH_ptr;
.global psxH_ptr
.global inv_code_start
.global inv_code_end
+ .global rcnts
.bss
.align 4
.type dynarec_local, %object
.size dynarec_local, dynarec_local_end-dynarec_local
dynarec_local:
- .space dynarec_local_end-dynarec_local /*0x400630*/
+ .space dynarec_local_end-dynarec_local
next_interupt = dynarec_local + 64
.type next_interupt, %object
.size next_interupt, 4
.size intCycle, 256
psxRegs_end = intCycle + 256
-mem_rtab = psxRegs_end
+rcnts = psxRegs_end
+ .type rcnts, %object
+ .size rcnts, 7*4*4
+rcnts_end = rcnts + 7*4*4
+
+mem_rtab = rcnts_end
.type mem_rtab, %object
.size mem_rtab, 4
mem_wtab = mem_rtab + 4
.endif
.endm
+.macro mov_16 reg imm
+.if HAVE_ARMV7
+ movw \reg, #\imm
+.else
+ mov \reg, #(\imm & 0x00ff)
+ orr \reg, #(\imm & 0xff00)
+.endif
+.endm
+
+.macro mov_24 reg imm
+.if HAVE_ARMV7
+ movw \reg, #(\imm & 0xffff)
+ movt \reg, #(\imm >> 16)
+.else
+ mov \reg, #(\imm & 0x0000ff)
+ orr \reg, #(\imm & 0x00ff00)
+ orr \reg, #(\imm & 0xff0000)
+.endif
+.endm
+
.macro dyna_linker_main
/* r0 = virtual target address */
/* r1 = instruction to patch */
.global jump_handler_write_h
.global jump_handle_swl
.global jump_handle_swr
+.global rcnt0_read_count_m0
+.global rcnt0_read_count_m1
+.global rcnt1_read_count_m0
+.global rcnt1_read_count_m1
+.global rcnt2_read_count_m0
+.global rcnt2_read_count_m1
.macro pcsx_read_mem readop tab_shift
bx lr @ TODO?
+.macro rcntx_read_mode0 num
+ /* r0 = address, r2 = cycles */
+ ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*\num] @ cycleStart
+ mov r0, r2, lsl #16
+ sub r0, r3, lsl #16
+ lsr r0, #16
+ bx lr
+.endm
+
+rcnt0_read_count_m0:
+ rcntx_read_mode0 0
+
+rcnt1_read_count_m0:
+ rcntx_read_mode0 1
+
+rcnt2_read_count_m0:
+ rcntx_read_mode0 2
+
+rcnt0_read_count_m1:
+ /* r0 = address, r2 = cycles */
+ ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*0] @ cycleStart
+ mov_16 r1, 0x3334
+ sub r2, r2, r3
+ mul r0, r1, r2 @ /= 5
+ lsr r0, #16
+ bx lr
+
+rcnt1_read_count_m1:
+ /* r0 = address, r2 = cycles */
+ ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*1]
+ mov_24 r1, 0x1e6cde
+ sub r2, r2, r3
+ umull r3, r0, r1, r2 @ ~ /= hsync_cycles, max ~0x1e6cdd
+ bx lr
+
+rcnt2_read_count_m1:
+ /* r0 = address, r2 = cycles */
+ ldr r3, [fp, #rcnts-dynarec_local+6*4+7*4*2]
+ mov r0, r2, lsl #16-3
+ sub r0, r3, lsl #16-3
+ lsr r0, #16 @ /= 8
+ bx lr
+
@ vim:filetype=armasm
//#define memprintf printf
#define memprintf(...)
+static u32 *mem_readtab;
+static u32 *mem_writetab;
+static u32 mem_iortab[(1+2+4) * 0x1000 / 4];
+static u32 mem_iowtab[(1+2+4) * 0x1000 / 4];
+static u32 mem_ffwtab[(1+2+4) * 0x1000 / 4];
+//static u32 mem_unmrtab[(1+2+4) * 0x1000 / 4];
+static u32 mem_unmwtab[(1+2+4) * 0x1000 / 4];
+
+static void map_item(u32 *out, const void *h, u32 flag)
+{
+ u32 hv = (u32)h;
+ if (hv & 1)
+ fprintf(stderr, "%p has LSB set\n", h);
+ *out = (hv >> 1) | (flag << 31);
+}
+
+// size must be power of 2, at least 4k
+#define map_l1_mem(tab, i, addr, size, base) \
+ map_item(&tab[((addr)>>12) + i], (u8 *)(base) - (u32)(addr) - ((i << 12) & ~(size - 1)), 0)
+
+#define IOMEM32(a) (((a) & 0xfff) / 4)
+#define IOMEM16(a) (0x1000/4 + (((a) & 0xfff) / 2))
+#define IOMEM8(a) (0x1000/4 + 0x1000/2 + ((a) & 0xfff))
+
static u8 unmapped_mem[0x1000];
u32 read_mem_dummy()
sioWrite8((unsigned char)(value >> 24));
}
+static void map_rcnt_rcount0(u32 mode)
+{
+ if (mode & 0x01) { // gate
+ map_item(&mem_iortab[IOMEM32(0x1100)], &psxH[0x1000], 0);
+ map_item(&mem_iortab[IOMEM16(0x1100)], &psxH[0x1000], 0);
+ }
+ else if (mode & 0x100) { // pixel clock
+ map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m1, 1);
+ map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m1, 1);
+ }
+ else {
+ map_item(&mem_iortab[IOMEM32(0x1100)], rcnt0_read_count_m0, 1);
+ map_item(&mem_iortab[IOMEM16(0x1100)], rcnt0_read_count_m0, 1);
+ }
+}
+
+static void map_rcnt_rcount1(u32 mode)
+{
+ if (mode & 0x01) { // gate
+ map_item(&mem_iortab[IOMEM32(0x1110)], &psxH[0x1000], 0);
+ map_item(&mem_iortab[IOMEM16(0x1110)], &psxH[0x1000], 0);
+ }
+ else if (mode & 0x100) { // hcnt
+ map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m1, 1);
+ map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m1, 1);
+ }
+ else {
+ map_item(&mem_iortab[IOMEM32(0x1110)], rcnt1_read_count_m0, 1);
+ map_item(&mem_iortab[IOMEM16(0x1110)], rcnt1_read_count_m0, 1);
+ }
+}
+
+static void map_rcnt_rcount2(u32 mode)
+{
+ if (mode & 0x01) { // gate
+ map_item(&mem_iortab[IOMEM32(0x1120)], &psxH[0x1000], 0);
+ map_item(&mem_iortab[IOMEM16(0x1120)], &psxH[0x1000], 0);
+ }
+ else if (mode & 0x200) { // clk/8
+ map_item(&mem_iortab[IOMEM32(0x1120)], rcnt2_read_count_m1, 1);
+ map_item(&mem_iortab[IOMEM16(0x1120)], rcnt2_read_count_m1, 1);
+ }
+ else {
+ map_item(&mem_iortab[IOMEM32(0x1120)], rcnt2_read_count_m0, 1);
+ map_item(&mem_iortab[IOMEM16(0x1120)], rcnt2_read_count_m0, 1);
+ }
+}
+
#define make_rcnt_funcs(i) \
static u32 io_rcnt_read_count##i() { return psxRcntRcount(i); } \
static u32 io_rcnt_read_mode##i() { return psxRcntRmode(i); } \
static u32 io_rcnt_read_target##i() { return psxRcntRtarget(i); } \
static void io_rcnt_write_count##i(u32 val) { psxRcntWcount(i, val & 0xffff); } \
-static void io_rcnt_write_mode##i(u32 val) { psxRcntWmode(i, val); } \
+static void io_rcnt_write_mode##i(u32 val) { psxRcntWmode(i, val); map_rcnt_rcount##i(val); } \
static void io_rcnt_write_target##i(u32 val) { psxRcntWtarget(i, val & 0xffff); }
make_rcnt_funcs(0)
wfunc(a + 2, value >> 16);
}
-static u32 *mem_readtab;
-static u32 *mem_writetab;
-static u32 mem_iortab[(1+2+4) * 0x1000 / 4];
-static u32 mem_iowtab[(1+2+4) * 0x1000 / 4];
-static u32 mem_ffwtab[(1+2+4) * 0x1000 / 4];
-//static u32 mem_unmrtab[(1+2+4) * 0x1000 / 4];
-static u32 mem_unmwtab[(1+2+4) * 0x1000 / 4];
-
-static void map_item(u32 *out, const void *h, u32 flag)
-{
- u32 hv = (u32)h;
- if (hv & 1)
- fprintf(stderr, "%p has LSB set\n", h);
- *out = (hv >> 1) | (flag << 31);
-}
-
-// size must be power of 2, at least 4k
-#define map_l1_mem(tab, i, addr, size, base) \
- map_item(&tab[((addr)>>12) + i], (u8 *)(base) - (u32)(addr) - ((i << 12) & ~(size - 1)), 0)
-
-#define IOMEM32(a) (((a) & 0xfff) / 4)
-#define IOMEM16(a) (0x1000/4 + (((a) & 0xfff) / 2))
-#define IOMEM8(a) (0x1000/4 + 0x1000/2 + ((a) & 0xfff))
-
static void map_ram_write(void)
{
int i;
}
}
+void new_dyna_pcsx_mem_load_state(void)
+{
+ map_rcnt_rcount0(rcnts[0].mode);
+ map_rcnt_rcount1(rcnts[1].mode);
+ map_rcnt_rcount2(rcnts[2].mode);
+}
+
+int pcsxmem_is_handler_dynamic(u_int addr)
+{
+ if ((addr & 0xfffff000) != 0x1f801000)
+ return 0;
+
+ addr &= 0xffff;
+ return addr == 0x1100 || addr == 0x1110 || addr == 0x1120;
+}
+
void new_dyna_pcsx_mem_init(void)
{
int i;
mem_rtab = mem_readtab;
mem_wtab = mem_writetab;
+
+ new_dyna_pcsx_mem_load_state();
}
void new_dyna_pcsx_mem_reset(void)
void new_dyna_pcsx_mem_init(void);
void new_dyna_pcsx_mem_reset(void);
+void new_dyna_pcsx_mem_load_state(void);
+
+int pcsxmem_is_handler_dynamic(u_int addr);
--- /dev/null
+/*
+ * (C) GraÅžvydas "notaz" Ignotas, 2011
+ *
+ * This work is licensed under the terms of GNU GPL version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+static int pcsx_direct_read(int type, u_int addr, int cc_adj, int cc, int rs, int rt)
+{
+ if ((addr & 0xfffff000) == 0x1f801000) {
+ u_int t;
+ switch (addr & 0xffff) {
+ case 0x1120: // rcnt2 count
+ if (rt < 0) goto dont_care;
+ if (cc < 0) return 0;
+ emit_readword((int)&rcnts[2].mode, HOST_TEMPREG);
+ emit_readword((int)&rcnts[2].cycleStart, rt);
+ emit_testimm(HOST_TEMPREG, 0x200);
+ emit_readword((int)&last_count, HOST_TEMPREG);
+ emit_sub(HOST_TEMPREG, rt, HOST_TEMPREG);
+ emit_add(HOST_TEMPREG, cc, HOST_TEMPREG);
+ if (cc_adj)
+ emit_addimm(HOST_TEMPREG, cc_adj, rt);
+ emit_shrne_imm(rt, 3, rt);
+ mov_loadtype_adj(type!=LOADW_STUB?type:LOADH_STUB, rt, rt);
+ goto hit;
+ case 0x1104:
+ case 0x1114:
+ case 0x1124: // rcnt mode
+ if (rt < 0) return 0;
+ t = (addr >> 4) & 3;
+ emit_readword((int)&rcnts[t].mode, rt);
+ emit_andimm(rt, ~0x1800, HOST_TEMPREG);
+ emit_writeword(HOST_TEMPREG, (int)&rcnts[t].mode);
+ mov_loadtype_adj(type, rt, rt);
+ goto hit;
+ }
+ }
+ else {
+ if (rt < 0)
+ goto dont_care;
+ }
+
+ return 0;
+
+hit:
+ assem_debug("pcsx_direct_read %08x end\n", addr);
+ return 1;
+
+dont_care:
+ assem_debug("pcsx_direct_read %08x dummy\n", addr);
+ return 1;
+}
+
+// vim:shiftwidth=2:expandtab
/******************************************************************************/
-typedef struct Rcnt
-{
- u16 mode, target;
- u32 rate, irq, counterState, irqState;
- u32 cycle, cycleStart;
-} Rcnt;
-
enum
{
Rc0Gate = 0x0001, // 0 not implemented
/******************************************************************************/
-static Rcnt rcnts[ CounterQuantity ];
+Rcnt rcnts[ CounterQuantity ];
static u32 hSyncCount = 0;
static u32 spuSyncCount = 0;
extern u32 psxNextCounter, psxNextsCounter;
+typedef struct Rcnt
+{
+ u16 mode, target;
+ u32 rate, irq, counterState, irqState;
+ u32 cycle, cycleStart;
+} Rcnt;
+extern Rcnt rcnts[];
+
void psxRcntInit();
void psxRcntUpdate();