diff options
| author | xctan <xctan@cirno.icu> | 2023-03-14 16:16:59 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-14 09:16:59 +0100 |
| commit | c48a2252d0e7d364bf3e45c2afb37810a70bc64d (patch) | |
| tree | 4966e354f7b3ad70fa8e0d885d2d202b0bae9293 | |
| parent | 978cd2ec51fe74e0e64a0caa565d36ef6b85bb08 (diff) | |
| download | box64-c48a2252d0e7d364bf3e45c2afb37810a70bc64d.tar.gz box64-c48a2252d0e7d364bf3e45c2afb37810a70bc64d.zip | |
[RV64_DYNAREC] Added C1 /7 SAR opcode (#559)
| -rwxr-xr-x | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 16 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_emit_shift.c | 78 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 15 |
5 files changed, 108 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8453bd13..1548b8a2 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -605,7 +605,7 @@ if(RV64_DYNAREC) #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_tests.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_math.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_logic.c" - #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_shift.c" + "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_emit_shift.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00.c" #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c" #"${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c" diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 1cf10f31..a574ce4c 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -162,6 +162,22 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; + case 0xC1: + nextop = F8; + switch((nextop>>3)&7) { + case 7: + INST_NAME("SAR Ed, Ib"); + SETFLAGS(X_ALL, SF_SET_PENDING); // some flags are left undefined + GETED(1); + u8 = (F8)&(rex.w?0x3f:0x1f); + emit_sar32c(dyn, ninst, rex, ed, u8, x3, x4); + if(u8) { WBACK; } + break; + default: + DEFAULT; + } + break; + default: DEFAULT; } diff --git a/src/dynarec/rv64/dynarec_rv64_emit_shift.c b/src/dynarec/rv64/dynarec_rv64_emit_shift.c new file mode 100644 index 00000000..c4eb103a --- /dev/null +++ b/src/dynarec/rv64/dynarec_rv64_emit_shift.c @@ -0,0 +1,78 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <pthread.h> +#include <errno.h> + +#include "debug.h" +#include "box64context.h" +#include "dynarec.h" +#include "emu/x64emu_private.h" +#include "emu/x64run_private.h" +#include "x64run.h" +#include "x64emu.h" +#include "box64stack.h" +#include "callback.h" +#include "emu/x64run_private.h" +#include "x64trace.h" +#include "dynarec_native.h" +#include "../tools/bridge_private.h" + +#include "rv64_printer.h" +#include "dynarec_rv64_private.h" +#include "dynarec_rv64_functions.h" +#include "dynarec_rv64_helper.h" + +// 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) +{ + 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_sar64:d_sar32); + } 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, F_CF); + } + + SRAIxw(s1, s1, c); + + // SRAIW sign-extends, so test sign bit before clearing upper bits + IFX(X_SF) { + BGE(s1, xZR, 4); + ORI(xFlags, xFlags, 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, F_ZF); + } + IFX(X_PF) { + emit_pf(dyn, ninst, s1, s3, s4); + } +} \ No newline at end of file diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 5d9f2140..84eaa0df 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -392,7 +392,7 @@ void emit_xor32(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, int s //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_sar32c(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); //void emit_shrd32c(dynarec_rv64_t* dyn, int ninst, rex_t rex, int s1, int s2, uint32_t c, int s3, int s4); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 10cf325b..b95f7278 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -168,7 +168,7 @@ f28–31 ft8–11 FP temporaries Caller #define XORxw(rd, rs1, rs2) do{ XOR(rd, rs1, rs2); if (!rex.w) ZEROUP(rd); }while(0) // rd = rs1>>rs2 logical #define SRL(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0110011)) -// rd = rs1>>rs2 aritmetic +// rd = rs1>>rs2 arithmetic #define SRA(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b101, rd, 0b0110011)) // rd = rs1 | rs2 #define OR(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b110, rd, 0b0110011)) @@ -235,7 +235,7 @@ f28–31 ft8–11 FP temporaries Caller #define SLLI(rd, rs1, imm6) EMIT(I_type(imm6, rs1, 0b001, rd, 0b0010011)) // Shift Right Logical Immediate #define SRLI(rd, rs1, imm6) EMIT(I_type(imm6, rs1, 0b101, rd, 0b0010011)) -// Shift Right Aritmetic Immediate +// Shift Right Arithmetic Immediate #define SRAI(rd, rs1, imm6) EMIT(I_type((imm6)|(0b010000<<6), rs1, 0b101, rd, 0b0010011)) // rd = rs1 + imm12 @@ -247,7 +247,16 @@ f28–31 ft8–11 FP temporaries Caller #define SLLW(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b001, rd, 0b0111011)) // rd = rs1>>rs2 logical #define SRLW(rd, rs1, rs2) EMIT(R_type(0b0000000, rs2, rs1, 0b101, rd, 0b0111011)) -// rd = rs1>>rs2 aritmetic +// rd = rs1>>rs2 arithmetic #define SRAW(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b101, rd, 0b0111011)) +// Shift Left Immediate, 32-bit, sign-extended +#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 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 +#define SRAIxw(rd, rs1, imm) if (rex.w) { SRAI(rd, rs1, imm); } else { SRAIW(rd, rs1, imm); } + #endif //__RV64_EMITTER_H__ |