From 90b1c9db91ccede5fa7a561548376edcf440e7dc Mon Sep 17 00:00:00 2001 From: kub Date: Wed, 11 Dec 2019 20:16:14 +0100 Subject: [PATCH] sh2 drc: cleanup, fix for drc crash, for mips code emitter --- cpu/drc/emit_mips.c | 110 ++++++++++++++++++------------------ cpu/sh2/compiler.c | 50 ++++++++++++---- cpu/sh2/compiler.h | 31 +++++----- cpu/sh2/sh2.h | 28 ++++----- pico/arm_features.h | 12 ++-- pico/pico_port.h | 2 + platform/common/disarm.c | 4 +- platform/common/disarm.h | 2 +- platform/common/dismips.c | 11 +++- platform/common/dismips.h | 2 +- platform/common/host_dasm.c | 4 +- tools/mkoffsets.sh | 15 +++-- 12 files changed, 151 insertions(+), 120 deletions(-) diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index 453801f1..765986a6 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -20,6 +20,9 @@ #define STATIC_SH2_REGS { SHR_SR,22 , SHR_R0,21 , SHR_R0+1,20 } // NB: the ubiquitous JZ74[46]0 uses MIPS32 Release 1, a slight MIPS II superset +#ifndef __mips_isa_rev +#define __mips_isa_rev 1 // surprisingly not always defined +#endif // registers usable for user code: r1-r25, others reserved or special #define Z0 0 // zero register @@ -333,32 +336,49 @@ static int emith_is_b(u32 op) // B { return ((op>>26) & 074) == OP_BEQ || ((op>>26) == OP__RT && ((op>>16) & 036) == RT_BLTZ); } // register usage for dependency evaluation XXX better do this as in emit_arm? -static uint64_t emith_has_rs[3] = // OP__FN, OP__RT, others - { 0x00fffffffffa0ff0ULL, 0x000fff0fUL, 0xffffffff0f007ff0ULL }; -static uint64_t emith_has_rt[3] = // OP__FN, OP__RT, others - { 0xff00fffffff00cffULL, 0x00000000UL, 0x8000ff0000000030ULL }; -static uint64_t emith_has_rd[3] = // OP__FN, OP__RT, others (rt instead of rd) - { 0xff00fffffff50fffULL, 0x00000000UL, 0x119100ff0f00ff00ULL }; +static uint64_t emith_has_rs[5] = // OP__FN1-3, OP__RT, others + { 0x005ffcffffda0fd2ULL, 0x0000003300000037ULL, 0x00000000000000ffULL, + 0x800f5f0fUL, 0xf7ffffff0ff07ff0ULL }; +static uint64_t emith_has_rt[5] = // OP__FN1-3, OP__RT, others + { 0xdd5ffcffffd00cddULL, 0x0000000000000037ULL, 0x0000001100000000ULL, + 0x00000000UL, 0x80007f440c300030ULL }; +static uint64_t emith_has_rd[5] = // OP__FN1-3, OP__RT, others(rt instead of rd) + { 0xdd00fcff00d50edfULL, 0x0000003300000004ULL, 0x08000011000000ffULL, + 0x00000000UL, 0x119100ff0f00ff00ULL }; #define emith_has_(rx,ix,op,sa,m) \ (emith_has_##rx[ix] & (1ULL << (((op)>>(sa)) & (m)))) static int emith_rs(u32 op) { if ((op>>26) == OP__FN) return emith_has_(rs,0,op, 0,0x3f) ? (op>>21)&0x1f : 0; + if ((op>>26) == OP__FN2) + return emith_has_(rs,1,op, 0,0x3f) ? (op>>21)&0x1f : 0; + if ((op>>26) == OP__FN3) + return emith_has_(rs,2,op, 0,0x3f) ? (op>>21)&0x1f : 0; if ((op>>26) == OP__RT) - return emith_has_(rs,1,op,16,0x1f) ? (op>>21)&0x1f : 0; - return emith_has_(rs,2,op,26,0x3f) ? (op>>21)&0x1f : 0; + return emith_has_(rs,3,op,16,0x1f) ? (op>>21)&0x1f : 0; + return emith_has_(rs,4,op,26,0x3f) ? (op>>21)&0x1f : 0; } static int emith_rt(u32 op) { if ((op>>26) == OP__FN) return emith_has_(rt,0,op, 0,0x3f) ? (op>>16)&0x1f : 0; + if ((op>>26) == OP__FN2) + return emith_has_(rt,1,op, 0,0x3f) ? (op>>16)&0x1f : 0; + if ((op>>26) == OP__FN3) + return emith_has_(rt,2,op, 0,0x3f) ? (op>>16)&0x1f : 0; if ((op>>26) == OP__RT) return 0; - return emith_has_(rt,2,op,26,0x3f) ? (op>>16)&0x1f : 0; + return emith_has_(rt,4,op,26,0x3f) ? (op>>16)&0x1f : 0; } static int emith_rd(u32 op) - { int ret = emith_has_(rd,2,op,26,0x3f) ? (op>>16)&0x1f :-1; + { int ret = emith_has_(rd,4,op,26,0x3f) ? (op>>16)&0x1f :-1; if ((op>>26) == OP__FN) ret = emith_has_(rd,0,op, 0,0x3f) ? (op>>11)&0x1f :-1; + if ((op>>26) == OP__FN2) + ret = emith_has_(rd,1,op, 0,0x3f) ? (op>>11)&0x1f :-1; + if ((op>>26) == OP__FN3 && (op&0x3f) == FN3_BSHFL) + ret = emith_has_(rd,2,op, 0,0x3f) ? (op>>11)&0x1f :-1; + if ((op>>26) == OP__FN3 && (op&0x3f) != FN3_BSHFL) + ret = emith_has_(rd,2,op, 0,0x3f) ? (op>>16)&0x1f :-1; if ((op>>26) == OP__RT) ret = -1; return (ret ?: -1); // Z0 doesn't have dependencies @@ -970,29 +990,23 @@ static void emith_log_imm(int op, int rd, int rs, u32 imm) #define emith_asr(d, s, cnt) \ EMIT(MIPS_ASR_IMM(d, s, cnt)) -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 -#define emith_ror(d, s, cnt) \ - EMIT(MIPS_ROR_IMM(d, s, cnt)) -#else #define emith_ror(d, s, cnt) do { \ - EMIT(MIPS_LSL_IMM(AT, s, 32-(cnt))); \ - EMIT(MIPS_LSR_IMM(d, s, cnt)); \ - EMIT(MIPS_OR_REG(d, d, AT)); \ + if (__mips_isa_rev < 2) { \ + EMIT(MIPS_LSL_IMM(AT, s, 32-(cnt))); \ + EMIT(MIPS_LSR_IMM(d, s, cnt)); \ + EMIT(MIPS_OR_REG(d, d, AT)); \ + } else EMIT(MIPS_ROR_IMM(d, s, cnt)); \ } while (0) -#endif #define emith_ror_c(cond, d, s, cnt) \ emith_ror(d, s, cnt) -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 -#define emith_rol(d, s, cnt) \ - EMIT(MIPS_ROR_IMM(d, s, 32-(cnt))) -#else #define emith_rol(d, s, cnt) do { \ - EMIT(MIPS_LSR_IMM(AT, s, 32-(cnt))); \ - EMIT(MIPS_LSL_IMM(d, s, cnt)); \ - EMIT(MIPS_OR_REG(d, d, AT)); \ + if (__mips_isa_rev < 2) { \ + EMIT(MIPS_LSR_IMM(AT, s, 32-(cnt))); \ + EMIT(MIPS_LSL_IMM(d, s, cnt)); \ + EMIT(MIPS_OR_REG(d, d, AT)); \ + } else EMIT(MIPS_ROR_IMM(d, s, 32-(cnt))); \ } while (0) -#endif #define emith_rorc(d) do { \ emith_lsr(d, d, 1); \ @@ -1082,13 +1096,11 @@ static void emith_log_imm(int op, int rd, int rs, u32 imm) } while (0) // signed/unsigned extend -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 -#define emith_clear_msb(d, s, count) /* bits to clear */ \ - EMIT(MIPS_EXT_IMM(d, s, 0, 32-(count))) -#else #define emith_clear_msb(d, s, count) /* bits to clear */ do { \ u32 t; \ - if ((count) >= 16) { \ + if (__mips_isa_rev >= 2) \ + EMIT(MIPS_EXT_IMM(d, s, 0, 32-(count))); \ + else if ((count) >= 16) { \ t = (count) - 16; \ t = 0xffff >> t; \ emith_and_r_r_imm(d, s, t); \ @@ -1097,27 +1109,19 @@ static void emith_log_imm(int op, int rd, int rs, u32 imm) emith_lsr(d, d, count); \ } \ } while (0) -#endif #define emith_clear_msb_c(cond, d, s, count) \ emith_clear_msb(d, s, count) -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 #define emith_sext(d, s, count) /* bits to keep */ do { \ - if (count == 8) \ + if (__mips_isa_rev >= 2 && count == 8) \ EMIT(MIPS_SEB_REG(d, s)); \ - else if (count == 16) \ + else if (__mips_isa_rev >= 2 && count == 16) \ EMIT(MIPS_SEH_REG(d, s)); \ else { \ emith_lsl(d, s, 32-(count)); \ emith_asr(d, d, 32-(count)); \ } \ } while (0) -#else -#define emith_sext(d, s, count) /* bits to keep */ do { \ - emith_lsl(d, s, 32-(count)); \ - emith_asr(d, d, 32-(count)); \ -} while (0) -#endif // multiply Rd = Rn*Rm (+ Ra); NB: next 2 insns after MFLO/MFHI mustn't be MULT static u8 *last_lohi; @@ -1716,26 +1720,20 @@ static int emith_cond_check(int cond, int *r) EMITH_SJMP_END(DCOND_EQ); \ } while (0) -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 -#define emith_write_sr(sr, srcr) \ - EMIT(MIPS_INS_IMM(sr, srcr, 0, 10)) -#else #define emith_write_sr(sr, srcr) do { \ - emith_lsr(sr, sr , 10); emith_lsl(sr, sr, 10); \ - emith_lsl(AT, srcr, 22); emith_lsr(AT, AT, 22); \ - emith_or_r_r(sr, AT); \ + if (__mips_isa_rev < 2) { \ + emith_lsr(sr, sr , 10); emith_lsl(sr, sr, 10); \ + emith_lsl(AT, srcr, 22); emith_lsr(AT, AT, 22); \ + emith_or_r_r(sr, AT); \ + } else EMIT(MIPS_INS_IMM(sr, srcr, 0, 10)); \ } while (0) -#endif -#if defined(__mips_isa_rev) && __mips_isa_rev >= 2 -#define emith_carry_to_t(sr, is_sub) \ - EMIT(MIPS_INS_IMM(sr, FC, 0, 1)) -#else #define emith_carry_to_t(sr, is_sub) do { \ - emith_and_r_imm(sr, 0xfffffffe); \ - emith_or_r_r(sr, FC); \ + if (__mips_isa_rev < 2) { \ + emith_and_r_imm(sr, 0xfffffffe); \ + emith_or_r_r(sr, FC); \ + } else EMIT(MIPS_INS_IMM(sr, FC, 0, 1)); \ } while (0) -#endif #define emith_t_to_carry(sr, is_sub) do { \ emith_and_r_r_imm(FC, sr, 1); \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index 57bfc212..ca9a0550 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -440,7 +440,7 @@ static int rcache_get_tmp(void); static void rcache_free_tmp(int hr); // Note: Register assignment goes by ABI convention. Caller save registers are -// TEMPORARY, the others are PRESERVED. Unusable regs are omitted. +// TEMPORARY, callee save registers are PRESERVED. Unusable regs are omitted. // there must be at least the free (not context or statically mapped) amount of // PRESERVED/TEMPORARY registers used by handlers in worst case (currently 4). // there must be at least 3 PARAM, and PARAM+TEMPORARY must be at least 4. @@ -496,6 +496,11 @@ static void REGPARM(2) (*sh2_drc_write8)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write16)(u32 a, u32 d); static void REGPARM(2) (*sh2_drc_write32)(u32 a, u32 d); +#ifdef DRC_SR_REG +void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2); +void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); +#endif + // flags for memory access #define MF_SIZEMASK 0x03 // size of access #define MF_POSTINCR 0x10 // post increment (for read_rr) @@ -1578,7 +1583,7 @@ static void rcache_unmap_vreg(int x) FOR_ALL_BITS_SET_DO(cache_regs[x].gregs, i, if (guest_regs[i].flags & GRF_DIRTY) { // if a dirty reg is unmapped save its value to context - if ((~rcache_regs_discard | rcache_regs_now) & (1 << i)) + if (~rcache_regs_discard & (1 << i)) emith_ctx_write(cache_regs[x].hreg, i * 4); guest_regs[i].flags &= ~GRF_DIRTY; } @@ -3107,6 +3112,7 @@ static void REGPARM(2) *sh2_translate(SH2 *sh2, int tcache_id) op_flags[i+1] |= OF_BTARGET; // RTE entrypoint in case of SR.IMASK change // unify T and SR since rcache doesn't know about "virtual" guest regs if (ops[i].source & BITMASK1(SHR_T)) ops[i].source |= BITMASK1(SHR_SR); + if (ops[i].dest & BITMASK1(SHR_T)) ops[i].source |= BITMASK1(SHR_SR); if (ops[i].dest & BITMASK1(SHR_T)) ops[i].dest |= BITMASK1(SHR_SR); #if LOOP_DETECTION // loop types detected: @@ -5028,7 +5034,6 @@ static void sh2_generate_utils(void) emith_move_r_r_ptr(arg0, CONTEXT_REG); emith_ctx_read(arg1, offsetof(SH2, drc_tmp)); // tcache_id emith_call(sh2_translate); -/* just after lookup function, jump to address returned */ emith_tst_r_r_ptr(RET_REG, RET_REG); EMITH_SJMP_START(DCOND_EQ); emith_jump_reg_c(DCOND_NE, RET_REG); @@ -5057,8 +5062,8 @@ static void sh2_generate_utils(void) emith_ctx_read(arg2, offsetof(SH2, rts_cache_idx)); emith_add_r_r_r_lsl_ptr(arg1, CONTEXT_REG, arg2, 0); emith_read_r_r_offs(arg3, arg1, offsetof(SH2, rts_cache)); -#if (DRC_DEBUG & 128) emith_cmp_r_r(arg0, arg3); +#if (DRC_DEBUG & 128) EMITH_SJMP_START(DCOND_EQ); emith_move_r_ptr_imm(arg3, (uptr)&rcmiss); emith_read_r_r_offs_c(DCOND_NE, arg1, arg3, 0); @@ -5067,7 +5072,6 @@ static void sh2_generate_utils(void) emith_jump_cond(DCOND_NE, sh2_drc_dispatcher); EMITH_SJMP_END(DCOND_EQ); #else - emith_cmp_r_r(arg0, arg3); emith_jump_cond(DCOND_NE, sh2_drc_dispatcher); #endif emith_read_r_r_offs_ptr(arg0, arg1, offsetof(SH2, rts_cache) + sizeof(void *)); @@ -5109,7 +5113,7 @@ static void sh2_generate_utils(void) emith_call(p32x_sh2_write32); // XXX: use sh2_drc_write32? // push PC rcache_get_reg_arg(0, SHR_SP, NULL); - emith_ctx_read(arg1, SHR_PC * 4); + rcache_get_reg_arg(1, SHR_PC, NULL); emith_move_r_r_ptr(arg2, CONTEXT_REG); rcache_invalidate_tmp(); emith_call(p32x_sh2_write32); @@ -5143,6 +5147,24 @@ static void sh2_generate_utils(void) emith_jump(sh2_drc_dispatcher); emith_flush(); +#ifdef DRC_SR_REG + // sh2_drc_save_sr(SH2 *sh2) + sh2_drc_save_sr = (void *)tcache_ptr; + tmp = rcache_get_reg(SHR_SR, RC_GR_READ, NULL); + emith_write_r_r_offs(tmp, arg0, SHR_SR * 4); + rcache_invalidate(); + emith_ret(); + emith_flush(); + + // sh2_drc_restore_sr(SH2 *sh2) + sh2_drc_restore_sr = (void *)tcache_ptr; + tmp = rcache_get_reg(SHR_SR, RC_GR_WRITE, NULL); + emith_read_r_r_offs(tmp, arg0, SHR_SR * 4); + rcache_flush(); + emith_ret(); + emith_flush(); +#endif + #ifdef PDB_NET // debug #define MAKE_READ_WRAPPER(func) { \ @@ -5204,6 +5226,10 @@ static void sh2_generate_utils(void) host_dasm_new_symbol(sh2_drc_read8_poll); host_dasm_new_symbol(sh2_drc_read16_poll); host_dasm_new_symbol(sh2_drc_read32_poll); +#ifdef DRC_SR_REG + host_dasm_new_symbol(sh2_drc_save_sr); + host_dasm_new_symbol(sh2_drc_restore_sr); +#endif #endif #if DRC_DEBUG @@ -5273,12 +5299,12 @@ static void sh2_smc_rm_blocks(u32 a, int len, int tcache_id, u32 shift) #endif } -void sh2_drc_wcheck_ram(unsigned int a, unsigned len, SH2 *sh2) +void sh2_drc_wcheck_ram(u32 a, unsigned len, SH2 *sh2) { sh2_smc_rm_blocks(a, len, 0, SH2_DRCBLK_RAM_SHIFT); } -void sh2_drc_wcheck_da(unsigned int a, unsigned len, SH2 *sh2) +void sh2_drc_wcheck_da(u32 a, unsigned len, SH2 *sh2) { sh2_smc_rm_blocks(a, len, 1 + sh2->is_slave, SH2_DRCBLK_DA_SHIFT); } @@ -5295,7 +5321,7 @@ int sh2_execute_drc(SH2 *sh2c, int cycles) sh2_drc_entry(sh2c); // TODO: irq cycles - ret_cycles = (signed int)sh2c->sr >> 12; + ret_cycles = (int32_t)sh2c->sr >> 12; if (ret_cycles > 0) dbg(1, "warning: drc returned with cycles: %d", ret_cycles); @@ -5777,6 +5803,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out, break; case 1: // DIV0U 0000000000011001 CHECK_UNHANDLED_BITS(0xf00, undefined); + opd->source = BITMASK1(SHR_SR); opd->dest = BITMASK2(SHR_SR, SHR_T); break; case 2: // MOVT Rn 0000nnnn00101001 @@ -5877,7 +5904,7 @@ u16 scan_block(u32 base_pc, int is_slave, u8 *op_flags, u32 *end_pc_out, opd->dest = BITMASK2(GET_Rn(), SHR_MEM); break; case 0x07: // DIV0S Rm,Rn 0010nnnnmmmm0111 - opd->source = BITMASK2(GET_Rm(), GET_Rn()); + opd->source = BITMASK3(SHR_SR, GET_Rm(), GET_Rn()); opd->dest = BITMASK2(SHR_SR, SHR_T); break; case 0x08: // TST Rm,Rn 0010nnnnmmmm1000 @@ -6470,6 +6497,9 @@ end: last_btarget = 0; op = 0; // delay/poll insns counter for (i = 0, pc = base_pc; i < i_end; i++, pc += 2) { + int null; + if ((op_flags[i] & OF_BTARGET) && dr_get_entry(pc, is_slave, &null)) + break; // branch target already compiled opd = &ops[i]; crc += FETCH_OP(pc); diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index 44620f48..804f2a70 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -1,7 +1,7 @@ int sh2_drc_init(SH2 *sh2); void sh2_drc_finish(SH2 *sh2); -void sh2_drc_wcheck_ram(unsigned int a, unsigned len, SH2 *sh2); -void sh2_drc_wcheck_da(unsigned int a, unsigned len, SH2 *sh2); +void sh2_drc_wcheck_ram(uint32_t a, unsigned len, SH2 *sh2); +void sh2_drc_wcheck_da(uint32_t a, unsigned len, SH2 *sh2); #ifdef DRC_SH2 void sh2_drc_mem_setup(SH2 *sh2); @@ -28,13 +28,13 @@ void sh2_drc_frame(void); #define OF_DELAY_LOOP (2 << 2) #define OF_POLL_LOOP (3 << 2) -unsigned short scan_block(unsigned int base_pc, int is_slave, - unsigned char *op_flags, unsigned int *end_pc, - unsigned int *base_literals, unsigned int *end_literals); +unsigned short scan_block(uint32_t base_pc, int is_slave, + unsigned char *op_flags, uint32_t *end_pc, + uint32_t *base_literals, uint32_t *end_literals); -#if defined(DRC_SH2) -// direct access to some host CPU registers used by the DRC -// XXX MUST match definitions for SHR_SR in cpu/sh2/compiler.c +#if defined(DRC_SH2) && defined(__GNUC__) +// direct access to some host CPU registers used by the DRC +// XXX MUST match definitions for SHR_SR in cpu/drc/emit_*.c #if defined(__arm__) #define DRC_SR_REG "r10" #elif defined(__aarch64__) @@ -47,19 +47,20 @@ unsigned short scan_block(unsigned int base_pc, int is_slave, #define DRC_SR_REG "edi" #elif defined(__x86_64__) #define DRC_SR_REG "ebx" -#else -#warning "direct DRC register access not available for this host" #endif #endif #ifdef DRC_SR_REG -#define DRC_DECLARE_SR register int sh2_sr asm(DRC_SR_REG) +extern void REGPARM(1) (*sh2_drc_save_sr)(SH2 *sh2); +extern void REGPARM(1) (*sh2_drc_restore_sr)(SH2 *sh2); + +#define DRC_DECLARE_SR register int32_t sh2_sr asm(DRC_SR_REG) #define DRC_SAVE_SR(sh2) \ - if ((sh2->state & (SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN) \ - sh2->sr = sh2_sr; + if (likely((sh2->state & (SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN)) \ + sh2_drc_save_sr(sh2) #define DRC_RESTORE_SR(sh2) \ - if ((sh2->state & (SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN) \ - sh2_sr = sh2->sr; + if (likely((sh2->state & (SH2_STATE_RUN|SH2_STATE_SLEEP)) == SH2_STATE_RUN)) \ + sh2_drc_restore_sr(sh2) #else #define DRC_DECLARE_SR #define DRC_SAVE_SR(sh2) diff --git a/cpu/sh2/sh2.h b/cpu/sh2/sh2.h index 5f1a8841..2d73db59 100644 --- a/cpu/sh2/sh2.h +++ b/cpu/sh2/sh2.h @@ -14,13 +14,13 @@ typedef enum { typedef struct SH2_ { // registers. this MUST correlate with enum sh2_reg_e. - unsigned int r[16] ALIGNED(32); - unsigned int pc; // 40 - unsigned int ppc; - unsigned int pr; - unsigned int sr; - unsigned int gbr, vbr; // 50 - unsigned int mach, macl; // 58 + uint32_t r[16] ALIGNED(32); + uint32_t pc; // 40 + uint32_t ppc; + uint32_t pr; + uint32_t sr; + uint32_t gbr, vbr; // 50 + uint32_t mach, macl; // 58 // common const void *read8_map; @@ -48,14 +48,14 @@ typedef struct SH2_ #define SH2_STATE_VPOLL (1 << 3) // polling VDP #define SH2_STATE_RPOLL (1 << 4) // polling address in SDRAM unsigned int state; - unsigned int poll_addr; + uint32_t poll_addr; int poll_cycles; int poll_cnt; // DRC branch cache. size must be 2^n and <=128 int rts_cache_idx; - struct { unsigned int pc; void *code; } rts_cache[16]; - struct { unsigned int pc; void *code; } branch_cache[128]; + struct { uint32_t pc; void *code; } rts_cache[16]; + struct { uint32_t pc; void *code; } branch_cache[128]; // interpreter stuff int icount; // cycles left in current timeslice @@ -79,15 +79,15 @@ typedef struct SH2_ unsigned int mult_m68k_to_sh2; unsigned int mult_sh2_to_m68k; - unsigned char data_array[0x1000]; // cache (can be used as RAM) - unsigned int peri_regs[0x200/4]; // periphereal regs + uint8_t data_array[0x1000]; // cache (can be used as RAM) + uint32_t peri_regs[0x200/4]; // periphereal regs } SH2; #define CYCLE_MULT_SHIFT 10 #define C_M68K_TO_SH2(xsh2, c) \ - (int)(((unsigned long long)(c) * (xsh2)->mult_m68k_to_sh2) >> CYCLE_MULT_SHIFT) + (int)(((uint64_t)(c) * (xsh2)->mult_m68k_to_sh2) >> CYCLE_MULT_SHIFT) #define C_SH2_TO_M68K(xsh2, c) \ - (int)(((unsigned long long)(c+3U) * (xsh2)->mult_sh2_to_m68k) >> CYCLE_MULT_SHIFT) + (int)(((uint64_t)(c+3U) * (xsh2)->mult_sh2_to_m68k) >> CYCLE_MULT_SHIFT) int sh2_init(SH2 *sh2, int is_slave, SH2 *other_sh2); void sh2_finish(SH2 *sh2); diff --git a/pico/arm_features.h b/pico/arm_features.h index 4b456f45..b772b77c 100644 --- a/pico/arm_features.h +++ b/pico/arm_features.h @@ -60,9 +60,8 @@ // load data address (LDR) either via literal pool or via GOT #ifdef __PIC__ -// can't use pool loads since ldr= only allows symbol or constants, not expr :-( +// can't use pool loads since ldr= only allows a symbol or a constant expr :-( #define PIC_LDR_INIT() \ - .ifndef PIC_LDR_DEF; PIC_LDR_DEF=1; \ .macro pic_ldr r t a; \ ldr \r, [pc, $.LD\@-.-8]; \ ldr \t, [pc, $.LD\@-.-4]; \ @@ -71,14 +70,11 @@ add pc, $4; \ .LD\@:.word _GLOBAL_OFFSET_TABLE_-.LP\@-8; \ .word \a(GOT); \ - .endm; \ - .endif; -#define PIC_LDR(r,t,a) \ - pic_ldr r, t, a + .endm; +#define PIC_LDR(r,t,a) pic_ldr r, t, a #else #define PIC_LDR_INIT() -#define PIC_LDR(r,t,a) \ - ldr r, =a +#define PIC_LDR(r,t,a) ldr r, =a #endif #endif /* __ARM_FEATURES_H__ */ diff --git a/pico/pico_port.h b/pico/pico_port.h index e26e6ca2..af9ce853 100644 --- a/pico/pico_port.h +++ b/pico/pico_port.h @@ -17,10 +17,12 @@ #define NOINLINE __attribute__((noinline)) #define ALIGNED(n) __attribute__((aligned(n))) #define unlikely(x) __builtin_expect((x), 0) +#define likely(x) __builtin_expect(!!(x), 1) #else #define NOINLINE #define ALIGNED(n) #define unlikely(x) (x) +#define likely(x) (x) #endif #ifdef _MSC_VER diff --git a/platform/common/disarm.c b/platform/common/disarm.c index 37fd810e..24992206 100644 --- a/platform/common/disarm.c +++ b/platform/common/disarm.c @@ -435,7 +435,7 @@ static int software_interrupt(unsigned int pc, unsigned int insn, char *buf, siz return 1; } -int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *addr) +int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, unsigned long *addr) { *addr = 0; @@ -467,7 +467,7 @@ int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *ad return block_data_transfer(pc, insn, buf, buf_len); if ((insn & 0x0e000000) == 0x0a000000) { - *addr = (long)pc + 8 + ((long)(insn << 8) >> 6); + *addr = (unsigned long)pc+8 + ((unsigned long)(insn << 8) >> 6); return branch(pc, insn, buf, buf_len); } diff --git a/platform/common/disarm.h b/platform/common/disarm.h index f1170894..a07675fd 100644 --- a/platform/common/disarm.h +++ b/platform/common/disarm.h @@ -23,6 +23,6 @@ #ifndef DISARM_H #define DISARM_H -int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *sym); +int disarm(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, unsigned long *sym); #endif /* DISARM_H */ diff --git a/platform/common/dismips.c b/platform/common/dismips.c index 19c0b427..dc06ce80 100644 --- a/platform/common/dismips.c +++ b/platform/common/dismips.c @@ -6,8 +6,9 @@ * See COPYING file in the top-level directory. */ -// XXX unimplemented: SYSCALL, BREAK, SYNC, SDBBP, T*, CACHE, PREF, -// MOVF/MOVT, LWC*/LDC*, SWC*/SDC*, COP*. +// unimplemented insns: MOV[FT], SYSCALL, BREAK, SYNC, SYNCI, T*, SDBBP, RDHWR, +// CACHE, PREF, LWC*/LDC*, SWC*/SDC*, and all of COP* (fpu, mmu, irq, exc, ...) +// unimplemented variants of insns: EHB, SSNOP (both SLL zero), JALR.HB, JR.HB // however, it's certainly good enough for anything picodrive DRC throws at it. #include @@ -79,6 +80,7 @@ struct insn { #define OP_SPECIAL 0x00 static const struct insn special_insns[] = { {0x00, S_IMM_DT, "sll"}, +// {0x01, , "movf\0movt"}, {0x02, S_IMM_DT|SR_BIT, "srl\0rotr"}, {0x03, S_IMM_DT, "sra"}, {0x04, REG_DTS, "sllv"}, @@ -146,6 +148,7 @@ static const struct insn special2_insns[] = { {0x21, REG_DS, "clo" }, {0x24, REG_DS, "dclz" }, {0x25, REG_DS, "dclo" }, +// {0x37, , "sdbbp" }, }; // instructions with opcode SPECIAL3 (R-type) @@ -159,6 +162,7 @@ static const struct insn special3_insns[] = { {0x05, F_IMM_TS, "dinsm" }, {0x06, F_IMM_TS, "dinsu" }, {0x07, F_IMM_TS, "dins" }, +// {0x3b, , "rdhwr" }, }; // instruction with opcode SPECIAL3 and function *BSHFL @@ -192,6 +196,7 @@ static const struct insn regimm_insns[] = { {0x12, B_IMM_S, "bltzall"}, {0x13, B_IMM_S, "bgezall"}, {0x13, B_IMM_S, "bgezall"}, +// {0x1f, , "synci" }, }; // instructions with other opcodes (I-type) @@ -316,7 +321,7 @@ static unsigned long j_target(unsigned long pc, uint32_t insn) } // main disassembler function -int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, uintptr_t *sym) +int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buflen, unsigned long *sym) { const struct insn *pi = decode_insn(insn); char *rs = register_names[(insn >> 21) & 0x1f]; diff --git a/platform/common/dismips.h b/platform/common/dismips.h index b547003b..8d105925 100644 --- a/platform/common/dismips.h +++ b/platform/common/dismips.h @@ -1,6 +1,6 @@ #ifndef DISMIPS_H #define DISMIPS_H -int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, uintptr_t *sym); +int dismips(uintptr_t pc, uint32_t insn, char *buf, size_t buf_len, unsigned long *sym); #endif /* DISMIPS_H */ diff --git a/platform/common/host_dasm.c b/platform/common/host_dasm.c index fc3cbe67..2084aa91 100644 --- a/platform/common/host_dasm.c +++ b/platform/common/host_dasm.c @@ -37,14 +37,14 @@ void host_dasm(void *addr, int len) void *end = (char *)addr + len; const char *name; char buf[64]; - long insn, symaddr; + unsigned long insn, symaddr; while (addr < end) { name = lookup_name(addr); if (name != NULL) printf("%s:\n", name); - insn = *(long *)addr; + insn = *(unsigned long *)addr; printf(" %08lx %08lx ", (long)addr, insn); if(disasm((unsigned)addr, insn, buf, sizeof(buf), &symaddr)) { diff --git a/tools/mkoffsets.sh b/tools/mkoffsets.sh index 349b8605..8a1092e0 100755 --- a/tools/mkoffsets.sh +++ b/tools/mkoffsets.sh @@ -12,15 +12,12 @@ ENDIAN= compile_rodata () { $CC $CFLAGS -I .. -c /tmp/getoffs.c -o /tmp/getoffs.o || exit 1 - # echo 'void dummy(void) { asm(""::"r" (&val)); }' >> /tmp/getoffs.c - # $CC $CFLAGS -I .. -nostdlib -Wl,-edummy /tmp/getoffs.c \ - # -o /tmp/getoffs.o || exit 1 # find the name of the .rodata section (in case -fdata-sections is used) rosect=$(readelf -S /tmp/getoffs.o | grep '\.rodata\|\.sdata' | sed 's/^[^.]*././;s/ .*//') - # read out .rodata section as hex string (should be only 4 or 8 bytes) + # read out .rodata section as hex string (should be only 4 bytes) ro=$(readelf -x $rosect /tmp/getoffs.o | grep '0x' | cut -c14-48 | - tr -d ' \n') + tr -d ' \n' | cut -c1-8) if [ "$ENDIAN" = "le" ]; then # swap needed for le target hex="" @@ -41,16 +38,18 @@ get_define () # prefix struct member member... struct=$1; shift field=$(echo $* | sed 's/ /./g') name=$(echo $* | sed 's/ /_/g') - echo '#include "pico/pico_int.h"' > /tmp/getoffs.c + echo '#include ' > /tmp/getoffs.c + echo '#include "pico/pico_int.h"' >> /tmp/getoffs.c echo "static const struct $struct p;" >> /tmp/getoffs.c - echo "const int val = (char *)&p.$field - (char*)&p;" >>/tmp/getoffs.c + echo "const int32_t val = (char *)&p.$field - (char*)&p;" >>/tmp/getoffs.c compile_rodata line=$(printf "#define %-20s 0x%04x" $prefix$name $rodata) } if echo $CFLAGS | grep -qe -flto; then CFLAGS="$CFLAGS -fno-lto"; fi # determine endianess -echo "const int val = 1;" >/tmp/getoffs.c +echo '#include ' >/tmp/getoffs.c +echo "const int32_t val = 1;" >>/tmp/getoffs.c compile_rodata ENDIAN=$(if [ "$rodata" -eq 1 ]; then echo be; else echo le; fi) # output header -- 2.39.5