From 440c6d2d9a1dfd021c05a9bfc774366e6da08059 Mon Sep 17 00:00:00 2001 From: xctan Date: Thu, 16 Mar 2023 14:51:32 +0800 Subject: [RV64_DYNAREC] Added {C1,D1} /{5,7} opcode and some fixes (#569) * [RV64_DYNAREC] Added C1 /5 SHR opcode and some fixes * [RV64_DYNAREC] Added D1 /{5,7} opcode --- src/dynarec/rv64/dynarec_rv64_00.c | 30 +++++++++++++ src/dynarec/rv64/dynarec_rv64_emit_shift.c | 69 ++++++++++++++++++++++++++++-- src/dynarec/rv64/dynarec_rv64_helper.h | 2 +- src/dynarec/rv64/rv64_emitter.h | 2 + 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 032358c9..2516507e 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -215,6 +215,14 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0xC1: nextop = F8; switch((nextop>>3)&7) { + case 5: + INST_NAME("SHR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + u8 = (F8)&(rex.w?0x3f:0x1f); + emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); + if(u8) { WBACK; } + break; case 7: INST_NAME("SAR Ed, Ib"); SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined @@ -351,6 +359,28 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; + case 0xD1: + nextop = F8; + switch((nextop>>3)&7) { + case 5: + INST_NAME("SHR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + emit_shr32c(dyn, ninst, rex, ed, 1, x3, x4); + WBACK; + break; + case 7: + INST_NAME("SAR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + emit_sar32c(dyn, ninst, rex, ed, 1, x3, x4); + WBACK; + break; + default: + DEFAULT; + } + break; + case 0xE8: INST_NAME("CALL Id"); i32 = F32S; diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c index c4eb103a..36c5c192 100644 --- a/src/dynarec/rv64/dynarec_rv64_emit_shift.c +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -23,6 +23,69 @@ #include "dynarec_rv64_functions.h" #include "dynarec_rv64_helper.h" +// emit SHR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch +void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) +{ + CLEAR_FLAGS(); + + IFX(X_PEND) { + MOV64x(s3, c); + SDxw(s1, xEmu, offsetof(x64emu_t, op1)); + SDxw(s3, xEmu, offsetof(x64emu_t, op2)); + SET_DF(s4, rex.w?d_shr64:d_shr32); + } else IFX(X_ALL) { + SET_DFNONE(s4); + } + if(!c) { + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + return; + } + IFX(X_CF) { + if (c > 1) { + SRAI(s3, s1, c-1); + ANDI(s3, s3, 1); // LSB + BEQZ(s3, 4); + } else { + // no need to shift + ANDI(s3, s1, 1); + BEQZ(s3, 4); + } + ORI(xFlags, xFlags, 1 << F_CF); + } + + SRLIxw(s1, s1, c); + + IFX(X_SF) { + BGE(s1, xZR, 4); + ORI(xFlags, xFlags, 1 << F_SF); + } + if (!rex.w) { + ZEROUP(s1); + } + IFX(X_PEND) { + SDxw(s1, xEmu, offsetof(x64emu_t, res)); + } + IFX(X_ZF) { + BNEZ(s1, 4); + ORI(xFlags, xFlags, 1 << F_ZF); + } + IFX(X_OF) { + if(c==1) { + SRLI(s3, s1, rex.w?62:30); + SRLI(s4, s1, rex.w?63:31); + XOR(s3, s3, s4); + ANDI(s3, s3, 1); + BEQZ(s3, 4); + ORI(xFlags, xFlags, 1 << F_OF2); + } + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} + // emit SAR32 instruction, from s1 , constant c, store result in s1 using s3 and s4 as scratch void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4) { @@ -52,7 +115,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, ANDI(s3, s1, 1); BEQZ(s3, 4); } - ORI(xFlags, xFlags, F_CF); + ORI(xFlags, xFlags, 1 << F_CF); } SRAIxw(s1, s1, c); @@ -60,7 +123,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, // SRAIW sign-extends, so test sign bit before clearing upper bits IFX(X_SF) { BGE(s1, xZR, 4); - ORI(xFlags, xFlags, F_SF); + ORI(xFlags, xFlags, 1 << F_SF); } if (!rex.w) { ZEROUP(s1); @@ -70,7 +133,7 @@ void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, } IFX(X_ZF) { BNEZ(s1, 4); - ORI(xFlags, xFlags, F_ZF); + ORI(xFlags, xFlags, 1 << F_ZF); } IFX(X_PF) { emit_pf(dyn, ninst, s1, s3, s4); diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 858fbc71..03592e93 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -568,7 +568,7 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s //void emit_shl32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); //void emit_shl32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); //void emit_shr32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s3, int s4); -//void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); +void emit_shr32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); void emit_sar32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); //void emit_rol32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); //void emit_ror32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, uint32_t c, int s3, int s4); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 24f36f52..5359daca 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -276,6 +276,8 @@ f28–31 ft8–11 FP temporaries Caller #define SLLIW(rd, rs1, imm5) EMIT(I_type(imm5, rs1, 0b001, rd, 0b0011011)) // Shift Right Logical Immediate, 32-bit, sign-extended #define SRLIW(rd, rs1, imm5) EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011)) +// Shift Right Logical Immediate +#define SRLIxw(rd, rs1, imm) if (rex.w) { SRLI(rd, rs1, imm); } else { SRLIW(rd, rs1, imm); } // Shift Right Arithmetic Immediate, 32-bit, sign-extended #define SRAIW(rd, rs1, imm5) EMIT(I_type((imm5)|(0b0100000<<5), rs1, 0b101, rd, 0b0011011)) // Shift Right Arithmetic Immediate -- cgit 1.4.1