diff options
| author | Haichen Wu <www.wxmqq@gmail.com> | 2024-04-04 19:43:30 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-04-04 13:43:30 +0200 |
| commit | a4142f68ce3a6b5d5034966ff887a00160539917 (patch) | |
| tree | b28254a91527bf89656fa000cb646570751de056 /src | |
| parent | 4a889e39ad9a8b39119e71a8c9640affd3591a34 (diff) | |
| download | box64-a4142f68ce3a6b5d5034966ff887a00160539917.tar.gz box64-a4142f68ce3a6b5d5034966ff887a00160539917.zip | |
[LA64_DYNAREC] Added more SSE/SSE2 instructions (#1410)
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_00.c | 3 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f20f.c | 85 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_f30f.c | 16 | ||||
| -rw-r--r-- | src/dynarec/la64/dynarec_la64_helper.h | 13 | ||||
| -rw-r--r-- | src/dynarec/la64/la64_printer.c | 32 |
5 files changed, 149 insertions, 0 deletions
diff --git a/src/dynarec/la64/dynarec_la64_00.c b/src/dynarec/la64/dynarec_la64_00.c index e8411efd..fe7b042d 100644 --- a/src/dynarec/la64/dynarec_la64_00.c +++ b/src/dynarec/la64/dynarec_la64_00.c @@ -122,6 +122,9 @@ uintptr_t dynarec64_00(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0: addr = dynarec64_0F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 1: + addr = dynarec64_F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); + break; case 2: addr = dynarec64_F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; diff --git a/src/dynarec/la64/dynarec_la64_f20f.c b/src/dynarec/la64/dynarec_la64_f20f.c new file mode 100644 index 00000000..54c8c746 --- /dev/null +++ b/src/dynarec/la64/dynarec_la64_f20f.c @@ -0,0 +1,85 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.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 "la64_printer.h" +#include "dynarec_la64_private.h" +#include "dynarec_la64_functions.h" +#include "dynarec_la64_helper.h" + +uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) +{ + (void)ip; (void)need_epilog; + + uint8_t opcode = F8; + uint8_t nextop; + uint8_t gd, ed; + uint8_t wback, wb1, wb2; + uint8_t u8; + uint64_t u64, j64; + int v0, v1; + int q0; + int d0, d1; + int64_t fixedaddress; + int unscaled; + + MAYUSE(d0); + MAYUSE(d1); + MAYUSE(q0); + MAYUSE(v0); + MAYUSE(v1); + + switch(opcode) { + case 0x10: + INST_NAME("MOVSD Gx, Ex"); + nextop = F8; + GETG; + if(MODREG) { + ed = (nextop&7)+ (rex.b<<3); + v0 = sse_get_reg(dyn, ninst, x1, gd, 1); + d0 = sse_get_reg(dyn, ninst, x1, ed, 0); + FMOV_D(v0, d0); + } else { + SMREAD(); + v0 = sse_get_reg_empty(dyn, ninst, x1, gd); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 8, 0); + FLD_D(v0, ed, fixedaddress); + // reset upper part + ST_D(xZR, xEmu, offsetof(x64emu_t, xmm[gd])+8); + } + break; + case 0x58: + INST_NAME("ADDSD Gx, Ex"); + nextop = F8; + // TODO: fastnan handling + GETGX(v0, 1); + GETEXSD(v1, 0); + FADD_D(v0, v0, v1); + break; + case 0x5C: + INST_NAME("SUBSD Gx, Ex"); + nextop = F8; + //TODO: fastnan handling + GETGX(v0, 1); + GETEXSD(v1, 0); + FSUB_D(v0, v0, v1); + break; + default: + DEFAULT; + } + return addr; +} \ No newline at end of file diff --git a/src/dynarec/la64/dynarec_la64_f30f.c b/src/dynarec/la64/dynarec_la64_f30f.c index 107e5f38..d36ea651 100644 --- a/src/dynarec/la64/dynarec_la64_f30f.c +++ b/src/dynarec/la64/dynarec_la64_f30f.c @@ -53,6 +53,22 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int nextop = F8; FAKEED; break; + case 0x7E: + INST_NAME("MOVQ Gx, Ex"); + nextop = F8; + // Will load Gx as SD. Is that a good choice? + if (MODREG) { + v1 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); + GETGX_empty(v0); + FMOV_D(v0, v1); + } else { + GETGX_empty(v0); + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); + FLD_D(v0, ed, fixedaddress); + } + ST_D(xZR, xEmu, offsetof(x64emu_t, xmm[gd]) + 8); + break; default: DEFAULT; } diff --git a/src/dynarec/la64/dynarec_la64_helper.h b/src/dynarec/la64/dynarec_la64_helper.h index 4d8a8d8c..3405afcb 100644 --- a/src/dynarec/la64/dynarec_la64_helper.h +++ b/src/dynarec/la64/dynarec_la64_helper.h @@ -195,6 +195,17 @@ VLD(a, ed, fixedaddress); \ } +// Get Ex as a double, not a quad (warning, x1 get used, x2 might too) +#define GETEXSD(a, D) \ + if (MODREG) { \ + a = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); \ + } else { \ + SMREAD(); \ + a = fpu_get_scratch(dyn); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, D); \ + FLD_D(a, ed, fixedaddress); \ + } + // Write gb (gd) back to original register / memory, using s1 as scratch #define GBBACK() BSTRINS_D(gb1, gd, gb2 + 7, gb2); @@ -505,6 +516,7 @@ void* la64_next(x64emu_t* emu, uintptr_t addr); #define dynarec64_F30F STEPNAME(dynarec64_F30F) #define dynarec64_660F STEPNAME(dynarec64_660F) #define dynarec64_F0 STEPNAME(dynarec64_F0) +#define dynarec64_F20F STEPNAME(dynarec64_F20F) #define geted STEPNAME(geted) #define geted32 STEPNAME(geted32) @@ -640,6 +652,7 @@ uintptr_t dynarec64_F30F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int uintptr_t dynarec64_66(dynarec_la64_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_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F0(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int* ok, int* need_epilog); +uintptr_t dynarec64_F20F(dynarec_la64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); #if STEP < 3 #define PASS3(A) diff --git a/src/dynarec/la64/la64_printer.c b/src/dynarec/la64/la64_printer.c index 742d730b..02c2db1e 100644 --- a/src/dynarec/la64/la64_printer.c +++ b/src/dynarec/la64/la64_printer.c @@ -7,6 +7,18 @@ #include "debug.h" static const char* Xt[] = {"xZR", "r1", "r2", "sp", "xEmu", "x1_r5", "x2_r6", "x3_r7", "x4_r8", "x5_r9", "x6_r10", "xMASK_r11", "xRAX_r12", "xRCX_r13", "xRDX_r14", "xRBX_r15", "xRSP_r16", "xRBP_r17", "xRSI_r18", "xRDI_r19", "xRIP_r20", "r21", "r22", "xR8_r23", "xR9_r24", "xR10_r25", "xR11_r26", "xR12_r27", "xR13_r28", "xR14_r29", "xR15_r30", "xFlags_r31"}; +static const char* fpnames[] = { + "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", "fa6", "fa7", + "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", + "ft8", "ft9", "ft10", "ft11", "ft12", "ft13", "ft14", "ft15", + "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", +}; +static const char* vrpnames[] = { + "vra0", "vra1", "vra2", "vra3", "vra4", "vra5", "vra6", "vra7", + "vrt0", "vrt1", "vrt2", "vrt3", "vrt4", "vrt5", "vrt6", "vrt7", + "vrt8", "vrt9", "vrt10", "vrt11", "vrt12", "vrt13", "vrt14", "vrt15", + "vrs0", "vrs1", "vrs2", "vrs3", "vrs4", "vrs5", "vrs6", "vrs7", +}; typedef struct la64_print_s { int d, j, k, a; @@ -450,6 +462,26 @@ const char* la64_print(uint32_t opcode, uintptr_t addr) snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "ST.D", Xt[Rd], Xt[Rj], signExtend(imm, 12)); return buff; } + // FLD.D + if(isMask(opcode, "0010101110iiiiiiiiiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "FLD.D", fpnames[Rd], Xt[Rj], signExtend(imm, 12)); + return buff; + } + // FADD.D + if(isMask(opcode, "00000001000000010kkkkkjjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "FADD.D", fpnames[Rd], fpnames[Rj], fpnames[Rk]); + return buff; + } + // FSUB.D + if(isMask(opcode, "00000001000000110kkkkkjjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %s", "FSUB.D", fpnames[Rd], fpnames[Rj], fpnames[Rk]); + return buff; + } + // VLD + if(isMask(opcode, "0010110000iiiiiiiiiiiijjjjjddddd", &a)) { + snprintf(buff, sizeof(buff), "%-15s %s, %s, %d", "VLD.D", vrpnames[Rd], Xt[Rj], signExtend(imm, 12)); + return buff; + } // EXT.W.H if(isMask(opcode, "0000000000000000010110jjjjjddddd", &a)) { snprintf(buff, sizeof(buff), "%-15s %s, %s", "EXT.W.H", Xt[Rd], Xt[Rj]); |