mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-24 19:00:48 +02:00
asm_tests: Implement x87 invalid operation bit on F80 mode
This commit is contained in:
1 parent
726656d0bf
commit
9a2f62c479
44 files changed
+1139
No files matched your search
@@ -0,0 +1,18 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test 0.0 / 0.0 = Invalid Operation (should set bit 0 of status word)
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
section .rodata
|
||||
; Define the 80-bit (10-byte) constant for positive infinity.
|
||||
positive_infinity: dt __Infinity__
|
||||
|
||||
section .text
|
||||
global _start
|
||||
_start:
|
||||
|
||||
finit ; Initialize the FPU
|
||||
fld tword [rel positive_infinity] ; Load the constant directly
|
||||
fcos
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with NaN input = Invalid Operation (should set bit 0 of status word)
|
||||
; Create NaN by computing 0.0 / 0.0
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; Try to convert NaN to integer - this should set Invalid Operation
|
||||
lea ebx, [.data]
|
||||
fist dword [ebx]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.data:
|
||||
dd 0
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with value too large for 32-bit integer = Invalid Operation
|
||||
; Load a large floating point value that exceeds INT32_MAX
|
||||
lea edx, [.large_value]
|
||||
fld tword [edx]
|
||||
|
||||
; Try to convert to 32-bit integer - should set Invalid Operation
|
||||
lea ebx, [.data]
|
||||
fist dword [ebx]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.large_value:
|
||||
dt 1e20
|
||||
.data:
|
||||
dd 0
|
||||
@@ -0,0 +1,28 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with 16-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a large number that will overflow int16
|
||||
|
||||
; Load 2^30 (larger than int16 range: max int16 = 32767, 2^30 = 1073741824)
|
||||
finit
|
||||
fild dword [.thirty]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int16 - this should overflow and be invalid
|
||||
fistp word [.dummy]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.thirty: dd 30
|
||||
.dummy: dw 0
|
||||
@@ -0,0 +1,28 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with 32-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a large number that will overflow int32
|
||||
|
||||
; Load 2^40 (larger than int32 range: max int32 = 2147483647, 2^40 = 1099511627776)
|
||||
finit
|
||||
fild dword [.forty]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int32 - this should overflow and be invalid
|
||||
fistp dword [.dummy]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.forty: dd 40
|
||||
.dummy: dd 0
|
||||
@@ -0,0 +1,28 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with 64-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a very large number that will overflow int64
|
||||
|
||||
; Load 2^75 (larger than int64 range)
|
||||
finit
|
||||
fild dword [.seventyfive]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int64 - this should overflow and be invalid
|
||||
fistp qword [.dummy]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.seventyfive: dd 75
|
||||
.dummy: dq 0
|
||||
@@ -0,0 +1,24 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FPREM with simple operands first
|
||||
finit
|
||||
|
||||
; Load simple operands: fprem(0, 1) should be valid and return 0
|
||||
fldz
|
||||
fld1
|
||||
|
||||
; Do FPREM: ST(0) = fprem(ST(0), ST(1)) = fprem(1.0, 0.0)
|
||||
; fprem(1.0, 0.0) should set Invalid Operation because divisor is zero
|
||||
fprem
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,29 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fptan(+infinity) in 32-bit mode = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov eax, 0x00000000
|
||||
mov [rel .pos_inf], eax
|
||||
mov eax, 0x80000000
|
||||
mov [rel .pos_inf + 4], eax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fptan
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,29 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fsin(+infinity) in 32-bit mode = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov eax, 0x00000000
|
||||
mov [rel .pos_inf], eax
|
||||
mov eax, 0x80000000
|
||||
mov [rel .pos_inf + 4], eax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fsin
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,29 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fsincos(+infinity) in 32-bit mode = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov eax, 0x00000000
|
||||
mov [rel .pos_inf], eax
|
||||
mov eax, 0x80000000
|
||||
mov [rel .pos_inf + 4], eax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fsincos
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,31 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ using FSUB with memory operand = Invalid Operation (should set bit 0 of status word) - 32bit mode
|
||||
|
||||
; Setup memory with +infinity (0x7FF0000000000000 for double precision +infinity)
|
||||
; In 32-bit mode, we need to store the double in two parts
|
||||
mov dword [.data], 0x00000000 ; Low 32 bits
|
||||
mov dword [.data+4], 0x7FF00000 ; High 32 bits
|
||||
|
||||
; Create +infinity by dividing 1.0 by 0.0
|
||||
fld1
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; Subtract ∞ - ∞ using memory operand - this should be invalid
|
||||
fsub qword [.data]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
|
||||
section .data
|
||||
.data: dq 0
|
||||
@@ -0,0 +1,24 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ using FSUBR = Invalid Operation (should set bit 0 of status word) - 32bit mode
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; duplicate +infinity
|
||||
fld st0
|
||||
|
||||
; Reverse subtract ∞ - ∞ using FSUBR - this should be invalid
|
||||
fsubr
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,22 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ × 0 = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; Load 0.0 and multiply with infinity
|
||||
fldz
|
||||
fmul
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,24 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; Duplicate +infinity on stack
|
||||
fld st0
|
||||
|
||||
; Subtract: +∞ - +∞ -> Invalid Operation
|
||||
fsub
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,24 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ = Invalid Operation (should set bit 0 of status word) - 32bit mode
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; Duplicate +infinity on stack
|
||||
fld st0
|
||||
|
||||
; Subtract +∞ - ∞ - this should be invalid
|
||||
fsub
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test (-∞) - (-∞) = Invalid Operation (should set bit 0 of status word) - 32bit mode
|
||||
; Create -infinity by dividing -1.0 by 0.0
|
||||
fld1
|
||||
fchs
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; duplicate -infinity on stack
|
||||
fld st0
|
||||
|
||||
; Subtract (-∞) - (-∞) - this should be invalid
|
||||
fsub
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,33 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test Invalid Operation with reduced precision (64-bit)
|
||||
; Set precision control to 64-bit (PC = 10b)
|
||||
fnstcw [.saved_cw]
|
||||
mov ax, [.saved_cw]
|
||||
and ax, 0xFCFF
|
||||
or ax, 0x0200
|
||||
mov [.new_cw], ax
|
||||
fldcw [.new_cw]
|
||||
|
||||
; Perform invalid operation: 0.0 / 0.0
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
; Restore original control word
|
||||
fldcw [.saved_cw]
|
||||
|
||||
hlt
|
||||
|
||||
.saved_cw: dw 0
|
||||
.new_cw: dw 0
|
||||
@@ -0,0 +1,18 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test with a simple 0/0 that we know works
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,18 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test sqrt(-1.0) = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fchs
|
||||
fsqrt
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,29 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "0",
|
||||
"RBX": "12346"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with valid 16-bit conversion
|
||||
; Load a value that fits in int16 range
|
||||
|
||||
finit
|
||||
fld qword [.value]
|
||||
|
||||
; Convert to int16 - this should work without overflow
|
||||
fistp word [.result]
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
; Load the result to verify conversion worked
|
||||
movzx ebx, word [.result]
|
||||
|
||||
hlt
|
||||
|
||||
.value: dq 12345.75
|
||||
.result: dw 0
|
||||
@@ -0,0 +1,18 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "0"
|
||||
},
|
||||
"Mode": "32BIT"
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test a valid operation that should NOT set Invalid Operation bit
|
||||
fld1
|
||||
fld1
|
||||
fadd
|
||||
|
||||
fstsw ax
|
||||
and eax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,17 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test 0.0 / 0.0 = Invalid Operation (should set bit 0 of status word)
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fcos(+infinity) = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov rax, 0x8000000000000000
|
||||
mov [rel .pos_inf], rax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fcos
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with NaN input = Invalid Operation (should set bit 0 of status word)
|
||||
; Create NaN by computing 0.0 / 0.0
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; Try to convert NaN to integer - this should set Invalid Operation
|
||||
lea rbx, [rel data]
|
||||
fist dword [rbx]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
align 8
|
||||
data:
|
||||
dd 0
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FIST with value too large for 32-bit integer = Invalid Operation
|
||||
; Load a large floating point value that exceeds INT32_MAX
|
||||
lea rdx, [rel large_value]
|
||||
fld tword [rdx]
|
||||
|
||||
; Try to convert to 32-bit integer - should set Invalid Operation
|
||||
lea rbx, [rel data]
|
||||
fist dword [rbx]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
align 8
|
||||
large_value:
|
||||
dt 1e20
|
||||
data:
|
||||
dd 0
|
||||
@@ -0,0 +1,35 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
section .rodata
|
||||
.thirty: dq 30
|
||||
|
||||
section .bss
|
||||
.dummy: resw 1
|
||||
|
||||
section .text
|
||||
global _start
|
||||
|
||||
_start:
|
||||
|
||||
; Test FIST with 16-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a large number that will overflow int16
|
||||
|
||||
; Load 2^30 (larger than int16 range: max int16 = 32767, 2^30 = 1073741824)
|
||||
finit
|
||||
fild dword [rel .thirty]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int16 - this should overflow and be invalid
|
||||
fistp word [rel .dummy]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,35 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
section .rodata
|
||||
.fifty: dq 50
|
||||
|
||||
section .bss
|
||||
.dummy: resd 1
|
||||
|
||||
section .text
|
||||
global _start
|
||||
|
||||
_start:
|
||||
|
||||
; Test FIST with 32-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a very large number that will overflow int32
|
||||
|
||||
; Load 2^50 (larger than int32 range)
|
||||
finit
|
||||
fild dword [rel .fifty]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int32 - this should overflow and be invalid
|
||||
fistp dword [rel .dummy]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,35 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
section .rodata
|
||||
.seventyfive: dq 75
|
||||
|
||||
section .bss
|
||||
.dummy: resq 1
|
||||
|
||||
section .text
|
||||
global _start
|
||||
|
||||
_start:
|
||||
|
||||
; Test FIST with 64-bit overflow = Invalid Operation (should set bit 0 of status word)
|
||||
; Create a very large number that will overflow int64
|
||||
|
||||
; Load 2^75 (larger than int64 range)
|
||||
finit
|
||||
fild dword [rel .seventyfive]
|
||||
fld1
|
||||
fscale
|
||||
|
||||
; Try to convert to int64 - this should overflow and be invalid
|
||||
fistp qword [rel .dummy]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,23 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test FPREM with simple operands first
|
||||
finit
|
||||
|
||||
; Load simple operands: fprem(0, 1) should be valid and return 0
|
||||
fldz
|
||||
fld1
|
||||
|
||||
; Do FPREM: ST(0) = fprem(ST(0), ST(1)) = fprem(1.0, 0.0)
|
||||
; fprem(1.0, 0.0) should set Invalid Operation because divisor is zero
|
||||
fprem
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fptan(+infinity) = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov rax, 0x8000000000000000
|
||||
mov [rel .pos_inf], rax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fptan
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fsin(+infinity) = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov rax, 0x8000000000000000
|
||||
mov [rel .pos_inf], rax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fsin
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fsin(-infinity) = Invalid Operation (should set bit 0 of status word)
|
||||
; Load negative infinity: exponent all 1s, mantissa 0x8000000000000000, sign bit set
|
||||
mov rax, 0x8000000000000000
|
||||
mov [rel .neg_inf], rax
|
||||
mov ax, 0xFFFF
|
||||
mov [rel .neg_inf + 8], ax
|
||||
|
||||
fld tword [rel .neg_inf]
|
||||
fsin
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.neg_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test fsincos(+infinity) = Invalid Operation (should set bit 0 of status word)
|
||||
; Load positive infinity: exponent all 1s, mantissa 0x8000000000000000
|
||||
mov rax, 0x8000000000000000
|
||||
mov [rel .pos_inf], rax
|
||||
mov ax, 0x7FFF
|
||||
mov [rel .pos_inf + 8], ax
|
||||
|
||||
fld tword [rel .pos_inf]
|
||||
fsincos
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
|
||||
.pos_inf:
|
||||
dq 0
|
||||
dw 0
|
||||
@@ -0,0 +1,23 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ using FSUB
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; duplicate +infinity
|
||||
fld st0
|
||||
|
||||
; Reverse subtract ∞ - ∞ using FSUBR - this should be invalid
|
||||
fsubr
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,23 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ × 0 = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; Load zero for multiplication
|
||||
fldz
|
||||
|
||||
; Multiply infinity by zero - this should be invalid
|
||||
fmul
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fldz
|
||||
fdiv ; st0 = +∞
|
||||
|
||||
; Duplicate infinity on stack
|
||||
fld st0
|
||||
|
||||
; Create -infinity by changing sign
|
||||
fchs
|
||||
|
||||
; Now compute +∞ + (-∞) which should be invalid
|
||||
fadd
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,26 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test ∞ - ∞ = Invalid Operation (should set bit 0 of status word)
|
||||
; Create +infinity by dividing 1.0 by 0.0
|
||||
fld1
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; Create +infinity by dividing 1.0 by 0.0
|
||||
fld1
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
; Subtract +∞ - ∞ - this should be invalid
|
||||
fsub
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,24 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test (-∞) - (-∞) = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fchs
|
||||
fldz
|
||||
fdiv ; st0 = -∞
|
||||
|
||||
; Duplicate -infinity on stack
|
||||
fld st0
|
||||
|
||||
; Subtract (-∞) - (-∞) - this should be invalid
|
||||
fsub
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,33 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test Invalid Operation with reduced precision (64-bit)
|
||||
; Set precision control to 64-bit (PC = 10b)
|
||||
fnstcw [rel saved_cw]
|
||||
mov ax, [rel saved_cw]
|
||||
and ax, 0xFCFF
|
||||
or ax, 0x0200
|
||||
mov [rel new_cw], ax
|
||||
fldcw [rel new_cw]
|
||||
|
||||
; Perform invalid operation: 0.0 / 0.0
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
; Restore original control word
|
||||
fldcw [rel saved_cw]
|
||||
|
||||
hlt
|
||||
|
||||
align 8
|
||||
saved_cw: dw 0
|
||||
new_cw: dw 0
|
||||
@@ -0,0 +1,17 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test with a simple 0/0 that we know works
|
||||
fldz
|
||||
fldz
|
||||
fdiv
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,17 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test sqrt(-1.0) = Invalid Operation (should set bit 0 of status word)
|
||||
fld1
|
||||
fchs
|
||||
fsqrt
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,36 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "0",
|
||||
"RBX": "12346"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
section .rodata
|
||||
.value: dq 12345.75
|
||||
|
||||
section .bss
|
||||
.result: resw 1
|
||||
|
||||
section .text
|
||||
global _start
|
||||
|
||||
_start:
|
||||
|
||||
; Test FIST with valid 16-bit conversion
|
||||
; Load a value that fits in int16 range
|
||||
|
||||
finit
|
||||
fld qword [rel .value]
|
||||
|
||||
; Convert to int16 - this should work without overflow
|
||||
fistp word [rel .result]
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
; Load the result to verify conversion worked
|
||||
movzx rbx, word [rel .result]
|
||||
|
||||
hlt
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "0"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
; Test valid operation should NOT set Invalid Operation bit
|
||||
; Clear any existing exception flags first
|
||||
finit
|
||||
|
||||
; Perform valid operations
|
||||
fld1
|
||||
fld1
|
||||
fadd
|
||||
|
||||
fld1
|
||||
fdiv
|
||||
|
||||
fld1
|
||||
fsqrt
|
||||
|
||||
fstsw ax
|
||||
and rax, 1
|
||||
|
||||
hlt
|
||||
Reference in new issue
Block a user