mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 14:00:16 +02:00
Merge pull request #5435 from Sonicadvance1/143
unittests/ASM: Add unittests to ensure correct cmpxchg8b/16b flag setting
This commit is contained in:
7 files changed
+296
-13
No files matched your search
@@ -274,7 +274,7 @@ DEF_OP(CmpPairZ) {
|
||||
|
||||
// Restore NzCV
|
||||
if (CTX->HostFeatures.SupportsFlagM) {
|
||||
rmif(TMP1, 0, 0xb /* NzCV */);
|
||||
rmif(TMP1, 28, 0xb /* NzCV */);
|
||||
} else {
|
||||
cset(ARMEmitter::Size::i32Bit, TMP2, ARMEmitter::Condition::CC_EQ);
|
||||
bfi(ARMEmitter::Size::i32Bit, TMP1, TMP2, 30 /* lsb: Z */, 1);
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"R13": "0x20",
|
||||
"R14": "0x0000000000010dd4",
|
||||
"R15": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; FEX-Emu had a bug where cmpxchg8b/cmpxchg16b wasn't setting z flag correctly on flagm supporting CPUs.
|
||||
; This runs through all the configurations to both ensure that the z flag is set correctly, and that the other flags aren't affected.
|
||||
; There is an additional cmpxchg8b test in another file.
|
||||
|
||||
global temp_data
|
||||
|
||||
%define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
|
||||
%define EMPTY_FLAGS
|
||||
|
||||
%define DATA_LOW 0x4142434445464748
|
||||
%define DATA_HIGH 0x5152535455565758
|
||||
|
||||
%define DATA_INCORRECT_LOW 0x4142433445464748
|
||||
%define DATA_INCORRECT_HIGH 0x5152533455565758
|
||||
|
||||
; Clobbers: RAX
|
||||
%macro reset_data 0
|
||||
mov rax, DATA_LOW
|
||||
mov [rel temp_data], rax
|
||||
mov rax, DATA_HIGH
|
||||
mov [rel temp_data + 8], rax
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX
|
||||
; Args: <immediate constant>
|
||||
%macro reset_flag 1
|
||||
mov rax, %1
|
||||
push rax
|
||||
popfq
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX, RBX, RCX, RDX
|
||||
; Compares incoming values against memory, and replaces
|
||||
; Args: <64-bit immediate>, <64-bit immediate>
|
||||
; Return: Compare result in ZF (ZF==1 == compare_success)
|
||||
%macro cas_u64x2 2
|
||||
mov rax, %1
|
||||
mov rdx, %2
|
||||
|
||||
mov rbx, 0
|
||||
mov rcx, 0
|
||||
cmpxchg16b [rel temp_data]
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX, RBX
|
||||
; Compares flags with correct result
|
||||
; Args: <jnz if ZF == 0, jz if ZF == 1>, <Expected other flags>
|
||||
%macro check_flags 2
|
||||
pushfq
|
||||
pop rbx
|
||||
|
||||
; Remove IF and Reserved
|
||||
and rbx, ~(0x202)
|
||||
|
||||
; just compare ZF
|
||||
mov rax, rbx
|
||||
and rax, (1 << 6)
|
||||
%if %1 == 0
|
||||
jz %%.no_error
|
||||
%else
|
||||
jnz %%.no_error
|
||||
%endif
|
||||
|
||||
hlt
|
||||
%%.no_error:
|
||||
|
||||
; compare full flags
|
||||
cmp rbx, %2
|
||||
|
||||
je %%.second_no_error
|
||||
hlt
|
||||
|
||||
%%.second_no_error:
|
||||
; Continue forward
|
||||
%endmacro
|
||||
|
||||
; Args: <Compare Result>, <Expected flags>, <Data to compare low>, <Data to compare high>
|
||||
%macro do_test 4
|
||||
reset_flag %2
|
||||
reset_data
|
||||
cas_u64x2 %3, %4
|
||||
|
||||
; Check flag adding reserved for comparison
|
||||
check_flags %1, %2
|
||||
%endmacro
|
||||
|
||||
mov r15, 0
|
||||
mov r14, 0
|
||||
mov r13, 0
|
||||
mov rsp, 0xe000_1000
|
||||
|
||||
; %define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
|
||||
%assign eq_val 0
|
||||
|
||||
; EQ
|
||||
%rep 2
|
||||
%assign flag_0 0
|
||||
%rep 2
|
||||
%assign flag_2 0
|
||||
%rep 2
|
||||
%assign flag_4 0
|
||||
%rep 2
|
||||
%assign flag_7 0
|
||||
%rep 2
|
||||
; if eq_val == 0 then zf is expected to be zero, aka non-match
|
||||
%if eq_val == 0
|
||||
%assign data_low DATA_LOW
|
||||
%assign data_high DATA_INCORRECT_HIGH
|
||||
%else
|
||||
%assign data_low DATA_LOW
|
||||
%assign data_high DATA_HIGH
|
||||
%endif
|
||||
|
||||
%assign expected_flags ((flag_0 << 0) | (flag_2 << 2) | (flag_4 << 4) | (flag_7 << 7) | (eq_val << 6))
|
||||
inc r13
|
||||
do_test eq_val, expected_flags, data_low, data_high
|
||||
%assign flag_7 flag_7+1
|
||||
%endrep
|
||||
%assign flag_4 flag_4+1
|
||||
%endrep
|
||||
%assign flag_2 flag_2+1
|
||||
%endrep
|
||||
%assign flag_0 flag_0+1
|
||||
%endrep
|
||||
|
||||
%assign eq_val eq_val+1
|
||||
%endrep
|
||||
|
||||
mov r15, 1
|
||||
lea r14, [rel .end]
|
||||
.end:
|
||||
hlt
|
||||
|
||||
align 4096
|
||||
temp_data:
|
||||
dq 0
|
||||
dq 0
|
||||
@@ -0,0 +1,144 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"R13": "0x20",
|
||||
"R14": "0x0000000000010c74",
|
||||
"R15": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; FEX-Emu had a bug where cmpxchg8b/cmpxchg16b wasn't setting z flag correctly on flagm supporting CPUs.
|
||||
; This runs through all the configurations to both ensure that the z flag is set correctly, and that the other flags aren't affected.
|
||||
; There is an additional cmpxchg16b test in another file.
|
||||
global temp_data
|
||||
|
||||
%define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
|
||||
%define EMPTY_FLAGS
|
||||
|
||||
%define DATA_LOW 0x4142434445464748
|
||||
%define DATA_HIGH 0x5152535455565758
|
||||
|
||||
%define DATA_INCORRECT_LOW 0x4142433445464748
|
||||
%define DATA_INCORRECT_HIGH 0x5152533455565758
|
||||
|
||||
; Clobbers: RAX
|
||||
%macro reset_data 0
|
||||
mov rax, DATA_LOW
|
||||
mov [rel temp_data], rax
|
||||
mov rax, DATA_HIGH
|
||||
mov [rel temp_data + 8], rax
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX
|
||||
; Args: <immediate constant>
|
||||
%macro reset_flag 1
|
||||
mov rax, %1
|
||||
push rax
|
||||
popfq
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX, RBX, RCX, RDX
|
||||
; Compares incoming values against memory, and replaces
|
||||
; Args: <64-bit immediate>
|
||||
; Return: Compare result in ZF (ZF==1 == compare_success)
|
||||
%macro cas_u32x2 1
|
||||
mov eax, (%1 & 0xFFFF_FFFF)
|
||||
mov edx, %1 >> 32
|
||||
|
||||
mov ebx, 0
|
||||
mov ecx, 0
|
||||
cmpxchg8b [rel temp_data]
|
||||
%endmacro
|
||||
|
||||
; Clobbers: RAX, RBX
|
||||
; Compares flags with correct result
|
||||
; Args: <jnz if ZF == 0, jz if ZF == 1>, <Expected other flags>
|
||||
%macro check_flags 2
|
||||
pushfq
|
||||
pop rbx
|
||||
|
||||
; Remove IF and Reserved
|
||||
and rbx, ~(0x202)
|
||||
|
||||
; just compare ZF
|
||||
mov rax, rbx
|
||||
and rax, (1 << 6)
|
||||
%if %1 == 0
|
||||
jz %%.no_error
|
||||
%else
|
||||
jnz %%.no_error
|
||||
%endif
|
||||
|
||||
hlt
|
||||
%%.no_error:
|
||||
|
||||
; compare full flags
|
||||
cmp rbx, %2
|
||||
|
||||
je %%.second_no_error
|
||||
hlt
|
||||
|
||||
%%.second_no_error:
|
||||
; Continue forward
|
||||
%endmacro
|
||||
|
||||
; Args: <Compare Result>, <Expected flags>, <Data to compare>
|
||||
%macro do_test 3
|
||||
reset_flag %2
|
||||
reset_data
|
||||
cas_u32x2 %3
|
||||
|
||||
; Check flag adding reserved for comparison
|
||||
check_flags %1, %2
|
||||
%endmacro
|
||||
|
||||
mov r15, 0
|
||||
mov r14, 0
|
||||
mov r13, 0
|
||||
mov rsp, 0xe000_1000
|
||||
|
||||
; %define FULL_FLAGS ((1 << 0) | (1 << 2) | (1 << 4) | (1 << 6) | (1 << 7))
|
||||
%assign eq_val 0
|
||||
|
||||
; EQ
|
||||
%rep 2
|
||||
%assign flag_0 0
|
||||
%rep 2
|
||||
%assign flag_2 0
|
||||
%rep 2
|
||||
%assign flag_4 0
|
||||
%rep 2
|
||||
%assign flag_7 0
|
||||
%rep 2
|
||||
; if eq_val == 0 then zf is expected to be zero, aka non-match
|
||||
%if eq_val == 0
|
||||
%assign data DATA_INCORRECT_LOW
|
||||
%else
|
||||
%assign data DATA_LOW
|
||||
%endif
|
||||
|
||||
%assign expected_flags ((flag_0 << 0) | (flag_2 << 2) | (flag_4 << 4) | (flag_7 << 7) | (eq_val << 6))
|
||||
inc r13
|
||||
do_test eq_val, expected_flags, data
|
||||
%assign flag_7 flag_7+1
|
||||
%endrep
|
||||
%assign flag_4 flag_4+1
|
||||
%endrep
|
||||
%assign flag_2 flag_2+1
|
||||
%endrep
|
||||
%assign flag_0 flag_0+1
|
||||
%endrep
|
||||
|
||||
%assign eq_val eq_val+1
|
||||
%endrep
|
||||
|
||||
mov r15, 1
|
||||
lea r14, [rel .end]
|
||||
.end:
|
||||
hlt
|
||||
|
||||
align 4096
|
||||
temp_data:
|
||||
dq 0
|
||||
dq 0
|
||||
@@ -377,7 +377,7 @@
|
||||
"mrs x0, nzcv",
|
||||
"cmp w20, w4",
|
||||
"ccmp w21, w5, #nzcv, eq",
|
||||
"rmif x0, #0, #NzCV",
|
||||
"rmif x0, #28, #NzCV",
|
||||
"csel x4, x20, x4, ne",
|
||||
"csel x5, x21, x5, ne",
|
||||
"subs x26, x4, #0x0 (0)"
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
"mrs x0, nzcv",
|
||||
"cmp w22, w4",
|
||||
"ccmp w23, w5, #nzcv, eq",
|
||||
"rmif x0, #0, #NzCV",
|
||||
"rmif x0, #28, #NzCV",
|
||||
"csel x4, x22, x4, ne",
|
||||
"csel x5, x23, x5, ne",
|
||||
"cfinv"
|
||||
|
||||
@@ -713,7 +713,7 @@
|
||||
"mrs x0, nzcv",
|
||||
"cmp w20, w4",
|
||||
"ccmp w21, w5, #nzcv, eq",
|
||||
"rmif x0, #0, #NzCV",
|
||||
"rmif x0, #28, #NzCV",
|
||||
"csel x4, x20, x4, ne",
|
||||
"csel x5, x21, x5, ne"
|
||||
]
|
||||
@@ -728,7 +728,7 @@
|
||||
"mrs x0, nzcv",
|
||||
"cmp x20, x4",
|
||||
"ccmp x21, x5, #nzcv, eq",
|
||||
"rmif x0, #0, #NzCV",
|
||||
"rmif x0, #28, #NzCV",
|
||||
"csel x4, x20, x4, ne",
|
||||
"csel x5, x21, x5, ne"
|
||||
]
|
||||
|
||||
@@ -1826,14 +1826,6 @@
|
||||
"strh w20, [x8, #-2]!"
|
||||
]
|
||||
},
|
||||
"push dword -1": {
|
||||
"ExpectedInstructionCount": 2,
|
||||
"Comment": "0x6a",
|
||||
"ExpectedArm64ASM": [
|
||||
"mov x20, #0xffffffffffffffff",
|
||||
"str x20, [x8, #-8]!"
|
||||
]
|
||||
},
|
||||
"push qword -1": {
|
||||
"ExpectedInstructionCount": 2,
|
||||
"Comment": "0x6a",
|
||||
|
||||
Reference in new issue
Block a user