sh2 drc, add powerpc64le backend

This commit is contained in:
kub 2020-06-19 00:14:28 +02:00
parent dae0d04dbf
commit 8bb489470a
10 changed files with 127 additions and 130 deletions

View file

@ -73,6 +73,10 @@ else ifneq (,$(findstring riscv,$(ARCH)))
use_fame ?= 1 use_fame ?= 1
use_cz80 ?= 1 use_cz80 ?= 1
use_sh2drc ?= 1 use_sh2drc ?= 1
else ifneq (,$(findstring powerpc,$(ARCH)))
use_fame ?= 1
use_cz80 ?= 1
use_sh2drc ?= 1
endif endif
-include Makefile.local -include Makefile.local
@ -270,7 +274,7 @@ pico/carthw_cfg.c: pico/carthw.cfg
# random deps # random deps
pico/carthw/svp/compiler.o : cpu/drc/emit_arm.c 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/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 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 pico/pico.o pico/cd/mcd.o pico/32x/32x.o : pico/pico_cmn.c pico/pico_int.h

View file

@ -1138,6 +1138,8 @@ static inline void emith_pool_adjust(int tcache_offs, int move_offs)
EOP_MOV_REG_ASR(d,d,32 - (bits)); \ EOP_MOV_REG_ASR(d,d,32 - (bits)); \
} while (0) } while (0)
#define emith_uext_ptr(r) /**/
#define emith_do_caller_regs(mask, func) do { \ #define emith_do_caller_regs(mask, func) do { \
u32 _reg_mask = (mask) & 0x500f; \ u32 _reg_mask = (mask) & 0x500f; \
if (_reg_mask) { \ if (_reg_mask) { \

View file

@ -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 host_instructions_updated(base, end) __builtin___clear_cache(base, end)
#define emith_update_cache() /**/ #define emith_update_cache() /**/
#define emith_rw_offs_max() 0xff #define emith_rw_offs_max() 0xff
#define emith_uext_ptr(r) /**/
// SH2 drc specific // SH2 drc specific

View file

@ -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 host_instructions_updated(base, end) __builtin___clear_cache(base, end)
#define emith_update_cache() /**/ #define emith_update_cache() /**/
#define emith_rw_offs_max() 0x7fff #define emith_rw_offs_max() 0x7fff
#define emith_uext_ptr(r) /**/
// SH2 drc specific // SH2 drc specific
#define emith_sh2_drc_entry() do { \ #define emith_sh2_drc_entry() do { \

View file

@ -6,8 +6,6 @@
* See COPYING file in the top-level directory. * 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 // NB bit numbers are reversed in PPC (MSB is bit 0). The emith_* functions and
// macros must take this into account. // macros must take this into account.
@ -34,7 +32,7 @@
// use CA and OV. // use CA and OV.
// Moreover, there's no easy possibility to get CA and OV for 32 bit arithmetic // Moreover, there's no easy possibility to get CA and OV for 32 bit arithmetic
// since all arithmetic/logical insns use 64 bit. // 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 #define HOST_REGS 32
@ -62,15 +60,6 @@
#define FV 16 // emulated processor flags: Nt^Ns (bit 31). others x #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 // unified conditions; virtual, not corresponding to anything real on PPC
#define DCOND_EQ 0x0 #define DCOND_EQ 0x0
#define DCOND_NE 0x1 #define DCOND_NE 0x1
@ -148,6 +137,14 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
// AA and LK in I,B-forms branches // AA and LK in I,B-forms branches
#define BAA (1<<1) #define BAA (1<<1)
#define BLK (1<<0) #define BLK (1<<0)
// 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 \ #define PPC_NOP \
PPC_INSN(OP_ORI, 0, 0, _, 0) // ori r0, r0, 0 PPC_INSN(OP_ORI, 0, 0, _, 0) // ori r0, r0, 0
@ -331,7 +328,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#define PPC_BL(offs26) \ #define PPC_BL(offs26) \
PPC_OP_IMM(OP_B,_,_,((offs26)&~3)|BLK) PPC_OP_IMM(OP_B,_,_,((offs26)&~3)|BLK)
#define PPC_RET() \ #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) \ #define PPC_RETCOND(cond) \
PPC_OP_REG(OP__CR,OPC_BCLR,(cond)>>3,(cond)&0x7,_) PPC_OP_REG(OP__CR,OPC_BCLR,(cond)>>3,(cond)&0x7,_)
#define PPC_BCTRCOND(cond) \ #define PPC_BCTRCOND(cond) \
@ -411,6 +408,8 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#define PPC_STP_REG PPC_STX_REG #define PPC_STP_REG PPC_STX_REG
#define PPC_BFXP_IMM PPC_BFX_IMM #define PPC_BFXP_IMM PPC_BFX_IMM
#define emith_uext_ptr(r) EMIT(PPC_EXTUW_REG(r, r))
// "long" multiplication, 32x32 bit = 64 bit // "long" multiplication, 32x32 bit = 64 bit
#define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \ #define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \
EMIT(PPC_EXTUW_REG(s1, s1)); \ 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_STP_REG PPC_STW_REG
#define PPC_BFXP_IMM PPC_BFXW_IMM #define PPC_BFXP_IMM PPC_BFXW_IMM
#define emith_uext_ptr(r) /**/
// "long" multiplication, 32x32 bit = 64 bit // "long" multiplication, 32x32 bit = 64 bit
#define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \ #define EMIT_PPC_MULLU_REG(dlo, dhi, s1, s2) do { \
int at = (dlo == s1 || dlo == s2 ? AT : dlo); \ int at = (dlo == s1 || dlo == s2 ? AT : dlo); \
@ -467,23 +468,7 @@ enum { OPS_STD, OPS_STDU /*,OPS_STQ*/ };
#endif #endif
#define PTR_SIZE (1<<PTR_SCALE) #define PTR_SIZE (1<<PTR_SCALE)
// "emulated" RISCV-insns for the flag handling stuff // "emulated" RISC-V SLTU insn for the flag handling stuff XXX cumbersome
#define EMIT_PPC_SLTW_IMM(rt, ra, imm) do { \
EMIT(PPC_CMPW_IMM(ra, imm)); \
EMIT(PPC_MFCR_REG(rt)); \
EMIT(PPC_BFXW_IMM(rt, rt, 0, 1)); \
} while (0)
#define EMIT_PPC_SLTWU_IMM(rt, ra, imm) do { \
EMIT(PPC_CMPLW_IMM(ra, imm)); \
EMIT(PPC_MFCR_REG(rt)); \
EMIT(PPC_BFXW_IMM(rt, rt, 0, 1)); \
} while (0)
#define EMIT_PPC_SLTW_REG(rt, ra, rb) do { \
EMIT(PPC_CMPW_REG(ra, rb)); \
EMIT(PPC_MFCR_REG(rt)); \
EMIT(PPC_BFXW_IMM(rt, rt, 0, 1)); \
} while (0)
#define EMIT_PPC_SLTWU_REG(rt, ra, rb) do { \ #define EMIT_PPC_SLTWU_REG(rt, ra, rb) do { \
EMIT(PPC_CMPLW_REG(ra, rb)); \ EMIT(PPC_CMPLW_REG(ra, rb)); \
EMIT(PPC_MFCR_REG(rt)); \ EMIT(PPC_MFCR_REG(rt)); \
@ -612,9 +597,8 @@ static void emith_set_arith_flags(int rt, int ra, int rb, s32 imm, int sub)
emith_cmp_ra = emith_cmp_rb = -1; emith_cmp_ra = emith_cmp_rb = -1;
} }
// since R5 has less-than and compare-branch insns, handle cmp separately by // handle cmp separately by storing the involved regs for later use.
// storing the involved regs for later use in one of those R5 insns. // this works for all conditions but VC/VS, but this is fortunately never used.
// This works for all conditions but VC/VS, but this is fortunately never used.
static void emith_set_compare_flags(int ra, int rb, s32 imm) static void emith_set_compare_flags(int ra, int rb, s32 imm)
{ {
emith_cmp_rb = rb; emith_cmp_rb = rb;
@ -873,7 +857,7 @@ static void emith_set_compare_flags(int ra, int rb, s32 imm)
static void emith_move_imm(int r, int ptr, uintptr_t imm) static void emith_move_imm(int r, int ptr, uintptr_t imm)
{ {
#ifdef __powerpc64__ #ifdef __powerpc64__
if ((u32)imm != imm && ptr) { if (ptr && (s32)imm != imm) {
emith_move_imm(r, 0, imm >> 32); emith_move_imm(r, 0, imm >> 32);
if (imm >> 32) if (imm >> 32)
EMIT(PPC_LSL_IMM(r, r, 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)); EMIT(PPC_ORT_IMM(r, r, (imm & 0xffff0000) >> 16));
} else } else
#endif #endif
{ if ((s16)imm != (s32)imm) {
int s = Z0, d = 0, c = 0; EMIT(PPC_ADDT_IMM(r, Z0, (u16)(imm>>16)));
if ((u16)imm) { if ((s16)imm)
EMIT(PPC_ADD_IMM(r, s, (u16)imm)); EMIT(PPC_OR_IMM(r, r, (u16)(imm)));
s = r, d = 1, c = (s16)imm < 0; } else EMIT(PPC_ADD_IMM(r, Z0, (u16)imm));
}
// 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));
}
} }
#define emith_move_r_ptr_imm(r, 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) } while (0)
#define emith_uext_ptr(r) \
EMIT(PPC_EXTUW_REG(r, r))
// multiply Rd = Rn*Rm (+ Ra) // multiply Rd = Rn*Rm (+ Ra)
#define emith_mul(d, s1, s2) \ #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) \ #define emith_read8s_r_r_r_c(cond, r, ra, rm) \
emith_read8s_r_r_r(r, ra, rm) emith_read8s_r_r_r(r, ra, rm)
#define emith_read16s_r_r_offs(r, ra, offs) \ #define emith_read16s_r_r_offs(r, ra, offs) do { \
EMIT(PPC_LDSH_IMM(r, ra, offs)) 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) \ #define emith_read16s_r_r_offs_c(cond, r, ra, offs) \
emith_read16s_r_r_offs(r, ra, offs) emith_read16s_r_r_offs(r, ra, offs)
#define emith_read16s_r_r_r(r, ra, rm) \ #define emith_read16s_r_r_r(r, ra, rm) do { \
EMIT(PPC_LDSH_REG(r, ra, rm)) 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) \ #define emith_read16s_r_r_r_c(cond, r, ra, rm) \
emith_read16s_r_r_r(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 // condition check for comparing 2 registers
switch (cond) { switch (cond) {
case DCOND_EQ: *op = PPC_CMPW_REG(rs, rt); b = PPC_EQ; break; case DCOND_EQ: *op = PPC_CMPW_REG(rs, rt); b = BEQ; break;
case DCOND_NE: *op = PPC_CMPW_REG(rs, rt); b = PPC_NE; break; case DCOND_NE: *op = PPC_CMPW_REG(rs, rt); b = BNE; break;
case DCOND_LO: *op = PPC_CMPLW_REG(rs, rt); b = PPC_LT; break; case DCOND_LO: *op = PPC_CMPLW_REG(rs, rt); b = BLT; break;
case DCOND_HS: *op = PPC_CMPLW_REG(rs, rt); b = PPC_GE; break; case DCOND_HS: *op = PPC_CMPLW_REG(rs, rt); b = BGE; break;
case DCOND_LS: *op = PPC_CMPLW_REG(rs, rt); b = PPC_LE; break; case DCOND_LS: *op = PPC_CMPLW_REG(rs, rt); b = BLE; break;
case DCOND_HI: *op = PPC_CMPLW_REG(rs, rt); b = PPC_GT; break; case DCOND_HI: *op = PPC_CMPLW_REG(rs, rt); b = BGT; break;
case DCOND_LT: *op = PPC_CMPW_REG(rs, rt); b = PPC_LT; break; case DCOND_LT: *op = PPC_CMPW_REG(rs, rt); b = BLT; break;
case DCOND_GE: *op = PPC_CMPW_REG(rs, rt); b = PPC_GE; break; case DCOND_GE: *op = PPC_CMPW_REG(rs, rt); b = BGE; break;
case DCOND_LE: *op = PPC_CMPW_REG(rs, rt); b = PPC_LE; break; case DCOND_LE: *op = PPC_CMPW_REG(rs, rt); b = BLE; break;
case DCOND_GT: *op = PPC_CMPW_REG(rs, rt); b = PPC_GT; break; case DCOND_GT: *op = PPC_CMPW_REG(rs, rt); b = BGT; break;
} }
return b; 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 // condition check for comparing register with immediate
switch (cond) { switch (cond) {
case DCOND_EQ: *op = PPC_CMPW_IMM(rs, (u16)imm), b = PPC_EQ; 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 = PPC_NE; 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 = PPC_LT; 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 = PPC_GE; 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 = PPC_LE; 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 = PPC_GT; 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 = PPC_LT; 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 = PPC_GE; 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 = PPC_LE; 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 = PPC_GT; break; case DCOND_GT: *op = PPC_CMPW_IMM(rs, (u16)imm), b = BGT; break;
} }
return b; return b;
@ -1396,29 +1369,29 @@ static int emith_cond_check(int cond)
// shortcut for V known to be 0 // shortcut for V known to be 0
if (b < 0 && emith_flg_noV) switch (cond) { if (b < 0 && emith_flg_noV) switch (cond) {
case DCOND_VS: /* no branch */ break; // never case DCOND_VS: /* no branch */ break; // never
case DCOND_VC: b = PPC_AL; break; // always case DCOND_VC: b = BXX; break; // always
case DCOND_LT: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_LT; break; // N case DCOND_LT: op = PPC_CMPW_IMM(FNZ, 0); b = BLT; break; // N
case DCOND_GE: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GE; 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 = PPC_LE; break; // N || Z case DCOND_LE: op = PPC_CMPW_IMM(FNZ, 0); b = BLE; break; // N || Z
case DCOND_GT: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GT; break; // !N && !Z case DCOND_GT: op = PPC_CMPW_IMM(FNZ, 0); b = BGT; break; // !N && !Z
} }
// the full monty if no shortcut // the full monty if no shortcut
if (b < 0) switch (cond) { if (b < 0) switch (cond) {
// conditions using NZ // conditions using NZ
case DCOND_EQ: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_EQ; break; // Z case DCOND_EQ: op = PPC_CMPW_IMM(FNZ, 0); b = BEQ; break; // Z
case DCOND_NE: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_NE; 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 = PPC_LT; break; // N case DCOND_MI: op = PPC_CMPW_IMM(FNZ, 0); b = BLT; break; // N
case DCOND_PL: op = PPC_CMPW_IMM(FNZ, 0); b = PPC_GE; break; // !N case DCOND_PL: op = PPC_CMPW_IMM(FNZ, 0); b = BGE; break; // !N
// conditions using C // conditions using C
case DCOND_LO: op = PPC_CMPW_IMM(FC , 0); b = PPC_NE; 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 = PPC_EQ; break; // !C case DCOND_HS: op = PPC_CMPW_IMM(FC , 0); b = BEQ; break; // !C
// conditions using CZ // conditions using CZ
case DCOND_LS: // C || Z case DCOND_LS: // C || Z
case DCOND_HI: // !C && !Z case DCOND_HI: // !C && !Z
EMIT(PPC_ADD_IMM(AT, FC, -1)); // !C && !Z EMIT(PPC_ADD_IMM(AT, FC, -1)); // !C && !Z
EMIT(PPC_AND_REG(AT, FNZ, AT)); 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; break;
// conditions using V // 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_XOR_REG(AT, FV, FNZ)); // V = Nt^Ns^Nd^C
EMIT(PPC_LSRW_IMM(AT, AT, 31)); EMIT(PPC_LSRW_IMM(AT, AT, 31));
EMIT(PPC_XOR_REG(AT, AT, FC)); 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; break;
// conditions using VNZ // conditions using VNZ
case DCOND_LT: // N^V case DCOND_LT: // N^V
case DCOND_GE: // !(N^V) case DCOND_GE: // !(N^V)
EMIT(PPC_LSRW_IMM(AT, FV, 31)); // Nd^V = Nt^Ns^C EMIT(PPC_LSRW_IMM(AT, FV, 31)); // Nd^V = Nt^Ns^C
EMIT(PPC_XOR_REG(AT, FC, AT)); 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; break;
case DCOND_LE: // (N^V) || Z case DCOND_LE: // (N^V) || Z
case DCOND_GT: // !(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_XOR_REG(AT, FC, AT));
EMIT(PPC_ADD_IMM(AT, AT, -1)); // !(Nd^V) && !Z EMIT(PPC_ADD_IMM(AT, AT, -1)); // !(Nd^V) && !Z
EMIT(PPC_AND_REG(AT, FNZ, AT)); 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; break;
} }
@ -1461,7 +1434,7 @@ static int emith_cond_check(int cond)
#define emith_jump_cond(cond, target) do { \ #define emith_jump_cond(cond, target) do { \
int mcond_ = emith_cond_check(cond); \ int mcond_ = emith_cond_check(cond); \
u32 disp_ = (u8 *)target - (u8 *)tcache_ptr; \ u32 disp_ = (u8 *)target - (u8 *)tcache_ptr; \
EMIT(PPC_BCOND(mcond_,disp_ & 0x0000ffff)); \ if (mcond_ >= 0) EMIT(PPC_BCOND(mcond_,disp_ & 0x0000ffff)); \
} while (0) } while (0)
#define emith_jump_cond_patchable(cond, target) \ #define emith_jump_cond_patchable(cond, target) \
emith_jump_cond(cond, target) emith_jump_cond(cond, target)
@ -1495,7 +1468,7 @@ static int emith_cond_check(int cond)
#define emith_jump_reg(r) do { \ #define emith_jump_reg(r) do { \
EMIT(PPC_MTSP_REG(r, CTR)); \ EMIT(PPC_MTSP_REG(r, CTR)); \
EMIT(PPC_BCTRCOND(PPC_AL)); \ EMIT(PPC_BCTRCOND(BXX)); \
} while(0) } while(0)
#define emith_jump_reg_c(cond, r) \ #define emith_jump_reg_c(cond, r) \
emith_jump_reg(r) emith_jump_reg(r)
@ -1516,7 +1489,7 @@ static int emith_cond_check(int cond)
#define emith_call_reg(r) do { \ #define emith_call_reg(r) do { \
EMIT(PPC_MTSP_REG(r, CTR)); \ EMIT(PPC_MTSP_REG(r, CTR)); \
EMIT(PPC_BLCTRCOND(PPC_AL)); \ EMIT(PPC_BLCTRCOND(BXX)); \
} while(0) } while(0)
#define emith_call_ctx(offs) do { \ #define emith_call_ctx(offs) do { \
@ -1570,7 +1543,7 @@ static int emith_cond_check(int cond)
#define emith_rw_offs_max() 0x7fff #define emith_rw_offs_max() 0x7fff
// SH2 drc specific // 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 { \ #define emith_sh2_drc_entry() do { \
int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; /* r14-r30 */ \ int _c, _z = PTR_SIZE; u32 _m = 0xffffc000; /* r14-r30 */ \
if (__builtin_parity(_m) == 1) _m |= 0x1; /* ABI align for SP is 16 */ \ 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)) \ if (_m & (1 << _c)) \
{ _o -= _z; if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); } \ { _o -= _z; if (_c) emith_write_r_r_offs_ptr(_c, SP, _o); } \
EMIT(PPC_MFSP_REG(10, LR)); \ 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_write_r_r_offs_ptr(SP, SP, -_s-STACK_EXTRA); /* XXX stdu */ \
emith_add_r_r_ptr_imm(SP, SP, -_s-STACK_EXTRA); \ emith_add_r_r_ptr_imm(SP, SP, -_s-STACK_EXTRA); \
} while (0) } while (0)
@ -1591,7 +1564,7 @@ static int emith_cond_check(int cond)
if (_m & (1 << _c)) \ if (_m & (1 << _c)) \
{ if (_c) emith_read_r_r_offs_ptr(_c, SP, _o); _o += _z; } \ { 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_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)); \ EMIT(PPC_MTSP_REG(10, LR)); \
emith_ret(); \ emith_ret(); \
} while (0) } while (0)
@ -1672,11 +1645,13 @@ static int emith_cond_check(int cond)
emith_tst_r_imm(sr, Q); /* if (Q ^ M) */ \ emith_tst_r_imm(sr, Q); /* if (Q ^ M) */ \
EMITH_JMP3_START(DCOND_EQ); \ EMITH_JMP3_START(DCOND_EQ); \
emith_add_r_r_r(rn, t_, rm); \ 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_JMP3_MID(DCOND_EQ); \
emith_sub_r_r_r(rn, t_, rm); \ emith_sub_r_r_r(rn, t_, rm); \
EMIT_PPC_SLTWU_REG(FC, t_, rn); \ EMIT(PPC_CMPLW_REG(t_, rn)); \
EMITH_JMP3_END(); \ EMITH_JMP3_END(); \
EMIT(PPC_MFCR_REG(FC)); \
EMIT(PPC_BFXW_IMM(FC, FC, 0, 1)); \
emith_eor_r_r(sr, FC); /* T ^= carry */ \ emith_eor_r_r(sr, FC); /* T ^= carry */ \
rcache_free_tmp(t_); \ rcache_free_tmp(t_); \
} while (0) } while (0)
@ -1737,7 +1712,7 @@ static int emith_cond_check(int cond)
EMIT(PPC_BFIW_IMM(sr, srcr, 22, 10)) EMIT(PPC_BFIW_IMM(sr, srcr, 22, 10))
#define emith_carry_to_t(sr, is_sub) \ #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) \ #define emith_t_to_carry(sr, is_sub) \
emith_and_r_r_imm(FC, sr, 1) emith_and_r_r_imm(FC, sr, 1)
@ -1755,26 +1730,27 @@ static int emith_cond_check(int cond)
((cond) ^ 1) ((cond) ^ 1)
// T bit handling // 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) static void emith_set_t_cond(int sr, int cond)
{ {
int b; int b;
u8 *ptr;
u32 val = 0;
// XXX optimization // catch never and always cases
b = emith_invert_branch(emith_cond_check(cond)); if ((b = emith_cond_check(cond)) < 0)
ptr = tcache_ptr; return;
EMIT(PPC_BCOND(b, 0)); else if (b == BXX) {
emith_or_r_imm(sr, T); emith_or_r_imm(sr, T);
val = (u8 *)tcache_ptr - (u8 *)(ptr); return;
EMIT_PTR(ptr, PPC_BCOND(b, val & 0x00001fff));
} }
// 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_get_t_cond() -1
#define emith_sync_t(sr) ((void)sr) #define emith_sync_t(sr) ((void)sr)

View file

@ -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 host_instructions_updated(base, end) __builtin___clear_cache(base, end)
#define emith_update_cache() /**/ #define emith_update_cache() /**/
#define emith_rw_offs_max() 0x7ff #define emith_rw_offs_max() 0x7ff
#define emith_uext_ptr(r) /**/
// SH2 drc specific // SH2 drc specific
#define emith_sh2_drc_entry() do { \ #define emith_sh2_drc_entry() do { \

View file

@ -622,6 +622,8 @@ enum { xAX = 0, xCX, xDX, xBX, xSP, xBP, xSI, xDI, // x86-64,i386 common
emith_asr(d, d, 32 - (bits)); \ emith_asr(d, d, 32 - (bits)); \
} while (0) } while (0)
#define emith_uext_ptr(r) /**/
#define emith_setc(r) do { \ #define emith_setc(r) do { \
assert(is_abcdx(r)); \ assert(is_abcdx(r)); \
EMIT_REX_IF(0, 0, r); \ EMIT_REX_IF(0, 0, r); \

View file

@ -189,7 +189,7 @@ static char sh2dasm_buff[64];
(sh2)->r[8], (sh2)->r[9], (sh2)->r[10], (sh2)->r[11], \ (sh2)->r[8], (sh2)->r[9], (sh2)->r[10], (sh2)->r[11], \
(sh2)->r[12], (sh2)->r[13], (sh2)->r[14], (sh2)->r[15]); \ (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, \ 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); \ (sh2)->gbr, (sh2)->vbr, (sh2)->mach, (sh2)->macl); \
printf("%csh2 tmp-p %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \ printf("%csh2 tmp-p %08x %08x %08x %08x %08x %08x %08x %08x\n", ms, \
(sh2)->drc_tmp, (sh2)->irq_cycles, \ (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(&fsh2, "file");
SH2_DUMP(sh2, "current"); SH2_DUMP(sh2, "current");
SH2_DUMP(&csh2[idx][0], "previous"); 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); exit(1);
} }
csh2[idx][0] = fsh2; csh2[idx][0] = fsh2;
@ -455,6 +459,8 @@ static void rcache_free_tmp(int hr);
#include "../drc/emit_mips.c" #include "../drc/emit_mips.c"
#elif defined(__riscv__) || defined(__riscv) #elif defined(__riscv__) || defined(__riscv)
#include "../drc/emit_riscv.c" #include "../drc/emit_riscv.c"
#elif defined(__powerpc__)
#include "../drc/emit_ppc.c"
#elif defined(__i386__) #elif defined(__i386__)
#include "../drc/emit_x86.c" #include "../drc/emit_x86.c"
#elif defined(__x86_64__) #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 u32 odd = a & 1; // need to fix odd address for correct byte addressing
la -= (s32)((a & ~mask) - *offs - odd); // diff between reg and memory la -= (s32)((a & ~mask) - *offs - odd); // diff between reg and memory
hr = hr2 = rcache_get_reg(r, rmode, NULL); hr = hr2 = rcache_get_reg(r, rmode, NULL);
if ((s32)a < 0) emith_uext_ptr(hr2);
if ((la & ~omask) - odd) { if ((la & ~omask) - odd) {
hr = rcache_get_tmp(); hr = rcache_get_tmp();
emith_add_r_r_ptr_imm(hr, hr2, (la & ~omask) - odd); emith_add_r_r_ptr_imm(hr, hr2, (la & ~omask) - odd);

View file

@ -48,6 +48,9 @@ unsigned short scan_block(uint32_t base_pc, int is_slave,
#elif defined(__riscv__) || defined(__riscv) #elif defined(__riscv__) || defined(__riscv)
#define DRC_SR_REG "s11" #define DRC_SR_REG "s11"
#define DRC_REG_LL 0 // no ABI for (__ILP32__ && __riscv_xlen != 32) #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__) #elif defined(__i386__)
#define DRC_SR_REG "edi" #define DRC_SR_REG "edi"
#define DRC_REG_LL 0 // 32 bit #define DRC_REG_LL 0 // 32 bit

View file

@ -29,7 +29,7 @@ void pemu_prep_defconfig(void)
void pemu_validate_config(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; PicoIn.opt &= ~POPT_EN_DRC;
#endif #endif
} }