diff --git a/CMakeLists.txt b/CMakeLists.txt index 526e7f241..ee66da7de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1031,12 +1031,7 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_00_3.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_0f_vector.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_64_vector.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_vector.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_67_32.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d8.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_d9.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_da.c" @@ -1051,7 +1046,6 @@ if(RV64_DYNAREC) "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_660f_vector.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f20f.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f30f.c" - "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_6664.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_66f0.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f.c" "${BOX64_ROOT}/src/dynarec/rv64/dynarec_rv64_f20f_vector.c" diff --git a/src/dynarec/dynarec_native_pass.c b/src/dynarec/dynarec_native_pass.c index 51bb1fc16..5897473ae 100644 --- a/src/dynarec/dynarec_native_pass.c +++ b/src/dynarec/dynarec_native_pass.c @@ -192,7 +192,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int } #endif - #if defined (ARM64) || defined (LA64) uint8_t pk = PK(0); rex.rex = 0; @@ -234,34 +233,6 @@ uintptr_t native_pass(dynarec_native_t* dyn, uintptr_t addr, int alternate, int addr = dynarec64_66(dyn, addr, ip, ninst, rex, &ok, &need_epilog); else addr = dynarec64_00(dyn, addr, ip, ninst, rex, &ok, &need_epilog); - #else - rep = 0; - rex.is32bits = is32bits; - uint8_t pk = PK(0); - while((pk==0xF2) || (pk==0xF3) || (pk==0x3E) || (pk==0x26) - || (is32bits && ((pk==0x2E) || (pk==0x36))) - ) { - switch(pk) { - case 0xF2: rep = 1; break; - case 0xF3: rep = 2; break; - case 0x2E: - case 0x36: - case 0x3E: - case 0x26: /* ignored */ break; - } - ++addr; - pk = PK(0); - } - rex.rex = 0; - if(!rex.is32bits) - while(pk>=0x40 && pk<=0x4f) { - rex.rex = pk; - ++addr; - pk = PK(0); - } - - addr = dynarec64_00(dyn, addr, ip, ninst, rex, rep, &ok, &need_epilog); - #endif if(dyn->abort) return ip; INST_EPILOG; diff --git a/src/dynarec/rv64/dynarec_rv64_00.c b/src/dynarec/rv64/dynarec_rv64_00.c index faf7430b2..2ccf55a3f 100644 --- a/src/dynarec/rv64/dynarec_rv64_00.c +++ b/src/dynarec/rv64/dynarec_rv64_00.c @@ -23,16 +23,16 @@ #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" -uintptr_t dynarec64_00(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_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t opcode; opcode = PK(0); switch (opcode) { - case 0x00 ... 0x3f: addr = dynarec64_00_0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; - case 0x40 ... 0x7f: addr = dynarec64_00_1(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; - case 0x80 ... 0xbf: addr = dynarec64_00_2(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; - case 0xc0 ... 0xff: addr = dynarec64_00_3(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); break; + case 0x00 ... 0x3f: addr = dynarec64_00_0(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x40 ... 0x7f: addr = dynarec64_00_1(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0x80 ... 0xbf: addr = dynarec64_00_2(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 0xc0 ... 0xff: addr = dynarec64_00_3(dyn, addr, ip, ninst, rex, ok, need_epilog); break; } return addr; diff --git a/src/dynarec/rv64/dynarec_rv64_00_0.c b/src/dynarec/rv64/dynarec_rv64_00_0.c index 067709824..dc8d109bf 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_0.c +++ b/src/dynarec/rv64/dynarec_rv64_00_0.c @@ -23,7 +23,7 @@ #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" -uintptr_t dynarec64_00_0(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_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t nextop, opcode; uint8_t gd, ed; @@ -212,7 +212,7 @@ uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0x0F: - switch (rep) { + switch (rex.rep) { case 0: if (cpuext.vector) retaddr = dynarec64_0F_vector(dyn, addr, ip, ninst, rex, ok, need_epilog); diff --git a/src/dynarec/rv64/dynarec_rv64_00_1.c b/src/dynarec/rv64/dynarec_rv64_00_1.c index ed5f2c814..f5166f0be 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_1.c +++ b/src/dynarec/rv64/dynarec_rv64_00_1.c @@ -25,7 +25,7 @@ int isSimpleWrapper(wrapper_t fun); -uintptr_t dynarec64_00_1(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_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t nextop, opcode; uint8_t gd, ed, tmp1, tmp2, tmp3; @@ -202,28 +202,6 @@ uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } } break; - case 0x64: - if (cpuext.vector) - retaddr = dynarec64_64_vector(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog); - addr = retaddr ? retaddr : dynarec64_64(dyn, addr, ip, ninst, rex, rep, _FS, ok, need_epilog); - break; - case 0x65: - if (cpuext.vector) - retaddr = dynarec64_64_vector(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog); - addr = retaddr ? retaddr : dynarec64_64(dyn, addr, ip, ninst, rex, rep, _GS, ok, need_epilog); - break; - case 0x66: - addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - break; - case 0x67: - if (rex.is32bits) - addr = dynarec64_67_32(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - else { - if (cpuext.vector) - retaddr = dynarec64_67_vector(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - addr = retaddr ? retaddr : dynarec64_67(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - } - break; case 0x68: INST_NAME("PUSH Id"); i64 = F32S; diff --git a/src/dynarec/rv64/dynarec_rv64_00_2.c b/src/dynarec/rv64/dynarec_rv64_00_2.c index 570710442..c6d305ba7 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_2.c +++ b/src/dynarec/rv64/dynarec_rv64_00_2.c @@ -23,7 +23,7 @@ #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" -uintptr_t dynarec64_00_2(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_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t nextop, opcode; uint8_t gd, ed; @@ -500,10 +500,14 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int if (MODREG) { // reg <= reg? that's an invalid operation DEFAULT; } else { // mem <= reg + rex.seg = 0; // to be safe SCRATCH_USAGE(0); addr = geted(dyn, addr, ninst, nextop, &ed, gd, x1, &fixedaddress, rex, NULL, 0, 0); if (gd != ed) { - MVxw(gd, ed); + if (rex.w && rex.is67) + ZEXTW2(gd, ed); + else + MVxw(gd, ed); } else if (!rex.w && !rex.is32bits) { ZEROUP(gd); // truncate the higher 32bits as asked } @@ -630,47 +634,77 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xRAX, xRAX, x1); break; case 0xA0: - INST_NAME("MOV AL,Ob"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV AL, Ob"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); + SMREADLOCK(lock); LBU(x1, x1, 0); ANDI(xRAX, xRAX, ~0xff); OR(xRAX, xRAX, x1); break; case 0xA1: - INST_NAME("MOV EAX,Od"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV EAX, Od"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); + SMREADLOCK(lock); LDxw(xRAX, x1, 0); break; case 0xA2: - INST_NAME("MOV Ob,AL"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV Ob, AL"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); SB(xRAX, x1, 0); - SMWRITE(); + SMWRITELOCK(lock); break; case 0xA3: - INST_NAME("MOV Od,EAX"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV Od, EAX"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); SDxw(xRAX, x1, 0); - SMWRITE(); + SMWRITELOCK(lock); break; case 0xA4: - if (rep) { + if (rex.rep) { INST_NAME("REP MOVSB"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -721,7 +755,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA5: - if (rep) { + if (rex.rep) { INST_NAME("REP MOVSD"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -754,10 +788,10 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SMWRITE(); break; case 0xA6: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ CMPSB"); } else { INST_NAME("REPZ CMPSB"); @@ -773,7 +807,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADDI(xRSI, xRSI, 1); ADDI(xRDI, xRDI, 1); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -786,7 +820,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SUBI(xRSI, xRSI, 1); SUBI(xRDI, xRDI, 1); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -808,10 +842,10 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xA7: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ CMPSD"); } else { INST_NAME("REPZ CMPSD"); @@ -827,7 +861,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ADDI(xRSI, xRSI, rex.w ? 8 : 4); ADDI(xRDI, xRDI, rex.w ? 8 : 4); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -840,7 +874,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int SUBI(xRSI, xRSI, rex.w ? 8 : 4); SUBI(xRDI, xRDI, rex.w ? 8 : 4); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -876,7 +910,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int emit_test32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); break; case 0xAA: - if (rep) { + if (rex.rep) { INST_NAME("REP STOSB"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -901,7 +935,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAB: - if (rep) { + if (rex.rep) { INST_NAME("REP STOSD"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -926,7 +960,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAC: - if (rep) { + if (rex.rep) { DEFAULT; } else { INST_NAME("LODSB"); @@ -938,7 +972,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAD: - if (rep) { + if (rex.rep) { DEFAULT; } else { INST_NAME("LODSD"); @@ -948,10 +982,10 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAE: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ SCASB"); } else { INST_NAME("REPZ SCASB"); @@ -966,7 +1000,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int LBU(x2, xRDI, 0); ADDI(xRDI, xRDI, 1); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -977,7 +1011,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int LBU(x2, xRDI, 0); SUBI(xRDI, xRDI, 1); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -998,10 +1032,10 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int } break; case 0xAF: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ SCASD"); } else { INST_NAME("REPZ SCASD"); @@ -1020,7 +1054,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int LDxw(x2, xRDI, 0); ADDI(xRDI, xRDI, rex.w ? 8 : 4); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -1031,7 +1065,7 @@ uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int LDxw(x2, xRDI, 0); SUBI(xRDI, xRDI, rex.w ? 8 : 4); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); diff --git a/src/dynarec/rv64/dynarec_rv64_00_3.c b/src/dynarec/rv64/dynarec_rv64_00_3.c index 37a63ac9d..2bf9f137d 100644 --- a/src/dynarec/rv64/dynarec_rv64_00_3.c +++ b/src/dynarec/rv64/dynarec_rv64_00_3.c @@ -28,7 +28,7 @@ int isSimpleWrapper(wrapper_t fun); int isRetX87Wrapper(wrapper_t fun); -uintptr_t dynarec64_00_3(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_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t nextop, opcode; uint8_t gd, ed; @@ -878,40 +878,40 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int OR(xRAX, xRAX, x1); break; case 0xD8: - addr = dynarec64_D8(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_D8(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xD9: - addr = dynarec64_D9(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_D9(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDA: - addr = dynarec64_DA(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DA(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDB: - addr = dynarec64_DB(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DB(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDC: - addr = dynarec64_DC(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DC(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDD: - addr = dynarec64_DD(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DD(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDE: - addr = dynarec64_DE(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DE(dyn, addr, ip, ninst, rex, ok, need_epilog); break; case 0xDF: - addr = dynarec64_DF(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + addr = dynarec64_DF(dyn, addr, ip, ninst, rex, ok, need_epilog); break; -#define GO(Z) \ +#define GO(Z, R) \ BARRIER(BARRIER_MAYBE); \ JUMP(addr + i8, 1); \ if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \ /* out of the block */ \ i32 = dyn->insts[ninst].epilog - (dyn->native_size); \ if (Z) { \ - BNE(xRCX, xZR, i32); \ + BNE(R, xZR, i32); \ } else { \ - BEQ(xRCX, xZR, i32); \ + BEQ(R, xZR, i32); \ }; \ if (dyn->insts[ninst].x64.jmp_insts == -1) { \ if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \ @@ -926,39 +926,69 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int /* inside the block */ \ i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \ if (Z) { \ - BEQ(xRCX, xZR, i32); \ + BEQ(R, xZR, i32); \ } else { \ - BNE(xRCX, xZR, i32); \ + BNE(R, xZR, i32); \ }; \ } case 0xE0: INST_NAME("LOOPNZ"); READFLAGS(X_ZF); i8 = F8S; - SUBI(xRCX, xRCX, 1); - ANDI(x1, xFlags, 1 << F_ZF); - CBNZ_NEXT(x1); - GO(0); + if (rex.is32bits && rex.is67) { + ADDIW(x3, x3, -1); + INSH(xRCX, x3, x5, x6, 1, 1); // x3 will be zexth'ed + ANDI(x1, xFlags, 1 << F_ZF); + CBNZ_NEXT(x1); + GO(0, x3); + } else { + ADDIy(xRCX, xRCX, -1); + ANDI(x1, xFlags, 1 << F_ZF); + CBNZ_NEXT(x1); + GO(0, xRCX); + } break; case 0xE1: INST_NAME("LOOPZ"); READFLAGS(X_ZF); i8 = F8S; - SUBI(xRCX, xRCX, 1); - ANDI(x1, xFlags, 1 << F_ZF); - CBZ_NEXT(x1); - GO(0); + if (rex.is32bits && rex.is67) { + ADDIW(x3, x3, -1); + INSH(xRCX, x3, x5, x6, 1, 1); // x3 will be zexth'ed + ANDI(x1, xFlags, 1 << F_ZF); + CBZ_NEXT(x1); + GO(0, x3); + } else { + ADDIy(xRCX, xRCX, -1); + ANDI(x1, xFlags, 1 << F_ZF); + CBZ_NEXT(x1); + GO(0, xRCX); + } break; case 0xE2: INST_NAME("LOOP"); i8 = F8S; - SUBI(xRCX, xRCX, 1); - GO(0); + if (rex.is32bits && rex.is67) { + ADDIW(x3, x3, -1); + INSH(xRCX, x3, x5, x6, 1, 1); // x3 will be zexth'ed + GO(0, x3); + } else { + ADDIy(xRCX, xRCX, -1); + GO(0, xRCX); + } break; case 0xE3: INST_NAME("JECXZ"); i8 = F8S; - GO(1); + if (rex.is32bits && rex.is67) { + ZEXTH(x3, xRCX); + GO(1, x3); + } else if (rex.is32bits || rex.is67) { + ADDIy(x3, xRCX, 0); + GO(1, x3); + } else { + GO(1, xRCX); + } break; #undef GO @@ -1148,9 +1178,6 @@ uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int *need_epilog = 0; *ok = 0; break; - case 0xF0: - addr = dynarec64_F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - break; case 0xF4: INST_NAME("HLT"); if (box64_unittest_mode) { // HLT in unittest mode is an exit diff --git a/src/dynarec/rv64/dynarec_rv64_0f.c b/src/dynarec/rv64/dynarec_rv64_0f.c index 7b48b7a28..6a3e2a15a 100644 --- a/src/dynarec/rv64/dynarec_rv64_0f.c +++ b/src/dynarec/rv64/dynarec_rv64_0f.c @@ -1870,7 +1870,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); LDxw(x1, x3, fixedaddress); ed = x1; } @@ -1926,7 +1927,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); LDxw(x1, x3, fixedaddress); ed = x1; wback = x3; @@ -2156,7 +2158,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); LDxw(x1, x3, fixedaddress); ed = x1; wback = x3; @@ -2329,7 +2332,8 @@ uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); LDxw(x1, x3, fixedaddress); ed = x1; wback = x3; diff --git a/src/dynarec/rv64/dynarec_rv64_64.c b/src/dynarec/rv64/dynarec_rv64_64.c deleted file mode 100644 index 3b2a888d5..000000000 --- a/src/dynarec/rv64/dynarec_rv64_64.c +++ /dev/null @@ -1,621 +0,0 @@ -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" -#include "custommem.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog) -{ - (void)ip; - (void)rep; - (void)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t u8; - uint8_t gd, ed, eb1, eb2, gb1, gb2; - uint8_t gback, wback, wb1, wb2, wb; - int64_t i64, j64; - uint64_t u64; - int v0, v1; - int q0; - int d0; - int64_t fixedaddress, gdoffset; - int unscaled; - MAYUSE(eb1); - MAYUSE(eb2); - MAYUSE(wb1); - MAYUSE(wb2); - MAYUSE(gb1); - MAYUSE(gb2); - MAYUSE(j64); - MAYUSE(d0); - MAYUSE(q0); - MAYUSE(v0); - MAYUSE(v1); - - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - GETREX(); - - switch (opcode) { - case 0x03: - INST_NAME("ADD Gd, Seg:Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - GETGD; - GETEDO(x4, 0, x5); - emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); - break; - case 0x0F: - opcode = F8; - switch (opcode) { - case 0x11: - switch (rep) { - case 0: - INST_NAME("MOVUPS Ex,Gx"); - nextop = F8; - GETGX(); - GETEX(x2, 0, 8); - if (!MODREG) { - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - ADDz(x4, x4, wback); - wback = x4; - } - LD(x3, gback, gdoffset + 0); - LD(x5, gback, gdoffset + 8); - SD(x3, wback, fixedaddress + 0); - SD(x5, wback, fixedaddress + 8); - if (!MODREG) - SMWRITE2(); - break; - case 1: - INST_NAME("MOVSD Ex, Gx"); - nextop = F8; - GETG; - v0 = sse_get_reg(dyn, ninst, x1, gd, 0); - if (MODREG) { - ed = (nextop & 7) + (rex.b << 3); - d0 = sse_get_reg(dyn, ninst, x1, ed, 0); - FMVD(d0, v0); - } else { - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, x4, ed); - ed = x4; - FSD(v0, ed, fixedaddress); - SMWRITE2(); - } - break; - case 2: - INST_NAME("MOVSS Ex, Gx"); - nextop = F8; - GETG; - v0 = sse_get_reg(dyn, ninst, x1, gd, 1); - if (MODREG) { - q0 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 1); - FMVS(q0, v0); - } else { - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - addr = geted(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, x4, ed); - ed = x4; - FSW(v0, ed, fixedaddress); - SMWRITE2(); - } - break; - default: - DEFAULT; - } - break; - - case 0x18: - case 0x19: - case 0x1F: - INST_NAME("NOP (multibyte)"); - nextop = F8; - FAKEED; - break; - default: - DEFAULT; - } - break; - case 0x2B: - INST_NAME("SUB Gd, Seg:Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - GETGD; - GETEDO(x4, 0, x5); - emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); - break; - - case 0x33: - INST_NAME("XOR Gd, Seg:Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - GETGD; - GETEDO(x4, 0, x5); - emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); - break; - - case 0x66: - addr = dynarec64_6664(dyn, addr, ip, ninst, rex, seg, ok, need_epilog); - break; - case 0x80: - nextop = F8; - switch ((nextop >> 3) & 7) { - case 0: // ADD - INST_NAME("ADD Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_add8c(dyn, ninst, x1, u8, x2, x4, x5, x6); - EBBACK(x5, 0); - break; - case 1: // OR - INST_NAME("OR Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_or8c(dyn, ninst, x1, u8, x2, x4, x5); - EBBACK(x5, 0); - break; - case 2: // ADC - INST_NAME("ADC Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_adc8c(dyn, ninst, x1, u8, x2, x4, x5, x6); - EBBACK(x5, 0); - break; - case 3: // SBB - INST_NAME("SBB Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_sbb8c(dyn, ninst, x1, u8, x2, x4, x5, x6); - EBBACK(x5, 0); - break; - case 4: // AND - INST_NAME("AND Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_and8c(dyn, ninst, x1, u8, x2, x4); - EBBACK(x5, 0); - break; - case 5: // SUB - INST_NAME("SUB Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_sub8c(dyn, ninst, x1, u8, x2, x4, x5, x6); - EBBACK(x5, 0); - break; - case 6: // XOR - INST_NAME("XOR Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - emit_xor8c(dyn, ninst, x1, u8, x2, x4); - EBBACK(x5, 0); - break; - case 7: // CMP - INST_NAME("CMP Eb, Ib"); - grab_segdata(dyn, addr, ninst, x1, seg, (MODREG)); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEBO(x1, 1); - u8 = F8; - if (u8) { - MOV32w(x2, u8); - emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); - } else { - emit_cmp8_0(dyn, ninst, x1, x3, x4); - } - break; - default: - DEFAULT; - } - break; - case 0x81: - case 0x83: - nextop = F8; - grab_segdata(dyn, addr, ninst, x6, seg, (MODREG)); - switch ((nextop >> 3) & 7) { - case 0: // ADD - if (opcode == 0x81) { - INST_NAME("ADD Ed, Id"); - } else { - INST_NAME("ADD Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7); - WBACKO(x6); - break; - case 1: // OR - if (opcode == 0x81) { - INST_NAME("OR Ed, Id"); - } else { - INST_NAME("OR Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_or32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACKO(x6); - break; - case 2: // ADC - if (opcode == 0x81) { - INST_NAME("ADC Ed, Id"); - } else { - INST_NAME("ADC Ed, Ib"); - } - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - MOV64xw(x5, i64); - SD(x6, xEmu, offsetof(x64emu_t, scratch)); - emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x7); - LD(x6, xEmu, offsetof(x64emu_t, scratch)); - WBACKO(x6); - break; - case 3: // SBB - if (opcode == 0x81) { - INST_NAME("SBB Ed, Id"); - } else { - INST_NAME("SBB Ed, Ib"); - } - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - MOV64xw(x5, i64); - emit_sbb32(dyn, ninst, rex, ed, x5, x3, x4, x7); - WBACKO(x6); - break; - case 4: // AND - if (opcode == 0x81) { - INST_NAME("AND Ed, Id"); - } else { - INST_NAME("AND Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_and32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACKO(x6); - break; - case 5: // SUB - if (opcode == 0x81) { - INST_NAME("SUB Ed, Id"); - } else { - INST_NAME("SUB Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x7); - WBACKO(x6); - break; - case 6: // XOR - if (opcode == 0x81) { - INST_NAME("XOR Ed, Id"); - } else { - INST_NAME("XOR Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACKO(x6); - break; - case 7: // CMP - if (opcode == 0x81) { - INST_NAME("CMP Ed, Id"); - } else { - INST_NAME("CMP Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETEDO(x6, (opcode == 0x81) ? 4 : 1, x5); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - if (i64) { - MOV64x(x2, i64); - emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6); - } else - emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5); - break; - } - break; - case 0x88: - INST_NAME("MOV Seg:Eb, Gb"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); - if (rex.rex) { - gb2 = 0; - gb1 = TO_NAT(gd); - } else { - gb2 = ((gd & 4) >> 2); - gb1 = TO_NAT(gd & 3); - } - gd = x5; - if (gb2) { - SRLI(x5, gb1, 8); - gb1 = x5; - } - if (MODREG) { - ed = (nextop & 7) + (rex.b << 3); - if (rex.rex) { - eb1 = TO_NAT(ed); - eb2 = 0; - } else { - eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx - eb2 = ((ed & 4) >> 2); // L or H - } - ANDI(gd, gb1, 0xff); - if (eb2) { - MOV64x(x1, 0xffffffffffff00ffLL); - ANDI(x1, eb1, x1); - SLLI(gd, gd, 8); - OR(eb1, x1, gd); - } else { - ANDI(x1, eb1, ~0xff); - OR(eb1, x1, gd); - } - } else { - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - ADD(x4, ed, x4); - SB(gb1, x4, fixedaddress); - SMWRITE2(); - } - break; - case 0x89: - INST_NAME("MOV Seg:Ed, Gd"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - GETGD; - if (MODREG) { // reg <= reg - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); - } else { // mem <= reg - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, ed, x4); - SDxw(gd, x4, fixedaddress); - SMWRITE2(); - } - break; - - case 0x8B: - INST_NAME("MOV Gd, Seg:Ed"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - GETGD; - if (MODREG) { // reg <= reg - MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3))); - } else { // mem <= reg - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, ed, x4); - LDxw(gd, x4, fixedaddress); - } - break; - case 0x8E: - INST_NAME("MOV Seg,Ew"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - u8 = (nextop & 0x38) >> 3; - if (MODREG) { - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - } else { - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 0, 0); - ADDz(x4, wback, x4); - LHU(x1, x4, 0); - ed = x1; - } - SH(ed, xEmu, offsetof(x64emu_t, segs[u8])); - if((u8==_FS) || (u8==_GS)) { - // refresh offset if needed - CBZ_NEXT(ed); - MOV32w(x1, u8); - CALL(const_getsegmentbase, -1, x1, x2); - } - break; - case 0x8F: - INST_NAME("POP FS:Ed"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - if (MODREG) { - POP1z(TO_NAT((nextop & 7) + (rex.b << 3))); - } else { - POP1z(x3); // so this can handle POP [ESP] and maybe some variant too - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0); - if (ed == xRSP) { - ADDz(x4, ed, x4); - SDz(x3, x4, 0); - } else { - // complicated to just allow a segfault that can be recovered correctly - ADDIz(xRSP, xRSP, rex.is32bits ? -4 : -8); - ADDz(x4, ed, x4); - SDz(x3, x4, 0); - ADDIz(xRSP, xRSP, rex.is32bits ? 4 : 8); - } - } - break; - case 0xA1: - INST_NAME("MOV EAX,FS:Od"); - grab_segdata(dyn, addr, ninst, x4, seg, 0); - if (rex.is32bits) - u64 = F32; - else - u64 = F64; - if (u64 < 0x800) { - ADDIz(x1, x4, u64); - } else { - MOV64z(x1, u64); - ADDz(x1, x1, x4); - } - LDxw(xRAX, x1, 0); - break; - - case 0xA3: - INST_NAME("MOV FS:Od,EAX"); - grab_segdata(dyn, addr, ninst, x4, seg, 0); - if (rex.is32bits) - u64 = F32; - else - u64 = F64; - if (u64 < 0x800) { - ADDIz(x1, x4, u64); - } else { - MOV64z(x1, u64); - ADDz(x1, x1, x4); - } - SDxw(xRAX, x1, 0); - SMWRITE2(); - break; - - case 0xC6: - INST_NAME("MOV Seg:Eb, Ib"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - if (MODREG) { // reg <= u8 - u8 = F8; - if (!rex.rex) { - ed = (nextop & 7); - eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx - eb2 = (ed & 4) >> 2; // L or H - } else { - eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); - eb2 = 0; - } - - if (eb2) { - // load a mask to x3 (ffffffffffff00ff) - LUI(x3, 0xffff0); - ORI(x3, x3, 0xff); - // apply mask - AND(eb1, eb1, x3); - if (u8) { - if ((u8 << 8) < 2048) { - ADDI(x4, xZR, u8 << 8); - } else { - ADDI(x4, xZR, u8); - SLLI(x4, x4, 8); - } - OR(eb1, eb1, x4); - } - } else { - ANDI(eb1, eb1, 0xf00); // mask ffffffffffffff00 - ORI(eb1, eb1, u8); - } - } else { // mem <= u8 - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 1); - u8 = F8; - if (u8) { - ADDI(x3, xZR, u8); - ed = x3; - } else - ed = xZR; - ADDz(x4, wback, x4); - SB(ed, x4, fixedaddress); - SMWRITE2(); - } - break; - case 0xC7: - INST_NAME("MOV Seg:Ed, Id"); - nextop = F8; - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - if (MODREG) { // reg <= i32 - i64 = F32S; - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - MOV64xw(ed, i64); - } else { // mem <= i32 - addr = geted(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, 4); - i64 = F32S; - if (i64) { - MOV64x(x3, i64); - ed = x3; - } else - ed = xZR; - ADDz(x4, wback, x4); - SDxw(ed, x4, fixedaddress); - SMWRITE2(); - } - break; - - case 0xFF: - nextop = F8; - switch ((nextop >> 3) & 7) { - case 6: // Push Ed - INST_NAME("PUSH Ed"); - grab_segdata(dyn, addr, ninst, x6, seg, (MODREG)); - GETEDOz(x6, 0, x3); - PUSH1z(ed); - break; - default: - DEFAULT; - } - break; - default: - DEFAULT; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_64_vector.c b/src/dynarec/rv64/dynarec_rv64_64_vector.c deleted file mode 100644 index 64f965cae..000000000 --- a/src/dynarec/rv64/dynarec_rv64_64_vector.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" -#include "custommem.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -uintptr_t dynarec64_64_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog) -{ - (void)ip; - (void)rep; - (void)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t u8; - uint8_t gd, ed, eb1, eb2, gb1, gb2; - uint8_t gback, wback, wb1, wb2, wb; - int64_t i64, j64; - uint64_t u64; - int v0, v1; - int q0; - int d0; - int64_t fixedaddress, gdoffset; - int unscaled; - MAYUSE(eb1); - MAYUSE(eb2); - MAYUSE(wb1); - MAYUSE(wb2); - MAYUSE(gb1); - MAYUSE(gb2); - MAYUSE(j64); - MAYUSE(d0); - MAYUSE(q0); - MAYUSE(v0); - MAYUSE(v1); - - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - GETREX(); - - switch (opcode) { - case 0x0F: - opcode = F8; - switch (opcode) { - case 0x10: - DEFAULT_VECTOR; - case 0x11: - DEFAULT_VECTOR; - case 0x28: - DEFAULT_VECTOR; - case 0x29: - DEFAULT_VECTOR; - case 0x6F: - DEFAULT_VECTOR; - default: - DEFAULT_VECTOR; - } - break; - default: - return 0; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_66.c b/src/dynarec/rv64/dynarec_rv64_66.c index 5c808ab77..b7b9659ea 100644 --- a/src/dynarec/rv64/dynarec_rv64_66.c +++ b/src/dynarec/rv64/dynarec_rv64_66.c @@ -22,7 +22,7 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_66(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_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t opcode = F8; uint8_t nextop, u8; @@ -43,18 +43,8 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MAYUSE(j64); MAYUSE(lock); - while ((opcode == 0x2E) || (opcode == 0x36) || (opcode == 0x66)) // ignoring CS:, SS: or multiple 0x66 - opcode = F8; - - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - GETREX(); - - if (rex.w && !(opcode == 0x0f || opcode == 0xf0 || opcode == 0x64 || opcode == 0x65)) // rex.w cancels "66", but not for 66 0f type of prefix - return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode + if (rex.w && !(opcode == 0x0f)) // rex.w cancels "66", but not for 66 0f type of prefix + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); // addr-1, to "put back" opcode switch (opcode) { case 0x01: @@ -126,15 +116,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni INSHz(xRAX, x1, x3, x4, 1, 0); break; case 0x0F: - switch (rep) { - case 0: { + switch (rex.rep) { + case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; + default: { if (cpuext.vector) retaddr = dynarec64_660F_vector(dyn, addr, ip, ninst, rex, ok, need_epilog); addr = retaddr ? retaddr : dynarec64_660F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; } - case 1: addr = dynarec64_66F20F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; - case 2: addr = dynarec64_66F30F(dyn, addr, ip, ninst, rex, ok, need_epilog); break; } break; case 0x11: @@ -418,21 +408,54 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni POP1_16(x1); INSHz(gd, x1, x2, x3, 1, 0); break; - case 0x64: - addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _FS, ok, need_epilog); - break; - case 0x65: - addr = dynarec64_6664(dyn, addr, ip, ninst, rex, _GS, ok, need_epilog); - break; - case 0x66: - addr = dynarec64_66(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); + case 0x60: + if (rex.is32bits) { + INST_NAME("PUSHA 16bits (32bits)"); + MV(x1, xRSP); + PUSH1_16(xRAX); + PUSH1_16(xRCX); + PUSH1_16(xRDX); + PUSH1_16(xRBX); + PUSH1_16(x1); + PUSH1_16(xRBP); + PUSH1_16(xRSI); + PUSH1_16(xRDI); + } else + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); + break; + case 0x61: + if (rex.is32bits) { + INST_NAME("POPA 16bits (32bits)"); + POP1_16(x1); + INSH(xRDI, x1, x5, x6, 1, 0); + POP1_16(x1); + INSH(xRSI, x1, x5, x6, 0, 0); + POP1_16(x1); + INSH(xRBP, x1, x5, x6, 0, 0); + POP1_16(x1); // RSP ignored + POP1_16(x1); + INSH(xRBX, x1, x5, x6, 0, 0); + POP1_16(x1); + INSH(xRDX, x1, x5, x6, 0, 0); + POP1_16(x1); + INSH(xRCX, x1, x5, x6, 0, 0); + POP1_16(x1); + INSH(xRAX, x1, x5, x6, 0, 0); + } else + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); + break; + case 0x68: + INST_NAME("PUSH Iw"); + u16 = F16; + MOV32w(x2, u16); + PUSH1_16(x2); break; case 0x69: case 0x6B: if (opcode == 0x69) { - INST_NAME("IMUL Gw,Ew,Iw"); + INST_NAME("IMUL Gw, Ew, Iw"); } else { - INST_NAME("IMUL Gw,Ew,Ib"); + INST_NAME("IMUL Gw, Ew, Ib"); } SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); nextop = F8; @@ -462,6 +485,15 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni gd = x2; GWBACK; break; + case 0x6A: + INST_NAME("PUSH Ib"); + i16 = F8S; + MOV32w(x2, (uint16_t)i16); + PUSH1_16(x2); + break; + case 0x6C: + case 0x6E: + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0x70: case 0x71: case 0x72: @@ -472,14 +504,14 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni case 0x77: case 0x78: case 0x79: - case 0x7a: - case 0x7b: - case 0x7c: - case 0x7d: - case 0x7e: - case 0x7f: + case 0x7A: + case 0x7B: + case 0x7C: + case 0x7D: + case 0x7E: + case 0x7F: // just use regular conditional jump - return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0x81: case 0x83: @@ -729,6 +761,18 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE2(); } break; + case 0x8D: + INST_NAME("LEA Gd, Ed"); + nextop = F8; + GETGD; + if (MODREG) { // reg <= reg? that's an invalid operation + DEFAULT; + } else { // mem <= reg + rex.seg = 0; + addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 0, 0); + INSH(gd, ed, x5, x6, 1, 1); + } + break; case 0x8E: INST_NAME("MOV Seg, Ew"); nextop = F8; @@ -808,87 +852,44 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xA1: - INST_NAME("MOV EAX,Od"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV EAX, Od"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); - if (isLockAddress(u64)) - lock = 1; - else - lock = 0; + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); SMREADLOCK(lock); LHU(x2, x1, 0); INSHz(xRAX, x2, x3, x4, 1, 0); break; case 0xA3: - INST_NAME("MOV Od,EAX"); - if (rex.is32bits) - u64 = F32; + INST_NAME("MOV Od, EAX"); + if (rex.is32bits && rex.is67) + u64 = F16S; + else if (rex.is32bits || rex.is67) + u64 = F32S; else u64 = F64; - MOV64z(x1, u64); - if (isLockAddress(u64)) - lock = 1; - else - lock = 0; + MOV64y(x1, u64); + if (rex.seg) { + grab_segdata(dyn, addr, ninst, x3, rex.seg, 0); + ADDxREGy(x1, x3, x1); + } + lock = (rex.seg) ? 0 : isLockAddress(u64); SH(xRAX, x1, 0); SMWRITELOCK(lock); break; case 0xA4: - if (rep) { - INST_NAME("REP MOVSB"); - CBZ_NEXT(xRCX); - ANDI(x1, xFlags, 1 << F_DF); - BNEZ_MARK2(x1); - if (BOX64DRENV(dynarec_safeflags)) { - // check for overlapping - SUB(x2, xRDI, xRSI); - BLT_MARK(x2, 8); - } - OR(x1, xRSI, xRDI); - ANDI(x1, x1, 7); - BNEZ_MARK(x1); - ADDI(x6, xZR, 8); - MARK3; - BLT_MARK(xRCX, x6); - LD(x1, xRSI, 0); - SD(x1, xRDI, 0); - ADDI(xRSI, xRSI, 8); - ADDI(xRDI, xRDI, 8); - SUBI(xRCX, xRCX, 8); - BNEZ_MARK3(xRCX); - B_MARKLOCK_nocond; - MARK; // Part with DF==0 - LBU(x1, xRSI, 0); - SB(x1, xRDI, 0); - ADDI(xRSI, xRSI, 1); - ADDI(xRDI, xRDI, 1); - SUBI(xRCX, xRCX, 1); - BNEZ_MARK(xRCX); - B_MARKLOCK_nocond; - MARK2; // Part with DF==1 - LBU(x1, xRSI, 0); - SB(x1, xRDI, 0); - SUBI(xRSI, xRSI, 1); - SUBI(xRDI, xRDI, 1); - SUBI(xRCX, xRCX, 1); - BNEZ_MARK2(xRCX); - MARKLOCK; - // done - } else { - INST_NAME("MOVSB"); - GETDIR(x3, x1, 1); - LBU(x1, xRSI, 0); - SB(x1, xRDI, 0); - ADD(xRSI, xRSI, x3); - ADD(xRDI, xRDI, x3); - } - SMWRITE(); - break; + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0xA5: - if (rep) { + if (rex.rep) { INST_NAME("REP MOVSW"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -927,10 +928,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SMWRITE(); break; case 0xA7: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ CMPSW"); } else { INST_NAME("REPZ CMPSW"); @@ -946,7 +947,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni ADDI(xRSI, xRSI, 2); ADDI(xRDI, xRDI, 2); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -959,7 +960,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SUBI(xRSI, xRSI, 2); SUBI(xRDI, xRDI, 2); SUBI(xRCX, xRCX, 1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -990,7 +991,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_test16(dyn, ninst, x1, x2, x3, x4, x5); break; case 0xAB: - if (rep) { + if (rex.rep) { INST_NAME("REP STOSW"); CBZ_NEXT(xRCX); ANDI(x1, xFlags, 1 << F_DF); @@ -1015,7 +1016,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAD: - if (rep) { + if (rex.rep) { DEFAULT; } else { INST_NAME("LODSW"); @@ -1026,10 +1027,10 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xAF: - switch (rep) { + switch (rex.rep) { case 1: case 2: - if (rep == 1) { + if (rex.rep == 1) { INST_NAME("REPNZ SCASW"); } else { INST_NAME("REPZ SCASW"); @@ -1043,7 +1044,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LD(x2, xRDI, 0); ADD(xRDI, xRDI, x3); ADDI(xRCX, xRCX, -1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(xRAX, x2); } else { BNE_MARK3(xRAX, x2); @@ -1057,7 +1058,7 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni LHU(x2, xRDI, 0); ADD(xRDI, xRDI, x3); ADDI(xRCX, xRCX, -1); - if (rep == 1) { + if (rex.rep == 1) { BEQ_MARK3(x1, x2); } else { BNE_MARK3(x1, x2); @@ -1376,10 +1377,16 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; } break; - - case 0xF0: - return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - + case 0xE4: /* IN AL, Ib */ + case 0xE5: /* IN AX, Ib */ + case 0xE6: /* OUT Ib, AL */ + case 0xE7: /* OUT Ib, AX */ + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); + case 0xEC: /* IN AL, DX */ + case 0xED: /* IN AX, DX */ + case 0xEE: /* OUT DX, AL */ + case 0xEF: /* OUT DX, AX */ + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0xF7: nextop = F8; switch ((nextop >> 3) & 7) { @@ -1494,7 +1501,9 @@ uintptr_t dynarec64_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni DEFAULT; } break; - + case 0xF8: + case 0xF9: + return dynarec64_00(dyn, addr - 1, ip, ninst, rex, ok, need_epilog); case 0xFF: nextop = F8; switch ((nextop >> 3) & 7) { diff --git a/src/dynarec/rv64/dynarec_rv64_6664.c b/src/dynarec/rv64/dynarec_rv64_6664.c deleted file mode 100644 index 01e4589bf..000000000 --- a/src/dynarec/rv64/dynarec_rv64_6664.c +++ /dev/null @@ -1,104 +0,0 @@ -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -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) -{ - (void)ip; - (void)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t gd, ed; - int64_t j64; - int v0, v1; - int64_t fixedaddress; - int unscaled; - MAYUSE(j64); - - GETREX(); - - switch (opcode) { - case 0x89: - INST_NAME("MOV FS:Ew, Gw"); - nextop = F8; - GETGD; // don't need GETGW here - if (MODREG) { - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - if (rex.w) { - ADDI(ed, gd, 0); - } else { - if (ed != gd) { - LUI(x1, 0xffff0); - AND(gd, gd, x1); - ZEXTH(x1, ed); - OR(gd, gd, x1); - } - } - } else { - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, ed, x4); - if (rex.w) { - SD(gd, x4, fixedaddress); - } else { - SH(gd, x4, fixedaddress); - } - SMWRITE(); - } - break; - - case 0x8B: - INST_NAME("MOV Gd, FS:Ed"); - nextop = F8; - GETGD; - if (MODREG) { // reg <= reg - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - if (rex.w) { - MV(gd, ed); - } else { - if (ed != gd) { - LUI(x1, 0xffff0); - AND(gd, gd, x1); - ZEXTH(x1, ed); - OR(gd, gd, x1); - } - } - } else { // mem <= reg - grab_segdata(dyn, addr, ninst, x4, seg, (MODREG)); - SMREAD(); - addr = geted(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - ADDz(x4, ed, x4); - if (rex.w) { - LD(gd, x4, fixedaddress); - } else { - LHU(x1, x4, fixedaddress); - SRLI(gd, gd, 16); - SLLI(gd, gd, 16); - OR(gd, gd, x1); - } - } - break; - - default: - DEFAULT; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_66f0.c b/src/dynarec/rv64/dynarec_rv64_66f0.c index 6a16811f2..a01f06255 100644 --- a/src/dynarec/rv64/dynarec_rv64_66f0.c +++ b/src/dynarec/rv64/dynarec_rv64_66f0.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_66F0(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_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t opcode = F8; @@ -42,13 +41,6 @@ uintptr_t dynarec64_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int MAYUSE(wb2); MAYUSE(j64); - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - GETREX(); - switch (opcode) { case 0x0F: opcode = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_67.c b/src/dynarec/rv64/dynarec_rv64_67.c deleted file mode 100644 index a1cb02a67..000000000 --- a/src/dynarec/rv64/dynarec_rv64_67.c +++ /dev/null @@ -1,893 +0,0 @@ -#include -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -uintptr_t dynarec64_67(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)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t gd, ed, wback, wb, wb1, wb2, gback, gb, gb1, gb2, eb1, eb2; - int64_t fixedaddress, gdoffset; - int unscaled; - int8_t i8; - uint8_t u8; - int32_t i32; - int64_t j64, i64; - int cacheupd = 0; - int lock; - int v0, v1, s0; - MAYUSE(i32); - MAYUSE(j64); - MAYUSE(v0); - MAYUSE(v1); - MAYUSE(s0); - MAYUSE(lock); - MAYUSE(cacheupd); - - if (rex.is32bits) { - // should do a different file - DEFAULT; - return addr; - } - - GETREX(); - - rep = 0; - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - switch (opcode) { - - case 0x01: - INST_NAME("ADD Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_add32(dyn, ninst, rex, ed, gd, x3, x4, x5); - WBACK; - break; - case 0x02: - INST_NAME("ADD Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - FAST_8BIT_OPERATION(gb, wb, x1, ADD(gb, gb, x1)); - GETEB32(x2, 0); - GETGB(x1); - emit_add8(dyn, ninst, x1, x2, x3, x4, x6); - GBBACK(x4); - break; - case 0x03: - INST_NAME("ADD Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_add32(dyn, ninst, rex, gd, ed, x3, x4, x5); - break; - - case 0x05: - INST_NAME("ADD EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - emit_add32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); - break; - - case 0x09: - INST_NAME("OR Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_or32(dyn, ninst, rex, ed, gd, x3, x4); - WBACK; - break; - case 0x0A: - INST_NAME("OR Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - FAST_8BIT_OPERATION(gb, wb, x1, OR(gb, gb, x1)); - GETEB32(x2, 0); - GETGB(x1); - emit_or8(dyn, ninst, x1, x2, x3, x4); - GBBACK(x4); - break; - case 0x0B: - INST_NAME("OR Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_or32(dyn, ninst, rex, gd, ed, x3, x4); - break; - - case 0x0D: - INST_NAME("OR EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - emit_or32c(dyn, ninst, rex, xRAX, i64, x3, x4); - break; - - case 0x0F: - opcode = F8; - switch (opcode) { - case 0x11: - switch (rep) { - case 0: - INST_NAME("MOVUPS Ex, Gx"); - nextop = F8; - GETGX(); - GETEX32(x2, 0, 8); - LD(x3, gback, gdoffset + 0); - LD(x4, gback, gdoffset + 8); - SD(x3, wback, fixedaddress + 0); - SD(x4, wback, fixedaddress + 8); - if (!MODREG) SMWRITE2(); - break; - default: - DEFAULT; - } - break; - case 0x2E: - // no special check... - case 0x2F: - switch (rep) { - case 0: - if (opcode == 0x2F) { - INST_NAME("COMISS Gx, Ex"); - } else { - INST_NAME("UCOMISS Gx, Ex"); - } - SETFLAGS(X_ALL, SF_SET, NAT_FLAGS_NOFUSION); - nextop = F8; - GETGXSS(s0); - if (MODREG) { - v0 = sse_get_reg(dyn, ninst, x1, (nextop & 7) + (rex.b << 3), 0); - } else { - v0 = fpu_get_scratch(dyn); - SMREAD(); - addr = geted32(dyn, addr, ninst, nextop, &ed, x1, x2, &fixedaddress, rex, NULL, 1, 0); - FLW(v0, ed, fixedaddress); - } - CLEAR_FLAGS(); - // if isnan(s0) || isnan(v0) - IFX (X_ZF | X_PF | X_CF) { - FEQS(x3, s0, s0); - FEQS(x2, v0, v0); - AND(x2, x2, x3); - BNE_MARK(x2, xZR); - ORI(xFlags, xFlags, (1 << F_ZF) | (1 << F_PF) | (1 << F_CF)); - B_NEXT_nocond; - } - MARK; - // else if isless(d0, v0) - IFX (X_CF) { - FLTS(x2, s0, v0); - BEQ_MARK2(x2, xZR); - ORI(xFlags, xFlags, 1 << F_CF); - B_NEXT_nocond; - } - MARK2; - // else if d0 == v0 - IFX (X_ZF) { - FEQS(x2, s0, v0); - CBZ_NEXT(x2); - ORI(xFlags, xFlags, 1 << F_ZF); - } - break; - default: - DEFAULT; - } - break; - case 0xB6: - INST_NAME("MOVZX Gd, Eb"); - nextop = F8; - GETGD; - SCRATCH_USAGE(0); - if (MODREG) { - if (rex.rex) { - eb1 = TO_NAT((nextop & 7) + (rex.b << 3)); - eb2 = 0; - } else { - ed = (nextop & 7); - eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx - eb2 = (ed & 4) >> 2; // L or H - } - if (eb2) { - SRLI(gd, eb1, 8); - ANDI(gd, gd, 0xff); - } else { - ANDI(gd, eb1, 0xff); - } - } else { - SMREAD(); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - LBU(gd, ed, fixedaddress); - } - break; - case 0xB7: - INST_NAME("MOVZX Gd, Ew"); - nextop = F8; - GETGD; - SCRATCH_USAGE(0); - if (MODREG) { - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - ZEXTH(gd, ed); - } else { - SMREAD(); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - LHU(gd, ed, fixedaddress); - } - break; - default: - DEFAULT; - } - break; - - case 0x11: - INST_NAME("ADC Ed, Gd"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_adc32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); - WBACK; - break; - - case 0x13: - INST_NAME("ADC Gd, Ed"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_adc32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6); - break; - - case 0x15: - INST_NAME("ADC EAX, Id"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - MOV64xw(x1, i64); - emit_adc32(dyn, ninst, rex, xRAX, x1, x3, x4, x5, x6); - break; - - case 0x19: - INST_NAME("SBB Ed, Gd"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_sbb32(dyn, ninst, rex, ed, gd, x3, x4, x5); - WBACK; - break; - case 0x1A: - INST_NAME("SBB Gb, Eb"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - FAST_8BIT_OPERATION(gb, wb, x1, { - SUB(gb, gb, x1); - ANDI(x2, xFlags, 1 << F_CF); - SLLI(x2, x2, 64 - 8); - SUB(gb, gb, x2); - }); - GETEB32(x2, 0); - GETGB(x1); - emit_sbb8(dyn, ninst, x1, x2, x3, x4, x5); - GBBACK(x4); - break; - case 0x1B: - INST_NAME("SBB Gd, Ed"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_sbb32(dyn, ninst, rex, gd, ed, x3, x4, x5); - break; - - case 0x1D: - INST_NAME("SBB EAX, Id"); - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - MOV64xw(x2, i64); - emit_sbb32(dyn, ninst, rex, xRAX, x2, x3, x4, x5); - break; - - case 0x21: - INST_NAME("AND Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_and32(dyn, ninst, rex, ed, gd, x3, x4); - WBACK; - break; - case 0x22: - INST_NAME("AND Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETEB32(x2, 0); - GETGB(x1); - emit_and8(dyn, ninst, x1, x2, x3, x4); - GBBACK(x4); - break; - case 0x23: - INST_NAME("AND Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_and32(dyn, ninst, rex, gd, ed, x3, x4); - break; - - case 0x25: - INST_NAME("AND EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - emit_and32c(dyn, ninst, rex, xRAX, i64, x3, x4); - break; - - case 0x29: - INST_NAME("SUB Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_sub32(dyn, ninst, rex, ed, gd, x3, x4, x5); - WBACK; - break; - case 0x2A: - INST_NAME("SUB Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - FAST_8BIT_OPERATION(gb, wb, x1, SUB(gb, gb, x1)); - GETEB32(x2, 0); - GETGB(x1); - emit_sub8(dyn, ninst, x1, x2, x3, x4, x5); - GBBACK(x5); - break; - case 0x2B: - INST_NAME("SUB Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_sub32(dyn, ninst, rex, gd, ed, x3, x4, x5); - break; - - case 0x2D: - INST_NAME("SUB EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - emit_sub32c(dyn, ninst, rex, xRAX, i64, x3, x4, x5, x6); - break; - - case 0x31: - INST_NAME("XOR Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_xor32(dyn, ninst, rex, ed, gd, x3, x4); - WBACK; - break; - case 0x32: - INST_NAME("XOR Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - FAST_8BIT_OPERATION(gb, wb, x1, XOR(gb, gb, x1)); - GETEB32(x2, 0); - GETGB(x1); - emit_xor8(dyn, ninst, x1, x2, x3, x4); - GBBACK(x4); - break; - case 0x33: - INST_NAME("XOR Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_xor32(dyn, ninst, rex, gd, ed, x3, x4); - break; - - case 0x35: - INST_NAME("XOR EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - emit_xor32c(dyn, ninst, rex, xRAX, i64, x3, x4); - break; - - case 0x38: - INST_NAME("CMP Eb, Gb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETEB32(x1, 0); - GETGB(x2); - emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); - break; - case 0x39: - INST_NAME("CMP Ed, Gd"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_cmp32(dyn, ninst, rex, ed, gd, x3, x4, x5, x6); - break; - case 0x3A: - INST_NAME("CMP Gb, Eb"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETEB32(x2, 0); - GETGB(x1); - emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); - break; - case 0x3B: - INST_NAME("CMP Gd, Ed"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - nextop = F8; - GETGD; - GETED32(0); - emit_cmp32(dyn, ninst, rex, gd, ed, x3, x4, x5, x6); - break; - case 0x3C: - INST_NAME("CMP AL, Ib"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - u8 = F8; - ANDI(x1, xRAX, 0xff); - if (u8) { - MOV32w(x2, u8); - emit_cmp8(dyn, ninst, x1, x2, x3, x4, x5, x6); - } else { - emit_cmp8_0(dyn, ninst, x1, x3, x4); - } - break; - case 0x3D: - INST_NAME("CMP EAX, Id"); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - i64 = F32S; - if (i64) { - MOV64x(x2, i64); - emit_cmp32(dyn, ninst, rex, xRAX, x2, x3, x4, x5, x6); - } else - emit_cmp32_0(dyn, ninst, rex, 0xC0 /* fake nextop */, xRAX, x3, x4, x5); - break; - case 0x63: - INST_NAME("MOVSXD Gd, Ed"); - nextop = F8; - GETGD; - SCRATCH_USAGE(0); - if (rex.w) { - if (MODREG) { // reg <= reg - ADDIW(gd, TO_NAT((nextop & 7) + (rex.b << 3)), 0); - } else { // mem <= reg - SMREAD(); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - LW(gd, ed, fixedaddress); - } - } else { - if (MODREG) { // reg <= reg - ZEXTW2(gd, TO_NAT((nextop & 7) + (rex.b << 3))); - } else { // mem <= reg - SMREAD(); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, NULL, 1, 0); - LWU(gd, ed, fixedaddress); - } - } - break; - case 0x66: - opcode = F8; - switch (opcode) { - case 0x89: - INST_NAME("MOV Ew, Gw"); - nextop = F8; - GETGD; // don't need GETGW here - if (MODREG) { - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - if (ed != gd) { - LUI(x1, 0xffff0); - AND(ed, ed, x1); - ZEXTH(x2, gd); - OR(ed, ed, x2); - } - } else { - SCRATCH_USAGE(0); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); - SH(gd, ed, fixedaddress); - SMWRITELOCK(lock); - } - break; - - default: - DEFAULT; - } - break; - - case 0x81: - case 0x83: - nextop = F8; - switch ((nextop >> 3) & 7) { - case 0: // ADD - if (opcode == 0x81) { - INST_NAME("ADD Ed, Id"); - } else { - INST_NAME("ADD Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_add32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); - WBACK; - break; - case 1: // OR - if (opcode == 0x81) { - INST_NAME("OR Ed, Id"); - } else { - INST_NAME("OR Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_or32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACK; - break; - case 2: // ADC - if (opcode == 0x81) { - INST_NAME("ADC Ed, Id"); - } else { - INST_NAME("ADC Ed, Ib"); - } - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - MOV64xw(x5, i64); - emit_adc32(dyn, ninst, rex, ed, x5, x3, x4, x6, x7); - WBACK; - break; - case 3: // SBB - if (opcode == 0x81) { - INST_NAME("SBB Ed, Id"); - } else { - INST_NAME("SBB Ed, Ib"); - } - READFLAGS(X_CF); - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - MOV64xw(x6, i64); - emit_sbb32(dyn, ninst, rex, ed, x6, x3, x4, x5); - WBACK; - break; - case 4: // AND - if (opcode == 0x81) { - INST_NAME("AND Ed, Id"); - } else { - INST_NAME("AND Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_and32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACK; - break; - case 5: // SUB - if (opcode == 0x81) { - INST_NAME("SUB Ed, Id"); - } else { - INST_NAME("SUB Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_sub32c(dyn, ninst, rex, ed, i64, x3, x4, x5, x6); - WBACK; - break; - case 6: // XOR - if (opcode == 0x81) { - INST_NAME("XOR Ed, Id"); - } else { - INST_NAME("XOR Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - emit_xor32c(dyn, ninst, rex, ed, i64, x3, x4); - WBACK; - break; - case 7: // CMP - if (opcode == 0x81) { - INST_NAME("CMP Ed, Id"); - } else { - INST_NAME("CMP Ed, Ib"); - } - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); - GETED32((opcode == 0x81) ? 4 : 1); - if (opcode == 0x81) - i64 = F32S; - else - i64 = F8S; - if (i64) { - MOV64x(x2, i64); - emit_cmp32(dyn, ninst, rex, ed, x2, x3, x4, x5, x6); - } else - emit_cmp32_0(dyn, ninst, rex, nextop, ed, x3, x4, x5); - break; - } - break; - - case 0x88: - INST_NAME("MOV Eb, Gb"); - nextop = F8; - gd = ((nextop & 0x38) >> 3) + (rex.r << 3); - if (rex.rex) { - gb2 = 0; - gb1 = TO_NAT(gd); - } else { - gb2 = ((gd & 4) >> 2); - gb1 = TO_NAT(gd & 3); - } - gd = x4; - if (gb2) { - SRLI(x4, gb1, 8); - gb1 = x4; - } - if (MODREG) { - ed = (nextop & 7) + (rex.b << 3); - if (rex.rex) { - eb1 = TO_NAT(ed); - eb2 = 0; - } else { - eb1 = TO_NAT(ed & 3); // Ax, Cx, Dx or Bx - eb2 = ((ed & 4) >> 2); // L or H - } - ANDI(gd, gb1, 0xff); - if (eb2) { - MOV64x(x1, 0xffffffffffff00ffLL); - AND(x1, eb1, x1); - SLLI(gd, gd, 8); - OR(eb1, x1, gd); - } else { - ANDI(x1, eb1, ~0xff); - OR(eb1, x1, gd); - } - } else { - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); - SB(gb1, ed, fixedaddress); - SMWRITELOCK(lock); - } - break; - case 0x89: - INST_NAME("MOV Ed, Gd"); - nextop = F8; - GETGD; - SCRATCH_USAGE(0); - if (MODREG) { // reg <= reg - MVxw(TO_NAT((nextop & 7) + (rex.b << 3)), gd); - } else { // mem <= reg - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); - SDxw(gd, ed, fixedaddress); - SMWRITELOCK(lock); - } - break; - case 0x8B: - INST_NAME("MOV Gd, Ed"); - nextop = F8; - GETGD; - SCRATCH_USAGE(0); - if (MODREG) { - MVxw(gd, TO_NAT((nextop & 7) + (rex.b << 3))); - } else { - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 0); - SMREADLOCK(lock); - LDxw(gd, ed, fixedaddress); - } - break; - case 0x8D: - INST_NAME("LEA Gd, Ed"); - nextop = F8; - GETGD; - if (MODREG) { // reg <= reg? that's an invalid operation - DEFAULT; - } else { // mem <= reg - SCRATCH_USAGE(0); - addr = geted32(dyn, addr, ninst, nextop, &ed, gd, x1, &fixedaddress, rex, NULL, 0, 0); - ZEXTW2(gd, ed); - } - break; - - case 0xC1: - nextop = F8; - switch ((nextop >> 3) & 7) { - case 5: - INST_NAME("SHR Ed, Ib"); - u8 = geted_ib(dyn, addr, ninst, nextop) & (rex.w ? 0x3f : 0x1f); - // flags are not affected if count is 0, we make it a nop if possible. - if (u8) { - SETFLAGS(X_ALL, SF_SET_PENDING, NAT_FLAGS_FUSION); // some flags are left undefined - GETED32(1); - F8; - emit_shr32c(dyn, ninst, rex, ed, u8, x3, x4); - WBACK; - } else { - if (MODREG && !rex.w) { - GETED(1); - ZEROUP(ed); - } else { - FAKEED; - } - F8; - } - break; - default: - DEFAULT; - } - break; - - case 0xC7: - INST_NAME("MOV Ed, Id"); - nextop = F8; - if (MODREG) { // reg <= i32 - SCRATCH_USAGE(0); - i64 = F32S; - ed = TO_NAT((nextop & 7) + (rex.b << 3)); - MOV64xw(ed, i64); - } else { // mem <= i32 - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x1, &fixedaddress, rex, &lock, 1, 4); - i64 = F32S; - MOV64x(x3, i64); - SDxw(x3, ed, fixedaddress); - SMWRITELOCK(lock); - } - break; - -#define GO(Z) \ - BARRIER(BARRIER_MAYBE); \ - JUMP(addr + i8, 1); \ - if (dyn->insts[ninst].x64.jmp_insts == -1 || CHECK_CACHE()) { \ - /* out of the block */ \ - i32 = dyn->insts[ninst].epilog - (dyn->native_size); \ - if (Z) { \ - BNE(x1, xZR, i32); \ - } else { \ - BEQ(x1, xZR, i32); \ - }; \ - if (dyn->insts[ninst].x64.jmp_insts == -1) { \ - if (!(dyn->insts[ninst].x64.barrier & BARRIER_FLOAT)) \ - fpu_purgecache(dyn, ninst, 1, x1, x2, x3); \ - jump_to_next(dyn, addr + i8, 0, ninst, rex.is32bits); \ - } else { \ - CacheTransform(dyn, ninst, cacheupd, x1, x2, x3); \ - i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \ - B(i32); \ - } \ - } else { \ - /* inside the block */ \ - i32 = dyn->insts[dyn->insts[ninst].x64.jmp_insts].address - (dyn->native_size); \ - if (Z) { \ - BEQ(x1, xZR, i32); \ - } else { \ - BNE(x1, xZR, i32); \ - }; \ - } - case 0xE0: - INST_NAME("LOOPNZ (32bits)"); - READFLAGS(X_ZF); - - i8 = F8S; - SUBI(xRCX, xRCX, 1); - ANDI(x1, xFlags, 1 << F_ZF); - CBNZ_NEXT(x1); - ZEXTW2(x1, xRCX); - GO(0); - break; - case 0xE1: - INST_NAME("LOOPZ (32bits)"); - READFLAGS(X_ZF); - i8 = F8S; - SUBI(xRCX, xRCX, 1); - ANDI(x1, xFlags, 1 << F_ZF); - CBZ_NEXT(x1); - ZEXTW2(x1, xRCX); - GO(0); - break; - case 0xE2: - INST_NAME("LOOP (32bits)"); - i8 = F8S; - SUBI(xRCX, xRCX, 1); - ZEXTW2(x1, xRCX); - GO(0); - break; - case 0xE3: - INST_NAME("JECXZ (32bits)"); - i8 = F8S; - ZEXTW2(x1, xRCX); - GO(1); - break; -#undef GO - - case 0xE8: - return dynarec64_00(dyn, addr - 1, ip, ninst, rex, rep, ok, need_epilog); // addr-1, to "put back" opcode) - - case 0xF7: - nextop = F8; - switch ((nextop >> 3) & 7) { - case 4: - INST_NAME("MUL EAX, Ed"); - SETFLAGS(X_ALL, SF_PENDING, NAT_FLAGS_NOFUSION); - GETED32(0); - if (rex.w) { - if (ed == xRDX) - gd = x3; - else - gd = xRDX; - MULHU(gd, xRAX, ed); - MUL(xRAX, xRAX, ed); - if (gd != xRDX) MV(xRDX, gd); - } else { - MUL(xRDX, xRAX, ed); // 64 <- 32x32 - ZEXTW2(xRAX, xRDX); - SRLIW(xRDX, xRDX, 32); - } - UFLAG_RES(xRAX); - UFLAG_OP1(xRDX); - UFLAG_DF(x2, rex.w ? d_mul64 : d_mul32); - break; - default: - DEFAULT; - } - break; - default: - DEFAULT; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_67_32.c b/src/dynarec/rv64/dynarec_rv64_67_32.c deleted file mode 100644 index 6e67039e2..000000000 --- a/src/dynarec/rv64/dynarec_rv64_67_32.c +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -uintptr_t dynarec64_67_32(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)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t gd, ed, wback, wb, wb1, wb2, gb1, gb2, eb1, eb2; - int64_t fixedaddress; - int unscaled; - int8_t i8; - uint8_t u8; - int32_t i32; - int64_t j64, i64; - int cacheupd = 0; - int lock; - int v0, v1, s0; - - if (!rex.is32bits) { - // should do a different file - DEFAULT; - return addr; - } - - rep = 0; - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - switch (opcode) { - default: - DEFAULT; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_67_vector.c b/src/dynarec/rv64/dynarec_rv64_67_vector.c deleted file mode 100644 index f022fa770..000000000 --- a/src/dynarec/rv64/dynarec_rv64_67_vector.c +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include -#include - -#include "debug.h" -#include "box64context.h" -#include "box64cpu.h" -#include "emu/x64emu_private.h" -#include "x64emu.h" -#include "box64stack.h" -#include "callback.h" -#include "emu/x64run_private.h" -#include "x64trace.h" -#include "dynarec_native.h" - -#include "rv64_printer.h" -#include "dynarec_rv64_private.h" -#include "../dynarec_helper.h" -#include "dynarec_rv64_functions.h" - -uintptr_t dynarec64_67_vector(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)need_epilog; - - uint8_t opcode = F8; - uint8_t nextop; - uint8_t gd, ed, wback, wb, wb1, wb2, gb, gb1, gb2, eb1, eb2; - int64_t fixedaddress; - int unscaled; - int8_t i8; - uint8_t u8; - int32_t i32; - int64_t j64, i64; - int cacheupd = 0; - int lock; - int v0, v1, s0; - MAYUSE(i32); - MAYUSE(j64); - MAYUSE(v0); - MAYUSE(v1); - MAYUSE(s0); - MAYUSE(lock); - MAYUSE(cacheupd); - - if (rex.is32bits) { - // should do a different file - DEFAULT; - return addr; - } - - GETREX(); - - rep = 0; - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - switch (opcode) { - case 0x0F: - opcode = F8; - switch (opcode) { - case 0x11: - switch (rep) { - case 0: - INST_NAME("MOVUPS Ex,Gx"); - nextop = F8; - if (MODREG) { - SET_ELEMENT_WIDTH(x1, VECTOR_SEWANY, 1); - GETGX_vector(v0, 0, dyn->vector_eew); - ed = (nextop & 7) + (rex.b << 3); - v1 = sse_get_reg_empty_vector(dyn, ninst, x1, ed); - VMV_V_V(v1, v0); - } else { - SET_ELEMENT_WIDTH(x1, VECTOR_SEW8, 1); // unaligned! - GETGX_vector(v0, 0, dyn->vector_eew); - addr = geted32(dyn, addr, ninst, nextop, &ed, x2, x3, &fixedaddress, rex, NULL, 0, 0); - VSE_V(v0, ed, dyn->vector_eew, VECTOR_UNMASKED, VECTOR_NFIELD1); - SMWRITE2(); - } - break; - default: - DEFAULT; - } - break; - case 0x2E: - case 0x2F: - DEFAULT_VECTOR; - case 0x6F: - switch (rep) { - case 2: - DEFAULT_VECTOR; - default: return 0; - } - break; - case 0x7F: - switch (rep) { - case 2: - DEFAULT_VECTOR; - default: return 0; - } - break; - default: - return 0; - } - break; - case 0x66: - opcode = F8; - GETREX(); - switch (opcode) { - case 0x0F: - nextop = F8; - switch (nextop) { - case 0x7E: - DEFAULT_VECTOR; - case 0xD6: - DEFAULT_VECTOR; - case 0xFE: - DEFAULT_VECTOR; - default: - return 0; - } - break; - default: - return 0; - } - break; - default: - return 0; - } - return addr; -} diff --git a/src/dynarec/rv64/dynarec_rv64_d8.c b/src/dynarec/rv64/dynarec_rv64_d8.c index 25a8fed55..80eeae110 100644 --- a/src/dynarec/rv64/dynarec_rv64_d8.c +++ b/src/dynarec/rv64/dynarec_rv64_d8.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_D8(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_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_d9.c b/src/dynarec/rv64/dynarec_rv64_d9.c index 16f4f84b4..a70a8af1f 100644 --- a/src/dynarec/rv64/dynarec_rv64_d9.c +++ b/src/dynarec/rv64/dynarec_rv64_d9.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_D9(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_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_da.c b/src/dynarec/rv64/dynarec_rv64_da.c index 729212823..e35eaf9ef 100644 --- a/src/dynarec/rv64/dynarec_rv64_da.c +++ b/src/dynarec/rv64/dynarec_rv64_da.c @@ -21,7 +21,7 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_DA(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_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { uint8_t nextop = F8; int64_t j64; diff --git a/src/dynarec/rv64/dynarec_rv64_db.c b/src/dynarec/rv64/dynarec_rv64_db.c index d31ddc11e..ca63decdb 100644 --- a/src/dynarec/rv64/dynarec_rv64_db.c +++ b/src/dynarec/rv64/dynarec_rv64_db.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -uintptr_t dynarec64_DB(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_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_dc.c b/src/dynarec/rv64/dynarec_rv64_dc.c index 76d1cea70..8deed88e8 100644 --- a/src/dynarec/rv64/dynarec_rv64_dc.c +++ b/src/dynarec/rv64/dynarec_rv64_dc.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -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_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_dd.c b/src/dynarec/rv64/dynarec_rv64_dd.c index d8cadd7fd..2562be71c 100644 --- a/src/dynarec/rv64/dynarec_rv64_dd.c +++ b/src/dynarec/rv64/dynarec_rv64_dd.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -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_DD(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_de.c b/src/dynarec/rv64/dynarec_rv64_de.c index fbb98e0db..16a27e065 100644 --- a/src/dynarec/rv64/dynarec_rv64_de.c +++ b/src/dynarec/rv64/dynarec_rv64_de.c @@ -21,10 +21,9 @@ #include "dynarec_rv64_functions.h" -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_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_df.c b/src/dynarec/rv64/dynarec_rv64_df.c index baff028fc..3cbc857e6 100644 --- a/src/dynarec/rv64/dynarec_rv64_df.c +++ b/src/dynarec/rv64/dynarec_rv64_df.c @@ -20,10 +20,9 @@ #include "../dynarec_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) +uintptr_t dynarec64_DF(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t nextop = F8; diff --git a/src/dynarec/rv64/dynarec_rv64_f0.c b/src/dynarec/rv64/dynarec_rv64_f0.c index 937ab8634..a083678f0 100644 --- a/src/dynarec/rv64/dynarec_rv64_f0.c +++ b/src/dynarec/rv64/dynarec_rv64_f0.c @@ -20,10 +20,9 @@ #include "dynarec_rv64_functions.h" -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_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog) { (void)ip; - (void)rep; (void)need_epilog; uint8_t opcode = F8; @@ -42,13 +41,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni MAYUSE(wb2); MAYUSE(j64); - while ((opcode == 0xF2) || (opcode == 0xF3)) { - rep = opcode - 0xF1; - opcode = F8; - } - - GETREX(); - switch (opcode) { case 0x01: nextop = F8; @@ -130,7 +122,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); ed = x1; wback = x3; MARKLOCK; @@ -147,7 +140,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xB0: - switch (rep) { + switch (rex.rep) { case 0: nextop = F8; if (MODREG) { @@ -206,7 +199,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xB1: - switch (rep) { + switch (rex.rep) { case 0: nextop = F8; if (MODREG) { @@ -272,7 +265,8 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni SRAI(x1, gd, 6); else SRAIW(x1, gd, 5); - ADDSL(x3, wback, x1, 2 + rex.w, x1); + if (!rex.w && !rex.is32bits) { ADDIW(x1, x1, 0); } + ADDSLy(x3, wback, x1, 2 + rex.w, x1); LDxw(x1, x3, fixedaddress); ed = x1; wback = x3; @@ -291,7 +285,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni } break; case 0xC1: - switch (rep) { + switch (rex.rep) { case 0: nextop = F8; if (MODREG) { @@ -318,7 +312,7 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni break; case 0xC7: - switch (rep) { + switch (rex.rep) { case 0: switch (rex.w) { case 0: @@ -569,9 +563,6 @@ uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ni emit_xor32(dyn, ninst, rex, x1, gd, x3, x4); } break; - case 0x66: - return dynarec64_66F0(dyn, addr, ip, ninst, rex, rep, ok, need_epilog); - case 0x80: nextop = F8; switch ((nextop >> 3) & 7) { diff --git a/src/dynarec/rv64/dynarec_rv64_helper.c b/src/dynarec/rv64/dynarec_rv64_helper.c index e5bc8f938..5b97534af 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.c +++ b/src/dynarec/rv64/dynarec_rv64_helper.c @@ -25,8 +25,6 @@ #include "dynarec_rv64_functions.h" #include "../dynarec_helper.h" -static uintptr_t geted_32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, int* l, int i12); - /* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta) { @@ -38,18 +36,19 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, dyn->insts[ninst].lock = 1; } - if (rex.is32bits) - return geted_32(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, l, i12); - int lock = l ? ((l == LOCK_LOCK) ? 1 : 2) : 0; - if (lock == 2) - *l = 0; + if (lock == 2) *l = 0; + + if (rex.is32bits && rex.is67) + return geted16(dyn, addr, ninst, nextop, ed, hint, scratch, fixaddress, rex, i12); + uint8_t ret = x2; *fixaddress = 0; if (hint > 0) ret = hint; int maxval = 2047; if (i12 > 1) maxval -= i12; + int seg_done = 0; MAYUSE(scratch); if (!(nextop & 0xC0)) { if ((nextop & 7) == 4) { @@ -60,25 +59,34 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, int64_t tmp = F32S; if (sib_reg != 4) { if (tmp && ((tmp < -2048) || (tmp > maxval) || !i12)) { - MOV64x(scratch, tmp); - ADDSL(ret, scratch, TO_NAT(sib_reg), sib >> 6, ret); + MOV64y(scratch, tmp); + ADDSLy(ret, scratch, TO_NAT(sib_reg), sib >> 6, ret); SCRATCH_USAGE(1); } else { if (sib >> 6) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); + SLLIy(ret, TO_NAT(sib_reg), (sib >> 6)); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } else ret = TO_NAT(sib_reg); *fixaddress = tmp; } } else { + if (rex.seg && !(tmp && ((tmp < -2048) || (tmp > maxval) || !i12))) { + grab_segdata(dyn, addr, ninst, ret, rex.seg, 0); + seg_done = 1; + *fixaddress = tmp; + } else if (rex.seg && tmp >= -2048 && tmp < 2048) { + grab_segdata(dyn, addr, ninst, ret, rex.seg, 0); + if (tmp) ADDI(ret, ret, tmp); + seg_done = 1; + } else + MOV64y(ret, tmp); switch (lock) { case 1: addLockAddress(tmp); break; case 2: if (isLockAddress(tmp)) *l = 1; break; } - MOV64x(ret, tmp); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { @@ -97,46 +105,72 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ADD(ret, TO_NAT(sib_reg2), scratch); SCRATCH_USAGE(1); } + if (rex.is32bits || rex.is67) ZEROUP(ret); } else { ret = TO_NAT(sib_reg2); } } } else if ((nextop & 7) == 5) { - int64_t tmp = F32S64; - int64_t adj = dyn->last_ip ? ((addr + delta) - dyn->last_ip) : 0; - if (i12 && adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) { - ret = xRIP; - *fixaddress = tmp + adj; - } else if (i12 && (tmp >= -2048) && (tmp <= maxval)) { - GETIP(addr + delta, scratch); - ret = xRIP; - *fixaddress = tmp; - SCRATCH_USAGE(1); - } else if (adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) { - ADDI(ret, xRIP, tmp + adj); - } else if ((tmp >= -2048) && (tmp <= maxval)) { - GETIP(addr + delta, scratch); - ADDI(ret, xRIP, tmp); - SCRATCH_USAGE(1); - } else if (tmp + addr + delta < 0x80000000LL && !dyn->need_reloc) { - MOV64x(ret, tmp + addr + delta); + if (rex.is32bits) { + int tmp = F32S; + if (rex.seg && tmp >= -2048 && tmp < 2048) { + grab_segdata(dyn, addr, ninst, ret, rex.seg, 0); + if (tmp) ADDI(ret, ret, tmp); + seg_done = 1; + } else + MOV32w(ret, tmp); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); + if (!rex.seg) + switch (lock) { + case 1: + addLockAddress(tmp); + if (fixaddress) *fixaddress = tmp; + break; + case 2: + if (isLockAddress(tmp)) *l = 1; + break; + } } else { - if (adj) { - MOV64x(ret, tmp + adj); - } else { - MOV64x(ret, tmp); + int64_t tmp = F32S64; + int64_t adj = dyn->last_ip ? ((addr + delta) - dyn->last_ip) : 0; + if (i12 && adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) { + ret = xRIP; + *fixaddress = tmp + adj; + } else if (i12 && (tmp >= -2048) && (tmp <= maxval)) { + GETIP(addr + delta, scratch); + ret = xRIP; + *fixaddress = tmp; + SCRATCH_USAGE(1); + } else if (adj && (tmp + adj >= -2048) && (tmp + adj <= maxval)) { + ADDI(ret, xRIP, tmp + adj); + } else if ((tmp >= -2048) && (tmp <= maxval)) { GETIP(addr + delta, scratch); + ADDIy(ret, xRIP, tmp); SCRATCH_USAGE(1); + } else if (tmp + addr + delta < 0x80000000LL && !dyn->need_reloc) { + MOV64y(ret, tmp + addr + delta); + } else { + if (adj) { + MOV64y(ret, tmp + adj); + } else { + MOV64y(ret, tmp); + GETIP(addr + delta, scratch); + SCRATCH_USAGE(1); + } + ADDy(ret, ret, xRIP); } - ADD(ret, ret, xRIP); - } - switch (lock) { - case 1: addLockAddress(addr + delta + tmp); break; - case 2: - if (isLockAddress(addr + delta + tmp)) *l = 1; - break; + if (!rex.seg) + switch (lock) { + case 1: + addLockAddress(addr + delta + tmp); + if (fixaddress) *fixaddress = addr + delta + tmp; + break; + case 2: + if (isLockAddress(addr + delta + tmp)) *l = 1; + break; + } + if (!IS_GPR(ret)) SCRATCH_USAGE(1); } - SCRATCH_USAGE(1); } else { ret = TO_NAT((nextop & 7) + (rex.b << 3)); } @@ -171,6 +205,7 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ADD(ret, TO_NAT(sib_reg2), scratch); SCRATCH_USAGE(1); } + if (rex.is32bits || rex.is67) ZEROUP(ret); } else { ret = TO_NAT(sib_reg2); } @@ -194,351 +229,140 @@ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, ADD(ret, TO_NAT(sib_reg2), scratch); SCRATCH_USAGE(1); } - ADDI(ret, ret, i64); + ADDIy(ret, ret, i64); } else { - ADDI(ret, TO_NAT(sib_reg2), i64); + ADDIy(ret, TO_NAT(sib_reg2), i64); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { - ADDI(ret, TO_NAT((nextop & 0x07) + (rex.b << 3)), i64); + ADDIy(ret, TO_NAT((nextop & 0x07) + (rex.b << 3)), i64); if (!IS_GPR(ret)) SCRATCH_USAGE(1); } } else { - MOV64x(scratch, i64); + MOV64y(scratch, i64); SCRATCH_USAGE(1); if ((nextop & 7) == 4) { if (sib_reg != 4) { - ADD(scratch, scratch, TO_NAT(sib_reg2)); - ADDSL(ret, scratch, TO_NAT(sib_reg), sib >> 6, ret); + ADDy(scratch, scratch, TO_NAT(sib_reg2)); + ADDSLy(ret, scratch, TO_NAT(sib_reg), sib >> 6, ret); } else { PASS3(int tmp = TO_NAT(sib_reg2)); - ADD(ret, tmp, scratch); + ADDy(ret, tmp, scratch); } } else { PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3))); - ADD(ret, tmp, scratch); + ADDy(ret, tmp, scratch); } } } } + if (rex.is67 && IS_GPR(ret) && !rex.seg) { + ZEXTW2(hint, ret); // truncate for is67 case only (is32bits case regs are already 32bits only) + ret = hint; + } + if (rex.seg && !seg_done) { + if (scratch == ret) + scratch = ret + 1; + SCRATCH_USAGE(1); + grab_segdata(dyn, addr, ninst, scratch, rex.seg, 0); + // seg offset is 64bits, so no truncation here + ADDxREGy(hint, scratch, ret); + ret = hint; + } *ed = ret; return addr; } -static uintptr_t geted_32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, int* l, int i12) +uintptr_t geted16(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int i12) { MAYUSE(dyn); MAYUSE(ninst); - int lock = l ? ((l == LOCK_LOCK) ? 1 : 2) : 0; - if (lock == 2) - *l = 0; uint8_t ret = x2; *fixaddress = 0; if (hint > 0) ret = hint; - int maxval = 2047; - if (i12 > 1) - maxval -= i12; MAYUSE(scratch); - if (!(nextop & 0xC0)) { - if ((nextop & 7) == 4) { - uint8_t sib = F8; - int sib_reg = (sib >> 3) & 0x7; - int sib_reg2 = sib & 0x7; - if (sib_reg2 == 5) { - int64_t tmp = F32S; - if (sib_reg != 4) { - if (tmp && ((tmp < -2048) || (tmp > maxval) || !i12)) { - // no need to zero up, as we did it below - rv64_move32(dyn, ninst, scratch, tmp, 0); - if ((sib >> 6)) { - SLLI(ret, TO_NAT(sib_reg), sib >> 6); - ADDW(ret, ret, scratch); - } else { - ADDW(ret, TO_NAT(sib_reg), scratch); - } - ZEROUP(ret); - SCRATCH_USAGE(1); - } else { - if (sib >> 6) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - ZEROUP(ret); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } else - ret = TO_NAT(sib_reg); - *fixaddress = tmp; - } - } else { - switch (lock) { - case 1: addLockAddress((int32_t)tmp); break; - case 2: - if (isLockAddress((int32_t)tmp)) *l = 1; - break; - } - MOV32w(ret, tmp); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } - } else { - if (sib_reg != 4) { - if ((sib >> 6)) { - SLLI(scratch, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, scratch, TO_NAT(sib_reg2)); - SCRATCH_USAGE(1); - } else { - ADDW(ret, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } - ZEROUP(ret); - } else { - ret = TO_NAT(sib_reg2); - } - } - } else if ((nextop & 7) == 5) { - uint32_t tmp = F32; - MOV32w(ret, tmp); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - switch (lock) { - case 1: addLockAddress(tmp); break; - case 2: - if (isLockAddress(tmp)) *l = 1; - break; - } - } else { - ret = TO_NAT(nextop & 7); - if (ret == hint) { - ZEXTW2(hint, ret); // to clear upper part - } - } + uint32_t m = nextop & 0xC7; + uint32_t n = (m >> 6) & 3; + int64_t offset = 0; + if (!n && (m & 7) == 6) { + offset = F16S; + MOV32w(ret, offset); } else { - int64_t i32; - uint8_t sib = 0; - int sib_reg = 0; - if ((nextop & 7) == 4) { - sib = F8; - sib_reg = (sib >> 3) & 7; + switch (n) { + case 0: offset = 0; break; + case 1: offset = F8S; break; + case 2: offset = F16S; break; } - int sib_reg2 = sib & 0x07; - if (nextop & 0x80) - i32 = F32S; - else - i32 = F8S; - if (i32 == 0 || ((i32 >= -2048) && (i32 <= maxval) && i12)) { - *fixaddress = i32; - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - if (sib >> 6) { - SLLI(scratch, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, scratch, TO_NAT(sib_reg2)); - SCRATCH_USAGE(1); - } else { - ADDW(ret, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } - ZEROUP(ret); - } else { - ret = TO_NAT(sib_reg2); - } - } else { - ret = TO_NAT(nextop & 0x07); - } - } else { - if (i32 >= -2048 && i32 <= 2047) { - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - if (sib >> 6) { - SLLI(scratch, TO_NAT(sib_reg), sib >> 6); - ADDW(scratch, scratch, TO_NAT(sib_reg2)); - } else - ADDW(scratch, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - SCRATCH_USAGE(1); - } else { - scratch = TO_NAT(sib_reg2); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } - } else { - scratch = TO_NAT(nextop & 0x07); - if (!IS_GPR(ret)) SCRATCH_USAGE(1); - } - ADDIW(ret, scratch, i32); - ZEROUP(ret); + if (offset && offset >= -2048 && offset <= 2047) { + *fixaddress = offset; + offset = 0; + } + switch (m & 7) { + case 0: // R_BX + R_SI + ZEXTH(ret, xRBX); + ZEXTH(scratch, xRSI); + ADD(ret, ret, scratch); + SCRATCH_USAGE(1); + break; + case 1: // R_BX + R_DI + ZEXTH(ret, xRBX); + ZEXTH(scratch, xRDI); + ADD(ret, ret, scratch); + SCRATCH_USAGE(1); + break; + case 2: // R_BP + R_SI + ZEXTH(ret, xRBP); + ZEXTH(scratch, xRSI); + ADD(ret, ret, scratch); + SCRATCH_USAGE(1); + break; + case 3: // R_BP + R_DI + ZEXTH(ret, xRBP); + ZEXTH(scratch, xRDI); + ADD(ret, ret, scratch); + SCRATCH_USAGE(1); + break; + case 4: // R_SI + ZEXTH(ret, xRSI); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); + break; + case 5: // R_DI + ZEXTH(ret, xRDI); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); + break; + case 6: // R_BP + ZEXTH(ret, xRBP); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); + break; + case 7: // R_BX + ZEXTH(ret, xRBX); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); + break; + } + if (offset) { + if (offset >= -2048 && offset < 2048) { + ADDI(ret, ret, offset); + if (!IS_GPR(ret)) SCRATCH_USAGE(1); } else { - // no need to zero up, as we did it below - rv64_move32(dyn, ninst, scratch, i32, 0); - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - ADDW(scratch, scratch, TO_NAT(sib_reg2)); - if (sib >> 6) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, ret, scratch); - } else - ADDW(ret, scratch, TO_NAT(sib_reg)); - } else { - PASS3(int tmp = TO_NAT(sib_reg2)); - ADDW(ret, tmp, scratch); - } - } else { - PASS3(int tmp = TO_NAT(nextop & 0x07)); - ADDW(ret, tmp, scratch); - } - ZEROUP(ret); + MOV64x(scratch, offset); + ADD(ret, ret, scratch); SCRATCH_USAGE(1); } } } - *ed = ret; - return addr; -} - -/* setup r2 to address pointed by ED, also fixaddress is an optionnal delta in the range [-absmax, +absmax], with delta&mask==0 to be added to ed for LDR/STR */ -uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta) -{ - MAYUSE(dyn); - MAYUSE(ninst); - MAYUSE(delta); - int lock = l ? ((l == LOCK_LOCK) ? 1 : 2) : 0; - if (lock == 2) - *l = 0; - uint8_t ret = x2; - *fixaddress = 0; - if (hint > 0) ret = hint; - int maxval = 2047; - if (i12 > 1) - maxval -= i12; - MAYUSE(scratch); - if (!(nextop & 0xC0)) { - if ((nextop & 7) == 4) { - uint8_t sib = F8; - int sib_reg = ((sib >> 3) & 0x7) + (rex.x << 3); - int sib_reg2 = (sib & 0x7) + (rex.b << 3); - if ((sib & 0x7) == 5) { - int64_t tmp = F32S; - if (sib_reg != 4) { - if (tmp && ((tmp < -2048) || (tmp > maxval) || !i12)) { - MOV64x(scratch, tmp); - if ((sib >> 6)) { - SLLI(ret, TO_NAT(sib_reg), sib >> 6); - ADDW(ret, ret, scratch); - } else { - ADDW(ret, TO_NAT(sib_reg), scratch); - } - ZEROUP(ret); - } else { - if (sib >> 6) - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - else - ret = TO_NAT(sib_reg); - *fixaddress = tmp; - } - } else { - switch (lock) { - case 1: addLockAddress(tmp); break; - case 2: - if (isLockAddress(tmp)) *l = 1; - break; - } - MOV64x(ret, tmp); - } - } else { - if (sib_reg != 4) { - if ((sib >> 6)) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, ret, TO_NAT(sib_reg2)); - } else { - ADDW(ret, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - } - ZEROUP(ret); - } else { - ret = TO_NAT(sib_reg2); - } - } - } else if ((nextop & 7) == 5) { - uint32_t tmp = F32; - // no need to zero up, as we did it below - rv64_move32(dyn, ninst, ret, tmp, 0); - GETIP(addr + delta, scratch); - ADDW(ret, ret, xRIP); - ZEROUP(ret); - switch (lock) { - case 1: addLockAddress(addr + delta + tmp); break; - case 2: - if (isLockAddress(addr + delta + tmp)) *l = 1; - break; - } - } else { - ret = TO_NAT((nextop & 7) + (rex.b << 3)); - if (ret == hint) { - ZEXTW2(hint, ret); // to clear upper part - } - } - } else { - int64_t i64; - uint8_t sib = 0; - int sib_reg = 0; - if ((nextop & 7) == 4) { - sib = F8; - sib_reg = ((sib >> 3) & 7) + (rex.x << 3); - } - int sib_reg2 = (sib & 0x07) + (rex.b << 3); - if (nextop & 0x80) - i64 = F32S; - else - i64 = F8S; - if (i64 == 0 || ((i64 >= -2048) && (i64 <= maxval) && i12)) { - *fixaddress = i64; - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - if (sib >> 6) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, ret, TO_NAT(sib_reg2)); - } else { - ADDW(ret, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - } - ZEROUP(ret); - } else { - ret = TO_NAT(sib_reg2); - } - } else { - ret = TO_NAT((nextop & 0x07) + (rex.b << 3)); - } - } else { - if (i64 >= -2048 && i64 <= 2047) { - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - if (sib >> 6) { - SLLI(scratch, TO_NAT(sib_reg), sib >> 6); - ADDW(scratch, scratch, TO_NAT(sib_reg2)); - } else - ADDW(scratch, TO_NAT(sib_reg2), TO_NAT(sib_reg)); - } else { - scratch = TO_NAT(sib_reg2); - } - } else - scratch = TO_NAT((nextop & 0x07) + (rex.b << 3)); - ADDIW(ret, scratch, i64); - ZEROUP(ret); - } else { - // no need to zero up, as we did it below - rv64_move32(dyn, ninst, scratch, i64, 0); - if ((nextop & 7) == 4) { - if (sib_reg != 4) { - ADDW(scratch, scratch, TO_NAT(sib_reg2)); - if (sib >> 6) { - SLLI(ret, TO_NAT(sib_reg), (sib >> 6)); - ADDW(ret, ret, scratch); - } else - ADDW(ret, scratch, TO_NAT(sib_reg)); - } else { - PASS3(int tmp = TO_NAT(sib_reg2)); - ADDW(ret, tmp, scratch); - } - } else { - PASS3(int tmp = TO_NAT((nextop & 0x07) + (rex.b << 3))); - ADDW(ret, tmp, scratch); - } - ZEROUP(ret); - } - } + if (rex.seg) { + if (scratch == ret) + scratch = ret + 1; + SCRATCH_USAGE(1); + grab_segdata(dyn, addr, ninst, scratch, rex.seg, 0); + // seg offset is 64bits, so no truncation here + if (IS_GPR(ret)) { + ADD(hint, ret, scratch); + ret = hint; + } else + ADD(ret, ret, scratch); } *ed = ret; return addr; diff --git a/src/dynarec/rv64/dynarec_rv64_helper.h b/src/dynarec/rv64/dynarec_rv64_helper.h index 12785ec35..7410358ab 100644 --- a/src/dynarec/rv64/dynarec_rv64_helper.h +++ b/src/dynarec/rv64/dynarec_rv64_helper.h @@ -88,17 +88,6 @@ LDz(x1, wback, fixedaddress); \ ed = x1; \ } -// GETED32 can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI -#define GETED32(D) \ - if (MODREG) { \ - ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ - wback = 0; \ - } else { \ - SMREAD(); \ - addr = geted32(dyn, addr, ninst, nextop, &wback, x2, x1, &fixedaddress, rex, NULL, 1, D); \ - LDxw(x1, wback, fixedaddress); \ - ed = x1; \ - } // GETEDH can use hint for wback and ret for ed. wback is 0 if ed is xEAX..xEDI #define GETEDH(hint, ret, D) \ if (MODREG) { \ @@ -178,30 +167,6 @@ OR(g, g, gd); \ } while (0) -// GETEDO can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI -#define GETEDO(O, D, S) \ - if (MODREG) { \ - ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ - wback = 0; \ - } else { \ - SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &wback, x2, S, &fixedaddress, rex, NULL, 1, D); \ - ADDz(S, wback, O); \ - LDxw(x1, S, fixedaddress); \ - ed = x1; \ - } -// GETEDOz can use r1 for ed, and r2 for wback. wback is 0 if ed is xEAX..xEDI -#define GETEDOz(O, D, S) \ - if (MODREG) { \ - ed = TO_NAT((nextop & 7) + (rex.b << 3)); \ - wback = 0; \ - } else { \ - SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &wback, x2, S, &fixedaddress, rex, NULL, 1, D); \ - ADDz(S, wback, O); \ - LDz(x1, S, fixedaddress); \ - ed = x1; \ - } #define WBACKO(O) \ if (wback) { \ ADDz(O, wback, O); \ @@ -261,37 +226,6 @@ wb1 = 1; \ ed = i; \ } -// GETEBO will use i for ed, i is also Offset, and can use r3 for wback. -#define GETEBO(i, D) \ - if (MODREG) { \ - if (rex.rex) { \ - wback = TO_NAT((nextop & 7) + (rex.b << 3)); \ - wb2 = 0; \ - } else { \ - wback = (nextop & 7); \ - wb2 = (wback >> 2) * 8; \ - wback = TO_NAT(wback & 3); \ - } \ - if (wb2) { \ - if (cpuext.xtheadbb) { \ - TH_EXTU(i, wback, 15, 8); \ - } else { \ - SRLI(i, wback, wb2); \ - ANDI(i, i, 0xff); \ - } \ - } else \ - ANDI(i, wback, 0xff); \ - wb1 = 0; \ - ed = i; \ - } else { \ - SMREAD(); \ - addr = geted(dyn, addr, ninst, nextop, &wback, x3, x2, &fixedaddress, rex, NULL, 1, D); \ - ADDz(x3, wback, i); \ - if (wback != x3) wback = x3; \ - LBU(i, wback, fixedaddress); \ - wb1 = 1; \ - ed = i; \ - } // GETSEB sign extend EB, will use i for ed, and can use r3 for wback. #define GETSEB(i, D) \ if (MODREG) { \ @@ -1265,11 +1199,8 @@ #define dynarec64_00_2 STEPNAME(dynarec64_00_2) #define dynarec64_00_3 STEPNAME(dynarec64_00_3) #define dynarec64_0F STEPNAME(dynarec64_0F) -#define dynarec64_64 STEPNAME(dynarec64_64) #define dynarec64_65 STEPNAME(dynarec64_65) #define dynarec64_66 STEPNAME(dynarec64_66) -#define dynarec64_67 STEPNAME(dynarec64_67) -#define dynarec64_67_32 STEPNAME(dynarec64_67_32) #define dynarec64_D8 STEPNAME(dynarec64_D8) #define dynarec64_D9 STEPNAME(dynarec64_D9) #define dynarec64_DA STEPNAME(dynarec64_DA) @@ -1283,13 +1214,10 @@ #define dynarec64_660F38 STEPNAME(dynarec64_660F38) #define dynarec64_66F20F STEPNAME(dynarec64_66F20F) #define dynarec64_66F30F STEPNAME(dynarec64_66F30F) -#define dynarec64_6664 STEPNAME(dynarec64_6664) #define dynarec64_66F0 STEPNAME(dynarec64_66F0) #define dynarec64_F20F STEPNAME(dynarec64_F20F) #define dynarec64_F30F STEPNAME(dynarec64_F30F) -#define dynarec64_64_vector STEPNAME(dynarec64_64_vector) -#define dynarec64_67_vector STEPNAME(dynarec64_67_vector) #define dynarec64_0F_vector STEPNAME(dynarec64_0F_vector) #define dynarec64_660F_vector STEPNAME(dynarec64_660F_vector) #define dynarec64_F20F_vector STEPNAME(dynarec64_F20F_vector) @@ -1304,7 +1232,6 @@ #define dynarec64_AVX_F3_0F STEPNAME(dynarec64_AVX_F3_0F) #define geted STEPNAME(geted) -#define geted32 STEPNAME(geted32) #define geted16 STEPNAME(geted16) #define jump_to_epilog STEPNAME(jump_to_epilog) #define jump_to_epilog_fast STEPNAME(jump_to_epilog_fast) @@ -1470,13 +1397,7 @@ /* setup r2 to address pointed by */ uintptr_t geted(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta); - -/* setup r2 to address pointed by */ -uintptr_t geted32(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int* l, int i12, int delta); - -/* setup r2 to address pointed by */ -// uintptr_t geted16(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, int64_t* fixaddress, int absmax, uint32_t mask, int s); - +uintptr_t geted16(dynarec_rv64_t* dyn, uintptr_t addr, int ninst, uint8_t nextop, uint8_t* ed, uint8_t hint, uint8_t scratch, int64_t* fixaddress, rex_t rex, int i12); // generic x64 helper void jump_to_epilog(dynarec_rv64_t* dyn, uintptr_t ip, int reg, int ninst); @@ -1717,37 +1638,30 @@ void fpu_pushcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07); void fpu_popcache(dynarec_rv64_t* dyn, int ninst, int s1, int not07); -uintptr_t dynarec64_00(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_00_0(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_00_1(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_00_2(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_00_3(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_00(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_00_0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_00_1(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_00_2(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_00_3(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_0F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); -uintptr_t dynarec64_64(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog); -// uintptr_t dynarec64_65(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_66(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_67(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_67_vector(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_67_32(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_D8(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_D9(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_DA(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_DB(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_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_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_66(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_D8(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_D9(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_DA(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_DB(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); +uintptr_t dynarec64_DC(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog); +uintptr_t dynarec64_DE(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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* ok, int* need_epilog); +uintptr_t dynarec64_F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, 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_660F38(dynarec_rv64_t* dyn, uintptr_t addr, uint8_t opcode, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_66F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_66F30F(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); -uintptr_t dynarec64_66F0(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_66F0(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F20F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F30F(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); -uintptr_t dynarec64_64_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int rep, int seg, int* ok, int* need_epilog); uintptr_t dynarec64_0F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_660F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); uintptr_t dynarec64_F20F_vector(dynarec_rv64_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, rex_t rex, int* ok, int* need_epilog); diff --git a/src/dynarec/rv64/rv64_emitter.h b/src/dynarec/rv64/rv64_emitter.h index f5ad25301..41d9f658d 100644 --- a/src/dynarec/rv64/rv64_emitter.h +++ b/src/dynarec/rv64/rv64_emitter.h @@ -23,6 +23,14 @@ MOV32w(A, B); \ } \ } while (0) +#define MOV64y(A, B) \ + do { \ + if (rex.is32bits || rex.is67) { \ + MOV32w(A, B); \ + } else { \ + MOV64x(A, B); \ + } \ + } while (0) #define MOV64z(A, B) \ do { \ if (rex.is32bits) { \ @@ -117,6 +125,24 @@ ZEROUP(rd); \ } \ } while (0) +#define ADDy(rd, rs1, rs2) \ + do { \ + if (rex.is32bits || rex.is67) { \ + ADDW(rd, rs1, rs2); \ + ZEROUP(rd); \ + } else { \ + ADD(rd, rs1, rs2); \ + } \ + } while (0) +#define ADDxREGy(rd, rs1, rs2) \ + do { \ + if (rex.is32bits || rex.is67) { \ + ADDIW(rs2, rs2, 0); \ + ADD(rd, rs1, rs2); \ + } else { \ + ADD(rd, rs1, rs2); \ + } \ + } while (0) // rd = rs1 - rs2 #define SUB(rd, rs1, rs2) EMIT(R_type(0b0100000, rs2, rs1, 0b000, rd, 0b0110011)) // rd = rs1 - rs2 @@ -534,6 +560,15 @@ ZEROUP(rd); \ } \ } while (0) +#define ADDIy(rd, rs1, imm12) \ + do { \ + if (rex.is32bits || rex.is67) { \ + ADDIW(rd, rs1, imm12); \ + ZEROUP(rd); \ + } else { \ + ADDI(rd, rs1, imm12); \ + } \ + } while (0) // rd = rs1 + (rs2 << imm2) #define ADDSL(rd, rs1, rs2, imm2, scratch) \ @@ -547,6 +582,13 @@ SLLI(scratch, rs2, imm2); \ ADD(rd, rs1, scratch); \ } +#define ADDSLy(rd, rs1, rs2, imm2, scratch) \ + if (rex.is32bits || rex.is67) { \ + ADDSL(rd, rs1, rs2, imm2, scratch); \ + ZEROUP(rd); \ + } else { \ + ADDSL(rd, rs1, rs2, imm2, scratch); \ + } #define SEXT_W(rd, rs1) ADDIW(rd, rs1, 0) @@ -599,6 +641,15 @@ ZEROUP(rd); \ } \ } while (0) +#define SLLIy(rd, rs1, imm) \ + do { \ + if (rex.is32bits || rex.is67) { \ + SLLIW(rd, rs1, imm); \ + ZEROUP(rd); \ + } else { \ + SLLI(rd, rs1, imm); \ + } \ + } while (0) // Shift Right Logical Immediate, 32-bit, sign-extended #define SRLIW(rd, rs1, imm5) EMIT(I_type(imm5, rs1, 0b101, rd, 0b0011011)) // Shift Right Logical Immediate