From 8bb489470a3daf6841500cd4be8044ea6611393e Mon Sep 17 00:00:00 2001 From: kub Date: Fri, 19 Jun 2020 00:14:28 +0200 Subject: [PATCH] sh2 drc, add powerpc64le backend --- Makefile | 6 +- cpu/drc/emit_arm.c | 2 + cpu/drc/emit_arm64.c | 1 + cpu/drc/emit_mips.c | 1 + cpu/drc/emit_ppc.c | 234 +++++++++++++++++++------------------------ cpu/drc/emit_riscv.c | 1 + cpu/drc/emit_x86.c | 2 + cpu/sh2/compiler.c | 9 +- cpu/sh2/compiler.h | 3 + platform/linux/emu.c | 2 +- 10 files changed, 129 insertions(+), 132 deletions(-) diff --git a/Makefile b/Makefile index 053e1606..c23841d7 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,10 @@ else ifneq (,$(findstring riscv,$(ARCH))) use_fame ?= 1 use_cz80 ?= 1 use_sh2drc ?= 1 +else ifneq (,$(findstring powerpc,$(ARCH))) +use_fame ?= 1 +use_cz80 ?= 1 +use_sh2drc ?= 1 endif -include Makefile.local @@ -270,7 +274,7 @@ pico/carthw_cfg.c: pico/carthw.cfg # random deps pico/carthw/svp/compiler.o : cpu/drc/emit_arm.c -cpu/sh2/compiler.o : cpu/drc/emit_arm.c cpu/drc/emit_arm64.c +cpu/sh2/compiler.o : cpu/drc/emit_arm.c cpu/drc/emit_arm64.c cpu/drc/emit_ppc.c cpu/sh2/compiler.o : cpu/drc/emit_x86.c cpu/drc/emit_mips.c cpu/drc/emit_riscv.c cpu/sh2/mame/sh2pico.o : cpu/sh2/mame/sh2.c pico/pico.o pico/cd/mcd.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h diff --git a/cpu/drc/emit_arm.c b/cpu/drc/emit_arm.c index e27054a3..3f373435 100644 --- a/cpu/drc/emit_arm.c +++ b/cpu/drc/emit_arm.c @@ -1138,6 +1138,8 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs) EOP_MOV_REG_ASR(d,d,32 - (bits)); \ } while (0) +#define emith_uext_ptr(r) /**/ + #define emith_do_caller_regs(mask, func) do { \ u32 _reg_mask = (mask) & 0x500f; \ if (_reg_mask) { \ diff --git a/cpu/drc/emit_arm64.c b/cpu/drc/emit_arm64.c index f4645bc1..ae7077a0 100644 --- a/cpu/drc/emit_arm64.c +++ b/cpu/drc/emit_arm64.c @@ -1176,6 +1176,7 @@ static void emith_ldst_offs(int sz, int rd, int rn, int o9, int ld, int mode) #define host_instructions_updated(base, end) __builtin___clear_cache(base, end) #define emith_update_cache() /**/ #define emith_rw_offs_max() 0xff +#define emith_uext_ptr(r) /**/ // SH2 drc specific diff --git a/cpu/drc/emit_mips.c b/cpu/drc/emit_mips.c index 8cb094de..8eddd219 100644 --- a/cpu/drc/emit_mips.c +++ b/cpu/drc/emit_mips.c @@ -1563,6 +1563,7 @@ static int emith_cond_check(int cond, int *r) #define host_instructions_updated(base, end) __builtin___clear_cache(base, end) #define emith_update_cache() /**/ #define emith_rw_offs_max() 0x7fff +#define emith_uext_ptr(r) /**/ // SH2 drc specific #define emith_sh2_drc_entry() do { \ diff --git a/cpu/drc/emit_ppc.c b/cpu/drc/emit_ppc.c index fb2ca44b..286d4166 100644 --- a/cpu/drc/emit_ppc.c +++ b/cpu/drc/emit_ppc.c @@ -6,8 +6,6 @@ * See COPYING file in the top-level directory. */ -// WARNING: unfinished, neither thoroughly tested nor optimized. little endian only! - // NB bit numbers are reversed in PPC (MSB is bit 0). The emith_* functions and // macros must take this into account. @@ -34,7 +32,7 @@ // use CA and OV. // Moreover, there's no easy possibility to get CA and OV for 32 bit arithmetic // since all arithmetic/logical insns use 64 bit. -// For now, use the "no flags" code from the RISCV backend. +// For now, use the "no flags" code from the RISC-V backend. #define HOST_REGS 32 @@ -42,7 +40,7 @@ // reserved: r0(zero), r1(stack), r2(TOC), r13(TID) #define RET_REG 3 #define PARAM_REGS { 3, 4, 5, 6, 7, 8, 9, 10 } -#define PRESERVED_REGS { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,31 } +#define PRESERVED_REGS { 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 } #define TEMPORARY_REGS { 11, 12 } #define CONTEXT_REG 31 @@ -50,27 +48,18 @@ // if RA is 0 in non-update memory insns, ADDI/ADDIS, ISEL, it aliases with zero #define Z0 0 // zero register -#define SP 1 // stack pointer +#define SP 1 // stack pointer // SPR registers -#define XER -1 // exception register -#define LR -8 // link register -#define CTR -9 // counter register +#define XER -1 // exception register +#define LR -8 // link register +#define CTR -9 // counter register // internally used by code emitter: -#define AT 0 // emitter temporary (can't be fully used anyway) +#define AT 0 // emitter temporary (can't be fully used anyway) #define FNZ 14 // emulated processor flags: N (bit 31) ,Z (all bits) #define FC 15 // emulated processor flags: C (bit 0), others 0 #define FV 16 // emulated processor flags: Nt^Ns (bit 31). others x -// PPC conditions, BO0-BO4:BI2-BI4 since we only need CR0 -#define PPC_LT 0x60 -#define PPC_GE 0x20 -#define PPC_GT 0x61 -#define PPC_LE 0x21 -#define PPC_EQ 0x62 -#define PPC_NE 0x22 -#define PPC_AL 0xa0 - // unified conditions; virtual, not corresponding to anything real on PPC #define DCOND_EQ 0x0 #define DCOND_NE 0x1 @@ -94,8 +83,8 @@ #define PPC_INSN(op, b10, b15, b20, b31) \ (((op)<<26)|((b10)<<21)|((b15)<<16)|((b20)<<11)|((b31)<<0)) -#define _ 0 // marker for "field unused" -#define __(n) o##n // enum marker for "undefined" +#define _ 0 // marker for "field unused" +#define __(n) o##n // enum marker for "undefined" #define _CB(v,l,s,d) ((((v)>>(s))&((1<<(l))-1))<<(d)) // copy l bits // NB everything privileged or unneeded at 1st sight is left out @@ -148,8 +137,16 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; // AA and LK in I,B-forms branches #define BAA (1<<1) #define BLK (1<<0) - -#define PPC_NOP \ +// BO and BI condition codes in B-form, BO0-BO4:BI2-BI4 since we only need CR0 +#define BLT 0x60 +#define BGE 0x20 +#define BGT 0x61 +#define BLE 0x21 +#define BEQ 0x62 +#define BNE 0x22 +#define BXX 0xa0 // unconditional, aka always + +#define PPC_NOP \ PPC_INSN(OP_ORI, 0, 0, _, 0) // ori r0, r0, 0 // arithmetic/logical @@ -331,7 +328,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_BL(offs26) \ PPC_OP_IMM(OP_B,_,_,((offs26)&~3)|BLK) #define PPC_RET() \ - PPC_OP_REG(OP__CR,OPC_BCLR,PPC_AL>>3,_,_) + PPC_OP_REG(OP__CR,OPC_BCLR,BXX>>3,_,_) #define PPC_RETCOND(cond) \ PPC_OP_REG(OP__CR,OPC_BCLR,(cond)>>3,(cond)&0x7,_) #define PPC_BCTRCOND(cond) \ @@ -411,6 +408,8 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_STP_REG PPC_STX_REG #define PPC_BFXP_IMM PPC_BFX_IMM +#define emith_uext_ptr(r) EMIT(PPC_EXTUW_REG(r, r)) + // "long" multiplication, 32x32 bit = 64 bit #define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \ EMIT(PPC_EXTUW_REG(s1, s1)); \ @@ -442,6 +441,8 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #define PPC_STP_REG PPC_STW_REG #define PPC_BFXP_IMM PPC_BFXW_IMM +#define emith_uext_ptr(r) /**/ + // "long" multiplication, 32x32 bit = 64 bit #define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \ int at = (dlo == s1 || dlo == s2 ? AT : dlo); \ @@ -467,23 +468,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ }; #endif #define PTR_SIZE (1<> 32); if (imm >> 32) EMIT(PPC_LSL_IMM(r, r, 32)); @@ -883,23 +867,11 @@ static void emith_move_imm(int r, int ptr, uintptr_t imm) EMIT(PPC_ORT_IMM(r, r, (imm & 0xffff0000) >> 16)); } else #endif - { - int s = Z0, d = 0, c = 0; - if ((u16)imm) { - EMIT(PPC_ADD_IMM(r, s, (u16)imm)); - s = r, d = 1, c = (s16)imm < 0; - } - // adjust for sign extension in ADDI - if (!d) // low part == 0 - EMIT(PPC_ADDT_IMM(r, s, (u16)(imm>>16))); - else if (c && (u16)(~imm>>16)) // low part < 0 - EMIT(PPC_XORT_IMM(r, s, (u16)(~imm>>16))); - else if (!c && (u16)(imm>>16)) // low part > 0 - EMIT(PPC_ORT_IMM(r, s, (u16)(imm>>16))); - // make sure to clear upper half if this is a ptr - if (ptr && !(imm >> 32) && c) - EMIT(PPC_EXTUW_REG(r, r)); - } + if ((s16)imm != (s32)imm) { + EMIT(PPC_ADDT_IMM(r, Z0, (u16)(imm>>16))); + if ((s16)imm) + EMIT(PPC_OR_IMM(r, r, (u16)(imm))); + } else EMIT(PPC_ADD_IMM(r, Z0, (u16)imm)); } #define emith_move_r_ptr_imm(r, imm) \ @@ -1176,9 +1148,6 @@ static void emith_add_imm(int rt, int ra, u32 imm) } \ } while (0) -#define emith_uext_ptr(r) \ - EMIT(PPC_EXTUW_REG(r, r)) - // multiply Rd = Rn*Rm (+ Ra) #define emith_mul(d, s1, s2) \ @@ -1248,13 +1217,17 @@ static void emith_add_imm(int rt, int ra, u32 imm) #define emith_read8s_r_r_r_c(cond, r, ra, rm) \ emith_read8s_r_r_r(r, ra, rm) -#define emith_read16s_r_r_offs(r, ra, offs) \ - EMIT(PPC_LDSH_IMM(r, ra, offs)) +#define emith_read16s_r_r_offs(r, ra, offs) do { \ + EMIT(PPC_LDH_IMM(r, ra, offs)); \ + EMIT(PPC_EXTSH_REG(r, r)); \ +} while (0) #define emith_read16s_r_r_offs_c(cond, r, ra, offs) \ emith_read16s_r_r_offs(r, ra, offs) -#define emith_read16s_r_r_r(r, ra, rm) \ - EMIT(PPC_LDSH_REG(r, ra, rm)) +#define emith_read16s_r_r_r(r, ra, rm) do { \ + EMIT(PPC_LDH_REG(r, ra, rm)); \ + EMIT(PPC_EXTSH_REG(r, r)); \ +} while (0) #define emith_read16s_r_r_r_c(cond, r, ra, rm) \ emith_read16s_r_r_r(r, ra, rm) @@ -1346,16 +1319,16 @@ static int emith_cmpr_check(int rs, int rt, int cond, u32 *op) // condition check for comparing 2 registers switch (cond) { - case DCOND_EQ: *op = PPC_CMPW_REG(rs, rt); b = PPC_EQ; break; - case DCOND_NE: *op = PPC_CMPW_REG(rs, rt); b = PPC_NE; break; - case DCOND_LO: *op = PPC_CMPLW_REG(rs, rt); b = PPC_LT; break; - case DCOND_HS: *op = PPC_CMPLW_REG(rs, rt); b = PPC_GE; break; - case DCOND_LS: *op = PPC_CMPLW_REG(rs, rt); b = PPC_LE; break; - case DCOND_HI: *op = PPC_CMPLW_REG(rs, rt); b = PPC_GT; break; - case DCOND_LT: *op = PPC_CMPW_REG(rs, rt); b = PPC_LT; break; - case DCOND_GE: *op = PPC_CMPW_REG(rs, rt); b = PPC_GE; break; - case DCOND_LE: *op = PPC_CMPW_REG(rs, rt); b = PPC_LE; break; - case DCOND_GT: *op = PPC_CMPW_REG(rs, rt); b = PPC_GT; break; + case DCOND_EQ: *op = PPC_CMPW_REG(rs, rt); b = BEQ; break; + case DCOND_NE: *op = PPC_CMPW_REG(rs, rt); b = BNE; break; + case DCOND_LO: *op = PPC_CMPLW_REG(rs, rt); b = BLT; break; + case DCOND_HS: *op = PPC_CMPLW_REG(rs, rt); b = BGE; break; + case DCOND_LS: *op = PPC_CMPLW_REG(rs, rt); b = BLE; break; + case DCOND_HI: *op = PPC_CMPLW_REG(rs, rt); b = BGT; break; + case DCOND_LT: *op = PPC_CMPW_REG(rs, rt); b = BLT; break; + case DCOND_GE: *op = PPC_CMPW_REG(rs, rt); b = BGE; break; + case DCOND_LE: *op = PPC_CMPW_REG(rs, rt); b = BLE; break; + case DCOND_GT: *op = PPC_CMPW_REG(rs, rt); b = BGT; break; } return b; @@ -1367,16 +1340,16 @@ static int emith_cmpi_check(int rs, s32 imm, int cond, u32 *op) // condition check for comparing register with immediate switch (cond) { - case DCOND_EQ: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_EQ; break; - case DCOND_NE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_NE; break; - case DCOND_LO: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = PPC_LT; break; - case DCOND_HS: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = PPC_GE; break; - case DCOND_LS: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = PPC_LE; break; - case DCOND_HI: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = PPC_GT; break; - case DCOND_LT: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_LT; break; - case DCOND_GE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_GE; break; - case DCOND_LE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_LE; break; - case DCOND_GT: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_GT; break; + case DCOND_EQ: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BEQ; break; + case DCOND_NE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BNE; break; + case DCOND_LO: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = BLT; break; + case DCOND_HS: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = BGE; break; + case DCOND_LS: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = BLE; break; + case DCOND_HI: *op = PPC_CMPLW_IMM(rs, (u16)imm), b = BGT; break; + case DCOND_LT: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BLT; break; + case DCOND_GE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BGE; break; + case DCOND_LE: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BLE; break; + case DCOND_GT: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BGT; break; } return b; @@ -1396,29 +1369,29 @@ static int emith_cond_check(int cond) // shortcut for V known to be 0 if (b < 0 && emith_flg_noV) switch (cond) { case DCOND_VS: /* no branch */ break; // never - case DCOND_VC: b = PPC_AL; break; // always - case DCOND_LT: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_LT; break; // N - case DCOND_GE: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GE; break; // !N - case DCOND_LE: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_LE; break; // N || Z - case DCOND_GT: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GT; break; // !N && !Z + case DCOND_VC: b = BXX; break; // always + case DCOND_LT: op = PPC_CMPW_IMM(FNZ, 0); b = BLT; break; // N + case DCOND_GE: op = PPC_CMPW_IMM(FNZ, 0); b = BGE; break; // !N + case DCOND_LE: op = PPC_CMPW_IMM(FNZ, 0); b = BLE; break; // N || Z + case DCOND_GT: op = PPC_CMPW_IMM(FNZ, 0); b = BGT; break; // !N && !Z } // the full monty if no shortcut if (b < 0) switch (cond) { // conditions using NZ - case DCOND_EQ: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_EQ; break; // Z - case DCOND_NE: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_NE; break; // !Z - case DCOND_MI: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_LT; break; // N - case DCOND_PL: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GE; break; // !N + case DCOND_EQ: op = PPC_CMPW_IMM(FNZ, 0); b = BEQ; break; // Z + case DCOND_NE: op = PPC_CMPW_IMM(FNZ, 0); b = BNE; break; // !Z + case DCOND_MI: op = PPC_CMPW_IMM(FNZ, 0); b = BLT; break; // N + case DCOND_PL: op = PPC_CMPW_IMM(FNZ, 0); b = BGE; break; // !N // conditions using C - case DCOND_LO: op = PPC_CMPW_IMM(FC , 0); b = PPC_NE; break; // C - case DCOND_HS: op = PPC_CMPW_IMM(FC , 0); b = PPC_EQ; break; // !C + case DCOND_LO: op = PPC_CMPW_IMM(FC , 0); b = BNE; break; // C + case DCOND_HS: op = PPC_CMPW_IMM(FC , 0); b = BEQ; break; // !C // conditions using CZ case DCOND_LS: // C || Z case DCOND_HI: // !C && !Z EMIT(PPC_ADD_IMM(AT, FC, -1)); // !C && !Z EMIT(PPC_AND_REG(AT, FNZ, AT)); - op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_HI ? PPC_NE : PPC_EQ); + op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_HI ? BNE : BEQ); break; // conditions using V @@ -1427,14 +1400,14 @@ static int emith_cond_check(int cond) EMIT(PPC_XOR_REG(AT, FV, FNZ)); // V = Nt^Ns^Nd^C EMIT(PPC_LSRW_IMM(AT, AT, 31)); EMIT(PPC_XOR_REG(AT, AT, FC)); - op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_VS ? PPC_NE : PPC_EQ); + op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_VS ? BNE : BEQ); break; // conditions using VNZ case DCOND_LT: // N^V case DCOND_GE: // !(N^V) EMIT(PPC_LSRW_IMM(AT, FV, 31)); // Nd^V = Nt^Ns^C EMIT(PPC_XOR_REG(AT, FC, AT)); - op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_LT ? PPC_NE : PPC_EQ); + op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_LT ? BNE : BEQ); break; case DCOND_LE: // (N^V) || Z case DCOND_GT: // !(N^V) && !Z @@ -1442,7 +1415,7 @@ static int emith_cond_check(int cond) EMIT(PPC_XOR_REG(AT, FC, AT)); EMIT(PPC_ADD_IMM(AT, AT, -1)); // !(Nd^V) && !Z EMIT(PPC_AND_REG(AT, FNZ, AT)); - op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_GT ? PPC_NE : PPC_EQ); + op = PPC_CMPW_IMM(AT , 0); b = (cond == DCOND_GT ? BNE : BEQ); break; } @@ -1461,7 +1434,7 @@ static int emith_cond_check(int cond) #define emith_jump_cond(cond, target) do { \ int mcond_ = emith_cond_check(cond); \ u32 disp_ = (u8 *)target - (u8 *)tcache_ptr; \ - EMIT(PPC_BCOND(mcond_,disp_ & 0x0000ffff)); \ + if (mcond_ >= 0) EMIT(PPC_BCOND(mcond_,disp_ & 0x0000ffff)); \ } while (0) #define emith_jump_cond_patchable(cond, target) \ emith_jump_cond(cond, target) @@ -1495,7 +1468,7 @@ static int emith_cond_check(int cond) #define emith_jump_reg(r) do { \ EMIT(PPC_MTSP_REG(r, CTR)); \ - EMIT(PPC_BCTRCOND(PPC_AL)); \ + EMIT(PPC_BCTRCOND(BXX)); \ } while(0) #define emith_jump_reg_c(cond, r) \ emith_jump_reg(r) @@ -1516,7 +1489,7 @@ static int emith_cond_check(int cond) #define emith_call_reg(r) do { \ EMIT(PPC_MTSP_REG(r, CTR)); \ - EMIT(PPC_BLCTRCOND(PPC_AL)); \ + EMIT(PPC_BLCTRCOND(BXX)); \ } while(0) #define emith_call_ctx(offs) do { \ @@ -1564,13 +1537,13 @@ static int emith_cond_check(int cond) #define emith_pool_check() /**/ #define emith_pool_commit(j) /**/ #define emith_insn_ptr() ((u8 *)tcache_ptr) -#define emith_flush() /**/ +#define emith_flush() /**/ #define host_instructions_updated(base, end) __builtin___clear_cache(base, end) -#define emith_update_cache() /**/ +#define emith_update_cache() /**/ #define emith_rw_offs_max() 0x7fff // SH2 drc specific -#define STACK_EXTRA (64+48) // Param, ABI (LR,CR,FP etc) save areas +#define STACK_EXTRA ((8+6)*PTR_SIZE) // Param, ABI (LR,CR,FP etc) save areas #define emith_sh2_drc_entry() do { \ int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; /* r14-r30 */ \ if (__builtin_parity(_m) == 1) _m |= 0x1; /* ABI align for SP is 16 */ \ @@ -1579,7 +1552,7 @@ static int emith_cond_check(int cond) if (_m & (1 << _c)) \ { _o -= _z; if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); } \ EMIT(PPC_MFSP_REG(10, LR)); \ - emith_write_r_r_offs_ptr(10, SP, 16); \ + emith_write_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \ emith_write_r_r_offs_ptr(SP, SP, -_s-STACK_EXTRA); /* XXX stdu */ \ emith_add_r_r_ptr_imm(SP, SP, -_s-STACK_EXTRA); \ } while (0) @@ -1591,7 +1564,7 @@ static int emith_cond_check(int cond) if (_m & (1 << _c)) \ { if (_c) emith_read_r_r_offs_ptr(_c, SP, _o); _o += _z; } \ emith_add_r_r_ptr_imm(SP, SP, _s+STACK_EXTRA); \ - emith_read_r_r_offs_ptr(10, SP, 16); \ + emith_read_r_r_offs_ptr(10, SP, 2*PTR_SIZE); \ EMIT(PPC_MTSP_REG(10, LR)); \ emith_ret(); \ } while (0) @@ -1672,11 +1645,13 @@ static int emith_cond_check(int cond) emith_tst_r_imm(sr, Q); /* if (Q ^ M) */ \ EMITH_JMP3_START(DCOND_EQ); \ emith_add_r_r_r(rn, t_, rm); \ - EMIT_PPC_SLTWU_REG(FC, rn, t_); \ + EMIT(PPC_CMPLW_REG(rn, t_)); \ EMITH_JMP3_MID(DCOND_EQ); \ emith_sub_r_r_r(rn, t_, rm); \ - EMIT_PPC_SLTWU_REG(FC, t_, rn); \ + EMIT(PPC_CMPLW_REG(t_, rn)); \ EMITH_JMP3_END(); \ + EMIT(PPC_MFCR_REG(FC)); \ + EMIT(PPC_BFXW_IMM(FC, FC, 0, 1)); \ emith_eor_r_r(sr, FC); /* T ^= carry */ \ rcache_free_tmp(t_); \ } while (0) @@ -1737,7 +1712,7 @@ static int emith_cond_check(int cond) EMIT(PPC_BFIW_IMM(sr, srcr, 22, 10)) #define emith_carry_to_t(sr, is_sub) \ - EMIT(PPC_BFIW_IMM(sr, FC, 31, 1)) + EMIT(PPC_BFIW_IMM(sr, FC, 32-__builtin_ffs(T), 1)) #define emith_t_to_carry(sr, is_sub) \ emith_and_r_r_imm(FC, sr, 1) @@ -1755,26 +1730,27 @@ static int emith_cond_check(int cond) ((cond) ^ 1) // T bit handling -static void emith_clr_t_cond(int sr) -{ - emith_bic_r_imm(sr, T); -} - static void emith_set_t_cond(int sr, int cond) { int b; - u8 *ptr; - u32 val = 0; - - // XXX optimization - b = emith_invert_branch(emith_cond_check(cond)); - ptr = tcache_ptr; - EMIT(PPC_BCOND(b, 0)); - emith_or_r_imm(sr, T); - val = (u8 *)tcache_ptr - (u8 *)(ptr); - EMIT_PTR(ptr, PPC_BCOND(b, val & 0x00001fff)); + + // catch never and always cases + if ((b = emith_cond_check(cond)) < 0) + return; + else if (b == BXX) { + emith_or_r_imm(sr, T); + return; + } + + // extract bit from CR and insert into T + EMIT(PPC_MFCR_REG(AT)); + EMIT(PPC_BFXW_IMM(AT, AT, (b&7), 1)); + if (!(b & 0x40)) EMIT(PPC_XOR_IMM(AT, AT, 1)); + EMIT(PPC_BFIW_IMM(sr, AT, 32-__builtin_ffs(T), 1)); } +#define emith_clr_t_cond(sr) ((void)sr) + #define emith_get_t_cond() -1 #define emith_sync_t(sr) ((void)sr) diff --git a/cpu/drc/emit_riscv.c b/cpu/drc/emit_riscv.c index 69ed530e..954d14a7 100644 --- a/cpu/drc/emit_riscv.c +++ b/cpu/drc/emit_riscv.c @@ -1400,6 +1400,7 @@ static int emith_cond_check(int cond, int *r, int *s) #define host_instructions_updated(base, end) __builtin___clear_cache(base, end) #define emith_update_cache() /**/ #define emith_rw_offs_max() 0x7ff +#define emith_uext_ptr(r) /**/ // SH2 drc specific #define emith_sh2_drc_entry() do { \ diff --git a/cpu/drc/emit_x86.c b/cpu/drc/emit_x86.c index 80ec0444..c836e159 100644 --- a/cpu/drc/emit_x86.c +++ b/cpu/drc/emit_x86.c @@ -622,6 +622,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common emith_asr(d, d, 32 - (bits)); \ } while (0) +#define emith_uext_ptr(r) /**/ + #define emith_setc(r) do { \ assert(is_abcdx(r)); \ EMIT_REX_IF(0, 0, r); \ diff --git a/cpu/sh2/compiler.c b/cpu/sh2/compiler.c index bfd9ec06..d1a971c6 100644 --- a/cpu/sh2/compiler.c +++ b/cpu/sh2/compiler.c @@ -189,7 +189,7 @@ static char sh2dasm_buff[64]; (sh2)->r[8], (sh2)->r[9], (sh2)->r[10], (sh2)->r[11], \ (sh2)->r[12], (sh2)->r[13], (sh2)->r[14], (sh2)->r[15]); \ printf("%csh2 pc-ml %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \ - (sh2)->pc, (sh2)->ppc, (sh2)->pr, (sh2)->sr&0x3ff, \ + (sh2)->pc, (sh2)->ppc, (sh2)->pr, (sh2)->sr&0xfff, \ (sh2)->gbr, (sh2)->vbr, (sh2)->mach, (sh2)->macl); \ printf("%csh2 tmp-p %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \ (sh2)->drc_tmp, (sh2)->irq_cycles, \ @@ -246,6 +246,10 @@ static void REGPARM(3) *sh2_drc_log_entry(void *block, SH2 *sh2, u32 sr) SH2_DUMP(&fsh2, "file"); SH2_DUMP(sh2, "current"); SH2_DUMP(&csh2[idx][0], "previous"); + char *ps = (char *)sh2, *pf = (char *)&fsh2; + for (idx = 0; idx < offsetof(SH2, read8_map); idx += sizeof(u32)) + if (*(u32 *)(ps+idx) != *(u32 *)(pf+idx)) + printf("diff reg %ld\n",idx/sizeof(u32)); exit(1); } csh2[idx][0] = fsh2; @@ -455,6 +459,8 @@ static void rcache_free_tmp(int hr); #include "../drc/emit_mips.c" #elif defined(__riscv__) || defined(__riscv) #include "../drc/emit_riscv.c" +#elif defined(__powerpc__) +#include "../drc/emit_ppc.c" #elif defined(__i386__) #include "../drc/emit_x86.c" #elif defined(__x86_64__) @@ -2572,6 +2578,7 @@ static int emit_get_rbase_and_offs(SH2 *sh2, sh2_reg_e r, int rmode, u32 *offs) u32 odd = a & 1; // need to fix odd address for correct byte addressing la -= (s32)((a & ~mask) - *offs - odd); // diff between reg and memory hr = hr2 = rcache_get_reg(r, rmode, NULL); + if ((s32)a < 0) emith_uext_ptr(hr2); if ((la & ~omask) - odd) { hr = rcache_get_tmp(); emith_add_r_r_ptr_imm(hr, hr2, (la & ~omask) - odd); diff --git a/cpu/sh2/compiler.h b/cpu/sh2/compiler.h index 00a8707b..b1b7487f 100644 --- a/cpu/sh2/compiler.h +++ b/cpu/sh2/compiler.h @@ -48,6 +48,9 @@ unsigned short scan_block(uint32_t base_pc, int is_slave, #elif defined(__riscv__) || defined(__riscv) #define DRC_SR_REG "s11" #define DRC_REG_LL 0 // no ABI for (__ILP32__ && __riscv_xlen != 32) +#elif defined(__powerpc__) +#define DRC_SR_REG "r30" +#define DRC_REG_LL 0 // no ABI for __ILP32__ #elif defined(__i386__) #define DRC_SR_REG "edi" #define DRC_REG_LL 0 // 32 bit diff --git a/platform/linux/emu.c b/platform/linux/emu.c index 5e4dd72a..005f82a3 100644 --- a/platform/linux/emu.c +++ b/platform/linux/emu.c @@ -29,7 +29,7 @@ void pemu_prep_defconfig(void) void pemu_validate_config(void) { -#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__i386__) && !defined(__x86_64__) +#if !defined(__arm__) && !defined(__aarch64__) && !defined(__mips__) && !defined(__riscv__) && !defined(__riscv) && !defined(__powerpc__) && !defined(__i386__) && !defined(__x86_64__) PicoIn.opt &= ~POPT_EN_DRC; #endif } -- 2.39.2