Skip to content

Commit e06788a

Browse files
committed
added tests for <fenv.h> and <cfenv>
1 parent ebbadac commit e06788a

10 files changed

Lines changed: 341 additions & 0 deletions

File tree

test/standalone/fenv/autotest.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"transfer_files": [
3+
"bin/DEMO.8xp"
4+
],
5+
"target": {
6+
"name": "DEMO",
7+
"isASM": true
8+
},
9+
"sequence": [
10+
"action|launch",
11+
"delay|1000",
12+
"hashWait|1",
13+
"key|enter",
14+
"delay|300",
15+
"hashWait|2"
16+
],
17+
"hashes": {
18+
"1": {
19+
"description": "All tests passed",
20+
"timeout": 5000,
21+
"start": "vram_start",
22+
"size": "vram_16_size",
23+
"expected_CRCs": [
24+
"38E2AD5A"
25+
]
26+
},
27+
"2": {
28+
"description": "Exit",
29+
"start": "vram_start",
30+
"size": "vram_16_size",
31+
"expected_CRCs": [
32+
"FFAF89BA",
33+
"101734A5",
34+
"9DA19F44",
35+
"A32840C8",
36+
"349F4775"
37+
]
38+
}
39+
}
40+
}

test/standalone/fenv/makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# ----------------------------
2+
# Makefile Options
3+
# ----------------------------
4+
5+
NAME = DEMO
6+
ICON = icon.png
7+
DESCRIPTION = "CE C Toolchain Demo"
8+
COMPRESSED = NO
9+
ARCHIVED = NO
10+
11+
CFLAGS = -Wall -Wextra -Oz
12+
CXXFLAGS = -Wall -Wextra -Oz
13+
14+
HAS_MATH_ERRNO = YES
15+
PREFER_OS_LIBC = NO
16+
PREFER_OS_CRT = NO
17+
18+
# ----------------------------
19+
20+
include $(shell cedev-config --makefile)

test/standalone/fenv/src/func.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#define C(expr) if (!(expr)) { return __LINE__; }
4+
5+
#ifdef __cplusplus
6+
extern "C" {
7+
#endif
8+
9+
int test_1_c(void);
10+
11+
int test_2_cpp(void);
12+
13+
int test_3_asm(void);
14+
15+
int test_4_c(void);
16+
17+
int test_5_cpp(void);
18+
19+
#ifdef __cplusplus
20+
}
21+
#endif

test/standalone/fenv/src/main.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <ti/screen.h>
2+
#include <ti/getcsc.h>
3+
#include <sys/util.h>
4+
#include <ti/sprintf.h>
5+
#include <stdio.h>
6+
#include <fenv.h>
7+
8+
#include "func.h"
9+
10+
#define TEST(test) do { \
11+
ret = test; \
12+
if (ret != 0) { \
13+
puts("failed " #test); \
14+
return ret; \
15+
} \
16+
} while(0)
17+
18+
int run_tests(void) {
19+
int ret = 0;
20+
21+
TEST(test_1_c());
22+
TEST(test_2_cpp());
23+
TEST(test_3_asm());
24+
TEST(test_4_c());
25+
TEST(test_5_cpp());
26+
27+
return ret;
28+
}
29+
30+
int main(void) {
31+
os_ClrHome();
32+
33+
int failed_test = run_tests();
34+
if (failed_test != 0) {
35+
char buf[sizeof("Failed test L-8388608")];
36+
boot_sprintf(buf, "Failed test L%d", failed_test);
37+
puts(buf);
38+
} else {
39+
puts("All tests passed");
40+
}
41+
42+
while (!os_GetCSC());
43+
44+
return 0;
45+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.assume adl=1
2+
3+
.section .text
4+
5+
.global _on_exit_func
6+
.type _on_exit_func, @function
7+
8+
; void on_exit_func(int, void*)
9+
_on_exit_func:
10+
ld hl, 6
11+
add hl, sp
12+
ld hl, (hl)
13+
ld bc, _fesetexceptflag
14+
; test that C fesetexceptflag and C++ fesetexceptflag have the same address
15+
or a, a
16+
sbc hl, bc
17+
add hl, bc
18+
ret z
19+
ld hl, _on_exit_func_error_str
20+
push hl
21+
call _puts
22+
pop hl
23+
.L.wait_loop:
24+
call _os_GetCSC
25+
or a, a
26+
jr z, .L.wait_loop
27+
ret
28+
29+
.section .rodata._on_exit_func_error_str
30+
31+
.local _on_exit_func_error_str
32+
_on_exit_func_error_str:
33+
.asciz "error:\nstd::fesetexceptflag\naddress mismatch"
34+
35+
.extern _fesetexceptflag
36+
.extern _puts
37+
.extern _os_GetCSC
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <fenv.h>
2+
3+
#include "func.h"
4+
5+
fenv_t env_data;
6+
7+
int test_1_c(void) {
8+
C(fegetround() == FE_TONEAREST);
9+
C(fetestexcept(FE_ALL_EXCEPT) == 0);
10+
11+
C(fesetround(FE_DOWNWARD) == 0);
12+
C(feraiseexcept(FE_DIVBYZERO) == 0);
13+
14+
C(feholdexcept(&env_data) == 0);
15+
16+
return 0;
17+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#include <fenv.h>
2+
3+
#include "func.h"
4+
5+
#ifdef fetestexcept
6+
#error "<fenv.h> functions cannot be macros in C++"
7+
#endif
8+
9+
int test_2_cpp(void) {
10+
fenv_t temp;
11+
12+
C(fetestexcept(FE_ALL_EXCEPT) == 0);
13+
C(fegetenv(&temp) == 0);
14+
C(feraiseexcept(FE_UNDERFLOW) == 0);
15+
16+
int (*testexcept)(int) = fetestexcept;
17+
C(testexcept(FE_UNDERFLOW) != 0);
18+
C(fesetenv(&temp) == 0);
19+
C(testexcept(FE_UNDERFLOW) == 0);
20+
C(::fetestexcept(FE_ALL_EXCEPT) == 0);
21+
22+
return 0;
23+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
.assume adl=1
2+
3+
.section .text
4+
5+
.global _test_3_asm
6+
.type _test_3_asm, @function
7+
8+
; int test_3_asm(void)
9+
_test_3_asm:
10+
ld hl, -3
11+
call __frameset
12+
13+
; preserve current rounding mode
14+
call _fegetround
15+
ld (ix - 3), hl
16+
17+
; compare it to the real deal
18+
ld a, (___fe_cur_env)
19+
cp a, l
20+
jr nz, .L.fail_1
21+
22+
; set a new and different rounding mode
23+
ld a, l
24+
xor a, 1
25+
ld l, a
26+
push hl
27+
call _fesetround
28+
pop bc
29+
30+
; return value should be zero
31+
add hl, bc
32+
or a, a
33+
sbc hl, bc
34+
jr nz, .L.fail_2
35+
36+
; see if changes were made correctly
37+
call _fegetround
38+
ld bc, (ix - 3)
39+
ld a, c
40+
xor a, 1
41+
ld c, a
42+
43+
or a, a
44+
sbc hl, bc
45+
add hl, bc
46+
jr nz, .L.fail_3
47+
48+
; restore current rounding mode
49+
ld a, (ix - 3)
50+
ld (___fe_cur_env), a
51+
52+
; passed tests
53+
ld hl, 0
54+
.L.finish:
55+
ld sp, ix
56+
pop ix
57+
ret
58+
59+
.L.fail_1:
60+
ld hl, 1000
61+
jr .L.finish
62+
63+
.L.fail_2:
64+
ld hl, 2000
65+
jr .L.finish
66+
67+
.L.fail_3:
68+
ld hl, 3000
69+
jr .L.finish
70+
71+
.extern __frameset
72+
.extern __fe_cur_env
73+
.extern _fegetround
74+
.extern _fesetround
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <fenv.h>
2+
#include <math.h>
3+
4+
#include "func.h"
5+
6+
int test_4_c(void) {
7+
int (*clearexcept)(int) = feclearexcept;
8+
int (*testexcept)(int) = fetestexcept;
9+
C(fegetround() == FE_DOWNWARD);
10+
C(feclearexcept(FE_ALL_EXCEPT) == 0);
11+
C(ilogbf(*(const float*)0xE40000) == FP_ILOGB0);
12+
C(fegetround() == FE_DOWNWARD);
13+
C(testexcept(FE_ALL_EXCEPT) != 0);
14+
C(clearexcept(FE_INVALID) == 0);
15+
C(fetestexcept(FE_ALL_EXCEPT) == 0);
16+
return 0;
17+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include <cfenv>
2+
#include <stdlib.h>
3+
4+
#include "func.h"
5+
6+
extern "C" fenv_t env_data;
7+
8+
#ifdef fetestexcept
9+
#error "<cfenv> functions cannot be macros in C++"
10+
#endif
11+
12+
extern "C" void on_exit_func(int, void*);
13+
14+
int test_5_cpp(void) {
15+
C(std::fetestexcept(FE_OVERFLOW) == 0);
16+
C(std::feraiseexcept(FE_OVERFLOW) == 0);
17+
int (*func)(const fenv_t*);
18+
func = feupdateenv;
19+
C(func(&env_data) == 0);
20+
func = ::feupdateenv;
21+
C(func(&env_data) == 0);
22+
func = std::feupdateenv;
23+
C(func(&env_data) == 0);
24+
25+
C(feupdateenv(&env_data) == 0);
26+
27+
C(::feupdateenv(&env_data) == 0);
28+
C(std::feupdateenv(&env_data) == 0);
29+
30+
C(std::fetestexcept(FE_OVERFLOW) != 0);
31+
C(on_exit(on_exit_func, reinterpret_cast<void*>(fesetexceptflag)) == 0);
32+
{
33+
using namespace std;
34+
func = feupdateenv;
35+
C(func(&env_data) == 0);
36+
func = ::feupdateenv;
37+
C(func(&env_data) == 0);
38+
func = std::feupdateenv;
39+
C(func(&env_data) == 0);
40+
41+
C(feupdateenv(&env_data) == 0);
42+
C(::feupdateenv(&env_data) == 0);
43+
C(std::feupdateenv(&env_data) == 0);
44+
}
45+
C(std::fegetround() == FE_DOWNWARD);
46+
return 0;
47+
}

0 commit comments

Comments
 (0)