diff options
| author | xctan <xctan@cirno.icu> | 2023-03-30 18:08:40 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-03-30 12:08:40 +0200 |
| commit | e82d5264144baa0236d751c63d8700c78eea0b46 (patch) | |
| tree | 7aff076b8986fc0ffecc85380748eb9f5e20a6fe /src | |
| parent | 0f11b55ba3c785ebf3bcb6998012621dae69d873 (diff) | |
| download | box64-e82d5264144baa0236d751c63d8700c78eea0b46.tar.gz box64-e82d5264144baa0236d751c63d8700c78eea0b46.zip | |
[RV64_DYNAREC] Added DF F0+i FCOMIP and DF /0 FILD opcodes (#649)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_00.c | 4 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_d8.c | 15 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_df.c | 119 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_helper.h | 2 | ||||
| -rw-r--r-- | src/dynarec/rv64/rv64_emitter.h | 9 |
5 files changed, 141 insertions, 8 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index 20cb4ecd..a7be6681 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -1445,6 +1445,10 @@ uintptr_t dynarec64_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; + case 0xDF: + addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + break; + case 0xE8: INST_NAME("CALL Id"); i32 = F32S; diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c index f7232a18..beadb202 100644 --- a/src/dynarec/rv64/dynarec_rv64_d8.c +++ b/src/dynarec/rv64/dynarec_rv64_d8.c @@ -44,21 +44,22 @@ uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni switch(nextop) { case 0xC0 ... 0xC7: - DEFAULT; + case 0xC8 ... 0xCF: - DEFAULT; + case 0xD0 ... 0xD7: - DEFAULT; + case 0xD8 ... 0xDF: - DEFAULT; + case 0xE0 ... 0xE7: - DEFAULT; + case 0xE8 ... 0xEF: - DEFAULT; + case 0xF0 ... 0xF7: - DEFAULT; + case 0xF8 ... 0xFF: DEFAULT; + break; default: switch((nextop>>3)&7) { diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c new file mode 100644 index 00000000..47f9579c --- /dev/null +++ b/src/dynarec/rv64/dynarec_rv64_df.c @@ -0,0 +1,119 @@ +#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 "emu/x87emu_private.h" +#include "dynarec_native.h" + +#include "rv64_printer.h" +#include "dynarec_rv64_private.h" +#include "dynarec_rv64_helper.h" +#include "dynarec_rv64_functions.h" + +uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog) +{ + (void)ip; (void)rep; (void)need_epilog; + + uint8_t nextop = F8; + uint8_t ed, wback, u8; + int v1, v2; + int s0; + int64_t j64; + int64_t fixedaddress; + + MAYUSE(s0); + MAYUSE(v2); + MAYUSE(v1); + MAYUSE(j64); + + switch(nextop) { + case 0xC0 ... 0xC7: + + case 0xE0: + + case 0xE8 ... 0xEF: + DEFAULT; + break; + + case 0xF0 ... 0xF7: + INST_NAME("FCOMIP ST0, STx"); + SETFLAGS(X_ALL, SF_SET); + v1 = x87_get_st(dyn, ninst, x1, x2, 0, X87_COMBINE(0, nextop&7)); + v2 = x87_get_st(dyn, ninst, x1, x2, nextop&7, X87_COMBINE(0, nextop&7)); + CLEAR_FLAGS(); + IFX(F_ZF | F_PF | F_CF) { + if(ST_IS_F(0)) { + FEQS(x5, v1, v1); + FEQS(x4, v2, v2); + AND(x5, x5, x4); + BEQZ(x5, 24); // undefined/NaN + FEQS(x5, v1, v2); + BNEZ(x5, 24); // equal + FLTS(x3, v1, v2); // x3 = (v1<v2)?1:0 + OR(xFlags, xFlags, x3); // CF is the least significant bit + JAL_gen(xZR, 16); // end + // NaN + ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF)); + JAL_gen(xZR, 8); // end + // equal + ORI(xFlags, xFlags, 1<<F_ZF); + // end + } else { + FEQD(x5, v1, v1); + FEQD(x4, v2, v2); + AND(x5, x5, x4); + BEQZ(x5, 24); // undefined/NaN + FEQD(x5, v1, v2); + BNEZ(x5, 24); // equal + FLTD(x3, v1, v2); // x3 = (v1<v2)?1:0 + OR(xFlags, xFlags, x3); // CF is the least significant bit + JAL_gen(xZR, 16); // end + // NaN + ORI(xFlags, xFlags, (1<<F_ZF) | (1<<F_PF) | (1<<F_CF)); + JAL_gen(xZR, 8); // end + // equal + ORI(xFlags, xFlags, 1<<F_ZF); + // end + } + } + x87_do_pop(dyn, ninst, x3); + break; + case 0xC8 ... 0xDF: + case 0xE1 ... 0xE7: + case 0xF8 ... 0xFF: + DEFAULT; + break; + + default: + switch((nextop>>3)&7) { + case 0: + INST_NAME("FILD ST0, Ew"); + v1 = x87_do_push(dyn, ninst, x1, EXT_CACHE_ST_F); + addr = geted(dyn, addr, ninst, nextop, &wback, x3, x4, &fixedaddress, rex, NULL, 1, 0); + LH(x1, wback, fixedaddress); + if(ST_IS_F(0)) { + FCVTSL(v1, x1); + } else { + FCVTDL(v1, x1); + } + break; + default: + DEFAULT; + break; + } + } + return addr; +} \ 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 17c7187e..4c8651c3 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -1008,7 +1008,7 @@ uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni //uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); //uintptr_t dynarec64_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); //uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); -//uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); uintptr_t dynarec64_660F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); //uintptr_t dynarec64_6664(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int seg, int* ok, int* need_epilog); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index 4f75e518..f3d2f4b1 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -396,6 +396,11 @@ f28–31 ft8–11 FP temporaries Caller #define FMINS(frd, frs1, frs2) EMIT(R_type(0b0010100, frs2, frs1, 0b000, frd, 0b1010011)) #define FMAXS(frd, frs1, frs2) EMIT(R_type(0b0010100, frs2, frs1, 0b001, frd, 0b1010011)) +// compare +#define FEQS(rd, frs1, frs2) EMIT(R_type(0b1010000, frs2, frs1, 0b010, rd, 0b1010011)) +#define FLTS(rd, frs1, frs2) EMIT(R_type(0b1010000, frs2, frs1, 0b001, rd, 0b1010011)) +#define FLES(rd, frs1, frs2) EMIT(R_type(0b1010000, frs2, frs1, 0b000, rd, 0b1010011)) + // RV64F // Convert from signed 64bits to Single #define FCVTSL(frd, rs1) EMIT(R_type(0b1101000, 0b00010, rs1, 0b000, frd, 0b1010011)) @@ -431,6 +436,10 @@ f28–31 ft8–11 FP temporaries Caller // Convert from signed 32bits to Double #define FCVTDW(frd, rs1) EMIT(R_type(0b1101001, 0b00000, rs1, 0b000, frd, 0b1010011)) +#define FEQD(rd, frs1, frs2) EMIT(R_type(0b1010001, frs2, frs1, 0b010, rd, 0b1010011)) +#define FLTD(rd, frs1, frs2) EMIT(R_type(0b1010001, frs2, frs1, 0b001, rd, 0b1010011)) +#define FLED(rd, frs1, frs2) EMIT(R_type(0b1010001, frs2, frs1, 0b000, rd, 0b1010011)) + #define FADDD(frd, frs1, frs2) EMIT(R_type(0b0000001, frs2, frs1, 0b000, frd, 0b1010011)) #define FSUBD(frd, frs1, frs2) EMIT(R_type(0b0000101, frs2, frs1, 0b000, frd, 0b1010011)) #define FMULD(frd, frs1, frs2) EMIT(R_type(0b0001001, frs2, frs1, 0b000, frd, 0b1010011)) |