X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=pico%2Fcarthw%2Fsvp%2Fcompiler.c;h=758d9261b7d699b56e4ea266d5c2b289c6d299ad;hb=d4d626658a7a999f48009f408b4a22d280ab80ea;hp=4fad3d77e2121093f304088daa559d3e0810b3e9;hpb=41397701210c08b9d25ca66cbe372c7ed86d6927;p=picodrive.git diff --git a/pico/carthw/svp/compiler.c b/pico/carthw/svp/compiler.c index 4fad3d7..758d926 100644 --- a/pico/carthw/svp/compiler.c +++ b/pico/carthw/svp/compiler.c @@ -1,13 +1,22 @@ -// SSP1601 to ARM recompiler - -// (c) Copyright 2008, Grazvydas "notaz" Ignotas -// Free for non-commercial use. +/* + * SSP1601 to ARM recompiler + * (C) notaz, 2008,2009,2010 + * + * This work is licensed under the terms of MAME license. + * See COPYING file in the top-level directory. + */ #include "../../pico_int.h" #include "../../../cpu/drc/cmn.h" #include "compiler.h" -#define u32 unsigned int +// FIXME: asm has these hardcoded +#define SSP_BLOCKTAB_ENTS (0x5090/2) +#define SSP_BLOCKTAB_IRAM_ONE (0x800/2) // table entries +#define SSP_BLOCKTAB_IRAM_ENTS (15*SSP_BLOCKTAB_IRAM_ONE) + +static u32 **ssp_block_table; // [0x5090/2]; +static u32 **ssp_block_table_iram; // [15][0x800/2]; static u32 *tcache_ptr = NULL; @@ -22,14 +31,15 @@ extern ssp1601_t *ssp; #define SSP_FLAG_Z (1<<0xd) #define SSP_FLAG_N (1<<0xf) -#ifndef ARM -#define DUMP_BLOCK 0x0c9a +#ifndef __arm__ +//#define DUMP_BLOCK 0x0c9a void ssp_drc_next(void){} void ssp_drc_next_patch(void){} void ssp_drc_end(void){} #endif -#include "gen_arm.c" +#define COUNT_OP +#include "../../../cpu/drc/emit_arm.c" // ----------------------------------------------------- @@ -279,11 +289,11 @@ static void tr_flush_dirty_prs(void) int i, ror = 0, reg; int dirty = dirty_regb >> 8; if ((dirty&7) == 7) { - emit_mov_const(A_COND_AL, 8, known_regs.r[0]|(known_regs.r[1]<<8)|(known_regs.r[2]<<16)); + emith_move_r_imm(8, known_regs.r[0]|(known_regs.r[1]<<8)|(known_regs.r[2]<<16)); dirty &= ~7; } if ((dirty&0x70) == 0x70) { - emit_mov_const(A_COND_AL, 9, known_regs.r[4]|(known_regs.r[5]<<8)|(known_regs.r[6]<<16)); + emith_move_r_imm(9, known_regs.r[4]|(known_regs.r[5]<<8)|(known_regs.r[6]<<16)); dirty &= ~0x70; } /* r0-r7 */ @@ -342,14 +352,14 @@ static void tr_make_dirty_ST(void) static void tr_mov16(int r, int val) { if (hostreg_r[r] != val) { - emit_mov_const(A_COND_AL, r, val); + emith_move_r_imm(r, val); hostreg_r[r] = val; } } static void tr_mov16_cond(int cond, int r, int val) { - emit_mov_const(cond, r, val); + emith_op_imm(cond, 0, A_OP_MOV, r, val); hostreg_r[r] = -1; } @@ -361,7 +371,7 @@ static void tr_flush_dirty_pmcrs(void) if (dirty_regb & KRREG_PMC) { val = known_regs.pmc.v; - emit_mov_const(A_COND_AL, 1, val); + emith_move_r_imm(1, val); EOP_STR_IMM(1,7,0x400+SSP_PMC*4); if (known_regs.emu_status & (SSP_PMC_SET|SSP_PMC_HAVE_ADDR)) { @@ -374,14 +384,14 @@ static void tr_flush_dirty_pmcrs(void) if (dirty_regb & (1 << (20+i))) { if (val != known_regs.pmac_read[i]) { val = known_regs.pmac_read[i]; - emit_mov_const(A_COND_AL, 1, val); + emith_move_r_imm(1, val); } EOP_STR_IMM(1,7,0x454+i*4); // pmac_read } if (dirty_regb & (1 << (25+i))) { if (val != known_regs.pmac_write[i]) { val = known_regs.pmac_write[i]; - emit_mov_const(A_COND_AL, 1, val); + emith_move_r_imm(1, val); } EOP_STR_IMM(1,7,0x46c+i*4); // pmac_write } @@ -786,7 +796,7 @@ static void tr_PMX_to_r0(int reg) if ((mode & 0xfff0) == 0x0800) { EOP_LDR_IMM(1,7,0x488); // rom_ptr - emit_mov_const(A_COND_AL, 0, (pmcv&0xfffff)<<1); + emith_move_r_imm(0, (pmcv&0xfffff)<<1); EOP_LDRH_REG(0,1,0); // ldrh r0, [r1, r0] known_regs.pmac_read[reg] += 1; } @@ -794,7 +804,7 @@ static void tr_PMX_to_r0(int reg) { int inc = get_inc(mode); EOP_LDR_IMM(1,7,0x490); // dram_ptr - emit_mov_const(A_COND_AL, 0, (pmcv&0xffff)<<1); + emith_move_r_imm(0, (pmcv&0xffff)<<1); EOP_LDRH_REG(0,1,0); // ldrh r0, [r1, r0] if (reg == 4 && (pmcv == 0x187f03 || pmcv == 0x187f04)) // wait loop detection { @@ -829,7 +839,7 @@ static void tr_PMX_to_r0(int reg) tr_flush_dirty_ST(); //tr_flush_dirty_pmcrs(); tr_mov16(0, reg); - emit_call(A_COND_AL, ssp_pm_read); + emith_call(ssp_pm_read); hostreg_clear(); } @@ -1028,7 +1038,7 @@ static void tr_r0_to_PMX(int reg) int inc = get_inc(mode); if (mode & 0x0400) tr_unhandled(); EOP_LDR_IMM(1,7,0x490); // dram_ptr - emit_mov_const(A_COND_AL, 2, addr<<1); + emith_move_r_imm(2, addr << 1); EOP_STRH_REG(0,1,2); // strh r0, [r1, r2] known_regs.pmac_write[reg] += inc; } @@ -1036,7 +1046,7 @@ static void tr_r0_to_PMX(int reg) { if (mode & 0x0400) tr_unhandled(); EOP_LDR_IMM(1,7,0x490); // dram_ptr - emit_mov_const(A_COND_AL, 2, addr<<1); + emith_move_r_imm(2, addr << 1); EOP_STRH_REG(0,1,2); // strh r0, [r1, r2] known_regs.pmac_write[reg] += (addr&1) ? 31 : 1; } @@ -1044,7 +1054,7 @@ static void tr_r0_to_PMX(int reg) { int inc = get_inc(mode); EOP_LDR_IMM(1,7,0x48c); // iram_ptr - emit_mov_const(A_COND_AL, 2, (addr&0x3ff)<<1); + emith_move_r_imm(2, (addr&0x3ff) << 1); EOP_STRH_REG(0,1,2); // strh r0, [r1, r2] EOP_MOV_IMM(1,0,1); EOP_STR_IMM(1,7,0x494); // iram_dirty @@ -1070,7 +1080,7 @@ static void tr_r0_to_PMX(int reg) tr_flush_dirty_ST(); //tr_flush_dirty_pmcrs(); tr_mov16(1, reg); - emit_call(A_COND_AL, ssp_pm_write); + emith_call(ssp_pm_write); hostreg_clear(); } @@ -1111,7 +1121,7 @@ static void tr_r0_to_PMC(int const_val) { tr_flush_dirty_ST(); if (known_regb & KRREG_PMC) { - emit_mov_const(A_COND_AL, 1, known_regs.pmc.v); + emith_move_r_imm(1, known_regs.pmc.v); EOP_STR_IMM(1,7,0x400+SSP_PMC*4); known_regb &= ~KRREG_PMC; dirty_regb &= ~KRREG_PMC; @@ -1190,7 +1200,10 @@ static int tr_detect_set_pm(unsigned int op, int *pc, int imm) int reg = is_write ? ((tmpv>>4)&0x7) : (tmpv&0x7); if (reg > 4) tr_unhandled(); if ((tmpv & 0x0f) != 0 && (tmpv & 0xf0) != 0) tr_unhandled(); - known_regs.pmac_read[is_write ? reg + 5 : reg] = pmcv; + if (is_write) + known_regs.pmac_write[reg] = pmcv; + else + known_regs.pmac_read[reg] = pmcv; known_regb |= is_write ? (1 << (reg+25)) : (1 << (reg+20)); dirty_regb |= is_write ? (1 << (reg+25)) : (1 << (reg+20)); known_regs.emu_status &= ~SSP_PMC_SET; @@ -1660,7 +1673,7 @@ static void emit_block_prologue(void) // check if there are enough cycles.. // note: r0 must contain PC of current block EOP_CMP_IMM(11,0,0); // cmp r11, #0 - emit_jump(A_COND_LE, ssp_drc_end); + emith_jump_cond(A_COND_LE, ssp_drc_end); } /* cond: @@ -1674,35 +1687,41 @@ static void emit_block_epilogue(int cycles, int cond, int pc, int end_pc) if (cond < 0 || (end_pc >= 0x400 && pc < 0x400)) { // indirect jump, or rom -> iram jump, must use dispatcher - emit_jump(A_COND_AL, ssp_drc_next); + emith_jump(ssp_drc_next); } else if (cond == A_COND_AL) { - u32 *target = (pc < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][pc] : ssp_block_table[pc]; + u32 *target = (pc < 0x400) ? + ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + pc] : + ssp_block_table[pc]; if (target != NULL) - emit_jump(A_COND_AL, target); + emith_jump(target); else { - int ops = emit_jump(A_COND_AL, ssp_drc_next); + int ops = emith_jump(ssp_drc_next); // cause the next block to be emitted over jump instruction tcache_ptr -= ops; } } else { - u32 *target1 = (pc < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][pc] : ssp_block_table[pc]; - u32 *target2 = (end_pc < 0x400) ? ssp_block_table_iram[ssp->drc.iram_context][end_pc] : ssp_block_table[end_pc]; + u32 *target1 = (pc < 0x400) ? + ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + pc] : + ssp_block_table[pc]; + u32 *target2 = (end_pc < 0x400) ? + ssp_block_table_iram[ssp->drc.iram_context * SSP_BLOCKTAB_IRAM_ONE + end_pc] : + ssp_block_table[end_pc]; if (target1 != NULL) - emit_jump(cond, target1); + emith_jump_cond(cond, target1); if (target2 != NULL) - emit_jump(tr_neg_cond(cond), target2); // neg_cond, to be able to swap jumps if needed + emith_jump_cond(tr_neg_cond(cond), target2); // neg_cond, to be able to swap jumps if needed #ifndef __EPOC32__ // emit patchable branches if (target1 == NULL) - emit_call(cond, ssp_drc_next_patch); + emith_call_cond(cond, ssp_drc_next_patch); if (target2 == NULL) - emit_call(tr_neg_cond(cond), ssp_drc_next_patch); + emith_call_cond(tr_neg_cond(cond), ssp_drc_next_patch); #else // won't patch indirect jumps if (target1 == NULL || target2 == NULL) - emit_jump(A_COND_AL, ssp_drc_next); + emith_jump(ssp_drc_next); #endif } } @@ -1746,7 +1765,7 @@ void *ssp_translate_block(int pc) if (ccount >= 100) { end_cond = A_COND_AL; jump_pc = pc; - emit_mov_const(A_COND_AL, 0, pc); + emith_move_r_imm(0, pc); } tr_flush_dirty_prs(); @@ -1754,7 +1773,7 @@ void *ssp_translate_block(int pc) tr_flush_dirty_pmcrs(); emit_block_epilogue(ccount, end_cond, jump_pc, pc); - if (tcache_ptr - tcache > SSP_TCACHE_SIZE/4) { + if (tcache_ptr - (u32 *)tcache > DRC_TCACHE_SIZE/4) { elprintf(EL_ANOMALY|EL_STATUS|EL_SVP, "tcache overflow!\n"); fflush(stdout); exit(1); @@ -1775,7 +1794,9 @@ void *ssp_translate_block(int pc) exit(0); #endif - handle_caches(); +#ifdef __arm__ + cache_flush_d_inval_i(tcache, tcache_ptr); +#endif return block_start; } @@ -1790,28 +1811,44 @@ static void ssp1601_state_load(void) ssp->drc.iram_context = 0; } +void ssp1601_dyn_exit(void) +{ + free(ssp_block_table); + free(ssp_block_table_iram); + ssp_block_table = ssp_block_table_iram = NULL; + + drc_cmn_cleanup(); +} + int ssp1601_dyn_startup(void) { drc_cmn_init(); - memset(tcache, 0, SSP_TCACHE_SIZE); - memset(ssp_block_table, 0, sizeof(ssp_block_table)); - memset(ssp_block_table_iram, 0, sizeof(ssp_block_table_iram)); - tcache_ptr = tcache; + ssp_block_table = calloc(sizeof(ssp_block_table[0]), SSP_BLOCKTAB_ENTS); + if (ssp_block_table == NULL) + return -1; + ssp_block_table_iram = calloc(sizeof(ssp_block_table_iram[0]), SSP_BLOCKTAB_IRAM_ENTS); + if (ssp_block_table_iram == NULL) { + free(ssp_block_table); + return -1; + } + + memset(tcache, 0, DRC_TCACHE_SIZE); + tcache_ptr = (void *)tcache; PicoLoadStateHook = ssp1601_state_load; n_in_ops = 0; -#ifdef ARM +#ifdef __arm__ // hle'd blocks ssp_block_table[0x800/2] = (void *) ssp_hle_800; ssp_block_table[0x902/2] = (void *) ssp_hle_902; - ssp_block_table_iram[ 7][0x030/2] = (void *) ssp_hle_07_030; - ssp_block_table_iram[ 7][0x036/2] = (void *) ssp_hle_07_036; - ssp_block_table_iram[ 7][0x6d6/2] = (void *) ssp_hle_07_6d6; - ssp_block_table_iram[11][0x12c/2] = (void *) ssp_hle_11_12c; - ssp_block_table_iram[11][0x384/2] = (void *) ssp_hle_11_384; - ssp_block_table_iram[11][0x38a/2] = (void *) ssp_hle_11_38a; + ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ONE + 0x030/2] = (void *) ssp_hle_07_030; + ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ONE + 0x036/2] = (void *) ssp_hle_07_036; + ssp_block_table_iram[ 7 * SSP_BLOCKTAB_IRAM_ONE + 0x6d6/2] = (void *) ssp_hle_07_6d6; + ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ONE + 0x12c/2] = (void *) ssp_hle_11_12c; + ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ONE + 0x384/2] = (void *) ssp_hle_11_384; + ssp_block_table_iram[11 * SSP_BLOCKTAB_IRAM_ONE + 0x38a/2] = (void *) ssp_hle_11_38a; #endif return 0; @@ -1842,7 +1879,7 @@ void ssp1601_dyn_run(int cycles) #ifdef DUMP_BLOCK ssp_translate_block(DUMP_BLOCK >> 1); #endif -#ifdef ARM +#ifdef __arm__ ssp_drc_entry(cycles); #endif }