From 8f52a3a3cc6c07f197d32fca2067dd6b827fae27 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Mon, 20 Mar 2023 18:48:09 +0800 Subject: [RV64_DYNAREC] Added 66 3D CMP opcode (#598) --- src/dynarec/rv64/dynarec_rv64_66.c | 13 ++++++ src/dynarec/rv64/dynarec_rv64_emit_tests.c | 66 ++++++++++++++++++++++++++++++ src/dynarec/rv64/dynarec_rv64_helper.h | 5 +-- 3 files changed, 81 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 86446b7a..9aaf4e2f 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -66,6 +66,19 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x3D: + INST_NAME("CMP AX, Iw"); + SETFLAGS(X_ALL, SF_SET_PENDING); + i32 = F16; + SLLI(x1, xRAX, 48); + SRLI(x1, xRAX, 48); + if(i32) { + MOV32w(x2, i32); + emit_cmp16(dyn, ninst, x1, x2, x3, x4, x5, x6); + } else { + emit_cmp16_0(dyn, ninst, x1, x3, x4); + } + break; case 0x70: case 0x71: case 0x72: diff --git a/src/dynarec/rv64/dynarec_rv64_emit_tests.c b/src/dynarec/rv64/dynarec_rv64_emit_tests.c index 7ce0ae58..9b0bcf09 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_tests.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_tests.c @@ -88,6 +88,72 @@ void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) } } +// emit CMP16 instruction, from cmp s1, s2, using s3 and s4 as scratch +void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6) +{ + CLEAR_FLAGS(); + IFX_PENDOR0 { + SH(s1, xEmu, offsetof(x64emu_t, op1)); + SH(s2, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, d_cmp16); + } else { + SET_DFNONE(); + } + + IFX(X_AF | X_CF | X_OF) { + // for later flag calculation + NOT(s5, s1); + } + + // It's a cmp, we can't store the result back to s1. + SUB(s6, s1, s2); + SLLI(s6, s6, 48); + SRLI(s6, s6, 48); + IFX_PENDOR0 { + SH(s6, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_SF) { + SRLI(s3, s6, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + CALC_SUB_FLAGS(s5, s2, s6, s3, s4, 16); + IFX(X_ZF) { + BNEZ(s6, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s6, s3, s4); + } +} + +// emit CMP16 instruction, from cmp s1 , #0, using s3 and s4 as scratch +void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4) +{ + CLEAR_FLAGS(); + IFX_PENDOR0 { + SH(s1, xEmu, offsetof(x64emu_t, op1)); + SH(xZR, xEmu, offsetof(x64emu_t, op2)); + SH(s1, xEmu, offsetof(x64emu_t, res)); + SET_DF(s3, d_cmp16); + } else { + SET_DFNONE(); + } + + IFX(X_SF) { + SRLI(s3, s1, 15); + BEQZ(s3, 8); + ORI(xFlags, xFlags, 1 << F_SF); + } + IFX(X_ZF) { + BNEZ(s1, 8); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit CMP32 instruction, from cmp s1, s2, using s3 and s4 as scratch void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index fc526327..a27315b6 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -337,7 +337,6 @@ ANDI(scratch1, scratch2, 0x80); \ } else { \ SRLI(scratch1, scratch2, (width)-1); \ - if ((width) == 16) ANDI(scratch1, scratch1, 1); \ } \ BEQZ(scratch1, 8); \ ORI(xFlags, xFlags, 1 << F_CF); \ @@ -650,10 +649,10 @@ void call_c(dynarec_rv64_t* dyn, int ninst, void* fnc, int reg, int ret, int sav void call_n(dynarec_rv64_t* dyn, int ninst, void* fnc, int w); void grab_segdata(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, int reg, int segment); void emit_cmp8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6); -//void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); +void emit_cmp16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5, int s6); void emit_cmp32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4, int s5, int s6); void emit_cmp8_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); -//void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); +void emit_cmp16_0(dynarec_rv64_t* dyn, int ninst, int s1, int s3, int s4); void emit_cmp32_0(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s3, int s4); void emit_test8(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); //void emit_test16(dynarec_rv64_t* dyn, int ninst, int s1, int s2, int s3, int s4, int s5); -- cgit 1.4.1