mirror of
https://github.com/ptitSeb/box86.git
synced 2024-12-03 12:30:47 +00:00
[DYNAREC] Fixed idiv optimisation, and added a new test about idiv opcode
This commit is contained in:
parent
2879cf51cd
commit
b655e89af0
@ -738,11 +738,16 @@ add_test(NAME longjumpInSignals COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref18.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
add_test(NAME x87 COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test19 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref19.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
add_test(NAME idiv COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
|
||||
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test20 -D TEST_OUTPUT=tmpfile.txt
|
||||
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref20.txt
|
||||
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
|
||||
|
||||
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
|
||||
foreach(file ${extension_tests})
|
||||
get_filename_component(testname "${file}" NAME_WE)
|
||||
|
@ -245,9 +245,12 @@ Op is 20-27
|
||||
// cmp.s dst, src, #imm
|
||||
#define CMPS_IMM8(src, imm8) \
|
||||
EMIT(0xe3500000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// cmn.s dst, src, #imm
|
||||
// cmn.s.cond dst, src, #imm
|
||||
#define CMNS_IMM8_COND(cond, src, imm8) \
|
||||
EMIT((cond) | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// cmn.s dst, src, #imm
|
||||
#define CMNS_IMM8(src, imm8) \
|
||||
EMIT(c__ | 0x03700000 | ((0) << 12) | ((src) << 16) | brIMM(imm8) )
|
||||
// tst.s dst, src1, src2, lsl #imm
|
||||
#define TSTS_REG_LSL_IMM5(src1, src2, imm5) \
|
||||
EMIT(0xe1100000 | ((0) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
|
||||
@ -257,6 +260,9 @@ Op is 20-27
|
||||
// tst.s dst, src1, #imm ror rot*2
|
||||
#define TSTS_IMM8_ROR(src, imm8, rot) \
|
||||
EMIT(0xe3100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// tst.s.cond dst, src1, #imm ror rot*2
|
||||
#define TSTS_IMM8_ROR_COND(cond, src, imm8, rot) \
|
||||
EMIT((cond) | 0x03100000 | ((0) << 12) | ((src) << 16) | ((rot)<<8) | brIMM(imm8) )
|
||||
// orr dst, src1, src2, lsl #imm
|
||||
#define ORR_REG_LSL_IMM5(dst, src1, src2, imm5) \
|
||||
EMIT(0xe1800000 | ((dst) << 12) | ((src1) << 16) | brLSL(imm5, src2) )
|
||||
|
@ -2683,31 +2683,29 @@ uintptr_t dynarec00(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst,
|
||||
GETED;
|
||||
SDIV(x2, xEAX, ed); // x1 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x1*ed)
|
||||
TSTS_IMM8_ROR(xEDX, 0b10, 1); // test if reminder is negative
|
||||
ADD_REG_LSL_IMM5_COND(cNE, xEDX, xEDX, ed, 0); // add ed if negative
|
||||
MOV_REG(xEAX, x2);
|
||||
} else {
|
||||
GETEDH(x1);
|
||||
// disabling the use of SDIV for now. It breaks X3Reunion
|
||||
// seems to be an issue with large number
|
||||
// for example EDX=0xffffffff EAX=0xe7f30000 and div ecx=0x186a0
|
||||
// gives wrong modulo
|
||||
if(arm_div && 0) {
|
||||
if(arm_div) {
|
||||
// check if a 32bits division is enough
|
||||
CMPS_IMM8(xEDX, 0); // compare to 0
|
||||
CMNS_IMM8_COND(cNE, xEDX, 1); // compare to FFFFFFFF if not 0
|
||||
TSTS_IMM8_ROR_COND(cEQ, xEAX, 0b10, 1); // also test that xEAX is not signed!
|
||||
B_MARK(cEQ);
|
||||
CMNS_IMM8(xEDX, 1); // compare to FFFFFFFF if not 0
|
||||
B_MARK2(cNE);
|
||||
TSTS_IMM8_ROR(xEAX, 0b10, 1); // also test that xEAX is signed!
|
||||
B_MARK(cNE);
|
||||
MARK2;
|
||||
}
|
||||
if(ed!=x1) {MOV_REG(x1, ed);}
|
||||
STM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
CALL(idiv32, -1, 0);
|
||||
LDM(xEmu, (1<<xEAX) | (1<<xECX) | (1<<xEDX));
|
||||
if(arm_div && 0) {
|
||||
if(arm_div) {
|
||||
B_NEXT(c__);
|
||||
MARK;
|
||||
SDIV(x2, xEAX, ed); // x2 = xEAX / ed
|
||||
MLS(xEDX, x2, ed, xEAX); // x14 = xEAX mod ed (i.e. xEAX - x2*ed)
|
||||
TSTS_IMM8_ROR(xEDX, 0b10, 1); // test if reminder is negative
|
||||
ADD_REG_LSL_IMM5_COND(cNE, xEDX, xEDX, ed, 0); // add ed if negative
|
||||
MOV_REG(xEAX, x2);
|
||||
SET_DFNONE(x2); // flags are undefined
|
||||
}
|
||||
|
11
tests/ref20.txt
Normal file
11
tests/ref20.txt
Normal file
@ -0,0 +1,11 @@
|
||||
SDHLD/SAR/IDIV 0x2d0 0x500 => 0x0 / 0x9000 (47185920/1280 => 36864 + 0)
|
||||
SDHLD/SAR/IDIV 0xfffffa5d 0x186a0 => 0xfffef4a0 / 0xfffffc4f (281474882142208/100000 => -945 + -68448)
|
||||
SDHLD/SAR/IDIV 0x1701 0x186a0 => 0xa220 / 0xf13 (385941504/100000 => 3859 + 41504)
|
||||
SDHLD/SAR/IDIV 0xffff9a19 0x186a0 => 0xffff6d00 / 0xffffbd38 (281473267073024/100000 => -17096 + -37632)
|
||||
SDHLD/SAR/IDIV 0xffffe7f3 0x186a0 => 0xffffebe0 / 0xfffff03d (281474573205504/100000 => -4035 + -5152)
|
||||
SDHLD/SAR/IDIV 0x15840 0x186a0 => 0xdd20 / 0xe19b (5775556608/100000 => 57755 + 56608)
|
||||
SDHLD/SAR/IDIV 0xff451330 0x186a0 => 0xfffee8a0 / 0xff857f2f (280672139739136/100000 => -8028369 + -71520)
|
||||
SDHLD/SAR/IDIV 0xffff626a 0x186a0 => 0xffff2fc0 / 0xffff98ba (281472332857344/100000 => -26438 + -53312)
|
||||
SDHLD/SAR/IDIV 0x9120 0x186a0 => 0x16d20 / 0x5f1b (2434793472/100000 => 24347 + 93472)
|
||||
|
||||
Done
|
BIN
tests/test20
Executable file
BIN
tests/test20
Executable file
Binary file not shown.
48
tests/test20.c
Normal file
48
tests/test20.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#error Nope!
|
||||
#else
|
||||
__attribute__((naked)) uint64_t _idiv_(uint32_t a, uint32_t b)
|
||||
{
|
||||
asm volatile (
|
||||
"xor %%eax, %%eax\n"
|
||||
"mov 4(%%esp), %%edx\n"
|
||||
"mov 8(%%esp), %%ecx\n"
|
||||
"shrd $0x10, %%edx, %%eax\n"
|
||||
"sar $0x10, %%edx\n"
|
||||
"idiv %%ecx\n"
|
||||
"ret"
|
||||
:::);
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
{
|
||||
uint32_t tests[][2] = {
|
||||
{0x000002d0, 0x00000500},
|
||||
{0xfffffa5d, 0x000186a0},
|
||||
{0x00001701, 0x000186a0},
|
||||
{0xffff9a19, 0x000186a0},
|
||||
{0xffffe7f3, 0x000186a0},
|
||||
{0x00015840, 0x000186a0},
|
||||
{0xff451330, 0x000186a0},
|
||||
{0xffff626a, 0x000186a0},
|
||||
{0x00009120, 0x000186a0},
|
||||
};
|
||||
int n = sizeof(tests)/sizeof(tests[0]);
|
||||
uint64_t res;
|
||||
for(int i=0; i<n; ++i) {
|
||||
printf("SDHLD/SAR/IDIV 0x%x 0x%x ", tests[i][0], tests[i][1]);
|
||||
res = _idiv_(tests[i][0], tests[i][1]);
|
||||
uint32_t divi = res & 0xffffffffLL;
|
||||
uint32_t modo = res >> 32;
|
||||
printf("=> 0x%x / 0x%x (%lld/%d => %d + %d)\n", modo, divi, ((int64_t)tests[i][0])<<16, tests[i][1], divi, modo);
|
||||
}
|
||||
printf("\nDone\n");
|
||||
}
|
Loading…
Reference in New Issue
Block a user