diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-21 13:52:46 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-21 13:52:46 +0100 |
| commit | 90bd5b0cb19c42f3f0de74dda3a3c6d560ab0a0e (patch) | |
| tree | 282bf2f04038e0b679d4400dbd61e5f6beee5825 /src | |
| parent | fd729da8f1146966ba63c14402aaae9f38b00ebc (diff) | |
| download | box64-90bd5b0cb19c42f3f0de74dda3a3c6d560ab0a0e.tar.gz box64-90bd5b0cb19c42f3f0de74dda3a3c6d560ab0a0e.zip | |
[DYNAREC] Added F2 0F 10/11 opcodes
Diffstat (limited to 'src')
| -rwxr-xr-x | src/dynarec/dynarec_arm64_f20f.c | 43 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_functions.c | 7 | ||||
| -rwxr-xr-x | src/dynarec/dynarec_arm64_functions.h | 2 |
3 files changed, 44 insertions, 8 deletions
diff --git a/src/dynarec/dynarec_arm64_f20f.c b/src/dynarec/dynarec_arm64_f20f.c index 1caa91b7..1ca91b65 100755 --- a/src/dynarec/dynarec_arm64_f20f.c +++ b/src/dynarec/dynarec_arm64_f20f.c @@ -27,18 +27,20 @@ if(MODREG) { \ a = sse_get_reg(dyn, ninst, x1, (nextop&7)+(rex.b<<3)); \ } else { \ - parity = getedparity(dyn, ninst, addr, nextop, 3); \ + parity = getedparity(dyn, ninst, addr, nextop, 7, D); \ a = fpu_get_scratch(dyn); \ if(parity) { \ - addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 3, rex, 0, D); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \ VLDR64_U12(a, ed, fixedaddress); \ } else { \ - addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 0, rex, 0, D); \ + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, D); \ LDRx_U12(x2, ed, fixedaddress+0); \ VMOVQDfrom(a, 0, x2); \ } \ } +#define GETGX gd = ((nextop&0x38)>>3)+(rex.r<<3) + uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t opcode = F8; @@ -62,10 +64,43 @@ uintptr_t dynarec64_F20F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int n switch(opcode) { + case 0x10: + INST_NAME("MOVSD Gx, Ex"); + nextop = F8; + GETGX; + if(MODREG) { + ed = (nextop&7)+ (rex.b<<3); + v0 = sse_get_reg(dyn, ninst, x1, gd); + d0 = sse_get_reg(dyn, ninst, x1, ed); + VMOV(v0, d0); + } else { + v0 = sse_get_reg_empty(dyn, ninst, x1, gd); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0); + LDRx_U12(x2, ed, fixedaddress); + VEORQ(v0, v0, v0); + VMOVQDfrom(v0, 0, x2); + } + break; + case 0x11: + INST_NAME("MOVSD Ex, Gx"); + nextop = F8; + GETGX; + v0 = sse_get_reg(dyn, ninst, x1, gd); + if(MODREG) { + ed = (nextop&7)+ (rex.b<<3); + d0 = sse_get_reg(dyn, ninst, x1, ed); + VMOV(d0, v0); + } else { + VMOVQDto(x2, v0, 0); + addr = geted(dyn, addr, ninst, nextop, &ed, x1, &fixedaddress, 0xfff<<3, 7, rex, 0, 0); + STRx_U12(x2, ed, fixedaddress); + } + break; + case 0x58: INST_NAME("ADDSD Gx, Ex"); nextop = F8; - gd = ((nextop&0x38)>>3)+(rex.r<<3); + GETGX; v0 = sse_get_reg(dyn, ninst, x1, gd); GETEX(d0, 0); FADDD(v0, v0, d0); diff --git a/src/dynarec/dynarec_arm64_functions.c b/src/dynarec/dynarec_arm64_functions.c index 24b1b55b..d2ba4f6f 100755 --- a/src/dynarec/dynarec_arm64_functions.c +++ b/src/dynarec/dynarec_arm64_functions.c @@ -240,8 +240,9 @@ void fpu_reset_reg(dynarec_arm_t* dyn) #define F8 *(uint8_t*)(addr++) #define F32 *(uint32_t*)(addr+=4, addr-4) +#define F32S64 (uint64_t)(int64_t)*(int32_t*)(addr+=4, addr-4) // Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD -int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity) +int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta) { uint32_t tested = (1<<parity)-1; @@ -252,7 +253,7 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i uint8_t sib = F8; int sib_reg = (sib>>3)&7; if((sib&0x7)==5) { - uint32_t tmp = F32; + uint64_t tmp = F32S64; if (sib_reg!=4) { // if XXXXXX+reg<<N then check parity of XXXXX and N should be enough return ((tmp&tested)==0 && (sib>>6)>=parity)?1:0; @@ -267,7 +268,7 @@ int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, i return ((sib&0x7)==4 && (sib>>6)>=parity)?1:0; } } else if((nextop&7)==5) { - uint32_t tmp = F32; + uint64_t tmp = F32S64+addr+delta; return (tmp&tested)?0:1; } else { return 0; diff --git a/src/dynarec/dynarec_arm64_functions.h b/src/dynarec/dynarec_arm64_functions.h index 0d6a02a5..085e4c1f 100755 --- a/src/dynarec/dynarec_arm64_functions.h +++ b/src/dynarec/dynarec_arm64_functions.h @@ -47,7 +47,7 @@ void fpu_free_reg(dynarec_arm_t* dyn, int reg); void fpu_reset_reg(dynarec_arm_t* dyn); // Get if ED will have the correct parity. Not emiting anything. Parity is 2 for DWORD or 3 for QWORD -int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity); +int getedparity(dynarec_arm_t* dyn, int ninst, uintptr_t addr, uint8_t nextop, int parity, int delta); // Do the GETED, but don't emit anything... uintptr_t fakeed(dynarec_arm_t* dyn, uintptr_t addr, int ninst, uint8_t nextop); |