diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_660f_vector.c | 38 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_functions.h | 3 | ||||
| -rw-r--r-- | src/dynarec/rv64/dynarec_rv64_private.h | 9 |
3 files changed, 44 insertions, 6 deletions
diff --git a/src/dynarec/rv64/dynarec_rv64_660f_vector.c b/src/dynarec/rv64/dynarec_rv64_660f_vector.c index 36b629a7..3155dfda 100644 --- a/src/dynarec/rv64/dynarec_rv64_660f_vector.c +++ b/src/dynarec/rv64/dynarec_rv64_660f_vector.c @@ -123,8 +123,44 @@ uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t i DEFAULT_VECTOR; } break; + case 0x6C: + INST_NAME("PUNPCKLQDQ Gx, Ex"); + nextop = F8; + SET_ELEMENT_WIDTH(x1, VECTOR_SEW64, 1); + // GX->q[0] = GX->q[0]; -> unchanged + // GX->q[1] = EX->q[0]; + GETGX_vector(v0, 1, VECTOR_SEW64); + q0 = fpu_get_scratch(dyn); + VXOR_VV(q0, q0, q0, VECTOR_UNMASKED); + VMV_V_I(VMASK, 0b10); + if (MODREG) { + v1 = sse_get_reg_vector(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0, VECTOR_SEW64); + if (v0 == v1) { + // for vrgather.vv, cannot be overlapped + v1 = fpu_get_scratch(dyn); + VMV_V_V(v1, v0); + } + VRGATHER_VV(v0, q0, v1, VECTOR_MASKED); + } else { + SMREAD(); + addr = geted(dyn, addr, ninst, nextop, &ed, x3, x2, &fixedaddress, rex, NULL, 0, 0); + VLUXEI64_V(v0, ed, q0, VECTOR_MASKED, VECTOR_NFIELD1); + } + break; case 0x6E: - return 0; + INST_NAME("MOVD Gx, Ed"); + nextop = F8; + GETED(0); + GETGX_empty_vector(v0); + if (rex.w) { + SET_ELEMENT_WIDTH(x3, VECTOR_SEW64, 1); + } else { + SET_ELEMENT_WIDTH(x3, VECTOR_SEW32, 1); + } + VXOR_VV(v0, v0, v0, VECTOR_UNMASKED); + VMV_V_I(VMASK, 1); + VMERGE_VXM(v0, ed, v0); + break; case 0x6F: INST_NAME("MOVDQA Gx, Ex"); nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_functions.h b/src/dynarec/rv64/dynarec_rv64_functions.h index 41d01c4b..04cf7c47 100644 --- a/src/dynarec/rv64/dynarec_rv64_functions.h +++ b/src/dynarec/rv64/dynarec_rv64_functions.h @@ -6,7 +6,8 @@ typedef struct x64emu_s x64emu_t; typedef struct dynarec_rv64_s dynarec_rv64_t; -#define SCRATCH0 2 +#define SCRATCH0 3 +#define VMASK 0 // Get an FPU scratch reg int fpu_get_scratch(dynarec_rv64_t* dyn); diff --git a/src/dynarec/rv64/dynarec_rv64_private.h b/src/dynarec/rv64/dynarec_rv64_private.h index 06312105..771e02d8 100644 --- a/src/dynarec/rv64/dynarec_rv64_private.h +++ b/src/dynarec/rv64/dynarec_rv64_private.h @@ -157,10 +157,11 @@ typedef struct dynarec_rv64_s { uint8_t vector_eew; // effective element width } dynarec_rv64_t; -// convert idx (0..24) to reg index (10..31 0..1) -#define EXTREG(A) (((A)+10)&31) -// convert reg index (10..31 0..1) to idx (0..24) -#define EXTIDX(A) (((A)-10)&31) +// v0 is hardware wired to vector mask register, which should be always reserved +// convert idx (0..23) to reg index (10..31 1..2) +#define EXTREG(A) (((A) + 10 + ((A) > 21)) & 31) +// convert reg index (10..31 1..2) to idx (0..23) +#define EXTIDX(A) (((A) - 10 - ((A) < 3)) & 31) void add_next(dynarec_rv64_t *dyn, uintptr_t addr); uintptr_t get_closest_next(dynarec_rv64_t *dyn, uintptr_t addr); |