Compare commits

...

195 Commits

Author SHA1 Message Date
Bob Andrews 9c03dc621e
Merge e3dd2e6523 into b1e1c13d4b 2024-05-01 21:23:49 +02:00
Bob Andrews b1e1c13d4b
Merge pull request #2437 from bbbradsmith/sim65-examples
provide simple examples for using sim65 with C and assembly code
2024-04-25 23:52:08 +02:00
bbbradsmith 8804dc7a58 give cl65 alternative 2024-04-16 16:56:13 -04:00
bbbradsmith 4bc726ebe2 clarify the meaning of the exit code unsigned limitation 2024-04-16 16:41:00 -04:00
bbbradsmith fa1a426c29 add -t sim6502 to cc65 and ca65 examples 2024-04-16 14:06:45 -04:00
bbbradsmith 89b709c7f8 make it clearer that explicit lib is required, note that exit is from stdlib.h, exit codes are unsigned, tweak "see below" for spacing, clarify that assembly can be used with C tests as well 2024-03-28 16:55:55 -04:00
bbbradsmith 79585194e6 provide simple examples for using sim65 with C and assembly code 2024-03-28 16:33:20 -04:00
mrdudz e3dd2e6523 Merge branch 'master' into fptest 2024-03-10 02:39:47 +01:00
mrdudz a0aea11f88 Merge branch 'master' into fptest 2024-03-10 02:34:39 +01:00
mrdudz 46be595d41 Merge branch 'master' into fptest 2024-02-03 17:26:36 +01:00
mrdudz bdd8e65464 Merge branch 'master' into fptest 2024-01-23 23:47:15 +01:00
mrdudz 344d6e186a Merge branch 'master' into fptest 2024-01-23 22:18:12 +01:00
mrdudz f24b23788d Merge branch 'master' into fptest 2024-01-22 19:10:28 +01:00
mrdudz 650868854d Merge branch 'master' into fptest 2024-01-22 18:37:23 +01:00
mrdudz 06b14216f0 Merge branch 'master' into fptest 2024-01-12 16:03:27 +01:00
mrdudz ececcad756 Merge branch 'master' into fptest
# Conflicts:
#	src/cc65/expr.c
2024-01-12 15:22:27 +01:00
mrdudz 2978667bdb Merge branch 'master' into fptest 2024-01-08 23:05:05 +01:00
mrdudz 58220e2908 Merge branch 'master' into fptest 2024-01-08 22:46:14 +01:00
mrdudz f801251f9f Merge branch 'master' into fptest 2024-01-08 22:14:56 +01:00
mrdudz 3ebeba0530 Merge branch 'master' into fptest 2023-12-10 23:26:30 +01:00
mrdudz 55b504652e Merge branch 'master' into fptest 2023-12-10 22:35:07 +01:00
mrdudz 718d8b9e3b Merge branch 'master' into fptest 2023-12-10 19:22:57 +01:00
mrdudz 70c32a039b Merge branch 'master' into fptest 2023-12-10 00:25:23 +01:00
mrdudz 0e9458041b Merge branch 'master' into fptest 2023-11-28 15:12:39 +01:00
mrdudz a20e7b385c Merge branch 'master' into fptest 2023-11-01 15:23:49 +01:00
mrdudz baf4768c84 Merge branch 'master' into fptest 2023-10-29 12:40:25 +01:00
mrdudz e3c2962b34 Merge branch 'master' into fptest 2023-10-26 20:08:22 +02:00
mrdudz 73607361f5 Merge branch 'master' into fptest 2023-10-26 20:03:47 +02:00
mrdudz bb2a367fcf Merge branch 'master' into fptest 2023-10-26 17:40:07 +02:00
mrdudz a5be3ca37c Merge branch 'master' into fptest 2023-10-26 17:10:20 +02:00
mrdudz d6dd1a1e21 Merge branch 'master' into fptest 2023-10-26 16:57:59 +02:00
mrdudz 0e63e31e19 Merge branch 'master' into fptest 2023-10-26 16:54:18 +02:00
mrdudz 1db3d87ac8 Merge branch 'master' into fptest 2023-10-26 16:51:33 +02:00
mrdudz 4ea7c9cbd0 Merge branch 'master' into fptest 2023-10-14 20:09:55 +02:00
mrdudz db7a38ea17 Merge branch 'master' into fptest 2023-10-14 18:44:19 +02:00
mrdudz 95c0f16cf8 must...not..enable...debug 2023-09-04 01:22:53 +02:00
mrdudz b7286ade4b checkstyle, ihre rezeptfreie Online Bestellung 2023-09-04 01:12:54 +02:00
mrdudz ee46184c62 some cleanup, updated softmath with some google results :), updated readme 2023-09-04 01:05:12 +02:00
mrdudz d771e86cdf wip deactivated hack and related tests 2023-09-04 01:02:53 +02:00
mrdudz c0061cdcfa logging 2023-09-02 23:34:38 +02:00
mrdudz 3a4d0d9f0c remove woy stuff 2023-09-02 23:33:51 +02:00
mrdudz 14c71cd958 remove woz float stuff and some test things 2023-09-02 23:11:55 +02:00
mrdudz 83d3927a7f disable debug, ooops 2023-09-02 06:58:12 +02:00
mrdudz c48cf428e9 fix division and multiplication for intvar vs floatvar 2023-09-02 06:53:33 +02:00
mrdudz f0eadc69e1 fix a regression that sneaked in, all subtractions should work again 2023-09-02 06:44:53 +02:00
mrdudz 341286bf16 fix float var - int const, fix int var - float var 2023-09-02 02:42:34 +02:00
mrdudz 82346b24db fix int var - float const, fix float var - int var 2023-09-02 01:56:18 +02:00
mrdudz a8e9783f1c fix int const - float var 2023-09-02 01:12:00 +02:00
mrdudz fee2b834b0 fix float const - int var 2023-09-02 00:08:21 +02:00
mrdudz 9481f7a498 fix const int + float 2023-09-01 23:43:02 +02:00
mrdudz 6f004dadf7 fix float const -/ int const 2023-09-01 22:15:52 +02:00
mrdudz 4390cd8874 update readme 2023-09-01 22:13:34 +02:00
mrdudz 013ef1553a beginning of a reference libm in C 2023-08-31 23:07:15 +02:00
mrdudz 86d0859d8d evil spaces 2023-08-31 05:20:34 +02:00
mrdudz 56496cf8e2 some updates 2023-08-31 05:20:25 +02:00
mrdudz abe65d524d make float X= const work, and a test for that 2023-08-31 05:04:02 +02:00
mrdudz 26a3aa9fb7 implement rsub 2023-08-31 04:41:23 +02:00
mrdudz ab238c1045 some fixes for X=, related tests 2023-08-31 00:44:03 +02:00
mrdudz 8dfe97b1df updates 2023-08-31 00:37:11 +02:00
mrdudz fdc5865d3f fix some warnings 2023-08-31 00:22:53 +02:00
mrdudz 00824427f7 some logging 2023-08-30 23:49:00 +02:00
mrdudz a77de923fc update readme 2023-08-30 02:41:46 +02:00
mrdudz 845c600824 update 2023-08-30 02:15:00 +02:00
mrdudz 29edbaa20e update readme 2023-08-30 02:13:16 +02:00
mrdudz 681fe5d562 update/add a bunch of tests. should be all for "basic" and "cmp" now 2023-08-30 02:12:43 +02:00
mrdudz babaf98040 another addition fix 2023-08-30 02:11:47 +02:00
mrdudz 771155ff02 add tests for float vs int var 2023-08-29 14:50:26 +02:00
mrdudz bb24862401 cleanup 2023-08-29 12:07:19 +02:00
mrdudz dd5f12b352 fix int variable + float constant, fix float variable + int constant, add tests 2023-08-29 12:00:17 +02:00
mrdudz 3164917f46 cleanup 2023-08-29 03:15:54 +02:00
mrdudz 109b770236 spaces! 2023-08-29 01:31:14 +02:00
mrdudz 2e220e709e some fixes relalated to comparing with integer constants, related tests. some fixes related to adding integers, related tests 2023-08-29 01:11:59 +02:00
mrdudz c4561e7989 some bugfixes/adjustments 2023-08-29 00:50:53 +02:00
mrdudz 97a4bc3a6c in g_typeadjust convert the other side to float if one side is float 2023-08-29 00:49:54 +02:00
mrdudz 36ea0cc90e cosmetics 2023-08-28 02:16:35 +02:00
mrdudz b7ce973a3f update readme 2023-08-28 02:05:34 +02:00
mrdudz a396f5b1c8 add floattest sample, which contains the stuff that can work without math.h 2023-08-28 02:02:36 +02:00
mrdudz 2da00e7daa fix output for negative numbers 2023-08-28 02:01:56 +02:00
mrdudz 23a2b13a62 add rough 3d function plotter, requires math.h 2023-08-28 01:18:30 +02:00
mrdudz 45e3f03862 brief test of everything in math.h 2023-08-28 01:17:03 +02:00
mrdudz c0cba14ea5 fix roundf 2023-08-27 23:12:20 +02:00
mrdudz 4c043aa98f use kernal function to convert float to string 2023-08-27 23:11:25 +02:00
mrdudz f587e6eaf9 add code for fnegeax, and tests for it 2023-08-27 05:15:04 +02:00
mrdudz f89b382d6f update readme to reflect current state 2023-08-27 00:16:02 +02:00
mrdudz b034fe35fc another case that doesnt fail 2023-08-26 23:14:50 +02:00
mrdudz ac320910ca updated 2023-08-26 23:08:51 +02:00
mrdudz 574030ac17 rename override file also in the Makefile :) 2023-08-26 22:38:02 +02:00
mrdudz fa347d416a move test to todo again, and patch the Makefile - it works in *one* particular config (only) 2023-08-26 22:34:25 +02:00
mrdudz 260fd7f004 rename 2023-08-26 22:05:27 +02:00
mrdudz 0c69e4e290 move test to test/val ... for some reason it is working now in this branch :) 2023-08-26 21:48:35 +02:00
mrdudz fcad1067ad fix some fallout 2023-08-25 23:04:13 +02:00
mrdudz 92d9e4fcd7 Merge branch 'master' into fptest
# Conflicts:
#	src/cc65/expr.c
#	src/cc65/scanner.c
2023-08-25 22:47:32 +02:00
mrdudz e4084eb129 Merge branch 'master' into fptest 2023-08-25 22:08:08 +02:00
mrdudz 0f7c299abc Merge branch 'master' into fptest
# Conflicts:
#	src/cc65/expr.c
#	test/todo/Makefile
2023-07-08 15:56:45 +02:00
mrdudz c92a8f863a Merge branch 'master' into fptest 2023-03-04 13:48:31 +01:00
mrdudz 61f2f4fa56 Merge branch 'master' into fptest 2023-01-28 11:22:20 +01:00
mrdudz 46bb7e8961 Merge branch 'master' into fptest 2022-11-19 22:12:26 +01:00
mrdudz 54f7325800 another test fixed 2022-11-19 00:06:37 +01:00
mrdudz 1413ab711e fix some compare tests 2022-11-18 23:38:40 +01:00
mrdudz 1ba10a9619 Merge branch 'master' into fptest
# Conflicts:
#	src/cc65/expr.c
2022-11-18 20:23:02 +01:00
mrdudz c9ff35933a Merge branch 'master' into fptest 2022-11-18 19:12:52 +01:00
mrdudz 820358ce9a Merge branch 'master' into fptest 2022-11-18 19:07:24 +01:00
mrdudz a83bd3a341 Merge branch 'master' into fptest 2022-11-18 19:02:23 +01:00
mrdudz 95e61fba13 trying to evade warning 2022-11-18 18:53:00 +01:00
mrdudz e30951cf9a spaces 2022-11-18 18:28:59 +01:00
mrdudz 9c90d38ccc following hack on head 2022-11-18 18:26:13 +01:00
mrdudz 40a52c2656 following the terrible hacking on head 2022-11-18 18:04:45 +01:00
mrdudz ea4aeffc34 ooops seems i forgot to add this /o\ 2022-11-18 02:34:51 +01:00
mrdudz a33b8f371a disable debug 2022-11-18 02:34:13 +01:00
mrdudz 2cfa3d905a make failing checks works again 2022-11-18 02:33:50 +01:00
mrdudz 705617cd5f add more checks that are related to recent fixes 2022-11-18 01:52:55 +01:00
mrdudz 965c1f5239 updated 2022-11-18 01:52:18 +01:00
mrdudz 7370478f80 cleanup 2022-11-18 01:52:00 +01:00
mrdudz e8e39db4ca add fastcall to some more functions 2022-11-18 01:17:25 +01:00
mrdudz 6e7fae3795 add comments 2022-11-18 01:17:05 +01:00
mrdudz d98b55f8ee fix issues with substraction 2022-11-18 01:16:55 +01:00
mrdudz c725cab7c6 crazy hack so the function works better even when typecasting seems broken 2022-11-18 00:55:00 +01:00
mrdudz 15b713f7f1 build mathtest for c64, link c64 float progs against the kernal wrapper 2022-11-17 22:48:21 +01:00
mrdudz 89341e0378 add mandelfloat sample 2022-11-17 22:14:43 +01:00
mrdudz ab568cf8ad rename source files to prevent weird conflicts when building 2022-11-17 21:52:49 +01:00
mrdudz c651cb4f1f cleanup 2022-11-17 20:41:49 +01:00
mrdudz cfdf6aef9d add some tests on comparing floats vs ints. not all cases working 2022-11-17 20:41:36 +01:00
mrdudz f7f5d39f20 fix some cases when comparing floats vs ints 2022-11-17 20:41:15 +01:00
mrdudz 54e7d71cb7 fix division test 2022-11-17 20:38:59 +01:00
mrdudz 14347c2220 cleanup 2022-11-17 19:39:35 +01:00
mrdudz 1ba0651b75 also delete quick.s 2022-11-17 19:16:39 +01:00
mrdudz 0c081b73d3 add logging and comments 2022-11-17 19:14:42 +01:00
mrdudz 44c55513f5 fix math function wrappers for cbmkernal 2022-11-17 19:12:27 +01:00
mrdudz 04d058297b dont include math.h 2022-11-17 19:11:29 +01:00
mrdudz 7f9ebe678c spaces 2022-11-14 01:27:19 +01:00
mrdudz 683a2e7d28 add a simple example program that uses floats :) 2022-11-14 01:25:25 +01:00
mrdudz 78df8e8c3f make cbm float library available 2022-11-14 01:22:03 +01:00
mrdudz 331a8c7bc3 fix (some) issues with float constants 2022-11-13 23:47:15 +01:00
mrdudz 7467503f6e in an expression when both sides are constant, and one side is float, convert the other side to float and make the result float 2022-11-13 21:21:17 +01:00
mrdudz 34420ac153 test for mixed expressions 2022-11-13 19:02:47 +01:00
mrdudz 80d6c71b23 add missing float conversion 2022-11-13 18:54:29 +01:00
mrdudz e77bf71ab9 fix g_div patch, hopefully checks works again 2022-11-13 17:50:40 +01:00
mrdudz c427fb36b2 don't attempt strength reduction on divisions with floats 2022-11-13 15:21:15 +01:00
mrdudz 797aba5c07 dont do strength reduction on floats :) 2022-11-13 15:12:01 +01:00
mrdudz 1494a1ac1c Merge branch 'master' into fptest
# Conflicts:
#	src/cc65/codegen.c
2022-11-13 14:07:44 +01:00
mrdudz bfd53911f6 adapt codegen comments from #1917 2022-11-13 13:41:41 +01:00
mrdudz 9e7e86e443 fix division problem, fix some other tests 2022-11-13 02:21:57 +01:00
mrdudz abe1926a48 remove useless if 2022-11-12 22:55:17 +01:00
mrdudz fd070c9b79 fix ternary operator 2022-11-12 19:08:03 +01:00
mrdudz 5c5653027a wrap asm log output into a macro 2022-11-12 18:44:28 +01:00
mrdudz 18dd61da42 another try of silencing 2022-11-12 18:24:31 +01:00
mrdudz a2d3e87c75 use conversion functions, should shut up windows compile 2022-11-12 18:11:28 +01:00
mrdudz 2583db3abb fix passing of value to push float 2022-11-12 18:04:23 +01:00
mrdudz 2099e56263 fall through comment 2022-11-12 17:52:16 +01:00
mrdudz 69b3659924 fix conversion of float to chars 2022-11-12 17:41:52 +01:00
mrdudz 694561e917 fix comparing float const vs const 2022-11-12 02:44:01 +01:00
mrdudz 62e211553b fix comparing float variable agains float constants 2022-11-12 02:04:29 +01:00
mrdudz af15ce8223 some cleanup, make testcompiles of the tests with gcc work again 2022-11-12 02:03:23 +01:00
mrdudz 89f8f51c32 Merge branch 'master' into fptest 2022-11-11 22:06:21 +01:00
mrdudz 9cdd74e2f1 Merge branch 'master' into fptest 2022-11-11 21:45:04 +01:00
mrdudz 6c5807001b add failing tests in test/todo 2022-11-11 00:52:42 +01:00
mrdudz c5728626b0 space! 2022-11-09 02:50:54 +01:00
mrdudz f55b9ce37e spaces 2022-11-09 02:48:14 +01:00
mrdudz bbe46bb883 move float libss into libsrc/float, move tests into the correct dirs for the testbench, move includes to toplevel include dir 2022-11-09 02:45:07 +01:00
mrdudz 57c9a4db8a Merge branch 'master' into fptest 2022-11-05 20:53:44 +01:00
mrdudz 4a8c13fd93 Merge branch 'master' into fptest 2022-11-05 20:43:47 +01:00
mrdudz 39e82722fc don't fall through 2022-11-05 15:58:11 +01:00
mrdudz c8cdc1dc60 fix whitespace 2022-09-18 00:36:30 +02:00
mrdudz 163f0d447d fix/update the float tests 2022-09-18 00:33:48 +02:00
mrdudz 4e61599779 fix rounding when converting to 16bit ints 2022-09-17 18:35:30 +02:00
mrdudz 3805c8754a hack up something that prints correct decimal places even with the bugs in the compiler 2022-09-17 18:35:02 +02:00
mrdudz 7693b86d7d fix ! operator 2022-09-17 16:54:09 +02:00
mrdudz 1f4f408572 correctly sign extend for 16bit->float conversion 2022-09-17 16:53:28 +02:00
mrdudz 13dd4e296f guard some more things with ifdef DOUBLES, removes some warnings 2022-09-17 16:52:24 +02:00
mrdudz 09d383dd32 make compare functions fastcall 2022-09-17 16:51:11 +02:00
mrdudz 0f5122be2f make tests "work" with softfloat 2022-09-13 23:26:09 +02:00
mrdudz c3bebd40ce Merge branch 'master' into fptest 2022-09-13 16:54:08 +02:00
mrdudz f337843c71 Merge branch 'master' into fptest 2022-08-27 12:28:09 +02:00
mrdudz 9610f20fd7 Merge remote-tracking branch 'upstream/master' into fptest 2022-08-27 00:31:36 +02:00
mrdudz 87b6ddd3e0 some cleanup, move everything we need into one directory 2022-08-23 15:12:02 +02:00
mrdudz 3c01489940 softfloat compiles and produces a working binary 2022-08-22 23:26:09 +02:00
mrdudz 69d5d4dcdd add older release of the berkeley softfloat lib,
this one can work without 64bit types.

missing support for passing structs by value will need a bit of hackery
2022-08-21 22:57:43 +02:00
mrdudz 731695a606 Revert "added Berkeley softfloat library - lets see if this can be ported"
this version of the library requires 64bit types

This reverts commit e7d7ad7df0.
2022-08-21 19:49:42 +02:00
mrdudz e7d7ad7df0 added Berkeley softfloat library - lets see if this can be ported 2022-08-21 19:31:32 +02:00
mrdudz 034d414d00 Merge remote-tracking branch 'upstream/master' into fptest
# Conflicts:
#	src/cc65/scanner.c
2022-08-21 18:10:11 +02:00
mrdudz 63dde66519 Merge remote-tracking branch 'upstream/master' into fptest 2022-07-21 02:58:12 +02:00
mrdudz 9ccb4a281a put pragmas into ifdefs for msvc 2022-07-21 02:46:01 +02:00
mrdudz 543c1c3889 another warning pragma 2022-07-21 02:41:20 +02:00
mrdudz 978bdedf33 switch off msvc warning 2022-07-21 02:38:20 +02:00
mrdudz 6001f5d0e0 silence more debug stuff 2022-07-21 02:31:55 +02:00
mrdudz 77ce005d0a more cleanup 2022-07-21 02:06:47 +02:00
mrdudz 63024cd056 cleanup 2022-07-21 00:54:53 +02:00
mrdudz b9bdcc51e0 some cleanup 2022-07-21 00:51:28 +02:00
mrdudz 6818fef71f update readme 2022-06-20 04:32:07 +02:00
mrdudz 96ee702220 update some basic functions 2022-06-20 04:31:51 +02:00
mrdudz 71c0c63f6c Merge remote-tracking branch 'upstream/master' into fptest 2022-06-20 02:05:19 +02:00
mrdudz 059b7875b3 fixup readme 2022-06-20 02:00:43 +02:00
mrdudz 00fabb8caf beginning of float libraries and test programs 2022-06-20 01:54:03 +02:00
mrdudz 1fb7c896b4 beginning of half broken 32bit float support 2022-06-20 01:51:19 +02:00
mrdudz 6a35bfd2fa fix scanning the fractional digits of a float 2022-06-15 23:04:57 +02:00
112 changed files with 14751 additions and 400 deletions

View File

@ -115,37 +115,78 @@ PVExit ($01)
<sect>Creating a Test in C<p>
For a C test compiled and linked with <tt/--target sim6502/ the
For a C test linked with <tt/--target sim6502/ and the <tt/sim6502.lib/ library,
command line arguments to <tt/sim65/ will be passed to <tt/main/,
and the return value from <tt/main/ will become sim65's exit code.
The <tt/exit/ function may also be used to terminate with an exit code.
The <tt/stdlib.h/ <tt/exit/ function may also be used to terminate with an exit code.
Exit codes are limited to 8 bits.
Exit codes are limited to an unsigned 8 bit value. (E.g. returning -1 will give an exit code of 255.)
The standard C library high level file input and output is functional.
A sim65 application can be written like a command line application,
providing arguments to <tt/main/ and using the <tt/stdio.h/ interfaces.
providing command line arguments to <tt/main/ and using the <tt/stdio.h/ interfaces
to interact with the console or access files.
Internally, file input and output is provided at a lower level by
a set of built-in paravirtualization functions (<ref id="paravirt-internal" name="see below">).
a set of built-in paravirtualization functions (see <ref id="paravirt-internal" name="below">).
Example:
<tscreen><verb>
#include <stdio.h>
int main()
{
printf("Hello!\n");
return 5;
}
// Build and run:
// cl65 -t sim6502 -o example.prg example.c
// sim65 example.prg
// Build and run, separate steps:
// cc65 -t sim6502 -o example.s example.c
// ca65 -t sim6502 -o example.o example.s
// ld65 -t sim6502 -o example.prg example.o sim6502.lib
// sim65 example.prg
</verb></tscreen>
<sect>Creating a Test in Assembly<p>
Assembly tests may similarly be assembled and linked with
<tt/--target sim6502/ or <tt/--target sim65c02/.
Define and export <tt/_main/ as an entry point,
Though a C test may also link with assembly code,
a pure assembly test can also be created.
Link with <tt/--target sim6502/ or <tt/--target sim65c02/ and the corresponding library,
define and export <tt/_main/ as an entry point,
and the sim65 library provides two ways to return an 8-bit exit code:
<itemize>
<item>Return from <tt/_main/ with the exit code in <tt/A/.
<item><tt/jmp exit/ with the code in <tt/A/.
<item><tt/jmp exit/ with the code in <tt/A/. (<tt/.import exit/ from the sim65 library.)
</itemize>
The binary file has a 12 byte header:
Example:
<tscreen><verb>
.export _main
_main:
lda #5
rts
; Build and run:
; cl65 -t sim6502 -o example.prg example.s
; sim65 example.prg
; Build and run, separate steps:
; ca65 -t sim6502 -o example.o example.s
; ld65 -t sim6502 -o example.prg example.o sim6502.lib
; sim65 example.prg
</verb></tscreen>
Internally, the binary program file has a 12 byte header provided by the library:
<itemize>
@ -182,6 +223,9 @@ These use cc65 calling conventions, and are intended for use with the sim65 targ
<item><tt/IRQ/ and <tt/NMI/ events will not be generated, though <tt/BRK/
can be used if the IRQ vector at <tt/$FFFE/ is manually prepared by the test code.
<item>The <tt/sim6502/ or <tt/sim65c02/ targets provide a default configuration,
but if customization is needed <tt/sim6502.cfg/ or <tt/sim65c02.cfg/ might be used as a template.
</itemize>

54
include/_float.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef _FLOAT_H_
#define _FLOAT_H_
/* ieee754 32bit format:
*
* sign
* / /exponent/mantissa
* 3 32222222 22211111111110000000000
* 1 09876543 21098765432109876543210
*
* The sign is stored in bit 31.
* The exponent can be computed from bits 23-30 by subtracting 127. (128 = 2^1)
* The mantissa is stored in bits 0-22.
* An invisible leading bit (i.e. it is not actually stored) with value 1.0
* is placed in front, then bit 23 has a value of 1/2, bit 22 has value 1/4 etc.
* As a result, the mantissa has a value between 1.0 and 2.
*
* 1.0 = exp=127, mantissa=0
*
* If the exponent reaches -127 (binary 00000000), the leading 1 is no longer
* used to enable gradual underflow.
*
*/
typedef struct {
unsigned char exponent; /* msb is the sign */
unsigned char mantissa[3]; /* msb is lsb of exponent */
} FLOAT754;
/* we dont wanna seriously use double precision eh? ;=P */
/* #define double float */
/* string to/from float conversion functions */
char *_ftoa(char *buf, float n);
/* string conversion functions, these use the exponential form */
char * __fastcall__ _ftostr(char *d, float s); /* for vsprintf */
float __fastcall__ _strtof(char *d);
/* beware, this is not standard */
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
/* degrees to radiants */
#define deg2rad(_fs, _n) ((_fs / _n) * (2.0f * M_PI))
/* radiants to degrees deg = (rad / (2 * pi)) * 256 */
#define rad2deg(_rad, _n) ((_rad / (2.0f * M_PI)) * _n)
/* resets fp-libs in Turbo-C and M$-C */
#define _fpreset()
#endif /* _FLOAT_H_ */

58
include/math.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef _MATH_H_
#define _MATH_H_
#include "_float.h"
/* double pow(double x, double y); */
float __fastcall__ powf(float f, float a); /* C99 */
/* double sin(double x); */
float __fastcall__ sinf(float s); /* C99 */
/* double cos(double x); */
float __fastcall__ cosf(float s); /* C99 */
/* double log(double x); */
float __fastcall__ logf(float x); /* C99 */
/* double exp(double x); */
float __fastcall__ expf(float x); /* C99 */
/* double sqrt(double x); */
float __fastcall__ sqrtf(float x); /* C99 */
/* double tan(double x); */
float __fastcall__ tanf(float x); /* C99 */
/* double atan(double x); */
float __fastcall__ atanf(float x); /* C99 */
/* double fabs(double x); */
float __fastcall__ fabsf(float x); /* C99 */
/* double round(double x); */ /* C99 */
float __fastcall__ roundf(float x); /* C99 */
/* double trunc(double x); */ /* C99 */
float __fastcall__ truncf(float x); /* C99 */
/* double ceil(double x) */
float __fastcall__ ceilf(float x); /* C99 */
/* double fmod(double x, double y); */
float __fastcall__ fmodf(float x, float y);
/* double floor(double x); */
float __fastcall__ floorf(float x);
/* beware, this is not standard */
#ifndef M_PI
#define M_PI 3.14159265358979323846f
#endif
/* FIXME */
float __fastcall__ _fatan2(float x, float y);
#endif /* _MATH_H_ */

View File

@ -177,8 +177,12 @@ endif
SRCDIRS = $(SRCDIR)
SRCDIRS += float/softfloat \
float/softmath
ifeq ($(TARGET),$(filter $(TARGET),$(CBMS)))
SRCDIRS += cbm
SRCDIRS += float/cbmkernal
endif
ifeq ($(TARGET),$(filter $(TARGET),$(GEOS)))

View File

@ -0,0 +1,70 @@
; import/overload stubs for the C64 kernal floating point implementation
.import ___cbmkernal_afloat
.import ___cbmkernal_aufloat
.import ___cbmkernal_axfloat
.import ___cbmkernal_axufloat
.import ___cbmkernal_eaxfloat
.import ___cbmkernal_eaxufloat
.import ___cbmkernal_feaxint
.import ___cbmkernal_feaxlong
.import ___cbmkernal_fbnegeax
.import ___cbmkernal_fnegeax
.import ___cbmkernal_ftosaddeax
.import ___cbmkernal_ftossubeax
.import ___cbmkernal_ftosrsubeax
.import ___cbmkernal_ftosdiveax
.import ___cbmkernal_ftosmuleax
.import ___cbmkernal_ftoseqeax
.import ___cbmkernal_ftosneeax
.import ___cbmkernal_ftosgteax
.import ___cbmkernal_ftoslteax
.import ___cbmkernal_ftosgeeax
.import ___cbmkernal_ftosleeax
.export afloat := ___cbmkernal_afloat
.export aufloat := ___cbmkernal_aufloat
.export axfloat := ___cbmkernal_axfloat
.export axufloat := ___cbmkernal_axufloat
.export eaxfloat := ___cbmkernal_eaxfloat
.export eaxufloat := ___cbmkernal_eaxufloat
.export feaxint := ___cbmkernal_feaxint
.export feaxlong := ___cbmkernal_feaxlong
.export fbnegeax := ___cbmkernal_fbnegeax
.export fnegeax := ___cbmkernal_fnegeax
.export ftosaddeax := ___cbmkernal_ftosaddeax
.export ftossubeax := ___cbmkernal_ftossubeax
.export ftosrsubeax := ___cbmkernal_ftosrsubeax
.export ftosdiveax := ___cbmkernal_ftosdiveax
.export ftosmuleax := ___cbmkernal_ftosmuleax
.export ftoseqeax := ___cbmkernal_ftoseqeax
.export ftosneeax := ___cbmkernal_ftosneeax
.export ftosgteax := ___cbmkernal_ftosgteax
.export ftoslteax := ___cbmkernal_ftoslteax
.export ftosgeeax := ___cbmkernal_ftosgeeax
.export ftosleeax := ___cbmkernal_ftosleeax
.import ___cbmkernal_powf
.import ___cbmkernal_sinf
.import ___cbmkernal_cosf
.import ___cbmkernal_logf
.import ___cbmkernal_expf
.import ___cbmkernal_sqrtf
.import ___cbmkernal_tanf
.import ___cbmkernal_atanf
.import ___cbmkernal_fabsf
.import ___cbmkernal_roundf
.import ___cbmkernal_truncf
.export _powf := ___cbmkernal_powf
.export _sinf := ___cbmkernal_sinf
.export _cosf := ___cbmkernal_cosf
.export _logf := ___cbmkernal_logf
.export _expf := ___cbmkernal_expf
.export _sqrtf := ___cbmkernal_sqrtf
.export _tanf := ___cbmkernal_tanf
.export _atanf := ___cbmkernal_atanf
.export _fabsf := ___cbmkernal_fabsf
.export _roundf := ___cbmkernal_roundf
.export _truncf := ___cbmkernal_truncf

View File

@ -0,0 +1,63 @@
FAC_EXPONENT = $61
FAC_MANTISSA0 = $62
FAC_MANTISSA1 = $63
FAC_MANTISSA2 = $64
FAC_MANTISSA3 = $65
FAC_SIGN = $66
ARG_EXPONENT = $69
ARG_MANTISSA0 = $6a
ARG_MANTISSA1 = $6b
ARG_MANTISSA2 = $6c
ARG_MANTISSA3 = $6d
ARG_SIGN = $6e
FAC_SIGN_COMPARE = $6f
FAC_ROUNDING = $70
; addresses of the floating point routines in CBM BASIC V2
; the following are the addresses in the VIC-20 ROM - the library can probably be
; used with other CBM targets just by adjusting these addresses
BASIC_FAC_Not = $ced4 ; in/out: FAC ; yup, c64 & vic are this different
BASIC_FAC_Cos = $e261 ; in/out: FAC
BASIC_FAC_Sin = $e268 ; in/out: FAC
BASIC_FAC_Tan = $e2b1 ; in/out: FAC
BASIC_FAC_Atn = $e30b ; in/out: FAC
BASIC_FAC_Rnd = $e094 ; in/out: FAC
BASIC_FAC_Int = $dccc ; in/out: FAC
BASIC_FAC_Sqr = $df71 ; in/out: FAC
BASIC_FAC_Exp = $dfed ; in/out: FAC
BASIC_FAC_Log = $d9ea ; in/out: FAC
BASIC_FAC_Round = $dc1b ; in/out: FAC
BASIC_FAC_Sgn = $dc39 ; in/out: FAC
BASIC_FAC_Abs = $dc58 ; in/out: FAC
BASIC_ARG_FAC_Or = $cfe6 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_And = $cfe9 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Sub = $d853 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Add = $d86a ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Mul = $da2b ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Div = $db12 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Pow = $df7b ; in: ARG,FAC out:FAC
BASIC_u8_to_FAC = $d3a2 ; y: value
BASIC_s8_to_FAC = $dc3c ; a: value
BASIC_u16_to_FAC = $dc49 ; a/y:lo/hi value (sta $62 sty $63 sec ldx#$90 jsr...)
BASIC_s16_to_FAC = $d395 ; a/y:lo/hi value
BASIC_FAC_to_u16 = $dc9b ; in:FAC out: y/a:lo/hi value
BASIC_string_to_FAC = $d7b5 ; in: $22/$23 ptr to str,a=strlen out: FAC value
BASIC_FAC_to_string = $dddd ; in: FAC value out: str at $0100 a/y ptr to str
BASIC_LoadARG = $da8c ; a/y:lo/hi ptr to 5-byte float
BASIC_LoadFAC = $dba2 ; a/y:lo/hi ptr to 5-byte float
BASIC_FAC_testsgn = $dc2b ; in: FAC(x1) out: a=0 (x1=0) a=1 (x1>0) a=255 (x1<0)
BASIC_FAC_cmp = $dc5b ; in: FAC(x1) a/y ptr lo/hi to x2 out: a=0 (x1=x2) a=1 (x1>x2) a=255 (x1<x2)
BASIC_FAC_Poly2 = $e040 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
BASIC_FAC_Poly1 = $e056 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)

View File

@ -0,0 +1,446 @@
.import __ctof
.import __utof
.import __itof
.import __stof
; 8bit signed -> float
.export ___cbmkernal_afloat
___cbmkernal_afloat:
jmp __ctof
; 8bit unsigned -> float
.export ___cbmkernal_aufloat
___cbmkernal_aufloat:
jmp __utof
; 16bit signed -> float
.export ___cbmkernal_axfloat
___cbmkernal_axfloat:
jmp __itof
; 16bit unsigned -> float
.export ___cbmkernal_axufloat
___cbmkernal_axufloat:
jmp __stof
; FIXME: this might be more accurate when done directly in one step (but the
; kernal can not do this for 32bit)
; 32bit signed -> float
.importzp sreg, tmp1
.import pusheax
.export ___cbmkernal_eaxfloat
___cbmkernal_eaxfloat:
sta tmp1
lda sreg
pha
lda sreg+1
pha
; get lower 16bit
lda tmp1
; convert lower 16 bit
jsr __stof
jsr pusheax ; push eax to stack
; / 65536
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jsr __fdiv
jsr pusheax ; push eax to stack
; get higher 16bit
pla
tax
pla
; convert higher 16 bit
jsr __itof
jsr __fadd
jsr pusheax ; push eax to stack
; * 65536
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jmp __fmul
; FIXME: this might be more accurate when done directly in one step (but the
; kernal can not do this for 32bit)
; 32bit unsigned -> float
.importzp sreg, tmp1
.import pusheax
.export ___cbmkernal_eaxufloat
___cbmkernal_eaxufloat:
sta tmp1
lda sreg
pha
lda sreg+1
pha
; get lower 16bit
lda tmp1
; convert lower 16 bit
jsr __stof
jsr pusheax ; push eax to stack
; / 65536
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jsr __fdiv
jsr pusheax ; push eax to stack
; get higher 16bit
pla
tax
pla
; convert higher 16 bit
jsr __stof
jsr __fadd
jsr pusheax ; push eax to stack
; * 65536
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jmp __fmul
;--------------------------------------------------------------
.import __ftoi
; float -> 16bit int
.export ___cbmkernal_feaxint
___cbmkernal_feaxint:
jmp __ftoi
; FIXME: this might be more accurate when done directly in one step (but the
; kernal can not do this for 32bit)
; float -> 32bit int
.importzp tmp1, tmp2
.export ___cbmkernal_feaxlong
___cbmkernal_feaxlong:
jsr pusheax
; primary = primary / 65536
jsr pusheax ; push eax to stack
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jsr __fdiv ; primary / TOS
; convert result to int and save
jsr __ftoi
sta tmp1
stx tmp2
; convert back to float
jsr __stof
; primary = primary * 65536
jsr pusheax ; push eax to stack
ldx #$00
lda #$80
sta sreg
lda #$47
sta sreg+1
jsr __fmul ; primary * TOS
; substract the result from the total number to get the rest
jsr __fsub
; convert rest to int
jsr __ftoi
ldy tmp2
sty sreg+1
ldy tmp1
sty sreg
rts
;--------------------------------------------------------------
.import __fnot
.import __fneg
; binary negate (not) for the ! operator. returns a bool!
.export ___cbmkernal_fbnegeax
.import bnegax
___cbmkernal_fbnegeax:
; FIXME: why does this not work with __fnot?
jsr __ftoi
jmp bnegax
.export ___cbmkernal_fnegeax
___cbmkernal_fnegeax:
jmp __fneg
;--------------------------------------------------------------
; math ops
.import __fadd
.import __fsub
.import __fdiv
.import __fmul
; Primary = TOS + Primary (like tosaddeax)
.export ___cbmkernal_ftosaddeax
___cbmkernal_ftosaddeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
; FAC: ieee float is in A/X/sreg/sreg+1
jmp __fadd
.export ___cbmkernal_ftossubeax
___cbmkernal_ftossubeax:
jmp __fsub
.export ___cbmkernal_ftosdiveax
___cbmkernal_ftosdiveax:
jmp __fdiv
.export ___cbmkernal_ftosmuleax
___cbmkernal_ftosmuleax:
jmp __fmul
.import __frsub
; Primary = Primary - TOS
.export ___cbmkernal_ftosrsubeax
___cbmkernal_ftosrsubeax:
jmp __frsub
;--------------------------------------------------------------
.import __fcmp
; test for equal
.export ___cbmkernal_ftoseqeax
___cbmkernal_ftoseqeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #0
beq @equal
lda #0
tax
rts
@equal:
ldx #0
lda #1
rts
; test for not equal
.export ___cbmkernal_ftosneeax
___cbmkernal_ftosneeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #0
beq @equal
ldx #0
lda #1
rts
@equal:
lda #0
tax
rts
; Test for greater than
.export ___cbmkernal_ftosgteax
___cbmkernal_ftosgteax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #255
bne @biggerorequal
; less
ldx #0
lda #1
rts
@biggerorequal:
lda #0
tax
rts
; Test for less than
.export ___cbmkernal_ftoslteax
___cbmkernal_ftoslteax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #1
beq @bigger
lda #0
tax
rts
@bigger:
ldx #0
lda #1
rts
; Test for greater than or equal to
.export ___cbmkernal_ftosgeeax
___cbmkernal_ftosgeeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #1
beq @bigger
; less than or equal
ldx #0
lda #1
rts
@bigger:
lda #0
tax
rts
; Test for less than or equal to
.export ___cbmkernal_ftosleeax
___cbmkernal_ftosleeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr __fcmp
; a=0 (==) / a=1 (>) / a=255 (<)
cmp #255
beq @smaller
; greater than or equal
ldx #0
lda #1
rts
@smaller:
lda #0
tax
rts
;--------------------------------------------------------------
; math.h
.import __fpow
.import __fsin
.import __fcos
.import __flog
.import __fexp
.import __fsqr
.import __ftan
.import __fatn
.import __fabs
.import __fround
.import __fint
.export ___cbmkernal_powf
___cbmkernal_powf:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp __fpow
.export ___cbmkernal_sinf
___cbmkernal_sinf:
; arg0: a/x/sreg/sreg+1
jmp __fsin
.export ___cbmkernal_cosf
___cbmkernal_cosf:
; arg0: a/x/sreg/sreg+1
jmp __fcos
.export ___cbmkernal_logf
___cbmkernal_logf:
; arg0: a/x/sreg/sreg+1
jmp __flog
.export ___cbmkernal_expf
___cbmkernal_expf:
; arg0: a/x/sreg/sreg+1
jmp __fexp
.export ___cbmkernal_sqrtf
___cbmkernal_sqrtf:
; arg0: a/x/sreg/sreg+1
jmp __fsqr
.export ___cbmkernal_tanf
___cbmkernal_tanf:
; arg0: a/x/sreg/sreg+1
jmp __ftan
.export ___cbmkernal_atanf
___cbmkernal_atanf:
; arg0: a/x/sreg/sreg+1
jmp __fatn
.export ___cbmkernal_fabsf
___cbmkernal_fabsf:
; arg0: a/x/sreg/sreg+1
jmp __fabs
; roundf rounds to the "nearest integer", "away from zero". that means
; For example, round(0.5) is 1.0, and round(-0.5) is -1.0.
.export ___cbmkernal_roundf
___cbmkernal_roundf:
; arg0: a/x/sreg/sreg+1
; jmp __fround
; primary = primary + 0.5
jsr pusheax ; push eax to stack
; ldy #$00
; sty sreg
; lda #$00
; sta sreg
; ldx #0
bit sreg+1
bpl @plus
; $3effffff
lda #$3e
sta sreg+1
ldx #$ff
txa
sta sreg
jsr __fadd
jmp __fint
@plus:
; $3fffffff
lda #$3f
sta sreg+1
ldx #0
txa
sta sreg
jsr __fadd
jmp __fint
.export ___cbmkernal_truncf
___cbmkernal_truncf:
; arg0: a/x/sreg/sreg+1
jmp __fint

View File

@ -0,0 +1,124 @@
#ifndef _CBMFS_H_
#define _CBMFS_H_
/*
format used in basic-variables
we dont use this format, although it saves one byte per variable, since that
removes the need of constantly converting between both formats. (someday
we may use an entire different (not cbm-specific), more accurate, format anyway)
sign
exponent / /mantissa
33333333 3 3222222222111111111110000000000
98765432 1 0987654321098765432109876543210
(the above seems to match wozniacs format)
* The exponent can be computed from bits 39-32 by subtracting 129 (!)
*/
typedef struct {
unsigned char exponent;
unsigned char mantissa[4];
} FLOATBAS;
/* CBM format used in floating-point akku
*
* this format can be directly used with most CBM BASIC routines
*
* exponent mantissa sign
* 44444444 33333333332222222222111111111100 00000000
* 76543210 98765432109876543210987654321098 76543210
*
* truncated to 32bit:
*
* exponent mantissa sign
* 33222222 2222111111111100 00000000
* 10987654 3210987654321098 76543210
*
* The exponent can be computed from bits 47-40 by subtracting 129 (!) (130 = 2^1)
* MSB of the Mantissa must always be 1, if it is 0 the value is 0
*
* 1.0 = exp=129, mantissa=$80
*
*/
typedef struct {
unsigned char exponent;
unsigned char mantissa[4];
unsigned char sign;
} FLOATFAC;
/* integer conversion functions */
float __fastcall__ _ctof(char v); /* afloat */
float __fastcall__ _utof(unsigned char v); /* aufloat */
float __fastcall__ _itof(int v); /* axfloat */
float __fastcall__ _stof(unsigned short v); /* axufloat */
int __fastcall__ _ftoi(float f); /* feaxint */
/* compare two floats, returns 0 if f = a, 1 if f < a, 255 if f > a */
unsigned char __fastcall__ _fcmp(float f, float a); /* ftos..eax */
/* arithmetic functions */
float __fastcall__ _fadd(float f, float a); /* ftosaddeax */
float __fastcall__ _fsub(float f, float a); /* ftossubeax */
float __fastcall__ _fmul(float f, float a); /* ftosmuleax */
float __fastcall__ _fdiv(float f, float a); /* ftosdiveax */
/* math functions */
float __fastcall__ _fpow(float f, float a); /* math.h powf */
float __fastcall__ _fsin(float s); /* math.h sinf */
float __fastcall__ _fcos(float s); /* math.h cosf */
float __fastcall__ _flog(float s); /* math.h logf */
float __fastcall__ _fexp(float s); /* math.h expf */
float __fastcall__ _fsqr(float s); /* math.h sqrtf */
float __fastcall__ _ftan(float s); /* math.h tanf */
float __fastcall__ _fatn(float s); /* math.h atanf */
float __fastcall__ _fabs(float s); /* math.h fabsf */
float __fastcall__ _fint(float s); /* math.h truncf */ /* truncate decimal fraction */
float __fastcall__ _fround(float s); /* math.h roundf */ /* rounding */
/* logical functions */
float __fastcall__ _fand(float f, float a);
float __fastcall__ _for(float f, float a);
float __fastcall__ _fnot(float f);
/* misc */
float __fastcall__ _frnd(float s); /* random number */
float __fastcall__ _fsgn(float s); /* "signum" returns 1 if positive, 0 if 0, -1 if negative */
float __fastcall__ _fneg(float f); /* negate (flip sign) FIXME: fnegeax */
unsigned char __fastcall__ _ftestsgn(float f); /* FIXME */
#if 0
typedef struct {
unsigned char exponent;
FLOATBAS coffs[8]; /* ? */
} FLOATPOLY;
#define fpoly FLOATPOLY
/* polynom1 f(x)=a1+a2*x^2+a3*x^3+...+an*x^n */
void _fpoly1(float *d,fpoly *a,float *x);
/* polynom2 f(x)=a1+a2*x^3+a3*x^5+...+an*x^(2n-1) */
void _fpoly2(float *d,fpoly *a,float *x);
#endif
/*
todo:
acos,asin,ceil,cosh,fmod,hypot,ldexp,log10,modf,poly,pow10,sinh
tanh,cabs,_matherr,matherr,
*/
#endif

View File

@ -0,0 +1,64 @@
FAC_EXPONENT = $61
FAC_MANTISSA0 = $62
FAC_MANTISSA1 = $63
FAC_MANTISSA2 = $64
FAC_MANTISSA3 = $65
FAC_SIGN = $66
ARG_EXPONENT = $69
ARG_MANTISSA0 = $6a
ARG_MANTISSA1 = $6b
ARG_MANTISSA2 = $6c
ARG_MANTISSA3 = $6d
ARG_SIGN = $6e
FAC_SIGN_COMPARE = $6f
FAC_ROUNDING = $70
; addresses of the floating point routines in CBM BASIC V2
; the following are the addresses in the C64 ROM - the library can probably be
; used with other CBM targets just by adjusting these addresses
BASIC_FAC_Not = $aed4 ; in/out: FAC
BASIC_FAC_Cos = $e264 ; in/out: FAC
BASIC_FAC_Sin = $e26b ; in/out: FAC
BASIC_FAC_Tan = $e2b4 ; in/out: FAC
BASIC_FAC_Atn = $e30e ; in/out: FAC
BASIC_FAC_Rnd = $e097 ; in/out: FAC
BASIC_FAC_Int = $bccc ; in/out: FAC
BASIC_FAC_Sqr = $bf71 ; in/out: FAC
BASIC_FAC_Exp = $bfed ; in/out: FAC
BASIC_FAC_Log = $b9ea ; in/out: FAC
BASIC_FAC_Round = $bc1b ; in/out: FAC
BASIC_FAC_Sgn = $bc39 ; in/out: FAC "signum" returns 1 if positive, 0 if 0, -1 if negative
BASIC_FAC_Abs = $bc58 ; in/out: FAC
BASIC_ARG_FAC_Or = $afe6 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_And = $afe9 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Sub = $b853 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Add = $b86a ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Mul = $ba2b ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Div = $bb12 ; in: ARG,FAC out:FAC
BASIC_ARG_FAC_Pow = $bf7b ; in: ARG,FAC out:FAC
BASIC_u8_to_FAC = $b3a2 ; y: value
BASIC_s8_to_FAC = $bc3c ; a: value
BASIC_u16_to_FAC = $bc49 ; a/y:lo/hi value (sta $62 sty $63 sec ldx#$90 jsr...)
BASIC_s16_to_FAC = $b395 ; a/y:lo/hi value
BASIC_FAC_to_u16 = $bc9b ; in:FAC out: y/a:lo/hi value
BASIC_string_to_FAC = $b7b5 ; in: $22/$23 ptr to str,a=strlen out: FAC value
BASIC_FAC_to_string = $bddd ; in: FAC value out: str at $0100 a/y ptr to str
BASIC_LoadARG = $ba8c ; a/y:lo/hi ptr to 5-byte float
BASIC_LoadFAC = $bba2 ; a/y:lo/hi ptr to 5-byte float
BASIC_FAC_testsgn = $bc2b ; in: FAC(x1) out: a=0 (x1=0) a=1 (x1>0) a=255 (x1<0)
BASIC_FAC_cmp = $bc5b ; in: FAC(x1) a/y ptr lo/hi to x2 out: a=0 (x1=x2) a=1 (x1>x2) a=255 (x1<x2)
BASIC_FAC_Poly2 = $e043 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)
BASIC_FAC_Poly1 = $e059 ; in: FAC x a/y ptr to poly (1byte grade,5bytes per coefficient)

View File

@ -0,0 +1,896 @@
BINARYFORMAT_CBM_UNPACKED = 0
BINARYFORMAT_CBM_PACKED = 1
BINARYFORMAT_IEEE754 = 2
; BEWARE: also change in float.h
;BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
;BINARYFORMAT = BINARYFORMAT_CBM_PACKED
BINARYFORMAT = BINARYFORMAT_IEEE754
.segment "LOWCODE"
;---------------------------------------------------------------------------------------------
.if .defined(__C64__)
__basicon:
sei
ldx #$37
stx $01
rts
__basicoff:
ldx #$36
stx $01
cli
rts
.endif
.macro __enable_basic_if_needed
.if .defined(__C64__)
jsr __basicon
.endif
.endmacro
.macro __disable_basic_if_needed
.if .defined(__C64__)
jsr __basicoff
.endif
.endmacro
.macro __return_with_cleanup
.if .defined(__C64__)
jmp __basicoff
.else
rts
.endif
.endmacro
;---------------------------------------------------------------------------------------------
; first come the actual stubs to floating point routines, these are ment to be
; used from further written ml-math routines aswell. (maybe also from the compiler?!)
;---------------------------------------------------------------------------------------------
.if .defined(__VIC20__)
.include "cbmfp-vic20.inc"
.else
.include "cbmfp.inc"
.endif
.importzp sreg, ptr1
;---------------------------------------------------------------------------------------------
; converter integer types to float
;---------------------------------------------------------------------------------------------
___float_s8_to_fac:
;a: low
__float_s8_to_fac:
__enable_basic_if_needed
jsr BASIC_s8_to_FAC
__return_with_cleanup
___float_u8_to_fac:
;a: low
tay
;y: low
__float_u8_to_fac:
__enable_basic_if_needed
jsr BASIC_u8_to_FAC
__return_with_cleanup
; get C-parameter (signed int), convert to FAC
___float_s16_to_fac:
;a: low x: high
tay
txa
;y: low a: high
; convert signed int (YA) to FAC
__float_s16_to_fac:
__enable_basic_if_needed ; enable BASIC (trashes X)
jsr BASIC_s16_to_FAC
__return_with_cleanup
; get C-parameter (unsigned short), convert to FAC
___float_u16_to_fac:
;a: low x: high
tay
txa
;y: low a: high
__float_u16_to_fac:
sta FAC_MANTISSA0
sty FAC_MANTISSA1
__enable_basic_if_needed
ldx #$90
sec
jsr BASIC_u16_to_FAC
__return_with_cleanup
; return to C, FAC as unsigned int
__float_fac_to_u16:
__enable_basic_if_needed
jsr BASIC_FAC_to_u16
__disable_basic_if_needed
ldx FAC_MANTISSA2
lda FAC_MANTISSA3
rts
;---------------------------------------------------------------------------------------------
; converter float to string and back
;---------------------------------------------------------------------------------------------
; this converts to exponential form, ie what %e in printf would give you
__float_fac_to_str:
__enable_basic_if_needed
jsr BASIC_FAC_to_string
__return_with_cleanup
___float_str_to_fac:
; jsr popax
__float_str_to_fac:
sta $22
stx $23
ldy #$00
@l: lda ($22),y
beq @s
iny
bne @l
@s: tya
__enable_basic_if_needed
jsr BASIC_string_to_FAC
__return_with_cleanup
;---------------------------------------------------------------------------------------------
; get C-parameter (float), convert to FAC
___float_float_to_fac:
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
sta FAC_MANTISSA1 ; 3
stx FAC_MANTISSA0 ; 2
ldy sreg ; 1
sty FAC_EXPONENT
ldy sreg+1 ; 0
sty FAC_SIGN
ldx #$00
stx FAC_MANTISSA2
stx FAC_MANTISSA3
stx FAC_ROUNDING
.endif
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
sta FAC_MANTISSA2 ; 3
stx FAC_MANTISSA1 ; 2
lda sreg ; 1
ora #$80
sta FAC_MANTISSA0
; bit7=0 sign=0
; bit7=1 sign=$ff
ldx #0
lda sreg
bpl @pos
dex
@pos:
stx FAC_SIGN
ldy sreg+1 ; 0
sty FAC_EXPONENT
ldx #$00
stx FAC_MANTISSA3
stx FAC_ROUNDING
.endif
.if BINARYFORMAT = BINARYFORMAT_IEEE754
; ieee float is in A/X/sreg/sreg+1
sta FAC_MANTISSA2
stx FAC_MANTISSA1
; shift msb from mantissa into exponent
asl sreg ; mantissa msb
rol sreg+1 ; exp
; sign is in carry
lda #$ff
bcs @l
lda #0
@l:
sta FAC_SIGN
lda sreg ; mantissa msb
lsr
ora #$80 ; msb of mantissa is always 1
sta FAC_MANTISSA0
lda sreg+1 ; exp
clc
adc #2
sta FAC_EXPONENT
ldx #$00
stx FAC_MANTISSA3
stx FAC_ROUNDING
.endif
rts
; load BASIC float into FAC
; in: pointer (a/x) to BASIC float (not packed)
__float_float_to_fac: ; only used in ATAN2?
sta ptr1
stx ptr1+1
ldy #$00
lda (ptr1),y
sta FAC_EXPONENT
iny
lda (ptr1),y
sta FAC_MANTISSA0
iny
lda (ptr1),y
sta FAC_MANTISSA1
iny
lda (ptr1),y
sta FAC_MANTISSA2
iny
lda (ptr1),y
sta FAC_MANTISSA3
iny
lda (ptr1),y
sta FAC_SIGN
ldx #$00
stx FAC_ROUNDING
; always load arg after fac so these can
; be removed in funcs that only take fac
eor ARG_SIGN
sta FAC_SIGN_COMPARE
rts
.import ldeaxysp
; get C-parameter (two floats), to FAC and ARG
___float_float_to_fac_arg:
jsr ___float_float_to_fac
___float_float_to_arg:
ldy #$03
jsr ldeaxysp
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
sta ARG_MANTISSA1 ; 3
stx ARG_MANTISSA0 ; 2
ldy sreg ; 1
sty ARG_EXPONENT
ldx #$00
stx ARG_MANTISSA2
stx ARG_MANTISSA3
lda sreg+1 ; 0
sta ARG_SIGN
eor FAC_SIGN
sta FAC_SIGN_COMPARE ; sign compare
.endif
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
sta ARG_MANTISSA2 ; 3
stx ARG_MANTISSA1 ; 2
lda sreg ; 1
ora #$80
sta ARG_MANTISSA0
; bit7=0 sign=0
; bit7=1 sign=$ff
ldx #0
lda sreg ; 1
bpl @pos
dex
@pos:
stx ARG_SIGN
ldy sreg+1 ; 0
sty ARG_EXPONENT
ldx #$00
stx ARG_MANTISSA3
lda ARG_SIGN
eor FAC_SIGN
sta FAC_SIGN_COMPARE ; sign compare
.endif
.if BINARYFORMAT = BINARYFORMAT_IEEE754
.import incsp4
; ieee float in a/x/sreg/sreg+1
sta ARG_MANTISSA2
stx ARG_MANTISSA1
asl sreg ; mantissa msb
rol sreg+1 ; exp
; sign is in carry
lda #$ff
bcs @l
lda #0
@l:
sta ARG_SIGN
lda sreg ; mantissa msb
lsr
ora #$80 ; the first bit in the mantissa should always be 1
sta ARG_MANTISSA0
lda sreg+1 ; exp
clc
adc #2
sta ARG_EXPONENT
ldx #$00
stx ARG_MANTISSA3
lda ARG_SIGN
eor FAC_SIGN
sta FAC_SIGN_COMPARE ; sign compare
.endif
jmp incsp4
; load BASIC float into ARG
; in: pointer (a/x) to BASIC float (not packed)
__float_float_to_arg: ; only used in ATAN2?
sta ptr1
stx ptr1+1
ldy #$00
lda (ptr1),y
sta ARG_EXPONENT
iny
lda (ptr1),y
sta ARG_MANTISSA0
iny
lda (ptr1),y
sta ARG_MANTISSA1
iny
lda (ptr1),y
sta ARG_MANTISSA2
iny
lda (ptr1),y
sta ARG_MANTISSA3
iny
lda (ptr1),y
sta ARG_SIGN
; sign compare
eor FAC_SIGN
sta FAC_SIGN_COMPARE
rts
; return to C, float as unsigned long
___float_fac_to_float:
.if BINARYFORMAT = BINARYFORMAT_CBM_UNPACKED
lda FAC_SIGN
sta sreg+1 ; 0
lda FAC_EXPONENT
sta sreg ; 1
ldx FAC_MANTISSA0 ; 2
lda FAC_MANTISSA1 ; 3
.endif
.if BINARYFORMAT = BINARYFORMAT_CBM_PACKED
lda FAC_EXPONENT
sta sreg+1 ; 0
; use the MSB of the mantissa for the sign
lda FAC_SIGN ; either $ff or $00
ora #$7f ; -> $ff or $7f
and FAC_MANTISSA0 ; bit7 of mantissa is always 1
sta sreg ; 1
ldx FAC_MANTISSA1 ; 2
lda FAC_MANTISSA2 ; 3
.endif
.if BINARYFORMAT = BINARYFORMAT_IEEE754
; return float in a/x/sreg/sreg+1
lda FAC_EXPONENT
sec
sbc #2
sta sreg+1 ; 0
lda FAC_MANTISSA0
asl
sta sreg ; 1
lda FAC_SIGN ; either $ff or $00
asl
ror sreg+1 ; exp
ror sreg ; mantissa msb
ldx FAC_MANTISSA1 ; 2
lda FAC_MANTISSA2 ; 3 lsb
.endif
rts
;; store float in memory
;; in: dest. pointer (a/x), float in FAC
;__float_fac_to_float: ; UNUSED
; sta ptr1
; stx ptr1+1
; ldy #$00
; lda FAC_EXPONENT
; sta (ptr1),y
; iny
; lda FAC_MANTISSA0
; sta (ptr1),y
; iny
; lda FAC_MANTISSA1
; sta (ptr1),y
; iny
; lda FAC_MANTISSA2
; sta (ptr1),y
; iny
; lda FAC_MANTISSA3
; sta (ptr1),y
; iny
; lda FAC_SIGN
; sta (ptr1),y
; rts
;; store packed float in memory
;; in: dest. pointer (a/x), float in FAC
;__float_fac_to_float_packed: ; UNUSED
; sta ptr1
; stx ptr1+1
; ldy #4
; lda FAC_MANTISSA3
; sta (ptr1),y
; dey
; lda FAC_MANTISSA2
; sta (ptr1),y
; dey
; lda FAC_MANTISSA1
; sta (ptr1),y
; dey
;; use the MSB of the mantissa for the sign
; lda FAC_SIGN
; ora #$7f
; and FAC_MANTISSA0
; sta (ptr1),y
; dey
; lda FAC_EXPONENT
; sta (ptr1),y
; rts
;; store packed float in memory
;; in: dest. pointer (a/x), float in ARG
__float_arg_to_float_packed:
sta ptr1
stx ptr1+1
ldy #4
lda ARG_MANTISSA3
sta (ptr1),y
dey
lda ARG_MANTISSA2
sta (ptr1),y
dey
lda ARG_MANTISSA1
sta (ptr1),y
dey
; use the MSB of the mantissa for the sign
lda ARG_SIGN
ora #$7f
and ARG_MANTISSA0
sta (ptr1),y
dey
lda ARG_EXPONENT
sta (ptr1),y
rts
;---------------------------------------------------------------------------------------------
.if 1 = 1
.export __ftostr
.importzp ptr1
.import popax, ldeaxysp, incsp4
; convert float to string
; char* __fastcall__ _ftostr(char *d, float s);
;-> char* __fastcall__ _ftostr(char *d, unsigned long s);
__ftostr:
jsr ___float_float_to_fac
jsr __float_fac_to_str
___float_strbuf_to_string:
jsr popax ; ptr to string
__float_strbuf_to_string:
sta ptr1
stx ptr1+1
ldy #$00
ldx #$00
; if next char is a minus, copy it
lda $0100,x
cmp #'-'
bne @s0
sta (ptr1),y
iny
inx
@s0:
; if next char is a space, skip it
lda $0100,x
cmp #' '
bne @s1
inx
@s1:
; if next char is a dot, copy a '0' to buffer
lda $0100,x
cmp #'.'
bne @s2
lda #'0'
sta (ptr1),y
iny
@s2:
; FIXME: we should handle the scientific notation somehow
; FIXME: we should handle very small numbers somehow (display 0)
@l:
lda $0100,x
sta (ptr1),y
beq @s
inx
iny
bne @l
@s:
lda ptr1
ldx ptr1+1
rts
.endif
.export __strtof
; convert a string to a float
; float __fastcall__ _strtof(char *d);
;-> unsigned long __fastcall__ _strtof(char *d);
__strtof:
jsr ___float_str_to_fac
jmp ___float_fac_to_float
.export __ctof
; convert char to float
; float __fastcall__ _ctof(char v);
;-> unsigned long __fastcall__ _ctof(char v);
__ctof:
jsr ___float_s8_to_fac
jmp ___float_fac_to_float
.export __utof
; convert unsigned char to float
; float __fastcall__ _utof(unsigned char v);
;-> unsigned long __fastcall__ _utof(unsigned char v);
__utof:
jsr ___float_u8_to_fac
jmp ___float_fac_to_float
.export __stof
; convert short to float
; float __fastcall__ _stof(unsigned short v);
;-> unsigned long __fastcall__ _stof(unsigned short v);
__stof:
jsr ___float_u16_to_fac
jmp ___float_fac_to_float
.export __itof
; convert integer to float
; float __fastcall__ _itof(int v);
;-> unsigned long __fastcall__ _itof(int v);
__itof:
;a: low x: high
jsr ___float_s16_to_fac
jmp ___float_fac_to_float
.export __ftoi
; convert float to integer
; int __fastcall__ _ftoi(float f);
;-> int __fastcall__ _ftoi(unsigned long f);
__ftoi:
jsr ___float_float_to_fac
jmp __float_fac_to_u16
;---------------------------------------------------------------------------------------------
; these functions take one arg (in FAC) and return result (in FAC) aswell
;---------------------------------------------------------------------------------------------
.macro __ffunc1 addr
jsr ___float_float_to_fac
__enable_basic_if_needed
jsr addr
__disable_basic_if_needed
jmp ___float_fac_to_float
.endmacro
.export __fabs, __fatn, __fcos, __fexp, __fint, __flog
.export __frnd, __fsgn, __fsin, __fsqr, __ftan, __fnot, __fround
__fabs: __ffunc1 BASIC_FAC_Abs
__fatn: __ffunc1 BASIC_FAC_Atn
__fcos: __ffunc1 BASIC_FAC_Cos
__fexp: __ffunc1 BASIC_FAC_Exp
;__ffre: __ffunc1 BASIC_FAC_Fre
__fint: __ffunc1 BASIC_FAC_Int ; truncate fractions
__flog: __ffunc1 BASIC_FAC_Log
;__fpos: __ffunc1 BASIC_FAC_Pos
__frnd: __ffunc1 BASIC_FAC_Rnd ; random numbers
__fsgn: __ffunc1 BASIC_FAC_Sgn ;"signum" returns 1 if positive, 0 if 0, -1 if negative
__fsin: __ffunc1 BASIC_FAC_Sin
__fsqr: __ffunc1 BASIC_FAC_Sqr
__ftan: __ffunc1 BASIC_FAC_Tan
__fnot: __ffunc1 BASIC_FAC_Not
__fround: __ffunc1 BASIC_FAC_Round ; rounding
;---------------------------------------------------------------------------------------------
; these functions take two args (in FAC and ARG) and return result (in FAC)
;---------------------------------------------------------------------------------------------
__float_ret2:
;jsr __basicoff
.if .defined(__C64__)
ldx #$36
stx $01
cli
.endif
jmp ___float_fac_to_float ; also pops pointer to float
.macro __ffunc2a addr
jsr ___float_float_to_fac_arg
__enable_basic_if_needed
lda FAC_EXPONENT
jsr addr
jmp __float_ret2
.endmacro
.macro __ffunc2b addr
jsr ___float_float_to_fac_arg
__enable_basic_if_needed
jsr addr
jmp __float_ret2
.endmacro
.macro __ffunc2c addr
jsr ___float_float_to_fac_arg
jsr __float_swap_fac_arg
__enable_basic_if_needed
lda FAC_EXPONENT
jsr addr
jmp __float_ret2
.endmacro
.export __fadd, __fsub, __fmul, __fdiv, __fpow
; float __fastcall__ _fadd(float f, float a);
;-> unsigned long __fastcall__ _fadd(unsigned long f, unsigned long a);
__fadd: __ffunc2a BASIC_ARG_FAC_Add
__fsub: __ffunc2a BASIC_ARG_FAC_Sub
__fmul: __ffunc2a BASIC_ARG_FAC_Mul
__fdiv: __ffunc2a BASIC_ARG_FAC_Div
__fpow: __ffunc2a BASIC_ARG_FAC_Pow
.export __fand, __for
__fand: __ffunc2b BASIC_ARG_FAC_And
__for: __ffunc2b BASIC_ARG_FAC_Or
.export __frsub
__frsub: __ffunc2c BASIC_ARG_FAC_Sub
__float_ret3:
;jsr __basicoff
.if .defined(__C64__)
ldx #$36
stx $01
cli
.endif
ldx #0
rts
.bss
tempfloat:
.res 5
.SEGMENT "LOWCODE"
.export __fcmp
__fcmp:
jsr ___float_float_to_fac_arg
lda #<tempfloat
ldx #>tempfloat
jsr __float_arg_to_float_packed
lda #<tempfloat
ldy #>tempfloat
___float_cmp_fac_arg:
__enable_basic_if_needed
; in: FAC=(x1) a/y= ptr lo/hi to x2
jsr BASIC_FAC_cmp
; a=0 (==) / a=1 (>) / a=255 (<)
jmp __float_ret3
.export __ftestsgn
__ftestsgn:
jsr ___float_float_to_fac
;___float_testsgn_fac:
__enable_basic_if_needed
; in: FAC(x1)
jsr BASIC_FAC_testsgn
jmp __float_ret3
___float_testsgn_fac:
lda FAC_EXPONENT
beq @s
lda FAC_SIGN
rol a
lda #$ff
bcs @s
lda #$01
@s:
rts
___float_testsgn_arg:
lda ARG_EXPONENT
beq @s
lda ARG_SIGN
rol a
lda #$ff
bcs @s
lda #$01
@s:
rts
;---------------------------------------------------------------------------------------------
; polynom1 f(x)=a1+a2*x^2+a3*x^3+...+an*x^n
;---------------------------------------------------------------------------------------------
.export __fpoly1
.import popax
__fpoly1:
jsr ___float_float_to_fac
;jsr popya
jsr popax
tay
txa
__enable_basic_if_needed
jsr BASIC_FAC_Poly1
jmp __float_ret2
;---------------------------------------------------------------------------------------------
; polynom2 f(x)=a1+a2*x^3+a3*x^5+...+an*x^(2n-1)
;---------------------------------------------------------------------------------------------
.export __fpoly2
.import popax
__fpoly2:
jsr ___float_float_to_fac
;jsr popya
jsr popax
tay
txa
__enable_basic_if_needed
jsr BASIC_FAC_Poly1
jmp __float_ret2
;---------------------------------------------------------------------------------------------
__float_atn_fac:
__enable_basic_if_needed
jsr BASIC_FAC_Atn
__return_with_cleanup
__float_div_fac_arg:
__enable_basic_if_needed
lda FAC_EXPONENT
jsr BASIC_ARG_FAC_Div
__return_with_cleanup
__float_add_fac_arg:
__enable_basic_if_needed
lda FAC_EXPONENT
jsr BASIC_ARG_FAC_Add
__return_with_cleanup
__float_swap_fac_arg: ; only used in ATAN2
lda FAC_EXPONENT
ldx ARG_EXPONENT
stx FAC_EXPONENT
sta ARG_EXPONENT
lda FAC_MANTISSA0
ldx ARG_MANTISSA0
stx FAC_MANTISSA0
sta ARG_MANTISSA0
lda FAC_MANTISSA1
ldx ARG_MANTISSA1
stx FAC_MANTISSA1
sta ARG_MANTISSA1
lda FAC_MANTISSA2
ldx ARG_MANTISSA2
stx FAC_MANTISSA2
sta ARG_MANTISSA2
lda FAC_MANTISSA3
ldx ARG_MANTISSA3
stx FAC_MANTISSA3
sta ARG_MANTISSA3
lda FAC_SIGN
ldx ARG_SIGN
stx FAC_SIGN
sta ARG_SIGN
rts
.export __fneg
__fneg:
jsr ___float_float_to_fac
lda FAC_EXPONENT
beq @sk
lda FAC_SIGN
eor #$FF
sta FAC_SIGN
@sk:
jmp ___float_fac_to_float
__f_pi2: .byte $81,$80+$49,$0f,$da,$a1,$00
__f_pi: .byte $82,$80+$49,$0f,$da,$a1,$00
__f_1pi2: .byte $83,$80+$16,$cb,$e3,$f9,$00
.export __fatan2
; float _fatan2(float x, float y)
;-> unsigned long _fatan2(unsigned long x, unsigned long y)
__fatan2:
jsr ___float_float_to_fac_arg
jsr ___float_testsgn_arg
beq @s11 ; =0
bpl @s12 ; <0
; arg>0
; a=atn(y/x)
jsr __float_swap_fac_arg
jsr __float_div_fac_arg
jsr __float_atn_fac
jmp __float_ret2
@s12: ; arg<0
; a=atn(y/x)+pi
jsr __float_swap_fac_arg
jsr __float_div_fac_arg
jsr __float_atn_fac
lda #<__f_pi
ldx #>__f_pi
jsr __float_float_to_arg
jsr __float_add_fac_arg
jmp __float_ret2
@s11: ; arg=0
jsr ___float_testsgn_fac
beq @s21 ; =0
bpl @s22 ; <0
; fac >0
; a= 0.5*pi
lda #<__f_pi2
ldx #>__f_pi2
jsr __float_float_to_fac
jmp __float_ret2
; fac =0
@s21:
; a= 0
lda #$00
sta FAC_MANTISSA0
jmp __float_ret2
; fac <0
@s22:
; a= 1.5*pi
lda #<__f_1pi2
ldx #>__f_1pi2
jsr __float_float_to_fac
jmp __float_ret2

View File

@ -0,0 +1,97 @@
#include <stdlib.h>
#include <stdio.h>
char buffer[32];
char * __fastcall__ _ftostr(char *d, float s)
{
float f;
unsigned char *p;
char *bp, *buf;
int exp;
unsigned long mantissa;
unsigned long val;
int sign;
unsigned char n;
static char digits[10]={0,1,2,3,4,5,6,7,8,9};
unsigned long mantissa_mod = 1000000000;
unsigned long mantissa_rest;
if (d == NULL) {
buf = bp = &buffer[0];
} else {
buf = bp = d;
}
f = s;
p = (unsigned char*)&f;
// printf("%02x %02x %02x %02x\n", p[3], p[2], p[1], p[0]);
sign = (p[3] & 0x80) ? 1 : 0;
exp = ((p[3] << 1) & 0xfe) | ((p[2] >> 7) & 1);
exp -= 127;
mantissa = p[2] & 0x7f;
mantissa <<=8;
mantissa |= p[1];
mantissa <<=8;
mantissa |= p[0];
*bp++ = sign ? '-' : ' ';
*bp++ = '1';
*bp++ = '.';
val = 0xff;
// printf("mantissa: %ld\n", mantissa);
mantissa_rest = mantissa;
for (n = 0; n < 10; n++) {
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
val = mantissa_rest / mantissa_mod;
// printf("n:%2d val:%ld\n", n, val);
// *bp++ = digits[(int)val];
*bp++ = '0' + val;
mantissa_rest -= (val * mantissa_mod);
}
mantissa_mod /= 10;
}
if (val == 0xff) {
*bp++ = '0';
}
// *bp++ = 'e';
// *bp++ = 0;
*bp++ = '*';
*bp++ = '2';
*bp++ = '^';
// printf("exp: %ld\n", exp);
mantissa_mod = 1000;
if (exp < 0) {
mantissa_rest = -1 * exp;
*bp++ = '-';
} else {
mantissa_rest = exp;
}
val = 0xff;
for (n = 0; n < 10; n++) {
// printf("n:%2d rest:%ld mod:%ld\n", n, mantissa_rest, mantissa_mod);
if ((mantissa_mod <= mantissa_rest) && (mantissa_rest > 0)) {
val = mantissa_rest / mantissa_mod;
// printf("n:%2d val:%ld\n", n, val);
// *bp++ = digits[(int)val];
*bp++ = '0' + val;
mantissa_rest -= (val * mantissa_mod);
}
mantissa_mod /= 10;
}
if (val == 0xff) {
*bp++ = '0';
}
*bp++ = 0;
return buf;
}

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export afloat
afloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export aufloat
aufloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export axfloat
axfloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export axufloat
axufloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export eaxfloat
eaxfloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export eaxufloat
eaxufloat:
; FIXME
rts

View File

@ -0,0 +1,7 @@
.include "ieee754.inc"
.export fbnegeax
fbnegeax:
; FIXME
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
; float -> 16bit int
.export feaxint
feaxint:
; FIXME
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
; float -> 32bit long
.export feaxlong
feaxlong:
; FIXME
rts

View File

@ -0,0 +1,637 @@
.include "ieee754.inc"
.importzp sp, sreg, tmp1
.import addysp1
.import addysp
.import popax
; Primary = TOS + Primary (like tosaddeax)
.export ftosaddeax
;ftosaddeax:
; FIXME
; rts
; CC65 runtime: long add
; ; EAX = TOS + EAX
;
; ;tosadd0ax:
; ldy #$00
; sty sreg
; sty sreg+1
;
; ;tosaddeax:
; clc
; ldy #0
; adc (sp),y ; lo byte
; iny
;
; sta tmp1 ; use as temp storage
; txa
; adc (sp),y ; byte 1
; tax
; iny
;
; lda sreg
; adc (sp),y ; byte 2
; sta sreg
; iny
;
; lda sreg+1
; adc (sp),y ; byte 3
; sta sreg+1
; lda tmp1 ; load byte 0
; jmp addysp1 ; drop TOS
; found at https://github.com/CrashAndSideburns/6502ieee754/blob/main/arithmetic/addition.s
;addition:
ftosaddeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
lda #0
sta SIGN_ONE
sta SIGN_TWO
; Pull 2 LSBs of second parameter off of stack.
pha
lda sreg+1
ASL
STA MANTISSA_TWO + 3
lda sreg+0
ROL
STA MANTISSA_TWO + 2
; Pull MSB of mantissa off of stack and shift exponent LSB into carry.
tax
ROL
STA MANTISSA_TWO + 1
; Pull MSB off of stack, shift in exponent LSB, store sign.
PLA
ROL
STA EXPONENT_TWO
ROL SIGN_TWO
;-----------------
; Pull 2 LSBs of first parameter off of stack.
ldy #0
lda (sp),y ; lsb
ASL
STA MANTISSA_ONE + 3
iny
lda (sp),y
ROL
STA MANTISSA_ONE + 2
; Pull MSB of mantissa off of stack and shift exponent LSB into carry.
iny
lda (sp),y
ROL
STA MANTISSA_ONE + 1
; Pull MSB off of stack, shift in exponent LSB, store sign.
iny
lda (sp),y ; msb
ROL
STA EXPONENT_ONE
ROL SIGN_ONE
; Add implicit 1 to mantissas if appropriate.
@add_second_implicit_bit:
LDA EXPONENT_TWO
CMP #$00
BEQ @add_first_implicit_bit
SEC
ROR MANTISSA_TWO + 1
ROR MANTISSA_TWO + 2
ROR MANTISSA_TWO + 3
@add_first_implicit_bit:
LDA EXPONENT_ONE
CMP #$00
BEQ @manage_special_values
SEC
ROR MANTISSA_ONE + 1
ROR MANTISSA_ONE + 2
ROR MANTISSA_ONE + 3
@manage_special_values:
; Check if first parameter has exponent #$ff.
; If it does, first parameter is some special quantity.
; If not, check if second parameter has epxonent #$ff.
; If it does, then it is special and the first parameter is not, so propagate.
; If neither parameter is special, move on to aligning mantissas.
LDA EXPONENT_ONE
CMP #$ff
BEQ @first_parameter_special
LDA EXPONENT_TWO
CMP #$ff
BEQ @propagate_second_parameter
JMP @align_mantissas
@first_parameter_special:
; Exponent is non-zero, so an implicit 1 has been added to mantissa.
; Unless the mantissa with added implicit 1 is $800000, return first param.
; If the mantissa is precisely $800000, first param is ±∞.
LDA MANTISSA_ONE + 1
CMP #$80
BNE @propagate_first_parameter
LDA MANTISSA_ONE + 2
CMP #$00
BNE @propagate_first_parameter
LDA MANTISSA_ONE + 3
CMP #$00
BEQ @first_parameter_infinite
@propagate_first_parameter:
; Shift out implicit bit, shift exponent and sign through.
; Push return value onto stack.
; Push return address onto stack.
; Return from subroutine.
ASL MANTISSA_ONE + 1
LSR SIGN_ONE
ROR EXPONENT_ONE
ROR MANTISSA_ONE + 1
; LDA EXPONENT_ONE
; PHA
; LDA MANTISSA_ONE + 1
; PHA
; LDA MANTISSA_ONE + 2
; PHA
; LDA MANTISSA_ONE + 3
; PHA
; LDA $01
; PHA
; LDA $00
; PHA
LDA EXPONENT_ONE
sta sreg+1
LDA MANTISSA_ONE + 1
sta sreg+0
LDX MANTISSA_ONE + 2
LDA MANTISSA_ONE + 3
; ldx #$43
; lda #$21
jmp addysp1 ; drop TOS
RTS
@first_parameter_infinite:
; Check if second parameter is also ±∞.
; If second param is not special, propagate infinity.
; If second param is NaN, propagate NaN.
LDA EXPONENT_TWO
CMP #$ff
BNE @propagate_first_parameter
LDA MANTISSA_TWO + 1
CMP #$80
BNE @propagate_second_parameter
LDA MANTISSA_TWO + 2
CMP #$00
BNE @propagate_second_parameter
LDA MANTISSA_TWO + 3
CMP #$00
BNE @propagate_second_parameter
@adding_infinities:
; First and second parameters are both ±∞.
; Check if they have opposite sign.
; (+∞)+(-∞) = (-∞)+(+∞) = NaN.
; If they have opposite sign, return a NaN.
; Otherwise, return the first parameter.
LDA SIGN_ONE
EOR SIGN_TWO
BEQ @propagate_first_parameter
; LDA #$ff
; PHA
; PHA
; PHA
; PHA
LDA #$ff
sta sreg+1
sta sreg
tax
jmp addysp1 ; drop TOS
; LDA $01
; PHA
; LDA $00
; PHA
RTS
@propagate_second_parameter:
; Shift out implicit bit, shift exponent and sign through.
; Push return value onto stack.
; Push return address onto stack.
; Return from subroutine.
ASL MANTISSA_TWO + 1
LSR SIGN_TWO
ROR EXPONENT_TWO
ROR MANTISSA_TWO + 1
; LDA EXPONENT_TWO
; PHA
; LDA MANTISSA_TWO + 1
; PHA
; LDA MANTISSA_TWO + 2
; PHA
; LDA MANTISSA_TWO + 3
; PHA
; LDA $01
; PHA
; LDA $00
; PHA
LDA EXPONENT_TWO
sta sreg+1
LDA MANTISSA_TWO + 1
sta sreg
LDX MANTISSA_TWO + 2
LDA MANTISSA_TWO + 3
jmp addysp1 ; drop TOS
RTS
@align_mantissas:
; Check if the mantissas differ by 25 or more.
; If they do, propagate the parameter with the larger mantissa.
; If they don't, shift the mantissa of the smaller parameter right.
SEC
LDA EXPONENT_TWO
SBC EXPONENT_ONE
BCC @first_difference_underflow
CMP #25
BCS @propagate_second_parameter
@first_difference_underflow:
SEC
LDA EXPONENT_ONE
SBC EXPONENT_TWO
BCC @second_difference_underflow
CMP #25
BCS @propagate_first_parameter
@second_difference_underflow:
CMP #$00
BEQ @apply_signs
TAX
BPL @shift_second_mantissa
@shift_first_mantissa:
LSR MANTISSA_ONE + 1
ROR MANTISSA_ONE + 2
ROR MANTISSA_ONE + 3
ROR MANTISSA_ONE + 4
ROR MANTISSA_ONE + 5
ROR MANTISSA_ONE + 6
INX
CPX #$00
BNE @shift_first_mantissa
LDA EXPONENT_TWO
STA EXPONENT_ONE
JMP @apply_signs
@shift_second_mantissa:
LSR MANTISSA_TWO + 1
ROR MANTISSA_TWO + 2
ROR MANTISSA_TWO + 3
ROR MANTISSA_TWO + 4
ROR MANTISSA_TWO + 5
ROR MANTISSA_TWO + 6
DEX
CPX #$00
BNE @shift_second_mantissa
@apply_signs:
; Check the signs of both floats.
; If a float has a 1 sign bit, take the 2's complement of the mantissa.
@negate_first_mantissa:
LDA SIGN_ONE
CMP #$00
BEQ @negate_second_mantissa
LDA MANTISSA_ONE
EOR #$ff
STA MANTISSA_ONE
LDA MANTISSA_ONE + 1
EOR #$ff
STA MANTISSA_ONE + 1
LDA MANTISSA_ONE + 2
EOR #$ff
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 3
EOR #$ff
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 4
EOR #$ff
STA MANTISSA_ONE + 4
LDA MANTISSA_ONE + 5
EOR #$ff
STA MANTISSA_ONE + 5
LDA MANTISSA_ONE + 6
EOR #$ff
CLC
ADC #$01
STA MANTISSA_ONE + 6
LDA MANTISSA_ONE + 5
ADC #$00
STA MANTISSA_ONE + 5
LDA MANTISSA_ONE + 4
ADC #$00
STA MANTISSA_ONE + 4
LDA MANTISSA_ONE + 3
ADC #$00
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 2
ADC #$00
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 1
ADC #$00
STA MANTISSA_ONE + 1
LDA MANTISSA_ONE
ADC #$00
STA MANTISSA_ONE
@negate_second_mantissa:
LDA SIGN_TWO
CMP #$00
BEQ @sum_mantissas
LDA MANTISSA_TWO
EOR #$ff
STA MANTISSA_TWO
LDA MANTISSA_TWO + 1
EOR #$ff
STA MANTISSA_TWO + 1
LDA MANTISSA_TWO + 2
EOR #$ff
STA MANTISSA_TWO + 2
LDA MANTISSA_TWO + 3
EOR #$ff
STA MANTISSA_TWO + 3
LDA MANTISSA_TWO + 4
EOR #$ff
STA MANTISSA_TWO + 4
LDA MANTISSA_TWO + 5
EOR #$ff
STA MANTISSA_TWO + 5
LDA MANTISSA_TWO + 6
EOR #$ff
CLC
ADC #$01
STA MANTISSA_TWO + 6
LDA MANTISSA_TWO + 5
ADC #$00
STA MANTISSA_TWO + 5
LDA MANTISSA_TWO + 4
ADC #$00
STA MANTISSA_TWO + 4
LDA MANTISSA_TWO + 3
ADC #$00
STA MANTISSA_TWO + 3
LDA MANTISSA_TWO + 2
ADC #$00
STA MANTISSA_TWO + 2
LDA MANTISSA_TWO + 1
ADC #$00
STA MANTISSA_TWO + 1
LDA MANTISSA_TWO
ADC #$00
STA MANTISSA_TWO
@sum_mantissas:
; Sum the mantissas to obtain the mantissa of the return float.
; Check if the resultant mantissa has a 1 MSB.
; If it does, set the result sign to 1 and take the 2's complement of the mantissa.
; If it doesn't, move on to normalising the resultant mantissa.
CLC
LDA MANTISSA_ONE + 6
ADC MANTISSA_TWO + 6
STA MANTISSA_ONE + 6
LDA MANTISSA_ONE + 5
ADC MANTISSA_TWO + 5
STA MANTISSA_ONE + 5
LDA MANTISSA_ONE + 4
ADC MANTISSA_TWO + 4
STA MANTISSA_ONE + 4
LDA MANTISSA_ONE + 3
ADC MANTISSA_TWO + 3
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 2
ADC MANTISSA_TWO + 2
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 1
ADC MANTISSA_TWO + 1
STA MANTISSA_ONE + 1
LDA MANTISSA_ONE
ADC MANTISSA_TWO
STA MANTISSA_ONE
AND #$80
CMP #$00
BEQ @positive_sum
LDA MANTISSA_ONE
EOR #$ff
STA MANTISSA_ONE
LDA MANTISSA_ONE + 1
EOR #$ff
STA MANTISSA_ONE + 1
LDA MANTISSA_ONE + 2
EOR #$ff
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 3
EOR #$ff
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 4
EOR #$ff
STA MANTISSA_ONE + 4
LDA MANTISSA_ONE + 5
EOR #$ff
STA MANTISSA_ONE + 5
LDA MANTISSA_ONE + 6
EOR #$ff
CLC
ADC #$01
STA MANTISSA_ONE + 6
LDA MANTISSA_ONE + 5
ADC #$00
STA MANTISSA_ONE + 5
LDA MANTISSA_ONE + 4
ADC #$00
STA MANTISSA_ONE + 4
LDA MANTISSA_ONE + 3
ADC #$00
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 2
ADC #$00
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 1
ADC #$00
STA MANTISSA_ONE + 1
LDA MANTISSA_ONE
ADC #$00
STA MANTISSA_ONE
LDA #$01
STA SIGN_ONE
JMP @normalise_mantissa
@positive_sum:
LDA #$00
STA SIGN_ONE
@normalise_mantissa:
; Now that the new mantissa has been computed, normalise it.
; Check if the LSB of the byte before the MSB of the mantissa is 1.
; If it is, shift the mantissa down and increment the mantissa.
; If it isn't, move on to checking if we must shift left.
LDA MANTISSA_ONE
AND #$01
CMP #$01
BNE @no_overflow
LSR MANTISSA_ONE
ROR MANTISSA_ONE + 1
ROR MANTISSA_ONE + 2
ROR MANTISSA_ONE + 3
ROR MANTISSA_ONE + 4
ROR MANTISSA_ONE + 5
ROR MANTISSA_ONE + 6
INC EXPONENT_ONE
JMP @round
@no_overflow:
; Check if the MSB of the mantissa is 1.
; If it is, move on to rounding.
; If it isn't, shift mantissa left and decrement exponent until MSB is 1 or exponent is 0.
LDA MANTISSA_ONE + 1
AND #$80
CMP #$80
BEQ @round
LDA EXPONENT_ONE
CMP #$00
BEQ @round
ASL MANTISSA_ONE + 6
ROL MANTISSA_ONE + 5
ROL MANTISSA_ONE + 4
ROL MANTISSA_ONE + 3
ROL MANTISSA_ONE + 2
ROL MANTISSA_ONE + 1
ROL MANTISSA_ONE
DEC EXPONENT_ONE
JMP @no_overflow
@round:
; Check if we have already produced ±∞ in the event that we decide not to round.
; If we have, return ±∞.
; If we haven't, check if the MSB of the byte after the mantissa is 0.
; If it is, return, trucating the subsequent bits.
; If it isn't, check if any subsequent bits are 1.
; If any are, round up.
; If none are, check if the LSB of the mantissa is 1.
; If it is, round up.
; If it isn't, return.
LDA EXPONENT_ONE
CMP #$ff
BEQ @return_infinity
LDA MANTISSA_ONE + 4
AND #$80
CMP #$00
BEQ @return
LDA MANTISSA_ONE + 4
AND #$7f
CMP #$00
BNE @round_up
LDA MANTISSA_ONE + 5
CMP #$00
BNE @round_up
LDA MANTISSA_ONE + 6
CMP #$00
BNE @round_up
LDA MANTISSA_ONE + 3
AND #$01
CMP #$00
BEQ @return
@round_up:
; Increment the mantissa by 1.
; If the increment doesn't overflow, return.
; If it does, shift the mantissa right and increment the exponent.
; Check if incrementing the exponent left us with an exponent of #$ff.
; If it did, return ±∞.
; If it didn't, round again.
CLC
LDA MANTISSA_ONE + 3
ADC #$01
STA MANTISSA_ONE + 3
LDA MANTISSA_ONE + 2
ADC #$00
STA MANTISSA_ONE + 2
LDA MANTISSA_ONE + 1
ADC #$00
STA MANTISSA_ONE + 1
BCC @return
ROL MANTISSA_ONE + 1
ROL MANTISSA_ONE + 2
ROL MANTISSA_ONE + 3
ROL MANTISSA_ONE + 4
ROL MANTISSA_ONE + 5
ROL MANTISSA_ONE + 6
INC EXPONENT_ONE
LDA EXPONENT_ONE
CMP #$ff
BEQ @return_infinity
JMP @round
@return_infinity:
; If we have to return ±∞ due to an over/underflow, clear the mantissa.
LDA #$00
STA MANTISSA_ONE + 1
STA MANTISSA_ONE + 2
STA MANTISSA_ONE + 3
@return:
; Shift out implicit bit, shift exponent and sign through.
; Push return value onto stack.
; Push return address onto stack.
; Return from subroutine.
LDA EXPONENT_ONE
CMP #$00
BNE @return_normal
LSR MANTISSA_ONE + 1
ROR MANTISSA_ONE + 2
ROR MANTISSA_ONE + 3
BCS @round_up
@return_normal:
ASL MANTISSA_ONE + 1
LSR SIGN_ONE
ROR EXPONENT_ONE
ROR MANTISSA_ONE + 1
; LDA EXPONENT_ONE
; PHA
; LDA MANTISSA_ONE + 1
; PHA
; LDA MANTISSA_ONE + 2
; PHA
; LDA MANTISSA_ONE + 3
; PHA
; LDA $01
; PHA
; LDA $00
; PHA
LDA EXPONENT_ONE
sta sreg+1
LDA MANTISSA_ONE + 1
sta sreg
LDX MANTISSA_ONE + 2
LDA MANTISSA_ONE + 3
jmp addysp1 ; drop TOS
RTS

View File

@ -0,0 +1,12 @@
.include "ieee754.inc"
.importzp sp, sreg, tmp1
.import addysp1
.import addysp
.import popax
.export ftosdiveax
ftosdiveax:
; FIXME
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftoseqeax
ftoseqeax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftosgeeax
ftosgeeax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftosgteax
ftosgteax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftosleeax
ftosleeax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftoslteax
ftoslteax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,12 @@
.include "ieee754.inc"
.importzp sp, sreg, tmp1
.import addysp1
.import addysp
.import popax
.export ftosmuleax
ftosmuleax:
; FIXME
rts

View File

@ -0,0 +1,8 @@
.include "ieee754.inc"
.export ftosneeax
ftosneeax:
; FIXME
lda #0
tax
rts

View File

@ -0,0 +1,43 @@
.importzp sp, sreg, tmp1
.import addysp1
.import addysp
.import popax
.include "ieee754.inc"
.import ftosaddeax
.export ftossubeax
ftossubeax:
; FIXME
rts
; found at https://github.com/CrashAndSideburns/6502ieee754/blob/main/arithmetic/addition.s
; subtraction:
; Pull MSB of second parameter off of stack, flip sign bit, and push back to stack.
; Proceed to addition.
; TSX
; TXA
; CLC
; ADC #$05
; TAX
; TXS
; PLA
; EOR #$80
; PHA
; TXA
; SEC
; SBC #$05
; TAX
; TXS
pha
ldy #3
lda (sp),y ; msb
eor #$80
sta (sp),y ; msb
pla
jmp ftosaddeax

View File

@ -0,0 +1,7 @@
SIGN_ONE = $e2
EXPONENT_ONE = $e3
MANTISSA_ONE = $e4 ; e4, e5, e6, e7, e8, e9, ea (7 bytes)
SIGN_TWO = $eb
EXPONENT_TWO = $ec
MANTISSA_TWO = $ed

324
libsrc/float/readme.md Normal file
View File

@ -0,0 +1,324 @@
## cc65 floating point support
The current main goal is to implement IEEE754 support *in the compiler*, using
the "float" datatype as the common 32bit float.
*** ANYTHING ELSE COMES LATER ***
You can not use any of this to write software yet. Don't bother. This is for
people who want to help pushing the floating point support further.
You can however try the current state of development. You should be able to
build small (and slow...) programs that use floats on any supported target.
- Build the compiler/toolchain/libs from this fptest branch.
- Now you can build and run the samples and/or tests.
```
samples/floattest.c
samples/mandelfloat.c
samples/mathtest.c
samples/tgisincos.c
```
full math.h is available for C64 when linking agains fp754kernal.o (see below)
### Further info
- Right now by default all targets will use the Berkeley Softfloat Library. This
solves the annoying "chicken and egg" problem of having to implement the float
support both in the compiler and in the target library at the same time, before
anything can be tested properly. Fortunately that also means we can use the
simulator for running test programs, and test changes in the compiler using
our test bench, and that against a library that is known to somewhat work
correctly :)
- The default library also contains a collection of math functions (which i
dubbed "softmath"), which may fill the gap until more targets have specific
wrappers and/or a generic math library (in assembly) was written.
- The default library can be overridden by linking an override file, similar to
how you can use the soft80 implementation for conio. Right now such override
files are provided for the C64 (c64-fp754kernal.o) and VIC20
(vic20-fp754kernal.o). The samples will automatically use the overrides.
### WANTED
- For the time being, i will not look at writing IEEE754 functions in assembly.
Please see below for more info on what is needed to do this, should you be
interested in doing this. Please contact me before you are putting work into
this, so we can discuss some things and prevent anyone wasting time :)
- It might be possible to produce a similar kernal- or OS- wrapper override file
as the C64 one for other targets (or port the C64 one to other CBM targets).
- If you create a new one, keep in mind that the compiler *right now* will
currently work with IEEE754 floats, which your library calls must also work
with (which will involve converting forth and back to whatever other format
at runtime), and there is no easy way tp change that.
### Roadmap
- Test/Fix using the Softfloat lib some more, fix as much tests as possible
- When all obvious tests have been created and work OK, we can merge
- for the failing tests, create "negative" cases
After the merge, the following things can be done more or less independent from
each other (not necessarily by me :)):
- implement IEEE754 library
- for generic support this will be the best compromise for standard compliance
and speed, but will take more RAM than alternatives.
- Once implemented, it will work for all targets.
- implement support for native FP routines
- Some targets have FP routines in ROM (or OS) that can be used instead of
providing our own in the library. This may or may not save RAM, and may or
may not be faster than the default library.
- The wrapper library must implement conversion from/to 32bit IEEE754
- implement support for native FP formats
- for this the wrappers in fp.c must be used in the compiler at all places.
- also we must *implement* the native format on the host in fp.c
- if the native format uses a different number of bytes than 4 for its native
format, we must add support for this in the compiler at various places
- last not least a wrapper library that uses the native format must be created
- it is not unlikely that we will need extra tests for the native format
## The Compiler
NOT WORKING YET:
/test/val/float-basic-var-var.c +=, -=
/test/val/float-basic-var-intvar.c +=, -=
/test/val/float-basic-var-intconst.c *, /, +=, -=, *=, /=
/test/val/float-basic-intvar-const.c +=, -=, *=, /=
/test/val/float-basic-intvar-var.c +=, /=
/test/val/float-basic-intconst-var.c *, /
/test/val/float-cmp-const-intvar.c
/test/val/float-cmp-intvar-const.c
/test/val/float-cmp-var-intvar.c
- float values written as "12.34f" work, but "12.34" does not - should it?
TODO:
- more tests are needed
- warnings
- errors
- register variables
- more/all tests should check local/global/register variables
### Files & Functions
#### assignment.c
src/cc65/assignment.c
```
OpAssignArithmetic Parse an "=" or "op=" operation for arithmetic lhs
OpAddSubAssign Parse a "+=" or "-=" operation
```
#### codegen.c
src/cc65/codegen.c
src/cc65/codegen.h
```
g_getimmed Load a constant into the primary register
g_getstatic Fetch an static memory cell into the primary register
g_getlocal Fetch specified local object (local var) into the primary register
g_putstatic
g_reglong
g_regfloat Make sure, the value in the primary register a float. Convert if necessary
g_typeadjust
g_typecast Cast the value in the primary register to the operand size that is flagged by the lhs value
oper Encode a binary operation.
g_push
g_push_float Push the primary register or a constant value onto the stack
g_inc
g_dec
g_defdata
g_defdata_float
(see below) g_add, g_sub, g_mul, g_div, g_neg, g_bneg
(see below) g_eq, g_ne, g_lt, g_gt, g_le, g_ge
(invalid) g_mod, g_or, g_xor, g_and, g_asr, g_asl
```
#### datatype.c
src/cc65/datatype.c
```
ArithmeticConvert Perform the usual arithmetic conversions for binary operators.
```
#### expr.c
src/cc65/expr.c
```
LimitExprValue
parseadd
parsesub
```
#### fp.c
src/common/fp.c (OK)
src/common/fp.h (OK)
wrapper for doing floating point operations on target floats
```
FP_D_As32bitRaw converts double into 32bit (float) and then returns its raw content as a 32bit int
```
#### initdata.c
src/cc65/initdata.c
```
DefineData Output a data definition for the given expression
```
#### loadexpr.c
src/cc65/loadexpr.c
```
LoadExpr Load an expression into the primary register if it is not already there.
```
#### locals.c
src/cc65/locals.c (OK?)
```
ParseAutoDecl Parse the declarator of an auto variable.
```
#### scanner.c
src/cc65/scanner.c (OK?)
```
NumericConst Parse a numeric constant
```
Note: Scanner fixes should be directly promoted to upstream. Any differences in
this branch should be related to debugging/logging.
#### typeconv.c
src/cc65/typeconv.c (OK?)
```
DoConversion Emit code to convert the given expression to a new type
```
--------------------------------------------------------------------------------
## The Library
### variants
The floating point support calls library functions for any operations on non
constant values.
#### softfloat
This is a Port of "Berkeley SoftFloat Release 2c". It is currently used by
default for all targets.
#### softmath
Contains a collection of math functions, (hopefully) enough to completely
implement math.h in C. This is currently used by default for all targets.
#### cbmkernal
This is a wrapper to the CBM kernal functions. This is fairly complete,
including math functions. To use this, link against c64-fp754kernal.o. The c64
samples will do this by default.
#### ieee754
This should become a freestanding IEEE754 library, which can completely replace
the softfloat (and softmath) library.
- basically everything missing except addition/substraction
- compare functions are missing
- mul, div functions are missing
- type conversion functions are missing
--------------------------------------------------------------------------------
### runtime functions
These must be available in the runtime library.
```
func description softfloat cbmfp 754 codegen.c
aufloat Primary 8bit unsigned -> float - * - g_regfloat
afloat Primary 8bit signed -> float - * - g_regfloat
axufloat Primary 16bit unsigned -> float * * - g_regfloat
axfloat Primary 16bit signed -> float * * - g_regfloat
eaxufloat Primary 32bit unsigned -> float * * - g_regfloat
eaxfloat Primary 32bit signed -> float * * - g_regfloat
feaxint Primary float -> 16bit int - * - g_regint
feaxlong Primary float -> 32bit long - * - g_reglong
ftosaddeax Primary = TOS + Primary * * ? g_add
ftossubeax Primary = TOS - Primary * * ? g_sub
ftosrsubeax Primary = Primary - TOS * * - g_rsub
ftosmuleax Primary = TOS * Primary * * - g_mul
ftosdiveax Primary = TOS / Primary * * - g_div
fnegeax Primary = -Primary * * - g_neg
fbnegeax Primary = !Primary (return bool!) * * - g_bneg
ftosgeeax Test for greater than or equal to * * - g_ge
ftosgteax Test for greater than * * - g_gt
ftosleeax Test for less than or equal to * * - g_le
ftoslteax Test for less than * * - g_lt
ftosneeax Test for not equal * * - g_ne
ftoseqeax Test for equal * * - g_eq
```
### math.h functions
These are optional, required for standard libm.
```
func description softmath cbmfp 754
float powf(float f, float a) * * -
float sinf(float s) * * -
float cosf(float s) * * -
float logf(float x) * * -
float expf(float x) * * -
float sqrtf(float x) * * -
float tanf(float x) * * -
float atanf(float x) * * -
float fabsf(float x) * * -
float roundf(float x) * * -
float truncf(float x) * * -
float ceilf(float x) * - -
float floorf(float x) * - -
float fmodf(float x, float y) * - -
```
### extra functions
Optional utility functions.
```
func description softfloat cbmfp 754
char *_ftostr(char *d, float s) * * ? for printf family
float _strtof(char *d) - * - for scanf family
```
--------------------------------------------------------------------------------
- https://www.geeksforgeeks.org/ieee-standard-754-floating-point-numbers/
- https://www.h-schmidt.net/FloatConverter/IEEE754.html

View File

@ -0,0 +1,70 @@
#undef DOUBLES // implement double precision floats
/*----------------------------------------------------------------------------
| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
*----------------------------------------------------------------------------*/
#define LITTLEENDIAN
/*----------------------------------------------------------------------------
| The macro `BITS64' can be defined to indicate that 64-bit integer types are
| supported by the compiler.
*----------------------------------------------------------------------------*/
#undef BITS64
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines the most convenient type that holds
| integers of at least as many bits as specified. For example, `uint8' should
| be the most convenient type that can hold unsigned integers of as many as
| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most
| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
| to the same as `int'.
*----------------------------------------------------------------------------*/
typedef unsigned char flag;
typedef unsigned char uint8;
typedef signed char int8;
typedef unsigned short uint16;
typedef signed short int16;
typedef unsigned long uint32;
typedef signed long int32;
#ifdef BITS64
typedef unsigned long long int uint64;
typedef signed long long int int64;
#endif
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines a type that holds integers
| of _exactly_ the number of bits specified. For instance, for most
| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
| `unsigned short int' and `signed short int' (or `short int'), respectively.
*----------------------------------------------------------------------------*/
typedef unsigned char bits8;
typedef signed char sbits8;
typedef unsigned short bits16;
typedef signed short sbits16;
typedef unsigned long bits32;
typedef signed long sbits32;
#ifdef BITS64
typedef unsigned long long int bits64;
typedef signed long long int sbits64;
#endif
#ifdef BITS64
/*----------------------------------------------------------------------------
| The `LIT64' macro takes as its argument a textual integer literal and
| if necessary ``marks'' the literal as having a 64-bit integer type.
| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
| appended with the letters `LL' standing for `long long', which is `gcc's
| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
| defined as the identity macro: `#define LIT64( a ) a'.
*----------------------------------------------------------------------------*/
#define LIT64( a ) a##LL
#endif
/*----------------------------------------------------------------------------
| The macro `INLINE' can be used before functions that should be inlined. If
| a compiler does not support explicit inlining, this macro should be defined
| to be `static'.
*----------------------------------------------------------------------------*/
#define INLINE static

View File

@ -0,0 +1,83 @@
Package Overview for Berkeley SoftFloat Release 2c
John R. Hauser
2015 January 30
----------------------------------------------------------------------------
Overview
Berkeley SoftFloat is a software implementation of binary floating-point
that conforms to the IEEE Standard for Floating-Point Arithmetic.
Release 2c updates an older version of SoftFloat that has for most purposes
been supplanted by Release 3 or later. For the latest version of SoftFloat,
see Web page `http://www.jhauser.us/arithmetic/SoftFloat.html'.
SoftFloat is distributed in the form of C source code. For Release 2c,
compiling the SoftFloat sources generates two things:
-- A SoftFloat object file (typically `softfloat.o') containing the complete
set of IEC/IEEE floating-point routines.
-- A `timesoftfloat' program for evaluating the speed of the SoftFloat
routines. (The SoftFloat module is linked into this program.)
This version of the SoftFloat package is documented in four text files:
SoftFloat.txt Documentation for using the SoftFloat functions.
SoftFloat-source.txt Documentation for compiling SoftFloat.
SoftFloat-history.txt History of major changes to SoftFloat.
timesoftfloat.txt Documentation for using `timesoftfloat'.
Other files in the package comprise the source code for SoftFloat.
Please be aware that some work is involved in porting this software to other
targets. It is not just a matter of getting `make' to complete without
error messages. You should not attempt to compile this release of SoftFloat
without first reading both `SoftFloat.txt' and `SoftFloat-source.txt'.
Depending on your needs, you may find that newer versions of SoftFloat are
less work to port.
----------------------------------------------------------------------------
Legal Notice
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
possible in part by the International Computer Science Institute, located
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
was partially provided by the National Science Foundation under grant
MIP-9311980. The original version of this code was written as part of a
project to build a fixed-point vector processor in collaboration with the
University of California at Berkeley, overseen by Profs. Nelson Morgan and
John Wawrzynek.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
THE SOFTWARE.
The following are expressly permitted, even for commercial purposes:
(1) distribution of SoftFloat in whole or in part, as long as this and
other legal notices remain and are prominent, and provided also that, for a
partial distribution, prominent notice is given that it is a subset of the
original; and
(2) inclusion or use of SoftFloat in whole or in part in a derivative
work, provided that the use restrictions above are met and the minimal
documentation requirements stated in the source code are satisfied.
----------------------------------------------------------------------------
Contact Information
At the time of this writing, the most up-to-date information about SoftFloat
and the latest release can be found at the Web page `http://www.jhauser.us/
arithmetic/SoftFloat.html'.

View File

@ -0,0 +1,389 @@
Berkeley SoftFloat Release 2c General Documentation
John R. Hauser
2015 January 30
----------------------------------------------------------------------------
Introduction
Berkeley SoftFloat is a software implementation of binary floating-point
that conforms to the IEEE Standard for Floating-Point Arithmetic. For
Release 2c of SoftFloat, as many as four formats are supported: 32-bit
single-precision, 64-bit double-precision, 80-bit double-extended-precision,
and 128-bit quadruple-precision. All operations required by the older 1985
version of the IEEE Standard are implemented, except for conversions to and
from decimal.
This document gives information about the types defined and the routines
implemented by this release of SoftFloat. It does not attempt to define or
explain the IEEE Floating-Point Standard. Details about the standard are
available elsewhere.
----------------------------------------------------------------------------
Limitations
SoftFloat is written in C and is designed to work with other C code. The
SoftFloat header files assume an ISO/ANSI-style C compiler. No attempt
has been made to accomodate compilers that are not ISO-conformant. In
particular, the distributed header files will not be acceptable to any
compiler that does not recognize function prototypes.
Support for the 80-bit double-extended-precision and 128-bit quadruple-
precision formats depends on a C compiler that implements 64-bit integer
arithmetic. If the largest integer format supported by the C compiler is
32 bits, SoftFloat is limited to only 32-bit single-precision and 64-bit
double-precision. When that is the case, all references in this document
to 80-bit double-extended-precision, 128-bit quadruple-precision, and 64-bit
integers should be ignored.
----------------------------------------------------------------------------
Contents
Introduction
Limitations
Contents
Legal Notice
Types and Functions
Rounding Modes
Double-Extended-Precision Rounding Precision
Exceptions and Exception Flags
Function Details
Conversion Functions
Basic Arithmetic Functions
Remainder Functions
Round-to-Integer Functions
Comparison Functions
Signaling NaN Test Functions
Raise-Exception Function
Contact Information
----------------------------------------------------------------------------
Legal Notice
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
possible in part by the International Computer Science Institute, located
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
was partially provided by the National Science Foundation under grant
MIP-9311980. The original version of this code was written as part of a
project to build a fixed-point vector processor in collaboration with the
University of California at Berkeley, overseen by Profs. Nelson Morgan and
John Wawrzynek.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
THE SOFTWARE.
The following are expressly permitted, even for commercial purposes:
(1) distribution of SoftFloat in whole or in part, as long as this and
other legal notices remain and are prominent, and provided also that, for a
partial distribution, prominent notice is given that it is a subset of the
original; and
(2) inclusion or use of SoftFloat in whole or in part in a derivative
work, provided that the use restrictions above are met and the minimal
documentation requirements stated in the source code are satisfied.
----------------------------------------------------------------------------
Types and Functions
When 64-bit integers are supported by the compiler, the `softfloat.h' header
file defines four types: `float32' (32-bit single-precision), `float64'
(64-bit double-precision), `floatx80' (80-bit double-extended-precision),
and `float128' (128-bit quadruple-precision). The `float32' and `float64'
types are defined in terms of 32-bit and 64-bit integer types, respectively,
while the `float128' type is defined as a structure of two 64-bit integers,
taking into account the byte order of the particular machine being used.
The `floatx80' type is defined as a structure containing one 16-bit and one
64-bit integer, with the machine's byte order again determining the order
within the structure.
When 64-bit integers are _not_ supported by the compiler, the `softfloat.h'
header file defines only two types: `float32' and `float64'. Because
the ISO/ANSI C Standard guarantees at least one built-in integer type of
32 bits, the `float32' type is identified with an appropriate integer type.
The `float64' type is defined as a structure of two 32-bit integers, with
the machine's byte order determining the order of the fields.
In either case, the types in `softfloat.h' are defined such that if a system
implements the usual C `float' and `double' types according to the IEEE
Standard, then the `float32' and `float64' types should be indistinguishable
in memory from the native `float' and `double' types. (On the other hand,
when `float32' or `float64' values are placed in processor registers by
the compiler, the type of registers used may differ from those used for the
native `float' and `double' types.)
SoftFloat implements the following arithmetic operations:
-- Conversions among all the floating-point formats, and also between
integers (32-bit and 64-bit) and any of the floating-point formats.
-- The usual add, subtract, multiply, divide, and square root operations for
all floating-point formats.
-- For each format, the floating-point remainder operation defined by the
IEEE Standard.
-- For each floating-point format, a "round to integer" operation that
rounds to the nearest integer value in the same format. (The floating-
point formats can hold integer values, of course.)
-- Comparisons between two values in the same floating-point format.
The only functions required by the 1985 IEEE Standard that are not provided
are conversions to and from decimal.
----------------------------------------------------------------------------
Rounding Modes
All four rounding modes prescribed by the 1985 IEEE Standard are implemented
for all operations that require rounding. The rounding mode is selected
by the global variable `float_rounding_mode'. This variable may be set
to one of the values `float_round_nearest_even', `float_round_to_zero',
`float_round_down', or `float_round_up'. The rounding mode is initialized
to nearest/even.
----------------------------------------------------------------------------
Double-Extended-Precision Rounding Precision
For 80-bit double-extended-precision (`floatx80') only, the rounding
precision of the basic arithmetic operations is controlled by the global
variable `floatx80_rounding_precision'. The operations affected are:
floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
When `floatx80_rounding_precision' is set to its default value of 80,
these operations are rounded (as usual) to the full precision of the 80-bit
double-extended-precision format. Setting `floatx80_rounding_precision' to
32 or to 64 causes the operations listed to be rounded to reduced precision
equivalent to 32-bit single-precision (`float32') or to 64-bit double-
precision (`float64'), respectively. When rounding to reduced precision,
additional bits in the result significand beyond the rounding point are set
to zero. The consequences of setting `floatx80_rounding_precision' to a
value other than 32, 64, or 80 is not specified. Operations other than the
ones listed above are not affected by `floatx80_rounding_precision'.
----------------------------------------------------------------------------
Exceptions and Exception Flags
All five exception flags required by the IEEE Standard are implemented.
Each flag is stored as a separate bit in the global variable
`float_exception_flags'. The positions of the exception flag bits within
this variable are determined by the bit masks `float_flag_inexact',
`float_flag_underflow', `float_flag_overflow', `float_flag_divbyzero', and
`float_flag_invalid'. The exception flags variable is initialized to all 0,
meaning no exceptions.
An individual exception flag can be cleared with the statement
float_exception_flags &= ~ float_flag_<exception>;
where `<exception>' is the appropriate name. To raise a floating-point
exception, the SoftFloat function `float_raise' should be used (see below).
In the terminology of the IEEE Standard, SoftFloat can detect tininess
for underflow either before or after rounding. The choice is made by
the global variable `float_detect_tininess', which can be set to either
`float_tininess_before_rounding' or `float_tininess_after_rounding'.
Detecting tininess after rounding is better because it results in fewer
spurious underflow signals. The other option is provided for compatibility
with some systems. Like most systems, SoftFloat always detects loss of
accuracy for underflow as an inexact result.
----------------------------------------------------------------------------
Function Details
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Conversion Functions
All conversions among the floating-point formats are supported, as are all
conversions between a floating-point format and 32-bit and 64-bit signed
integers. The complete set of conversion functions is:
int32_to_float32 int64_to_float32
int32_to_float64 int64_to_float64
int32_to_floatx80 int64_to_floatx80
int32_to_float128 int64_to_float128
float32_to_int32 float32_to_int64
float64_to_int32 float64_to_int64
floatx80_to_int32 floatx80_to_int64
float128_to_int32 float128_to_int64
float32_to_float64 float32_to_floatx80 float32_to_float128
float64_to_float32 float64_to_floatx80 float64_to_float128
floatx80_to_float32 floatx80_to_float64 floatx80_to_float128
float128_to_float32 float128_to_float64 float128_to_floatx80
Each conversion function takes one operand of the appropriate type and
returns one result. Conversions from a smaller to a larger floating-point
format are always exact and so require no rounding. Conversions from 32-bit
integers to 64-bit double-precision and larger formats are also exact, and
likewise for conversions from 64-bit integers to 80-bit double-extended-
precision and 128-bit quadruple-precision.
Conversions from floating-point to integer raise the invalid exception if
the source value cannot be rounded to a representable integer of the desired
size (32 or 64 bits). If the floating-point operand is a NaN, the largest
positive integer is returned. Otherwise, if the conversion overflows, the
largest integer with the same sign as the operand is returned.
On conversions to integer, if the floating-point operand is not already
an integer value, the operand is rounded according to the current rounding
mode as specified by `float_rounding_mode'. Because C (and perhaps other
languages) require that conversions to integers be rounded toward zero, the
following functions are provided for improved speed and convenience:
float32_to_int32_round_to_zero float32_to_int64_round_to_zero
float64_to_int32_round_to_zero float64_to_int64_round_to_zero
floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero
float128_to_int32_round_to_zero float128_to_int64_round_to_zero
These variant functions ignore `float_rounding_mode' and always round toward
zero.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Basic Arithmetic Functions
The following basic arithmetic functions are provided:
float32_add float32_sub float32_mul float32_div float32_sqrt
float64_add float64_sub float64_mul float64_div float64_sqrt
floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
float128_add float128_sub float128_mul float128_div float128_sqrt
Each function takes two operands, except for `sqrt' which takes only one.
The operands and result are all of the same type.
Rounding of the 80-bit double-extended-precision (`floatx80') functions is
affected by the `floatx80_rounding_precision' variable, as explained above
in the section _Double-Extended-Precision Rounding Precision_.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Remainder Functions
For each format, SoftFloat implements the remainder function according to
the IEEE Standard. The remainder functions are:
float32_rem
float64_rem
floatx80_rem
float128_rem
Each remainder function takes two operands. The operands and result are all
of the same type. Given operands x and y, the remainder functions return
the value x - n*y, where n is the integer closest to x/y. If x/y is exactly
halfway between two integers, n is the even integer closest to x/y. The
remainder functions are always exact and so require no rounding.
Depending on the relative magnitudes of the operands, the remainder
functions can take considerably longer to execute than the other SoftFloat
functions. This is inherent in the remainder operation itself and is not a
flaw in the SoftFloat implementation.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Round-to-Integer Functions
For each format, SoftFloat implements the round-to-integer function
specified by the IEEE Standard. The functions are:
float32_round_to_int
float64_round_to_int
floatx80_round_to_int
float128_round_to_int
Each function takes a single floating-point operand and returns a result of
the same type. (Note that the result is not an integer type.) The operand
is rounded to an exact integer according to the current rounding mode, and
the resulting integer value is returned in the same floating-point format.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Comparison Functions
The following floating-point comparison functions are provided:
float32_eq float32_le float32_lt
float64_eq float64_le float64_lt
floatx80_eq floatx80_le floatx80_lt
float128_eq float128_le float128_lt
Each function takes two operands of the same type and returns a 1 or 0
representing either _true_ or _false_. The abbreviation `eq' stands for
"equal" (=); `le' stands for "less than or equal" (<=); and `lt' stands for
"less than" (<).
The usual greater-than (>), greater-than-or-equal (>=), and not-equal (!=)
functions are easily obtained using the functions provided. The not-equal
function is just the logical complement of the equal function. The greater-
than-or-equal function is identical to the less-than-or-equal function with
the operands reversed, and the greater-than function is identical to the
less-than function with the operands reversed.
The IEEE Standard specifies that the less-than-or-equal and less-than
functions raise the invalid exception if either input is any kind of NaN.
The equal functions, on the other hand, are defined not to raise the invalid
exception on quiet NaNs. For completeness, SoftFloat provides the following
additional functions:
float32_eq_signaling float32_le_quiet float32_lt_quiet
float64_eq_signaling float64_le_quiet float64_lt_quiet
floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet
float128_eq_signaling float128_le_quiet float128_lt_quiet
The `signaling' equal functions are identical to the standard functions
except that the invalid exception is raised for any NaN input. Likewise,
the `quiet' comparison functions are identical to their counterparts except
that the invalid exception is not raised for quiet NaNs.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Signaling NaN Test Functions
The following functions test whether a floating-point value is a signaling
NaN:
float32_is_signaling_nan
float64_is_signaling_nan
floatx80_is_signaling_nan
float128_is_signaling_nan
The functions take one operand and return 1 if the operand is a signaling
NaN and 0 otherwise.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Raise-Exception Function
SoftFloat provides a function for raising floating-point exceptions:
float_raise
The function takes a mask indicating the set of exceptions to raise. No
result is returned. In addition to setting the specified exception flags,
this function may cause a trap or abort appropriate for the current system.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
----------------------------------------------------------------------------
Contact Information
At the time of this writing, the most up-to-date information about SoftFloat
and the latest release can be found at the Web page `http://www.jhauser.us/
arithmetic/SoftFloat.html'.

View File

@ -0,0 +1,65 @@
History of Major Changes to Berkeley SoftFloat, up to Release 2c
John R. Hauser
2015 January 31
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 2c (2015 January)
-- Fixed mistakes affecting some 64-bit processors.
-- Further improved the documentation and the wording for the legal
restrictions on using SoftFloat.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 2b (2002 May)
-- Made minor updates to the documentation, including improved wording for
the legal restrictions on using SoftFloat.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 2a (1998 December)
-- Added functions to convert between 64-bit integers (int64) and all
supported floating-point formats.
-- Fixed a bug in all 64-bit-version square root functions except
`float32_sqrt' that caused the result sometimes to be off by 1 unit in
the last place (1 ulp) from what it should be. (Bug discovered by Paul
Donahue.)
-- Improved the Makefiles.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 2 (1997 June)
-- Created the 64-bit (bits64) version, adding the floatx80 and float128
formats.
-- Changed the source directory structure, splitting the sources into a
`bits32' and a `bits64' version. Renamed `environment.h' to `milieu.h'
to avoid confusion with environment variables.
-- Fixed a small error that caused `float64_round_to_int' often to round the
wrong way in nearest/even mode when the operand was between 2^20 and 2^21
and halfway between two integers.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 1a (1996 July)
-- Corrected a mistake that caused borderline underflow cases not to raise
the underflow flag when they should have. (Problem reported by Doug
Priest.)
-- Added the `float_detect_tininess' variable to control whether tininess is
detected before or after rounding.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Release 1 (1996 July)
-- Original release.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -0,0 +1,644 @@
/*============================================================================
This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
Arithmetic Package, Release 2c, by John R. Hauser.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
SOFTWARE.
Derivative works require also that (1) the source code for the derivative work
includes prominent notice that the work is derivative, and (2) the source code
includes prominent notice of these three paragraphs for those parts of this
code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are "jammed" into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 32, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
| The result is stored in the location pointed to by `zPtr'.
*----------------------------------------------------------------------------*/
INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
{
bits32 z;
if ( count == 0 ) {
z = a;
}
else if ( count < 32 ) {
z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
}
else {
z = ( a != 0 );
}
*zPtr = z;
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' can be arbitrarily large; in particular, if `count' is greater
| than 64, the result will be 0. The result is broken into two 32-bit pieces
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shift64Right(
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
{
bits32 z0, z1;
int8 negCount = ( - count ) & 31;
if ( count == 0 ) {
z1 = a1;
z0 = a0;
}
else if ( count < 32 ) {
z1 = ( a0<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
z1 = ( count < 64 ) ? ( a0>>( count & 31 ) ) : 0;
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. If any nonzero bits are shifted off, they
| are "jammed" into the least significant bit of the result by setting the
| least significant bit to 1. The value of `count' can be arbitrarily large;
| in particular, if `count' is greater than 64, the result will be either 0
| or 1, depending on whether the concatenation of `a0' and `a1' is zero or
| nonzero. The result is broken into two 32-bit pieces which are stored at
| the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shift64RightJamming(
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
{
bits32 z0, z1;
int8 negCount = ( - count ) & 31;
if ( count == 0 ) {
z1 = a1;
z0 = a0;
}
else if ( count < 32 ) {
z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
z0 = a0>>count;
}
else {
if ( count == 32 ) {
z1 = a0 | ( a1 != 0 );
}
else if ( count < 64 ) {
z1 = ( a0>>( count & 31 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
}
else {
z1 = ( ( a0 | a1 ) != 0 );
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
| by 32 _plus_ the number of bits given in `count'. The shifted result is
| at most 64 nonzero bits; these are broken into two 32-bit pieces which are
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
| off form a third 32-bit result as follows: The _last_ bit shifted off is
| the most-significant bit of the extra result, and the other 31 bits of the
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
| were all zero. This extra result is stored in the location pointed to by
| `z2Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0', `a1', and `a2' are considered
| to form a fixed-point value with binary point between `a1' and `a2'. This
| fixed-point value is shifted right by the number of bits given in `count',
| and the integer part of the result is returned at the locations pointed to
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
| corrupted as described above, and is returned at the location pointed to by
| `z2Ptr'.)
*----------------------------------------------------------------------------*/
INLINE void
shift64ExtraRightJamming(
bits32 a0,
bits32 a1,
bits32 a2,
int16 count,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr
)
{
bits32 z0, z1, z2;
int8 negCount = ( - count ) & 31;
if ( count == 0 ) {
z2 = a2;
z1 = a1;
z0 = a0;
}
else {
if ( count < 32 ) {
z2 = a1<<negCount;
z1 = ( a0<<negCount ) | ( a1>>count );
z0 = a0>>count;
}
else {
if ( count == 32 ) {
z2 = a1;
z1 = a0;
}
else {
a2 |= a1;
if ( count < 64 ) {
z2 = a0<<negCount;
z1 = a0>>( count & 31 );
}
else {
z2 = ( count == 64 ) ? a0 : ( a0 != 0 );
z1 = 0;
}
}
z0 = 0;
}
z2 |= ( a2 != 0 );
}
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
/*----------------------------------------------------------------------------
| Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' must be less than 32. The result is broken into two 32-bit
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shortShift64Left(
bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
{
*z1Ptr = a1<<count;
*z0Ptr =
( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 31 ) );
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
| by the number of bits given in `count'. Any bits shifted off are lost.
| The value of `count' must be less than 32. The result is broken into three
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
| `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
shortShift96Left(
bits32 a0,
bits32 a1,
bits32 a2,
int16 count,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr
)
{
bits32 z0, z1, z2;
int8 negCount;
z2 = a2<<count;
z1 = a1<<count;
z0 = a0<<count;
if ( 0 < count ) {
negCount = ( ( - count ) & 31 );
z1 |= a2>>negCount;
z0 |= a1>>negCount;
}
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
/*----------------------------------------------------------------------------
| Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
| any carry out is lost. The result is broken into two 32-bit pieces which
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
add64(
bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
{
bits32 z1;
z1 = a1 + b1;
*z1Ptr = z1;
*z0Ptr = a0 + b0 + ( z1 < a1 );
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
| 96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
| modulo 2^96, so any carry out is lost. The result is broken into three
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr',
| `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
add96(
bits32 a0,
bits32 a1,
bits32 a2,
bits32 b0,
bits32 b1,
bits32 b2,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr
)
{
bits32 z0, z1, z2;
int8 carry0, carry1;
z2 = a2 + b2;
carry1 = ( z2 < a2 );
z1 = a1 + b1;
carry0 = ( z1 < a1 );
z0 = a0 + b0;
z1 += carry1;
z0 += ( z1 < carry1 );
z0 += carry0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
/*----------------------------------------------------------------------------
| Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
| 64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
| 2^64, so any borrow out (carry out) is lost. The result is broken into two
| 32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
| `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
sub64(
bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
{
*z1Ptr = a1 - b1;
*z0Ptr = a0 - b0 - ( a1 < b1 );
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
| the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
| is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
| into three 32-bit pieces which are stored at the locations pointed to by
| `z0Ptr', `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
sub96(
bits32 a0,
bits32 a1,
bits32 a2,
bits32 b0,
bits32 b1,
bits32 b2,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr
)
{
bits32 z0, z1, z2;
int8 borrow0, borrow1;
z2 = a2 - b2;
borrow1 = ( a2 < b2 );
z1 = a1 - b1;
borrow0 = ( a1 < b1 );
z0 = a0 - b0;
z0 -= ( z1 < borrow1 );
z1 -= borrow1;
z0 -= borrow0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
/*----------------------------------------------------------------------------
| Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
| into two 32-bit pieces which are stored at the locations pointed to by
| `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
INLINE void mul32To64( bits32 a, bits32 b, bits32 *z0Ptr, bits32 *z1Ptr )
{
bits16 aHigh, aLow, bHigh, bLow;
bits32 z0, zMiddleA, zMiddleB, z1;
aLow = a;
aHigh = a>>16;
bLow = b;
bHigh = b>>16;
z1 = ( (bits32) aLow ) * bLow;
zMiddleA = ( (bits32) aLow ) * bHigh;
zMiddleB = ( (bits32) aHigh ) * bLow;
z0 = ( (bits32) aHigh ) * bHigh;
zMiddleA += zMiddleB;
z0 += ( ( (bits32) ( zMiddleA < zMiddleB ) )<<16 ) + ( zMiddleA>>16 );
zMiddleA <<= 16;
z1 += zMiddleA;
z0 += ( z1 < zMiddleA );
*z1Ptr = z1;
*z0Ptr = z0;
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
| to obtain a 96-bit product. The product is broken into three 32-bit pieces
| which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
| `z2Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
mul64By32To96(
bits32 a0,
bits32 a1,
bits32 b,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr
)
{
bits32 z0, z1, z2, more1;
mul32To64( a1, b, &z1, &z2 );
mul32To64( a0, b, &z0, &more1 );
add64( z0, more1, 0, z1, &z0, &z1 );
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
| 64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
| product. The product is broken into four 32-bit pieces which are stored at
| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
*----------------------------------------------------------------------------*/
INLINE void
mul64To128(
bits32 a0,
bits32 a1,
bits32 b0,
bits32 b1,
bits32 *z0Ptr,
bits32 *z1Ptr,
bits32 *z2Ptr,
bits32 *z3Ptr
)
{
bits32 z0, z1, z2, z3;
bits32 more1, more2;
mul32To64( a1, b1, &z2, &z3 );
mul32To64( a1, b0, &z1, &more2 );
add64( z1, more2, 0, z2, &z1, &z2 );
mul32To64( a0, b0, &z0, &more1 );
add64( z0, more1, 0, z1, &z0, &z1 );
mul32To64( a0, b1, &more1, &more2 );
add64( more1, more2, 0, z2, &more1, &z2 );
add64( z0, z1, 0, more1, &z0, &z1 );
*z3Ptr = z3;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif
/*----------------------------------------------------------------------------
| Returns an approximation to the 32-bit integer quotient obtained by dividing
| `b' into the 64-bit value formed by concatenating `a0' and `a1'. The
| divisor `b' must be at least 2^31. If q is the exact quotient truncated
| toward zero, the approximation returned lies between q and q + 2 inclusive.
| If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
| unsigned integer is returned.
*----------------------------------------------------------------------------*/
static bits32 estimateDiv64To32( bits32 a0, bits32 a1, bits32 b )
{
bits32 b0, b1;
bits32 rem0, rem1, term0, term1;
bits32 z;
if ( b <= a0 ) return 0xFFFFFFFF;
b0 = b>>16;
z = ( b0<<16 <= a0 ) ? 0xFFFF0000 : ( a0 / b0 )<<16;
mul32To64( b, z, &term0, &term1 );
sub64( a0, a1, term0, term1, &rem0, &rem1 );
while ( ( (sbits32) rem0 ) < 0 ) {
z -= 0x10000;
b1 = b<<16;
add64( rem0, rem1, b0, b1, &rem0, &rem1 );
}
rem0 = ( rem0<<16 ) | ( rem1>>16 );
z |= ( b0<<16 <= rem0 ) ? 0xFFFF : rem0 / b0;
return z;
}
/*----------------------------------------------------------------------------
| Returns an approximation to the square root of the 32-bit significand given
| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
| `aExp' (the least significant bit) is 1, the integer returned approximates
| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
| case, the approximation returned lies strictly within +/-2 of the exact
| value.
*----------------------------------------------------------------------------*/
static bits32 estimateSqrt32( int16 aExp, bits32 a )
{
static const bits16 sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
};
static const bits16 sqrtEvenAdjustments[] = {
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
};
int8 index;
bits32 z;
index = ( a>>27 ) & 15;
if ( aExp & 1 ) {
z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
z = ( ( a / z )<<14 ) + ( z<<15 );
a >>= 1;
}
else {
z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
z = a / z + z;
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
}
return ( ( estimateDiv64To32( a, 0, z ) )>>1 ) + ( z>>1 );
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
static int8 countLeadingZeros32( bits32 a )
{
static const int8 countLeadingZerosHigh[] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int8 shiftCount;
shiftCount = 0;
if ( a < 0x10000 ) {
shiftCount += 16;
a <<= 16;
}
if ( a < 0x1000000 ) {
shiftCount += 8;
a <<= 8;
}
shiftCount += countLeadingZerosHigh[ a>>24 ];
return shiftCount;
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
| equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
| returns 0.
*----------------------------------------------------------------------------*/
INLINE flag eq64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
{
return ( a0 == b0 ) && ( a1 == b1 );
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
| than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
INLINE flag le64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
{
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
| than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
| returns 0.
*----------------------------------------------------------------------------*/
INLINE flag lt64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
{
return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
| equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
| returns 0.
*----------------------------------------------------------------------------*/
INLINE flag ne64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
{
return ( a0 != b0 ) || ( a1 != b1 );
}
#endif

View File

@ -0,0 +1,38 @@
/*============================================================================
This C header file template is part of the Berkeley SoftFloat IEEE Floating-
Point Arithmetic Package, Release 2c, by John R. Hauser.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
SOFTWARE.
Derivative works require also that (1) the source code for the derivative work
includes prominent notice that the work is derivative, and (2) the source code
includes prominent notice of these three paragraphs for those parts of this
code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Include common integer types and flags.
*----------------------------------------------------------------------------*/
#include "6502-CC65.h"
/*----------------------------------------------------------------------------
| Symbolic Boolean literals.
*----------------------------------------------------------------------------*/
enum {
FALSE = 0,
TRUE = 1
};

View File

@ -0,0 +1,179 @@
.importzp sreg, tmp1
.import _int32_to_float32
;------------------------------------------------------------------------------
; conversions: to float
; 16bit signed -> float
.export axfloat
axfloat:
; FIXME
; sign extend to 32bit
ldy #$ff
cpx #$80
bcs @sk
ldy #$00
@sk:
sty sreg
sty sreg+1
jmp _int32_to_float32
; 16bit unsigned -> float
.export axufloat
axufloat:
; FIXME
ldy #0
sty sreg
sty sreg+1
jmp _int32_to_float32
; 32bit signed -> float
.export eaxfloat
eaxfloat:
; FIXME
jmp _int32_to_float32
; 32bit unsigned -> float
.export eaxufloat
eaxufloat:
; FIXME
jmp _int32_to_float32
;------------------------------------------------------------------------------
; conversions: from float
.import _float32_to_int32
.import _float32_to_int32_round_to_zero
; float -> 16bit int
.export feaxint
feaxint:
; FIXME
jmp _float32_to_int32_round_to_zero
; jmp _float32_to_int32
; float -> 32bit int
.export feaxlong
feaxlong:
jmp _float32_to_int32_round_to_zero
; jmp _float32_to_int32
;------------------------------------------------------------------------------
; the ! operator, returns a bool (int)
.export fbnegeax
fbnegeax:
stx tmp1
ora tmp1
ora sreg
ora sreg+1
beq @ret1 ; is = 0
; return 0
lda #0
tax
rts
@ret1:
lda #1
ldx #0
rts
.import _float32_mul
; arg0: a/x/sreg/sreg+1
.export fnegeax
fnegeax:
pha
; txa
; pha
lda sreg+1
eor #$80 ; sign bit
sta sreg+1
; lda sreg+0
; eor #$ff ; sign bit
; sta sreg+0
; txa
; eor #$ff ; sign bit
; tax
; pla
; tax
pla
; eor #$ff ; sign bit
rts
.import _float32_add
.import _float32_sub
.import _float32_mul
.import _float32_div
.export ftosaddeax
ftosaddeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_add
.export ftossubeax
ftossubeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_sub
.export ftosmuleax
ftosmuleax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_mul
.export ftosdiveax
ftosdiveax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_div
.import _float32_rsub
.export ftosrsubeax
ftosrsubeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_rsub
.import _float32_eq
.import _float32_le
.import _float32_lt
; test for equal
.export ftoseqeax
ftoseqeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jmp _float32_eq
; test for not equal
.export ftosneeax
ftosneeax:
; arg0: a/x/sreg/sreg+1
; arg1: (sp),y (y=0..3)
jsr _float32_eq
eor #1
rts
; Test for less than or equal to
.export ftosleeax
ftosleeax:
jmp _float32_le
.export ftosgteax
ftosgteax:
jsr _float32_le
eor #1
rts
; Test for less than
.export ftoslteax
ftoslteax:
jmp _float32_lt
; Test for "not less than" -> "equal or greater than"
; Test for greater than or equal to
.export ftosgeeax
ftosgeeax:
jsr _float32_lt
eor #1
rts

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
#ifndef SOFTFLOAT_H_
#define SOFTFLOAT_H_
/*============================================================================
This C header file template is part of the Berkeley SoftFloat IEEE Floating-
Point Arithmetic Package, Release 2c, by John R. Hauser.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
SOFTWARE.
Derivative works require also that (1) the source code for the derivative work
includes prominent notice that the work is derivative, and (2) the source code
includes prominent notice of these three paragraphs for those parts of this
code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Software IEEE floating-point types.
*----------------------------------------------------------------------------*/
typedef unsigned long float32;
typedef struct {
unsigned long high, low;
} float64;
/*----------------------------------------------------------------------------
| Software IEEE floating-point underflow tininess-detection mode.
*----------------------------------------------------------------------------*/
extern signed char float_detect_tininess;
enum {
float_tininess_after_rounding = 0,
float_tininess_before_rounding = 1
};
/*----------------------------------------------------------------------------
| Software IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
extern signed char float_rounding_mode;
enum {
float_round_nearest_even = 0,
float_round_to_zero = 1,
float_round_down = 2,
float_round_up = 3
};
/*----------------------------------------------------------------------------
| Software IEEE floating-point exception flags.
*----------------------------------------------------------------------------*/
extern signed char float_exception_flags;
enum {
float_flag_inexact = 1,
float_flag_underflow = 2,
float_flag_overflow = 4,
float_flag_divbyzero = 8,
float_flag_invalid = 16
};
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software IEEE floating-point exception
| flags.
*----------------------------------------------------------------------------*/
void float_raise( signed char );
/*----------------------------------------------------------------------------
| Software IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32( int32 );
float64 int32_to_float64( int32 );
/*----------------------------------------------------------------------------
| Software IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
int32 float32_to_int32( float32 );
int32 float32_to_int32_round_to_zero( float32 );
float64 float32_to_float64( float32 );
/*----------------------------------------------------------------------------
| Software IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 __fastcall__ float32_round_to_int( float32 );
float32 __fastcall__ float32_add( float32, float32 );
float32 __fastcall__ float32_sub( float32, float32 );
float32 __fastcall__ float32_rsub( float32, float32 );
float32 __fastcall__ float32_mul( float32, float32 );
float32 __fastcall__ float32_div( float32, float32 );
float32 __fastcall__ float32_rem( float32, float32 );
float32 __fastcall__ float32_sqrt( float32 );
unsigned char __fastcall__ float32_eq( float32, float32 );
unsigned char __fastcall__ float32_le( float32, float32 );
unsigned char __fastcall__ float32_lt( float32, float32 );
unsigned char __fastcall__ float32_eq_signaling( float32, float32 );
unsigned char __fastcall__ float32_le_quiet( float32, float32 );
unsigned char __fastcall__ float32_lt_quiet( float32, float32 );
unsigned char __fastcall__ float32_is_signaling_nan( float32 );
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Software IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
signed short float64_to_int32( float64 );
signed short float64_to_int32_round_to_zero( float64 );
float32 float64_to_float32( float64 );
/*----------------------------------------------------------------------------
| Software IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int( float64 );
float64 float64_add( float64, float64 );
float64 float64_sub( float64, float64 );
float64 float64_mul( float64, float64 );
float64 float64_div( float64, float64 );
float64 float64_rem( float64, float64 );
float64 float64_sqrt( float64 );
unsigned char float64_eq( float64, float64 );
unsigned char float64_le( float64, float64 );
unsigned char float64_lt( float64, float64 );
unsigned char float64_eq_signaling( float64, float64 );
unsigned char float64_le_quiet( float64, float64 );
unsigned char float64_lt_quiet( float64, float64 );
unsigned char float64_is_signaling_nan( float64 );
#endif
#endif /* SOFTFLOAT_H_ */

View File

@ -0,0 +1,98 @@
#include <stdlib.h>
#include <stdio.h>
//#define DEBUG_VALUE
// This is really a terrible function that should get completely rewritten and
// tested by someone who knows what he is doing =P
char *_ftostr(char *buffer, float f) {
signed long intpart;
float fracpart;
float f1, f2;
signed long n0;
int is_negative;
unsigned long raw_value = *((unsigned long*)(&f));
is_negative = (raw_value & 0x80000000) ? 1 : 0; // very hacky indeed
if (!is_negative) {
intpart = (signed long)(f);
} else {
intpart = (signed long)(f);
intpart = -intpart;
}
f2 = intpart;
#if 0
if (!is_negative) {
if (f2 > f) {
if (intpart > 0) {
--intpart;
}
}
} else {
if (f2 > f) {
if (intpart > 0) {
--intpart;
}
}
// ++intpart;
}
if (!is_negative) {
if (intpart < 0) {
intpart *= -1;
}
} else {
if (intpart < 0) {
intpart *= -1;
}
}
#endif
f2 = intpart;
if (!is_negative) {
fracpart = f - f2;
} else {
fracpart = (-f) - f2;
}
f1 = 10000.0f;
f1 = f1 * fracpart;
n0 = (signed long)f1;
#if 0
// caution: make sure fracpart can never be negative
if (n0 < 0) {
n0 *= -1;
}
#endif
// printf("n0:%ld\n",n0);
#ifdef DEBUG_VALUE
if (n0 >= 1000) {
sprintf(buffer, "<0x%08lx:%s%ld.%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 100) {
sprintf(buffer, "<0x%08lx:%s%ld.0%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 10) {
sprintf(buffer, "<0x%08lx:%s%ld.00%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 1) {
sprintf(buffer, "<0x%08lx:%s%ld.000%ld>", raw_value, is_negative ? "-" : "", intpart, n0);
} else {
sprintf(buffer, "<0x%08lx:%s%ld.0000>", raw_value, is_negative ? "-" : "", intpart);
}
#else
if (n0 >= 1000) {
sprintf(buffer, "%s%ld.%ld", is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 100) {
sprintf(buffer, "%s%ld.0%ld", is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 10) {
sprintf(buffer, "%s%ld.00%ld", is_negative ? "-" : "", intpart, n0);
} else if (n0 >= 1) {
sprintf(buffer, "%s%ld.000%ld", is_negative ? "-" : "", intpart, n0);
} else {
sprintf(buffer, "%s%ld.0000", is_negative ? "-" : "", intpart);
}
#endif
return &buffer[0];
}

View File

@ -0,0 +1,400 @@
Berkeley SoftFloat Release 2c Source Documentation
John R. Hauser
2015 January 30
----------------------------------------------------------------------------
Introduction
Berkeley SoftFloat is a software implementation of binary floating-point
that conforms to the IEEE Standard for Floating-Point Arithmetic.
Release 2c of SoftFloat can support four floating-point formats: 32-bit
single-precision, 64-bit double-precision, 80-bit double-extended-precision,
and 128-bit quadruple-precision. All operations required by the older 1985
version of the IEEE Standard are implemented, except for conversions to and
from decimal. SoftFloat is distributed in the form of C source code, so a
C compiler is needed to compile the code. Support for the 80-bit double-
extended-precision and 128-bit quadruple-precision formats is dependent on
the C compiler implementing a 64-bit integer type.
This document gives information needed for compiling and/or porting this
SoftFloat release.
The source code for SoftFloat is intended to be relatively machine-
independent and should be compilable using most any ISO/ANSI C compiler. At
the time of this writing, SoftFloat has been successfully compiled with the
GNU C Compiler (`gcc') for several platforms.
----------------------------------------------------------------------------
Limitations
As supplied, SoftFloat requires an ISO/ANSI-style C compiler. No attempt
has been made to accomodate compilers that are not ISO-conformant. Older
"K&R-style" compilers are not adequate for compiling SoftFloat. All testing
I have done so far has been with the GNU C Compiler. Compilation with other
compilers should be possible but has not been tested by me.
The SoftFloat sources assume that source code file names can be longer than
8 characters. In order to compile under an MS-DOS-type system, many of the
source files will need to be renamed, and the source and Makefiles edited
appropriately. Once compiled, the SoftFloat binary does not depend on the
existence of long file names.
The underlying machine is assumed to be binary with a word size that is a
power of 2. Bytes are 8 bits. Arithmetic on signed integers must modularly
wrap around on overflows (as is already required for unsigned integers
in C).
Support for the 80-bit double-extended-precision and 128-bit quadruple-
precision formats depends on the C compiler implementing a 64-bit integer
type. If the largest integer type supported by the C compiler is 32 bits,
SoftFloat is limited to the 32-bit single-precision and 64-bit double-
precision formats.
----------------------------------------------------------------------------
Contents
Introduction
Limitations
Contents
Legal Notice
SoftFloat Source Directory Structure
SoftFloat Source Files
processors/*.h
softfloat/bits*/*/softfloat.h
softfloat/bits*/*/milieu.h
softfloat/bits*/*/softfloat-specialize
softfloat/bits*/softfloat-macros
softfloat/bits*/softfloat.c
Steps to Creating a `softfloat.o'
Making `softfloat.o' a Library
Testing SoftFloat
Timing SoftFloat
Compiler Options and Efficiency
Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
Contact Information
----------------------------------------------------------------------------
Legal Notice
SoftFloat was written by John R. Hauser. Release 2c of SoftFloat was made
possible in part by the International Computer Science Institute, located
at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding
was partially provided by the National Science Foundation under grant
MIP-9311980. The original version of this code was written as part of a
project to build a fixed-point vector processor in collaboration with the
University of California at Berkeley, overseen by Profs. Nelson Morgan and
John Wawrzynek.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
PERSONS AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR
OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN
HAUSER OR THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE,
OR INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF
THE SOFTWARE.
The following are expressly permitted, even for commercial purposes:
(1) distribution of SoftFloat in whole or in part, as long as this and
other legal notices remain and are prominent, and provided also that, for a
partial distribution, prominent notice is given that it is a subset of the
original; and
(2) inclusion or use of SoftFloat in whole or in part in a derivative
work, provided that the use restrictions above are met and the minimal
documentation requirements stated in the source code are satisfied.
----------------------------------------------------------------------------
SoftFloat Source Directory Structure
Because SoftFloat is targeted to multiple platforms, its source code
is slightly scattered between target-specific and target-independent
directories and files. The directory structure is as follows:
processors
softfloat
bits64
templates
386-Win32-GCC
SPARC-Solaris-GCC
bits32
templates
386-Win32-GCC
SPARC-Solaris-GCC
The two topmost directories and their contents are:
softfloat - Most of the source code needed for SoftFloat.
processors - Target-specific header files that are not specific to
SoftFloat.
The `softfloat' directory is further split into two parts:
bits64 - SoftFloat implementation using 64-bit integers.
bits32 - SoftFloat implementation using only 32-bit integers.
Within these directories are subdirectories for each of the targeted
platforms. The SoftFloat source code is distributed with targets
`386-Win32-GCC' and `SPARC-Solaris-GCC' (and perhaps others) already
prepared for both the 32-bit and 64-bit implementations. Source files
that are not within these target-specific subdirectories are intended to be
target-independent.
The naming convention used for the target-specific directories is
`<processor>-<executable-type>-<compiler>'. The names of the supplied
target directories should be interpreted as follows:
<processor>:
386 - Intel 386-compatible processor.
SPARC - SPARC processor (as used by Sun computers).
<executable-type>:
Win32 - Microsoft Win32 executable.
Solaris - Sun Solaris executable.
<compiler>:
GCC - GNU C Compiler.
You do not need to maintain this convention if you do not want to.
Alongside the supplied target-specific directories is a `templates'
directory containing a set of "generic" target-specific source files. A
new target directory can be created by copying the `templates' directory and
editing the files inside. (Complete instructions for porting SoftFloat to
a new target are in the section _Steps to Creating a `softfloat.o'_.) Note
that the `templates' directory will not work as a target directory without
some editing. To avoid confusion, it would be wise to refrain from editing
the files inside `templates' directly.
----------------------------------------------------------------------------
SoftFloat Source Files
The purpose of each source file is described below. In the following,
the `*' symbol is used in place of the name of a specific target, such as
`386-Win32-GCC' or `SPARC-Solaris-GCC', or in place of some other text, as
in `bits*' for either `bits32' or `bits64'.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
processors/*.h
The target-specific `processors' header file defines integer types
of various sizes, and also defines certain C preprocessor macros that
characterize the target. The two examples supplied are `386-GCC.h' and
`SPARC-GCC.h'. The naming convention used for processor header files is
`<processor>-<compiler>.h'.
If 64-bit integers are supported by the compiler, the macro name `BITS64'
should be defined here along with the corresponding 64-bit integer
types. In addition, the function-like macro `LIT64' must be defined for
constructing 64-bit integer literals (constants). The `LIT64' macro is used
consistently in the SoftFloat code to annotate 64-bit literals.
If `BITS64' is not defined, only the 32-bit version of SoftFloat can be
compiled. If `BITS64' _is_ defined, either can be compiled.
If an inlining attribute (such as an `inline' keyword) is provided by the
compiler, the macro `INLINE' should be defined to the appropriate keyword.
If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro
appears in the SoftFloat source code before every function that should
be inlined by the compiler. SoftFloat depends on inlining to obtain
good speed. Even if inlining cannot be forced with a language keyword,
the compiler may still be able to perform inlining on its own as an
optimization. If a command-line option is needed to convince the compiler
to perform this optimization, this should be assured in the Makefile. (See
the section _Compiler Options and Efficiency_ below.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
softfloat/bits*/*/softfloat.h
The target-specific `softfloat.h' header file defines the SoftFloat
interface as seen by clients.
Unlike the actual function definitions in `softfloat.c', the declarations
in `softfloat.h' do not use any of the types defined by the `processors'
header file. This is done so that clients will not have to include the
`processors' header file in order to use SoftFloat. Nevertheless, the
target-specific declarations in `softfloat.h' must match what `softfloat.c'
expects. For example, if `int32' is defined as `int' in the `processors'
header file, then in `softfloat.h' the output of `float32_to_int32' should
be stated as `int', although in `softfloat.c' it is given in target-
independent form as `int32'.
For the `bits64' implementation of SoftFloat, the macro names `FLOATX80'
and `FLOAT128' must be defined in order for the 80-bit double-extended-
precision and 128-bit quadruple-precision formats to be enabled in the
code. Conversely, either or both of these larger formats can be disabled by
simply removing the `#define' of the respective macro. When a format is not
enabled, none of the functions that either input or output the format are
defined, and no space is taken up in `softfloat.o' by such functions. There
is no provision for disabling the usual 32-bit single-precision and 64-bit
double-precision formats.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
softfloat/bits*/*/milieu.h
The target-specific `milieu.h' header file provides declarations that are
needed to compile SoftFloat. In addition, deviations from ISO/ANSI C by
the compiler (such as names not properly declared in system header files)
are corrected in this header if possible.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
softfloat/bits*/*/softfloat-specialize
This target-specific C source fragment defines:
-- whether tininess for underflow is detected before or after rounding by
default;
-- what (if anything) special happens when exceptions are raised;
-- how signaling NaNs are distinguished from quiet NaNs;
-- the default generated quiet NaNs; and
-- how NaNs are propagated from function inputs to output.
These details are not decided by the IEEE Standard. This fragment is
included verbatim within `softfloat.c' when SoftFloat is compiled.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
softfloat/bits*/softfloat-macros
This target-independent C source fragment defines a number of arithmetic
functions used as primitives within the `softfloat.c' source. Most of
the functions defined here are intended to be inlined for efficiency.
This fragment is included verbatim within `softfloat.c' when SoftFloat is
compiled.
Target-specific variations on this file are possible. See the section
_Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'_
below.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
softfloat/bits*/softfloat.c
The target-independent `softfloat.c' source file contains the body of the
SoftFloat implementation.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The inclusion of the files above within each other (using `#include') can be
shown graphically as follows:
softfloat/bits*/softfloat.c
softfloat/bits*/*/milieu.h
processors/*.h
softfloat/bits*/*/softfloat.h
softfloat/bits*/*/softfloat-specialize
softfloat/bits*/softfloat-macros
Note in particular that `softfloat.c' does not include the `processors'
header file directly. Rather, `softfloat.c' includes the target-specific
`milieu.h' header file, which in turn includes the appropriate processor
header file.
----------------------------------------------------------------------------
Steps to Creating a `softfloat.o'
Porting and/or compiling SoftFloat involves the following steps:
1. If one does not already exist, create an appropriate `.h' file in the
`processors' directory.
2. If `BITS64' is defined in the `processors' header file, choose whether
to compile the 32-bit or 64-bit implementation of SoftFloat. If
`BITS64' is not defined, your only choice is the 32-bit implementation.
The remaining steps occur within either the `bits32' or `bits64'
subdirectories.
3. If one does not already exist, create an appropriate target-specific
subdirectory by copying the given `templates' directory.
4. In the target-specific subdirectory, edit the files `softfloat-specialize'
and `softfloat.h' to define the desired exception handling functions
and mode control values. In the `softfloat.h' header file, ensure also
that all declarations give the proper target-specific type (such as
`int' or `long') corresponding to the target-independent type used in
`softfloat.c' (such as `int32'). None of the type names declared in the
`processors' header file should appear in `softfloat.h'.
5. In the target-specific subdirectory, edit the files `milieu.h' and
`Makefile' to reflect the current environment.
6. In the target-specific subdirectory, execute `make'.
For the targets that are supplied, if the expected compiler is available
(usually `gcc'), it should only be necessary to execute `make' in the
target-specific subdirectory.
----------------------------------------------------------------------------
Making `softfloat.o' a Library
SoftFloat is not made into a software library by the supplied Makefile.
If desired, `softfloat.o' can easily be put into its own library (typically
`softfloat.a' or `libsoftfloat.a') using the usual system tool (in UNIX,
`ar').
----------------------------------------------------------------------------
Testing SoftFloat
SoftFloat can be tested using the `testsoftfloat' program by the same
author. The `testsoftfloat' program is part of the TestFloat package
available at the Web page `http://www.jhauser.us/arithmetic/TestFloat.html'.
----------------------------------------------------------------------------
Timing SoftFloat
A program called `timesoftfloat' for timing the SoftFloat functions is
included with the SoftFloat source code. Compiling `timesoftfloat' should
pose no difficulties once `softfloat.o' exists. The supplied Makefile
will create a `timesoftfloat' executable by default after generating
`softfloat.o'. See `timesoftfloat.txt' for documentation about using
`timesoftfloat'.
----------------------------------------------------------------------------
Compiler Options and Efficiency
In order to get good speed with SoftFloat, it is important that the compiler
inline the routines that have been marked `INLINE' in the code. Even if
inlining cannot be forced by an appropriate definition of the `INLINE'
macro, the compiler may still be able to perform inlining on its own as
an optimization. In that case, the Makefile should be edited to give the
compiler whatever option is required to cause it to inline small functions.
----------------------------------------------------------------------------
Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
The `softfloat-macros' source fragment defines arithmetic functions used
as primitives by `softfloat.c'. This file has been written in a target-
independent form. For a given target, it may be possible to improve on
these functions using target-specific and/or non-ISO-C features (such
as `asm' statements). For example, one of the "macro" functions takes
two word-size integers and returns their full product in two words.
This operation can be done directly in hardware on many processors; but
because it is not available through standard C, the function defined in
`softfloat-macros' uses four multiplications to achieve the same result.
To address these shortcomings, a customized version of `softfloat-macros'
can be created in any of the target-specific subdirectories. A simple
modification to the target's Makefile should be sufficient to ensure that
the custom version is used instead of the generic one.
----------------------------------------------------------------------------
Contact Information
At the time of this writing, the most up-to-date information about SoftFloat
and the latest release can be found at the Web page `http://www.jhauser.us/
arithmetic/SoftFloat.html'.

View File

@ -0,0 +1,241 @@
/*============================================================================
This C source fragment is part of the Berkeley SoftFloat IEEE Floating-Point
Arithmetic Package, Release 2c, by John R. Hauser.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TOLERATE ALL LOSSES, COSTS, OR OTHER
PROBLEMS THEY INCUR DUE TO THE SOFTWARE WITHOUT RECOMPENSE FROM JOHN HAUSER OR
THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE, AND WHO FURTHERMORE EFFECTIVELY
INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE
(possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR OTHER
PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE, OR
INCURRED BY ANYONE DUE TO A DERIVATIVE WORK THEY CREATE USING ANY PART OF THE
SOFTWARE.
Derivative works require also that (1) the source code for the derivative work
includes prominent notice that the work is derivative, and (2) the source code
includes prominent notice of these three paragraphs for those parts of this
code that are retained.
=============================================================================*/
/*----------------------------------------------------------------------------
| Underflow tininess-detection mode, statically initialized to default value.
| (The declaration in `softfloat.h' must match the `int8' type here.)
*----------------------------------------------------------------------------*/
int8 float_detect_tininess = float_tininess_after_rounding;
/*----------------------------------------------------------------------------
| Raises the exceptions specified by `flags'. Floating-point traps can be
| defined here if desired. It is currently not possible for such a trap
| to substitute a result value. If traps are not implemented, this routine
| should be simply `float_exception_flags |= flags;'.
*----------------------------------------------------------------------------*/
void float_raise( int8 flags )
{
float_exception_flags |= flags;
}
/*----------------------------------------------------------------------------
| Internal canonical NaN format.
*----------------------------------------------------------------------------*/
typedef struct {
flag sign;
bits32 high, low;
} commonNaNT;
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
enum {
float32_default_nan = 0xFFFFFFFF
};
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_nan( float32 a )
{
return ( 0xFF000000 < (bits32) ( a<<1 ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float32_is_signaling_nan( float32 a )
{
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT *float32ToCommonNaN( float32 a )
{
static commonNaNT z;
if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
z.sign = a>>31;
z.low = 0;
z.high = a<<9;
return &z;
}
#endif
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the single-
| precision floating-point format.
*----------------------------------------------------------------------------*/
static float32 commonNaNToFloat32( commonNaNT *a )
{
return ( ( (bits32) a->sign )<<31 ) | 0x7FC00000 | ( a->high>>9 );
}
#endif
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static float32 propagateFloat32NaN( float32 a, float32 b )
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float32_is_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
bIsNaN = float32_is_nan( b );
bIsSignalingNaN = float32_is_signaling_nan( b );
a |= 0x00400000;
b |= 0x00400000;
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
if ( aIsNaN ) {
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
}
else {
return b;
}
}
#ifdef DOUBLES
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN. The `high' and
| `low' values hold the most- and least-significant bits, respectively.
*----------------------------------------------------------------------------*/
enum {
float64_default_nan_high = 0xFFFFFFFF,
float64_default_nan_low = 0xFFFFFFFF
};
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_nan( float64 a )
{
return
( 0xFFE00000 <= (bits32) ( a.high<<1 ) )
&& ( a.low || ( a.high & 0x000FFFFF ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
flag float64_is_signaling_nan( float64 a )
{
return
( ( ( a.high>>19 ) & 0xFFF ) == 0xFFE )
&& ( a.low || ( a.high & 0x0007FFFF ) );
}
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
static commonNaNT float64ToCommonNaN( float64 a )
{
commonNaNT z;
if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
z.sign = a.high>>31;
shortShift64Left( a.high, a.low, 12, &z.high, &z.low );
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the double-
| precision floating-point format.
*----------------------------------------------------------------------------*/
static float64 commonNaNToFloat64( commonNaNT a )
{
float64 z;
shift64Right( a.high, a.low, 12, &z.high, &z.low );
z.high |= ( ( (bits32) a.sign )<<31 ) | 0x7FF80000;
return z;
}
/*----------------------------------------------------------------------------
| Takes two double-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
static float64 propagateFloat64NaN( float64 a, float64 b )
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float64_is_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
bIsNaN = float64_is_nan( b );
bIsSignalingNaN = float64_is_signaling_nan( b );
a.high |= 0x00080000;
b.high |= 0x00080000;
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
if ( aIsNaN ) {
return ( aIsSignalingNaN & bIsNaN ) ? b : a;
}
else {
return b;
}
}
#endif

View File

@ -0,0 +1,4 @@
This is a collection of various math related functions found in math.h. All
functions are single precision (only), and are rather selected for their
compactness than speed.

View File

@ -0,0 +1,72 @@
#include <math.h>
#if 1
/* atan(x)= x(c1 + c2*x**2 + c3*x**4)/(c4 + c5*x**2 + c6*x**4 + x**6)
Accurate to about 13.7 decimal digits over the range [0, pi/12]. */
float _atan(float x)
{
const float c1= 48.70107004404898384f;
const float c2= 49.5326263772254345f;
const float c3= 9.40604244231624f;
const float c4= 48.70107004404996166f;
const float c5= 65.7663163908956299f;
const float c6= 21.587934067020262f;
float x2;
x2 = x * x;
return (x * (c1 + x2 * (c2 + x2 * c3)) / (c4 + x2 * (c5 + x2 * (c6 + x2))));
}
#define TAN_SIXTHPI 0.009138776996f
#define TAN_TWELFTHPI 0.004569293096f
float atanf(float x)
{
float y;
int complement= 0; // true if arg was >1
int region= 0; // true depending on region arg is in
int sign= 0; // true if arg was < 0
if (x < 0.0f ) {
// x = -x;
// x = x * -1.0f;
x = -1.0f * x;
sign = 1; // arctan(-x)=-arctan(x)
}
if (x > 1.0f) {
x = 1.0f / x; // keep arg between 0 and 1
complement = 1;
}
if (x > TAN_TWELFTHPI) {
/* FIXME: reduce arg to under tan(pi/12) */
#if 1
float n, m;
n = (TAN_SIXTHPI * x) + 1.0f;
m = (x - TAN_SIXTHPI);
// x = (x - TAN_SIXTHPI) / (1.0f + (TAN_SIXTHPI * x));
x = m / n;
#else
x = fmodf(x, TAN_SIXTHPI);
#endif
region = 1;
}
y = _atan(x);
if (region) { y += (M_PI / 6.0f); } /* correct for region we're in */
if (complement) { y= (M_PI / 2.0f) - y; } /* correct for 1/x */
if (sign) { y =- y; } /* correct for negative arg */
return y;
}
#endif
#if 0
float atanf(float x)
{
x = x;
return 0.0f;
}
#endif

View File

@ -0,0 +1,14 @@
#include <math.h>
/* FIXME: this is really too simple */
float ceilf(float x)
{
int n = (int) x;
if (n >= x) {
return n;
}
return n + 1;
}

View File

@ -0,0 +1,67 @@
/* nicked from https://github.com/AZHenley/cosine/blob/master/cosine.c */
/*
MIT License
Copyright (c) 2020 Austin Henley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <math.h>
#define RUNTERMS 8
float cosf(float x)
{
int i;
int div;
float num;
float result = 1.0f;
float inter = 1.0f;
float comp;
float den;
div = (int)(x / M_PI);
x = x - (div * M_PI);
num = x * x;
for (i = 1; i <= RUNTERMS; i++) {
comp = 2.0f * i;
den = comp * (comp - 1.0f);
inter *= num / den;
if (i % 2 == 0) {
result += inter;
} else {
result -= inter;
}
}
if (div % 2 != 0) {
return result * -1.0f;
}
return result;
}
#if 0
float cosf(float x) {
return sinf(x + (M_PI / 2.0));
}
#endif

View File

@ -0,0 +1,73 @@
#include <math.h>
#if 1
/* natural logarithm of 2 */
#define LN2 0.693147180559945309417f
// #include <stdio.h>
// char abuf[100];
// char abuf2[100];
// char abuf3[100];
float expf(float x)
{
float p;
int i;
int k;
// float i;
// float k;
float r;
float tn;
float x0 = fabsf(x); // FIXME: somehow this doesnt work!
if (x == 0) {
return 1;
}
x0 = fabsf(x);
// printf("x:%s x0:%s\n", _ftostr(abuf3, x), _ftostr(abuf, x0));
k = ceilf((x0 / LN2) - 0.5f);
p = (float)(1 << (int)k);
r = x0 - (LN2 * (float)k); // internal error
tn = 1.0f;
// printf("k:%s tn:%s r:%s\n", _ftostr(abuf3, k), _ftostr(abuf, tn), _ftostr(abuf2, r ));
for (i = 14; i > 0; --i) {
//tn = tn * (r / (float)i) + 1.0f;
float tmp;
tmp = (r / (float)i);
tn = tn * tmp;
tn = tn + 1.0f;
// printf("i:%d tn:%s tmp:%s\n", i, _ftostr(abuf, tn), _ftostr(abuf2, tmp ));
}
p *= tn;
if (x < 0) {
return 1.0f / p;
}
return p;
}
#endif
#if 0
static float expf(float n) {
int a = 0, b = n > 0;
float c = 1, d = 1, e = 1;
for (b || (n = -n); e + .00001 < (e += (d *= n) / (c *= ++a));); // "Floating point type is currently unsupported"
// for (b || (n = -n); e + .00001 < (e = e + (d *= n) / (c *= ++a));); // "Floating point type is currently unsupported"
// approximately 15 iterations
return b ? e : 1 / e;
}
#endif
#if 0
float expf(float x)
{
x = x;
return 0.0f;
}
#endif

View File

@ -0,0 +1,6 @@
#include <math.h>
float fabsf(float x) {
return x < 0.0f ? -x : x;
}

View File

@ -0,0 +1,17 @@
#include <math.h>
/* FIXME: this is really too simple */
float ffloor(float x)
{
signed long n;
float d;
n = (signed long)x;
d = (float)n;
if (x >= 0) {
return d;
}
return d - 1;
}

View File

@ -0,0 +1,9 @@
#include <math.h>
float fmodf(float x, float y)
{
float res;
res = x / y;
return x - (truncf(res) * y);
}

View File

@ -0,0 +1,130 @@
#include <math.h>
/* natural logarithm */
#if 1
/*#define LOGBASE 10*/
#define LOGBASE 2 /* e=2.7182818... */
float logf(float x)
{
int i;
float alpha;
float save;
float ans;
alpha = (x-1)/(x+1);
ans = alpha;
save = ans * alpha * alpha;
for (i = 2 ; i <= LOGBASE ; i++) {
ans += (1.0/(float)(2*i-1)) * save;
save = save * alpha * alpha;
}
return 2.0*ans;
}
#endif
#if 0
static int msb(int a)
{
unsigned int r = 0;
while(a >>= 1) {
r++;
}
return r;
}
float logf(float y)
{
float result;
int log2;
float divisor, x;
log2 = msb((int)y);
divisor = (float)(1 << log2);
x = y / divisor;
result = -1.7417939f + (2.8212026f + (-1.4699568f + (0.44717955f - 0.056570851f * x) * x) * x) * x;
result += ((float)log2) * 0.69314718f; // ln(2) = 0.69314718
return result;
}
#endif
#if 0
float logf(float x)
{
// ASSUMING:
// - non-denormalized numbers i.e. x > 2^126
// - integer is 32 bit. float is IEEE 32 bit.
// INSPIRED BY:
// - https://stackoverflow.com/a/44232045
// - http://mathonweb.com/help_ebook/html/algorithms.htm#ln
// - https://en.wikipedia.org/wiki/Fast_inverse_square_root
// FORMULA:
// x = m * 2^p =>
// ln(x) = ln(m) + ln(2)p,
// first normalize the value to between 1.0 and 2.0
// assuming normalized IEEE float
// sign exp frac
// 0b 0 [00000000] 00000000000000000000000
// value = (-1)^s * M * 2 ^ (exp-127)
//
// exp = 127 for x = 1,
// so 2^(exp-127) is the multiplier
// evil floating point bit level hacking
unsigned long bx = * (unsigned long *) (&x);
// extract exp, since x>0, sign bit must be 0
unsigned long ex = bx >> 23;
signed long t = (signed long)ex-(signed long)127;
unsigned long s = (t < 0) ? (-t) : t;
// reinterpret back to float
// 127 << 23 = 1065353216
// 0b11111111111111111111111 = 8388607
bx = 1065353216 | (bx & 8388607);
x = * (float *) (&bx);
// use remez algorithm to find approximation between [1,2]
// - see this answer https://stackoverflow.com/a/44232045
// - or this usage of C++/boost's remez implementation
// https://computingandrecording.wordpress.com/2017/04/24/
// e.g.
// boost::math::tools::remez_minimax<double> approx(
// [](const double& x) { return log(x); },
// 4, 0, 1, 2, false, 0, 0, 64);
//
// 4th order is:
// { -1.74178, 2.82117, -1.46994, 0.447178, -0.0565717 }
//
// 3rd order is:
// { -1.49278, 2.11263, -0.729104, 0.10969 }
return
/* less accurate */
-1.49278+(2.11263+(-0.729104+0.10969*x)*x)*x
/* OR more accurate */
// -1.7417939+(2.8212026+(-1.4699568+(0.44717955-0.056570851*x)*x)*x)*x
/* compensate for the ln(2)s. ln(2)=0.6931471806 */
+ 0.6931471806*t;
}
#endif
#if 0
float logf(float y)
{
return 0.0f;
}
#endif

View File

@ -0,0 +1,7 @@
#include <math.h>
float powf(float x, float y)
{
return expf(x * logf(y));
}

View File

@ -0,0 +1,11 @@
#include <math.h>
/* FIXME: this is really too simple */
float roundf(float x)
{
if (x > 0.0f) {
return (float)((signed long)(x + 0.5f));
}
return (float)((signed long)(x - 0.5f));
}

View File

@ -0,0 +1,6 @@
#include <math.h>
float sinf(float x) {
return cosf(x - (M_PI / 2.0));
}

View File

@ -0,0 +1,90 @@
#if 1
static float powerOfTen(int num)
{
int i;
// float rst = 1.0f;
float rst;
rst = 1.0f;
if(num >= 0) {
for(i = 0; i < num ; ++i) {
// rst *= 10.0;
rst = rst * 10.0f;
}
} else {
for(i = 0; i < (0 - num); ++i) {
// rst *= 0.1;
rst = rst * 0.1f;
}
}
return rst;
}
#define MAXDIGITS 8
float sqrtf(float a)
{
// float rst = 0.0f;
float rst;
// float z = a;
float z;
signed int i;
// float j = 1.0f;
float j;
float power;
rst = 0.0f;
z = a;
j = 1.0f;
for(i = MAXDIGITS ; i > 0 ; i--) {
power = powerOfTen(i);
// value must be bigger then 0
if(z - (( 2.0f * rst ) + ( j * power)) * ( j * power) >= 0) {
while( z - (( 2.0f * rst ) + ( j * power)) * ( j * power) >= 0) {
//j++;
j = j + 1.0f;
if(j >= 10.0f) {
break;
}
}
//j--; //correct the extra value by minus one to j
j = j - 1.0f;
//z -= (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
z = z - (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
//rst += j * power; // find sum of a
rst = rst + (j * power); // find sum of a
j = 1.0f;
}
}
for(i = 0 ; i >= 0 - MAXDIGITS ; i--) {
power = powerOfTen(i);
if(z - (( 2.0f * rst ) + ( j * power))*( j * power) >= 0) {
while( z - (( 2.0f * rst ) + ( j * power))*( j * power) >= 0) {
//j++;
j = j + 1.0f;
if(j >= 10.0f) {
break;
}
}
//j--; //correct the extra value by minus one to j
j = j - 1.0f;
//z -= (( 2.0f * rst ) + ( j * power))*( j * power); //find value of z
z = z - (( 2.0f * rst ) + ( j * power)) * ( j * power); //find value of z
//rst += j * power; // find sum of a
rst = rst + (j * power); // find sum of a
j = 1.0f;
}
}
// find the number on each digit
return rst;
}
#endif
#if 0
float sqrtf(float a)
{
a = a;
return 0.0f;
}
#endif

View File

@ -0,0 +1,52 @@
#include <math.h>
#if 1
/* The input argument is in radians. Note that the function
computes tan(pi*x/4), NOT tan(x); it's up to the range
reduction algorithm that calls this to scale things properly.
Algorithm:
tan(x)= x(c1 + c2*x**2 + c3*x**4)/(c4 + c5*x**2 + c6*x**4 + x**6)
Accurate to about 14 decimal digits over the range [0, pi/4]. */
static float _tan(float x)
{
const float c1=-34287.4662577359568109624f;
const float c2= 2566.7175462315050423295f;
const float c3=- 26.5366371951731325438f;
const float c4=-43656.1579281292375769579f;
const float c5= 12244.4839556747426927793f;
const float c6=- 336.611376245464339493f;
float x2;
x2 = x * x;
return (x * (c1 + x2 * (c2 + x2 * c3)) / (c4 + x2 * (c5 + x2 * (c6 + x2))));
}
float tanf(float x){
int octant;
x = fmodf(x, (2.0f * M_PI));
octant=(int)(x * (4.0f / M_PI));
switch (octant){
case 0: return _tan(x * (4.0f / M_PI));
case 1: return 1.0f / _tan(((M_PI / 2.0f) - x) * (4.0f / M_PI));
case 2: return -1.0f / _tan((x - (M_PI / 2.0f)) * (4.0f / M_PI));
case 3: return - _tan((M_PI - x) * (4.0f / M_PI));
case 4: return _tan((x - M_PI) * (4.0f / M_PI));
case 5: return 1.0f / _tan(((3.0f * M_PI / 2.0f) - x) * (4.0f / M_PI));
case 6: return -1.0f / _tan((x - (3.0f * M_PI / 2.0f)) * (4.0f / M_PI));
case 7: return - _tan(((2.0f * M_PI)-x) * (4.0f / M_PI));
}
}
#endif
#if 0
float tanf(float x)
{
x = x;
return 0.0f;
}
#endif

View File

@ -0,0 +1,8 @@
#include <math.h>
/* FIXME: this is really too simple */
float truncf(float x)
{
return (float)((signed long)x);
}

View File

@ -0,0 +1,66 @@
; import/overload stubs for the VIC20 kernal floating point implementation
.import ___cbmkernal_afloat
.import ___cbmkernal_aufloat
.import ___cbmkernal_axfloat
.import ___cbmkernal_axufloat
.import ___cbmkernal_eaxfloat
.import ___cbmkernal_eaxufloat
.import ___cbmkernal_feaxint
.import ___cbmkernal_feaxlong
.import ___cbmkernal_fbnegeax
.import ___cbmkernal_ftosaddeax
.import ___cbmkernal_ftossubeax
.import ___cbmkernal_ftosdiveax
.import ___cbmkernal_ftosmuleax
.import ___cbmkernal_ftoseqeax
.import ___cbmkernal_ftosneeax
.import ___cbmkernal_ftosgteax
.import ___cbmkernal_ftoslteax
.import ___cbmkernal_ftosgeeax
.import ___cbmkernal_ftosleeax
.export afloat := ___cbmkernal_afloat
.export aufloat := ___cbmkernal_aufloat
.export axfloat := ___cbmkernal_axfloat
.export axufloat := ___cbmkernal_axufloat
.export eaxfloat := ___cbmkernal_eaxfloat
.export eaxufloat := ___cbmkernal_eaxufloat
.export feaxint := ___cbmkernal_feaxint
.export feaxlong := ___cbmkernal_feaxlong
.export fbnegeax := ___cbmkernal_fbnegeax
.export ftosaddeax := ___cbmkernal_ftosaddeax
.export ftossubeax := ___cbmkernal_ftossubeax
.export ftosdiveax := ___cbmkernal_ftosdiveax
.export ftosmuleax := ___cbmkernal_ftosmuleax
.export ftoseqeax := ___cbmkernal_ftoseqeax
.export ftosneeax := ___cbmkernal_ftosneeax
.export ftosgteax := ___cbmkernal_ftosgteax
.export ftoslteax := ___cbmkernal_ftoslteax
.export ftosgeeax := ___cbmkernal_ftosgeeax
.export ftosleeax := ___cbmkernal_ftosleeax
.import ___cbmkernal_powf
.import ___cbmkernal_sinf
.import ___cbmkernal_cosf
.import ___cbmkernal_logf
.import ___cbmkernal_expf
.import ___cbmkernal_sqrtf
.import ___cbmkernal_tanf
.import ___cbmkernal_atanf
.import ___cbmkernal_fabsf
.import ___cbmkernal_roundf
.import ___cbmkernal_truncf
.export _powf := ___cbmkernal_powf
.export _sinf := ___cbmkernal_sinf
.export _cosf := ___cbmkernal_cosf
.export _logf := ___cbmkernal_logf
.export _expf := ___cbmkernal_expf
.export _sqrtf := ___cbmkernal_sqrtf
.export _tanf := ___cbmkernal_tanf
.export _atanf := ___cbmkernal_atanf
.export _fabsf := ___cbmkernal_fabsf
.export _roundf := ___cbmkernal_roundf
.export _truncf := ___cbmkernal_truncf

View File

@ -164,9 +164,11 @@ EXELIST_apple2 = \
checkversion \
diodemo \
enumdevdir \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
mousedemo \
multdemo \
ovrldemo \
@ -180,9 +182,11 @@ EXELIST_apple2enh = $(EXELIST_apple2)
EXELIST_atari = \
ascii \
checkversion \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
mousedemo \
multdemo \
ovrldemo \
@ -202,8 +206,10 @@ EXELIST_atari5200 = \
EXELIST_atmos = \
ascii \
checkversion \
floattest \
hello \
mandelbrot \
mandelfloat \
sieve \
terminal \
tgidemo
@ -215,24 +221,30 @@ EXELIST_c64 = \
ascii \
checkversion \
enumdevdir \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
mathtest \
mousedemo \
multdemo \
ovrldemo \
sieve \
terminal \
tinyshell \
tgidemo
tgidemo \
tgisincos
EXELIST_c128 = \
ascii \
checkversion \
enumdevdir \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
mousedemo \
sieve \
terminal \
@ -249,8 +261,10 @@ EXELIST_c16 = \
EXELIST_cbm510 = \
ascii \
checkversion \
floattest \
gunzip65 \
hello \
mandelfloat \
mousedemo \
terminal \
tinyshell \
@ -259,8 +273,10 @@ EXELIST_cbm510 = \
EXELIST_cbm610 = \
ascii \
checkversion \
floattest \
gunzip65 \
hello \
mandelfloat \
terminal \
tinyshell \
sieve
@ -273,9 +289,11 @@ EXELIST_cx16 = \
ascii \
checkversion \
enumdevdir \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
mousedemo \
sieve \
tinyshell \
@ -311,7 +329,9 @@ EXELIST_pet = \
ascii \
checkversion \
enumdevdir \
floattest \
hello \
mandelfloat \
tinyshell \
sieve
@ -319,8 +339,10 @@ EXELIST_plus4 = \
ascii \
checkversion \
enumdevdir \
floattest \
gunzip65 \
hello \
mandelfloat \
terminal \
tinyshell \
sieve
@ -343,9 +365,11 @@ EXELIST_kim1 = \
EXELIST_telestrat = \
ascii \
checkversion \
floattest \
gunzip65 \
hello \
mandelbrot \
mandelfloat \
sieve \
tgidemo
@ -353,8 +377,10 @@ EXELIST_vic20 = \
ascii \
checkversion \
enumdevdir \
floattest \
hello \
mandelbrot \
mandelfloat \
sieve \
tgidemo
@ -447,6 +473,22 @@ ovrldemo: overlaydemo.o
OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I)
# link float examples against the (much faster) kernal lib, if available
ifeq ($(SYS),c64)
floattest: override CFLAGS += -D DYN_DRV=0
floattest: floattest.o
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
mandelfloat.o: override CFLAGS += -D DYN_DRV=0
mandelfloat: mandelfloat.o
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
mathtest.o: override CFLAGS += -D DYN_DRV=0
mathtest: mathtest.o
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
tgisincos.o: override CFLAGS += -D DYN_DRV=0
tgisincos: tgisincos.o
$(LD) $(LDFLAGS) -o $@ -C c64.cfg -m $@.map $^ c64-fp754kernal.o $(SYS).lib
endif
# --------------------------------------------------------------------------
# TGI programs on the VIC-20 need a special ld65 configuration file.

36
samples/floattest.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <_float.h>
char buf[100];
// quick check to see if printing float value works
void constants(void)
{
printf("-100.0 %15s\n", _ftostr(buf, -100.0f));
printf(" -10.0 %15s\n", _ftostr(buf, -10.0f));
printf(" -1.0 %15s\n", _ftostr(buf, -1.0f));
printf(" -0.1 %15s\n", _ftostr(buf, -0.1f));
printf(" -0.01 %15s\n", _ftostr(buf, -0.01f));
printf(" -0.001 %15s\n", _ftostr(buf, -0.001f));
printf(" -0.0001 %15s\n", _ftostr(buf, -0.0001f));
printf(" -0.00001 %15s\n", _ftostr(buf, -0.00001f));
printf(" 0.0 %15s\n", _ftostr(buf, 0.0f));
printf(" 0.1 %15s\n", _ftostr(buf, 0.1f));
printf(" 0.01 %15s\n", _ftostr(buf, 0.01f));
printf(" 0.001 %15s\n", _ftostr(buf, 0.001f));
printf(" 0.0001 %15s\n", _ftostr(buf, 0.0001f));
printf(" 0.00001 %15s\n", _ftostr(buf, 0.00001f));
printf(" 1.0 %15s\n", _ftostr(buf, 1.0f));
printf(" 10.0 %15s\n", _ftostr(buf, 10.0f));
printf(" 100.0 %15s\n", _ftostr(buf, 100.0f));
printf("<key>\n");
// cgetc();
}
int main(void)
{
constants();
return 0;
}

74
samples/mandelfloat.c Normal file
View File

@ -0,0 +1,74 @@
/*
* $ cl65 -o mandelfloat.prg mandelfloat.c
*
* use the CBM kernal fp routines like this:
*
* $ cl65 -o mandelfloat.prg mandelfloat.c c64-fp488kernal.o
*
*/
#include <stdio.h>
#include <stdlib.h>
#define MAX_ITER 40
#define XRES 20
#define YRES 20
#define XMIN -2.25f
#define XMAX 2.25f
#define YMIN -2.25f
#define YMAX 2.25f
// FIXME: Invalid operands for binary operator '-'
// #define XRANGE (XMAX - XMIN)
// #define YRANGE (YMAX - YMIN)
#define XRANGE 4.5f
#define YRANGE 4.5f
#define XSTEP (XRANGE / XRES)
#define YSTEP (YRANGE / YRES)
char *colortab = ".+*#%$=-";
void color(int iterations) {
if (iterations >= MAX_ITER) {
putchar(' ');
} else {
putchar(colortab[iterations & 7]);
}
}
float x, y; /* Coordinates of the current point in the complex plane. */
float u, v; /* Coordinates of the iterated point. */
unsigned char i, j; /* Pixel counters */
unsigned char k; /* Iteration counter */
float u, v;
float u2, v2;
int main(void)
{
for (j = 0; j < YRES; j++) {
y = YMIN + j * YSTEP;
for(i = 0; i < XRES; i++) {
u = 0.0f;
v = 0.0f;
u2 = 0.0f;
v2 = 0.0f;
x = i * XSTEP + XMIN;
/* iterate the point */
for (k = 1; (k < MAX_ITER) && ((u2 + v2) < 4.0f); ++k) {
v = 2.0f * u * v + y;
u = u2 - v2 + x;
u2 = u * u;
v2 = v * v;
};
color(k);
}
putchar('\n');
}
}

218
samples/mathtest.c Normal file
View File

@ -0,0 +1,218 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef __CC65__
#include <conio.h> // for cgetc
#else
#define cgetc()
char *_ftostr(char *d, float s);
#endif
#ifdef __SIM6502__
#define cgetc()
#endif
char buf[100];
/*
float __fastcall__ sinf(float s);
float __fastcall__ cosf(float s);
float __fastcall__ tanf(float x);
float __fastcall__ atanf(float x);
*/
float atanvalues[8]= {
0.50f, // 0.46
-1.50f, // -0.98
};
void sincostanatan(void)
{
int n;
float angle = 0.0;
// float angle = -M_PI;
printf("sinus:\n");
angle = 0.0;
for (n = 0; n < 18; n++) {
printf("%15s ", _ftostr(buf, angle));
printf("%15s", _ftostr(buf, sinf(angle)));
printf("\n");
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
angle = angle + ((M_PI * 2.0f) / 16);
}
printf("<key>\n"); cgetc();
printf("cosinus:\n");
angle = 0.0;
for (n = 0; n < 18; n++) {
printf("%15s ", _ftostr(buf, angle));
printf("%15s", _ftostr(buf, cosf(angle)));
printf("\n");
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
angle = angle + ((M_PI * 2.0f) / 16);
}
printf("<key>\n"); cgetc();
printf("tangens:\n");
angle = 0.0;
for (n = 0; n < 18; n++) {
printf("%15s ", _ftostr(buf, angle));
printf("%15s", _ftostr(buf, tanf(angle)));
printf("\n");
// angle += (M_PI / 8); Error: Invalid left operand for binary operator '+='
angle = angle + ((M_PI * 2.0f) / 16);
}
printf("<key>\n"); cgetc();
printf("atan:\n");
angle = 0.0;
for (n = 0; n < 2; n++) {
printf("%15s ", _ftostr(buf, atanvalues[n]));
printf("%15s", _ftostr(buf, atanf(atanvalues[n])));
printf("\n");
}
printf("<key>\n"); cgetc();
}
/*
float __fastcall__ roundf(float x);
float __fastcall__ truncf(float x);
float __fastcall__ fabsf(float x);
*/
float roundtruncvals[22] = {
2.0f,
1.9f,
1.5f,
1.4f,
1.1f,
1.0f,
0.9f,
0.5f, // 1.0
0.4f,
0.1f,
0.0f,
-0.1f,
-0.4f,
-0.5f, // -1.0
-0.501f, // -1.0
-0.9f,
-1.0f,
-1.1f,
-1.4f,
-1.5f,
-1.5001f,
-1.9f,
// -2.0f,
// -2.1f,
};
void roundtruncabs(void)
{
int n;
printf("round/trunc:\n");
for (n = 0; n < 21; n++) {
printf("%12s", _ftostr(buf, roundtruncvals[n]));
printf("%12s", _ftostr(buf, roundf(roundtruncvals[n])));
printf("%12s", _ftostr(buf, truncf(roundtruncvals[n])));
printf("\n");
}
printf("<key>\n"); cgetc();
printf("abs/ceil:\n");
for (n = 0; n < 21; n++) {
printf("%12s", _ftostr(buf, roundtruncvals[n]));
printf("%12s", _ftostr(buf, fabsf(roundtruncvals[n])));
printf("%12s", _ftostr(buf, ceilf(roundtruncvals[n])));
printf("\n");
}
printf("<key>\n"); cgetc();
}
/*
float __fastcall__ powf(float f, float a);
float __fastcall__ sqrtf(float x);
*/
float powvals0[8] = {
2,
10,
2,
10
};
float powvals1[8] = {
3,
3,
4,
4
};
float sqrtvals[8] = {
9,
2,
1,
16,
0,
4,
5,
6
};
void powersqrt(void)
{
int n;
printf("pow:\n");
for (n = 0; n < 4; n++) {
printf("%12s", _ftostr(buf, powvals0[n]));
printf("%12s", _ftostr(buf, powvals1[n]));
printf("%12s", _ftostr(buf, powf(powvals0[n], powvals1[n])));
printf("\n");
}
printf("sqrt:\n");
for (n = 0; n < 8; n++) {
printf("%12s", _ftostr(buf, sqrtvals[n]));
printf("%12s", _ftostr(buf, sqrtf(sqrtvals[n])));
printf("\n");
}
printf("<key>\n"); cgetc();
}
/*
float __fastcall__ logf(float x);
float __fastcall__ expf(float x);
*/
float logvals[8] = {
1.0f, // 0
5.6f, // 1.72
10.0f, // 2.302585
};
float expvals[8] = {
12.0f, // 162754.79
5.0f, // 148.413159
4.0f, // 54.598150
3.0f, // 20.085537
};
void logexp(void)
{
int n;
printf("log:\n");
for (n = 0; n < 3; n++) {
printf("%12s", _ftostr(buf, logvals[n]));
printf("%12s", _ftostr(buf, logf(logvals[n])));
printf("\n");
}
printf("exp:\n");
for (n = 0; n < 4; n++) {
printf("%12s", _ftostr(buf, expvals[n]));
printf("%12s", _ftostr(buf, expf(expvals[n])));
printf("\n");
}
printf("<key>\n"); cgetc();
}
int main(void)
{
roundtruncabs();
sincostanatan();
logexp();
powersqrt();
}

View File

@ -81,6 +81,18 @@ Platforms: Runs on all platforms that have TGI support:
Apple ][, Atari, C64, C128, Oric Atmos and Telestrat, GEOS,
and NES.
-----------------------------------------------------------------------------
Name: mandelfloat
Description: A very simple mandelbrot calculator, which uses floats and out-
puts the result to console.
Platforms: Runs on all platforms that have putchar();
-----------------------------------------------------------------------------
Name: mathtest
Description: Uses the floating point math.h functions to plot some more or
less interesting pattern
Platforms: Runs on all platforms that have putchar();
-----------------------------------------------------------------------------
Name: mousedemo
Description: Shows how to use the mouse.

362
samples/tgisincos.c Normal file
View File

@ -0,0 +1,362 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cc65.h>
#include <conio.h>
#include <ctype.h>
#include <modload.h>
#include <tgi.h>
char buf[100]; // for ftostr
char buf2[100]; // for ftostr
char buf3[100]; // for ftostr
#ifndef DYN_DRV
# define DYN_DRV 1
#endif
#define COLOR_BACK TGI_COLOR_BLACK
#define COLOR_FORE TGI_COLOR_WHITE
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Driver stuff */
static unsigned MaxX;
static unsigned MaxY;
static unsigned AspectRatio;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static void CheckError (const char* S)
{
unsigned char Error = tgi_geterror ();
if (Error != TGI_ERR_OK) {
printf ("%s: %u\n", S, Error);
if (doesclrscrafterexit ()) {
cgetc ();
}
exit (EXIT_FAILURE);
}
}
#if DYN_DRV
static void DoWarning (void)
/* Warn the user that the dynamic TGI driver is needed for this program */
{
printf ("Warning: This program needs the TGI\n"
"driver on disk! Press 'y' if you have\n"
"it - any other key exits.\n");
if (tolower (cgetc ()) != 'y') {
exit (EXIT_SUCCESS);
}
printf ("OK. Please wait patiently...\n");
}
#endif
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLUE };
#if 1
int XRes, YRes;
float xf, xfMin, xfMax, xfDelta, yf, yfMin, yfMax, yfDelta;
float radiusf, zf, zScale;
int x,y;
// unsigned char YMax;
int YMax;
unsigned int XResHalf;
float yfMinSquare;
float yfD;
float a;
float b;
float yfSquare;
int xoff = 0;
int yoff = 0;
void Dosincos(void) {
#if 1
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
#endif
/* Get stuff from the graph lib */
XRes = tgi_getmaxx() + 1;
// XRes = 320;
YRes = tgi_getmaxy() + 1;
// YRes = 200;
YMax = YRes - 1;
/* Compute and draw a 3d function. */
yfMin = -144.0f;
yfMax = 144.0f;
yf = 0;
// printf("yf:%s\n", _ftostr(buf, yf));
// printf("min:%s\n", _ftostr(buf, yfMin));
// printf("max:%s\n", _ftostr(buf, yfMax));
yfDelta = 2.25f;
zScale = -10.0f;
XResHalf = XRes * 0.5f;
yfMinSquare = yfMin * yfMin;
yoff = 20;
xoff = 0;
// for( yf = yfMin; yf < yfMax; yf += yfDelta) { // FIXME
// for( yf = yfMin; yf < yfMax; yf = yf + yfDelta) { // FIXME
for( yf = yfMin; yf < yfMax; yf = yfDelta + yf ) { // FIXME
// printf("yf:%s min:%s max:%s\n", _ftostr(buf, yf), _ftostr(buf2, yfMin), _ftostr(buf3, yfMax));
#if 0
float yfD;
float a;
float b;
float yfSquare;
#endif
#if 0
/* add some very fake perspective */
yoff++;
xoff--;
#endif
// xfMax = sqrtf( yfMinSquare - yf * yf);
xfMax = sqrtf( yfMinSquare - (yf * yf));
xfMin = -xfMax; // trigger fnegeax
xfDelta = 1.0f;
// Constant terms from the inner loop
yfD = yf / yfDelta;
a = XResHalf + yfD;
// b= YMax + yfD - 90;
b= YMax + yfD - 90.0f;
yfSquare = yf * yf;
// for( xf = xfMin; xf < xfMax; xf += xfDelta) {
for( xf = xfMin; xf < xfMax; xf = xf + xfDelta) {
// printf("xf:%s xfmax:%s\n", _ftostr(buf2, xf), _ftostr(buf3, xfMax));
radiusf = .0327f * sqrtf( (xf * xf) + yfSquare);
zf = zScale * (cosf(7.7f * radiusf) +
cosf(8.5f * radiusf) +
cosf(9.3f * radiusf));
/* Scale to screen coordinates */
x = 1.0f * ( xf + a);
x += xoff;
y = 0.8f * ( b - zf);
y += yoff;
//printf("x: %d y: %d\n", x, y);
if( y > 0 && y < YRes) {
tgi_setpixel( x, y);
/* Clear horizon under y. */
if( y < YMax) {
tgi_setcolor (COLOR_BACK);
tgi_line( x, y + 1, x, YMax);
tgi_setcolor (COLOR_FORE);
}
}
}
}
cgetc();
}
#endif
/*
5 dim xp, yp, r, fl, xr, yr, x, y, f
6 dim ad, yq, xl, q
7 m7 = 504
e4 = 40
8 yl = 200
n1 = -1
n5 = 0.5
nh = 900
eh = 100
hs = 160
sf = 3136
vz = 196
s = 1
a = 7872
10 dim bi(7), mi(319), ma(319), l(3000), p(30,120)
11 for t = 0 to 7
bi(7-t) = s
s = s + s
next : rem bit table
13 for t = 0 to yl
if (7 and t) = 0 then a = a + 320
14 l(t) = a
next : rem line addr table
15 for x = 0 to 319
mi(x) = yl
ma(x) = n1
next : rem min/max buffer
19 for y = 30 to 0 step n1
yq = y * y
xp = int(4 * sqr(nh - yq) + n5)
20 for x= 0 to xp
r = sqr(x * x / sf + yq /vz)
21 f = cos(r) - cos(3 * r) / 3 + cos(5 * r) / 5 - cos(7 * r) / 7
p(y, x) = int(e4 * f + n5)
22 fl = 0
xp = hs + x - y
yp = eh + y + y - p(y, x)
23 if mi(xp) > yp then mi(xp) = yp: fl = 1
24 if ma(xp) < yp then ma(xp) = yp: fl = 1
25 if fl = 0 or yp < z or yp >= yl then 27
26 ad = l(yp) + (xp and m7) + (yp and 7)
poke ad, peek(ad) or bi(xp and 7)
27 fl = 0
xp = hs - x - y
28 if mi(xp) > yp then mi(xp) = yp: fl = 1
29 if ma(xp) < yp then ma(xp) = yp: fl = 1
30 if fl = 0 or yp < z or yp >= yl then 32
31 ad = l(yp) + (xp and m7) + (yp and 7)
poke ad, peek(ad) or bi(xp and 7)
32 next
next
33 for y = -1 to -30 step n1
yq = y * y
xp = int(4 * sqr(nh - yq) + n5)
35 for x = 0 to xp
36 fl = 0
xp = hs + x - y
yp = eh + y + y - p(-y,x)
37 if mi(xp) > yp then mi(xp) = yp: fl = 1
38 if ma(xp) < yp then ma(xp) = yp: fl = 1
39 if fl = 0 or yp < z or yp >= yl then 41
40 ad = l(yp) + (xp and m7) + (yp and 7)
poke ad, peek(ad) or bi(xp and 7)
41 fl = 0
xp = hs - x - y
42 if mi(xp) > yp then mi(xp) = yp: fl = 1
43 if ma(xp) < yp then ma(xp) = yp: fl = 1
44 if fl = 0 or yp < z or yp >= yl then 46
45 ad = l(yp) + (xp and m7) + (yp and 7)
poke ad, peek(ad) or bi(xp and 7)
46 next
next
*/
int mi[320];
int ma[320];
int x, y;
int xp, yp;
int yq;
float r;
float f;
int p[30][120];
unsigned char fl;
void DoHat(void) {
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
for (x = 0; x < 320; x++) {
mi[x] = 200;
ma[x] = -1;
}
for (y = 30; y >= 0; y--) {
yq = y * y;
// xp = (int) (4.0f * sqrtf(900.0f - yq) + 0.5f); // Error: Invalid operands for binary operator '-'
xp = (int) (4.0f * sqrtf((float)(900 - yq)) + 0.5f);
for (x = 0; x < xp; x++) {
r = sqrtf((float)x * (float)x / 3136.0f + (float)yq / 196.0f);
f = cosf(r) - cosf(3.0f * r) / 3.0f + cosf(5.0f * r) / 5.0f - cosf(7.0f * r) / 7.0f;
p[y][x] = (int)((40.0f * f) + 0.5f);
fl = 0;
xp = 160 + x - y;
yp = 100 + y + y - p[y][x];
if (mi[xp] > yp) { mi[xp] = yp; fl = 1; }
if (ma[xp] < yp) { ma[xp] = yp; fl = 1; }
if (!((fl == 0) || (yp < 0) || (yp >= 200))) {
tgi_setpixel( xp, yp);
}
fl = 0;
xp = 160 - x - y;
if (mi[xp] > yp) { mi[xp] = yp; fl = 1; }
if (ma[xp] < yp) { ma[xp] = yp; fl = 1; }
if (!((fl == 0) || (yp < 0) || (yp >= 200))) {
tgi_setpixel( xp, yp);
}
}
}
cgetc();
}
int main (void)
{
unsigned char Border;
#if 1
#if DYN_DRV
/* Warn the user that the tgi driver is needed */
DoWarning ();
/* Load and initialize the driver */
tgi_load_driver (tgi_stddrv);
CheckError ("tgi_load_driver");
#else
/* Install the driver */
tgi_install (tgi_static_stddrv);
CheckError ("tgi_install");
#endif
tgi_init ();
CheckError ("tgi_init");
/* Get stuff from the driver */
MaxX = tgi_getmaxx ();
MaxY = tgi_getmaxy ();
AspectRatio = tgi_getaspectratio ();
/* Set the palette, set the border color */
Border = bordercolor (COLOR_BLACK);
#endif
/* Do graphics stuff */
Dosincos();
// DoHat();
#if DYN_DRV
/* Unload the driver */
tgi_unload ();
#else
/* Uninstall the driver */
tgi_uninstall ();
#endif
/* Reset the border */
(void) bordercolor (Border);
/* Done */
printf ("Done\n");
return EXIT_SUCCESS;
}

View File

@ -31,7 +31,7 @@
/* */
/*****************************************************************************/
//#define DEBUG
/* cc65 */
#include "asmcode.h"
@ -48,7 +48,13 @@
#include "typecmp.h"
#include "typeconv.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* Code */
@ -451,6 +457,8 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
unsigned Flags;
int MustScale;
LOG(("OpAssignArithmetic '%s' (Gen=%p)\n", Op, Gen));
ED_Init (&Expr2);
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
@ -465,7 +473,9 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
PushAddr (Expr);
if (Gen == 0) {
// printf("OpAssignArithmetic (gen=0) 1 lhs: %s rhs: %s\n",
// (TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
// (TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int");
/* Read the expression on the right side of the '=' */
MarkedExprWithCheck (hie1, &Expr2);
@ -477,8 +487,11 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
/* If necessary, load the value into the primary register */
LoadExpr (CF_NONE, &Expr2);
LOG(("OpAssignArithmetic '%s' (0) 2 lhs: %s rhs: %s\n",
Op,
(TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
(TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int"));
} else {
/* Load the original value if necessary */
LoadExpr (CF_NONE, Expr);
@ -489,8 +502,14 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
/* Read the expression on the right side of the '=' or 'op=' */
MarkedExprWithCheck (hie1, &Expr2);
/* The rhs must be an integer (or a float, but we don't support that yet */
if (!IsClassInt (Expr2.Type)) {
LOG(("OpAssignArithmetic '%s' (!=0) 2 lhs: %s rhs: %s\n",
Op,
(TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "int",
(TypeOf (Expr2.Type) == CF_FLOAT) ? "float" : "int"));
/* The rhs must be an integer or a float */
if (!IsClassInt (Expr2.Type) && !IsClassFloat (Expr2.Type)) {
Error ("Invalid right operand for binary operator '%s'", Op);
/* Continue. Wrong code will be generated, but the compiler won't
** break, so this is the best error recovery.
@ -523,9 +542,19 @@ static void OpAssignArithmetic (const GenDesc* Gen, ExprDesc* Expr, const char*
/* Special handling for add and sub - some sort of a hack, but short code */
if (Gen->Func == g_add) {
g_inc (Flags | CF_CONST, Expr2.IVal);
LOG(("OpAssignArithmetic '%s' gen g_add\n", Op));
if (IsClassFloat (Expr2.Type)) {
g_inc (Flags | CF_CONST, FP_D_As32bitRaw(Expr2.V.FVal));
} else {
g_inc (Flags | CF_CONST, Expr2.IVal);
}
} else if (Gen->Func == g_sub) {
g_dec (Flags | CF_CONST, Expr2.IVal);
LOG(("OpAssignArithmetic '%s' gen g_sub\n", Op));
if (IsClassFloat (Expr2.Type)) {
g_dec (Flags | CF_CONST, FP_D_As32bitRaw(Expr2.V.FVal));
} else {
g_dec (Flags | CF_CONST, Expr2.IVal);
}
} else {
if (!ED_IsUneval (Expr)) {
if (Expr2.IVal == 0 && !ED_IsUneval (Expr)) {
@ -605,6 +634,8 @@ void OpAssign (const GenDesc* Gen, ExprDesc* Expr, const char* Op)
{
const Type* ltype = Expr->Type;
LOG(("OpAssign\n"));
ExprDesc Expr2;
ED_Init (&Expr2);
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
@ -677,8 +708,9 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
return;
}
/* There must be an integer or pointer on the left side */
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type)) {
LOG(("OpAddSubAssign '%s'\n", Op));
/* There must be an integer, pointer or float on the left side */
if (!IsClassInt (Expr->Type) && !IsTypePtr (Expr->Type) && !IsTypeFloat (Expr->Type)) {
Error ("Invalid left operand for binary operator '%s'", Op);
/* Continue. Wrong code will be generated, but the compiler won't
** break, so this is the best error recovery.
@ -706,11 +738,9 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
ED_Init (&Expr2);
Expr2.Flags |= Expr->Flags & E_MASK_KEEP_SUBEXPR;
/* Evaluate the rhs. We expect an integer here, since float is not
** supported
*/
/* Evaluate the rhs. We expect an integer or float here */
hie1 (&Expr2);
if (!IsClassInt (Expr2.Type)) {
if (!IsClassInt (Expr2.Type) && !IsClassFloat (Expr2.Type)) {
Error ("Invalid right operand for binary operator '%s'", Op);
/* Continue. Wrong code will be generated, but the compiler won't
** break, so this is the best error recovery.
@ -721,7 +751,10 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
lflags |= CG_TypeOf (Expr->Type) | CG_AddrModeFlags (Expr) | CF_FORCECHAR;
rflags |= CG_TypeOf (Expr2.Type) | CF_FORCECHAR;
LOG(("OpAddSubAssign '%s' lflags:%04x rflags:%04x\n", Op, lflags, rflags));
if (ED_IsConstAbs (&Expr2)) {
LOG(("OpAddSubAssign '%s' result is constant\n", Op));
/* The resulting value is a constant */
rflags |= CF_CONST;
lflags |= CF_CONST;
@ -731,6 +764,7 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
Expr2.IVal *= CheckedSizeOf (Indirect (Expr->Type));
}
} else {
LOG(("OpAddSubAssign '%s' result is not constant\n", Op));
/* Not constant, load into the primary */
LoadExpr (CF_NONE, &Expr2);
@ -756,19 +790,40 @@ void OpAddSubAssign (const GenDesc* Gen, ExprDesc *Expr, const char* Op)
** static variable, register variable, pooled literal or code
** label location.
*/
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
if (IsClassFloat (Expr->Type)) {
LOG(("OpAddSubAssign '%s' abs, float %08x (IVal:%08lx)\n", Op, FP_D_As32bitRaw(Expr2.V.FVal), Expr2.IVal));
/* FIXME: what about the case when expr2 is NOT float? */
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqstatic (lflags, Expr->Name, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
} else {
g_subeqstatic (lflags, Expr->Name, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
}
} else {
g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
LOG(("OpAddSubAssign '%s' abs, int\n", Op));
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
} else {
g_subeqstatic (lflags, Expr->Name, Expr->IVal, Expr2.IVal);
}
}
break;
case E_LOC_STACK:
/* Value on the stack */
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqlocal (lflags, Expr->IVal, Expr2.IVal);
if (IsClassFloat (Expr->Type)) {
LOG(("OpAddSubAssign '%s' stack, float\n", Op));
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqlocal (lflags, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
} else {
g_subeqlocal (lflags, Expr->IVal, FP_D_As32bitRaw(Expr2.V.FVal));
}
} else {
g_subeqlocal (lflags, Expr->IVal, Expr2.IVal);
LOG(("OpAddSubAssign '%s' stack, int\n", Op));
if (Gen->Tok == TOK_PLUS_ASSIGN) {
g_addeqlocal (lflags, Expr->IVal, Expr2.IVal);
} else {
g_subeqlocal (lflags, Expr->IVal, Expr2.IVal);
}
}
break;

File diff suppressed because it is too large Load Diff

View File

@ -218,6 +218,10 @@ void g_reglong (unsigned from);
** is irrelevent of signedness).
*/
void g_regfloat (unsigned from);
/* Convert the value in the primary register to a float
*/
unsigned g_typeadjust (unsigned lhs, unsigned rhs);
/* Adjust the integer operands before doing a binary operation. lhs is a flags
** value, that corresponds to the value on TOS, rhs corresponds to the value
@ -274,8 +278,15 @@ void g_restore_regvars (int StackOffs, int RegOffs, unsigned Bytes);
/*****************************************************************************/
void g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
#ifdef DEBUG
// #define g_getimmed(a,b,c) _g_getimmed((a),(b),(c),(__FILE__),(__FUNCTION__),(__LINE__))
// void _g_getimmed(unsigned Flags, uintptr_t Val, long Offs, char *file, const char *func, int line);
#define g_getimmed(a,b,c) _g_getimmed((a),(b),(c))
void _g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
#else
#define g_getimmed(a,b,c) _g_getimmed((a),(b),(c))
void _g_getimmed (unsigned Flags, uintptr_t Val, long Offs);
#endif
/* Load a constant into the primary register */
void g_getstatic (unsigned Flags, uintptr_t Label, long Offs);
@ -396,6 +407,8 @@ void g_test (unsigned flags);
void g_push (unsigned flags, unsigned long val);
/* Push the primary register or a constant value onto the stack */
void g_push_float (unsigned flags, double val);
/* Push the primary register or a constant value onto the stack */
void g_swap (unsigned flags);
/* Swap the primary register and the top of the stack. flags give the type
@ -467,6 +480,8 @@ void g_res (unsigned n);
void g_defdata (unsigned flags, uintptr_t val, long offs);
/* Define data with the size given in flags */
void g_defdata_float (unsigned flags, uintptr_t val, long offs);
/* Define data with the size given in flags */
void g_defbytes (const void* bytes, unsigned count);
/* Output a row of bytes as a constant */

View File

@ -668,14 +668,23 @@ const Type* ArithmeticConvert (const Type* lhst, const Type* rhst)
** of the result. This pattern is called the usual arithmetic conversions.
*/
if (IsTypeFloat (lhst) && IsTypeFloat (rhst)) {
/* FIXME: float - this needs much more special handling */
return type_float;
}
if (IsTypeFloat (lhst)) {
/* FIXME: float - this needs much more special handling */
return type_float;
}
if (IsTypeFloat (rhst)) {
/* FIXME: float - this needs much more special handling */
return type_float;
}
/* There are additional rules for floating point types that we don't bother with, since
** floating point types are not (yet) supported.
** The integral promotions are performed on both operands.
*/
if (IsClassFloat(lhst) || IsClassFloat(rhst)) {
Error ("Floating point arithmetic not supported.");
return type_long;
}
lhst = IntPromotion (lhst);
rhst = IntPromotion (rhst);

File diff suppressed because it is too large Load Diff

View File

@ -31,10 +31,11 @@
/* */
/*****************************************************************************/
//#define DEBUG
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
@ -66,7 +67,13 @@
#include "typeconv.h"
#include "initdata.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* Data */
@ -165,34 +172,48 @@ static void ClosingCurlyBraces (unsigned BracesExpected)
static void DefineData (ExprDesc* Expr)
/* Output a data definition for the given expression */
{
int isfloat = (CG_TypeOf (Expr->Type) == CF_FLOAT);
LOG(("%s:%d DefineData IVal: %ld V.FVal: %f isfloat:%d %d\n", __FILE__, __LINE__,
Expr->IVal, (double)(Expr->V.FVal.V), isfloat, ED_GetLoc (Expr)));
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
/* Immediate numeric value with no storage */
g_defdata (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
/* FIXME: float */
if (isfloat) {
g_defdata_float (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal), 0);
} else {
g_defdata (CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
}
break;
/* FIXME: float - other cases */
case E_LOC_ABS:
if (isfloat) { printf("%s:%d FIXME: E_LOC_ABS\n", __FILE__, __LINE__); exit(-1); }
/* Absolute numeric address */
g_defdata (CF_ABSOLUTE | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
break;
case E_LOC_GLOBAL:
if (isfloat) { printf("%s:%d FIXME: E_LOC_GLOBAL\n", __FILE__, __LINE__); exit(-1); }
/* Global variable */
g_defdata (CF_EXTERNAL, Expr->Name, Expr->IVal);
break;
case E_LOC_STATIC:
if (isfloat) { printf("%s:%d FIXME: E_LOC_STATIC\n", __FILE__, __LINE__); exit(-1); }
/* Static variable */
g_defdata (CF_STATIC, Expr->Name, Expr->IVal);
break;
case E_LOC_LITERAL:
if (isfloat) { printf("%s:%d FIXME: E_LOC_LITERAL\n", __FILE__, __LINE__); exit(-1); }
/* Literal in the literal pool */
g_defdata (CF_LITERAL, Expr->Name, Expr->IVal);
break;
case E_LOC_REGISTER:
if (isfloat) { printf("%s:%d FIXME: E_LOC_REGISTER\n", __FILE__, __LINE__); exit(-1); }
/* Register variable. Taking the address is usually not
** allowed.
*/
@ -203,6 +224,7 @@ static void DefineData (ExprDesc* Expr)
break;
case E_LOC_CODE:
if (isfloat) { printf("%s:%d FIXME: E_LOC_CODE\n", __FILE__, __LINE__); exit(-1); }
/* Code label location */
g_defdata (CF_CODE, Expr->Name, Expr->IVal);
break;

View File

@ -31,7 +31,9 @@
/* */
/*****************************************************************************/
//#define DEBUG
#include <stdlib.h>
/* cc65 */
#include "codegen.h"
@ -41,7 +43,13 @@
#include "global.h"
#include "loadexpr.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* Code */
@ -52,6 +60,7 @@
static void LoadAddress (unsigned Flags, ExprDesc* Expr)
/* Load the primary register with some address value. */
{
LOG(("LoadAddress flags:%04x\n", Flags));
switch (ED_GetLoc (Expr)) {
case E_LOC_ABS:
@ -119,6 +128,7 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
** unfortunately.
*/
{
/*LOG(("LoadExpr flags:%4x\n", Flags));*/
if (!ED_IsAddrExpr (Expr)) {
/* Lvalue. If this is a bit field its type is unsigned. But if the
@ -171,57 +181,88 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
}
/* Load the content of Expr */
/*LOG(("LoadExpr ED_GetLoc:%04x\n", ED_GetLoc (Expr)));*/
switch (ED_GetLoc (Expr)) {
case E_LOC_NONE:
/* FIXME: float */
/*LOG(("LoadExpr E_LOC_NONE (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
/* Immediate number constant */
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
if (CG_TypeOf (Expr->Type) == CF_FLOAT) {
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal), 0);
} else {
g_getimmed (Flags | CF_IMM | CG_TypeOf (Expr->Type) | CF_CONST, Expr->IVal, 0);
}
break;
case E_LOC_ABS:
LOG(("LoadExpr E_LOC_ABS (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));
if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_ABS\n", __FILE__, __LINE__); exit(-1); }
/* Absolute numeric addressed variable */
g_getstatic (Flags | CF_ABSOLUTE, Expr->IVal, 0);
break;
case E_LOC_GLOBAL:
/* Global variable */
/* LOG(("LoadExpr E_LOC_GLOBAL (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_GLOBAL\n", __FILE__, __LINE__); exit(-1); } */
/* Global variable, offset in IVal */
g_getstatic (Flags | CF_EXTERNAL, Expr->Name, Expr->IVal);
break;
case E_LOC_STATIC:
/* Static variable */
/* LOG(("LoadExpr E_LOC_STATIC (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_STATIC\n", __FILE__, __LINE__); exit(-1); } */
/* Static variable, offset in IVal */
g_getstatic (Flags | CF_STATIC, Expr->Name, Expr->IVal);
break;
case E_LOC_LITERAL:
/* Literal in the literal pool */
/* LOG(("LoadExpr E_LOC_LITERAL (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_LITERAL\n", __FILE__, __LINE__); exit(-1); } */
/* Literal in the literal pool, offset in IVal */
g_getstatic (Flags | CF_LITERAL, Expr->Name, Expr->IVal);
break;
case E_LOC_REGISTER:
/* Register variable */
/* LOG(("LoadExpr E_LOC_REGISTER (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_REGISTER\n", __FILE__, __LINE__); exit(-1); } */
/* Register variable, offset in IVal */
g_getstatic (Flags | CF_REGVAR, Expr->Name, Expr->IVal);
break;
case E_LOC_CODE:
/* Code label location */
/* LOG(("LoadExpr E_LOC_CODE (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_CODE\n", __FILE__, __LINE__); exit(-1); } */
/* Code label location, offset in IVal */
g_getstatic (Flags | CF_CODE, Expr->Name, Expr->IVal);
break;
case E_LOC_STACK:
/* Value on the stack */
/* LOG(("LoadExpr E_LOC_STACK (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer")); */
/* if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_STACK\n", __FILE__, __LINE__); exit(-1); } */
/* Fetch value on the stack (with offset in IVal) */
g_getlocal (Flags, Expr->IVal);
break;
case E_LOC_PRIMARY:
/*LOG(("LoadExpr E_LOC_PRIMARY (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
/*if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_PRIMARY\n", __FILE__, __LINE__); exit(-1); }*/
/* The primary register */
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
** offset. Adjust the value in the primary accordingly.
*/
g_inc (Flags | CF_CONST, Expr->IVal);
if (CG_TypeOf (Expr->Type) == CF_FLOAT) {
/* FIXME: float */
Flags |= CF_FLOAT;
if (Expr->V.FVal.V != 0.0f) {
g_inc (Flags | CF_CONST, FP_D_As32bitRaw(Expr->V.FVal));
}
} else {
if (Expr->IVal != 0) {
/* We have an expression in the primary plus a constant
** offset. Adjust the value in the primary accordingly.
*/
g_inc (Flags | CF_CONST, Expr->IVal);
/* We might want to clear the offset, but we can't */
/* We might want to clear the offset, but we can't */
}
}
if (Flags & CF_TEST) {
g_test (Flags);
@ -229,7 +270,9 @@ void LoadExpr (unsigned Flags, struct ExprDesc* Expr)
break;
case E_LOC_EXPR:
/* Reference to address in primary with offset in Expr */
/*LOG(("LoadExpr E_LOC_EXPR (%s)\n", (CG_TypeOf (Expr->Type) == CF_FLOAT) ? "float" : "integer"));*/
/*if (CG_TypeOf (Expr->Type) == CF_FLOAT) { printf("%s:%d FIXME: E_LOC_EXPR\n", __FILE__, __LINE__); exit(-1); }*/
/* Reference to address in primary with offset in IVal */
g_getind (Flags, Expr->IVal);
/* Since the content in primary is now overwritten with the

View File

@ -31,7 +31,7 @@
/* */
/*****************************************************************************/
//#define DEBUG
/* common */
#include "xmalloc.h"
@ -57,7 +57,13 @@
#include "typeconv.h"
#include "input.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* Code */
@ -199,6 +205,8 @@ static void ParseAutoDecl (Declarator* Decl)
/* Get the size of the variable */
unsigned Size = SizeOf (Decl->Type);
LOG(("ParseAutoDecl SIze:%d IsCompound:%d\n", Size, IsCompound));
/* Check if this is a variable on the stack or in static memory */
if (IS_Get (&StaticLocals) == 0) {
@ -275,7 +283,20 @@ static void ParseAutoDecl (Declarator* Decl)
}
/* Push the value */
g_push (Flags | CG_TypeOf (Sym->Type), Expr.IVal);
if (CG_TypeOf (Sym->Type) == CF_FLOAT) {
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4244 ) // conversion from double to float
#endif
/* FIXME: float */
LOG(("ParseAutoDecl Expr.V.FVal.V: %f\n", Expr.V.FVal.V));
g_push_float (Flags | CG_TypeOf (Sym->Type), Expr.V.FVal.V);
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
} else {
g_push (Flags | CG_TypeOf (Sym->Type), Expr.IVal);
}
/* This has to be done at sequence point */
DoDeferred (SQP_KEEP_NONE, &Expr);

View File

@ -31,7 +31,7 @@
/* */
/*****************************************************************************/
//#define DEBUG
#include <stdio.h>
#include <stdlib.h>
@ -62,7 +62,13 @@
#include "standard.h"
#include "symtab.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* data */
@ -696,6 +702,8 @@ static void NumericConst (void)
/* Float constant */
Double FVal = FP_D_FromInt (IVal); /* Convert to double */
LOG(("NumericConst start IVal:%ld FVal: %f\n", IVal, FVal.V));
/* Check for a fractional part and read it */
if (SB_Peek (&Src) == '.') {
@ -771,6 +779,8 @@ static void NumericConst (void)
}
}
LOG(("NumericConst end FVal: %f\n", FVal.V));
/* Check for a suffix and determine the type of the constant */
if (toupper (SB_Peek (&Src)) == 'F') {
SB_Skip (&Src);
@ -788,7 +798,7 @@ static void NumericConst (void)
NextTok.Tok = TOK_FCONST;
}
LOG(("NumericConst exit IsFloat:%d IVal: %ld FVal: %f\n", IsFloat, NextTok.IVal, NextTok.FVal.V));
/* We don't need the string buffer any longer */
SB_Done (&Src);
}

View File

@ -31,7 +31,7 @@
/* */
/*****************************************************************************/
//#define DEBUG
/* common */
#include "shift.h"
@ -47,7 +47,13 @@
#include "typecmp.h"
#include "typeconv.h"
#ifdef DEBUG
#define LOG(x) printf x
#define FIXME(x) printf x
#else
#define LOG(x)
#define FIXME(x)
#endif
/*****************************************************************************/
/* Code */
@ -97,7 +103,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
/* lvalue? */
if (ED_IsLVal (Expr)) {
LOG(("DoConversion 1 Old: %s New: %s\n",
(IsTypeFloat (OldType)) ? "float" : "int",
(IsTypeFloat (NewType)) ? "float" : "int"
));
/* We have an lvalue. If the new size is smaller than the old one,
** we don't need to do anything. The compiler will generate code
** to load only the portion of the value that is actually needed.
@ -106,7 +115,10 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
** If both sizes are equal, do also leave the value alone.
** If the new size is larger, we must convert the value.
*/
if (NewBits > OldBits) {
if ((NewBits > OldBits) ||
/* FIXME: float */
/* when either side is float, emit the call to the conversion code */
(IsTypeFloat (OldType) || IsTypeFloat (NewType))) {
/* Load the value into the primary */
LoadExpr (CF_NONE, Expr);
@ -116,12 +128,27 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
/* Value is now in primary and an rvalue */
ED_FinalizeRValLoad (Expr);
}
LOG(("DoConversion 1 done\n"));
} else if (ED_IsConstAbs (Expr)) {
LOG(("DoConversion 2 Old: %s New: %s\n",
(IsTypeFloat (OldType)) ? "float" : "int",
(IsTypeFloat (NewType)) ? "float" : "int"
));
/* A cast of a constant numeric value to another type. Be sure
** to handle sign extension correctly.
*/
/* FIXME: float --- start of new code */
/* convert from float to (signed) long first */
if (IsTypeFloat (OldType) && !IsTypeFloat (NewType)) {
OldBits = 32;
Expr->IVal = FP_D_ToLong(Expr->V.FVal);
LOG(("DoConversion 2 new ival: %ld\n", Expr->IVal));
} else if (!IsTypeFloat (OldType) && IsTypeFloat (NewType)) {
OldBits = 0;
Expr->V.FVal = FP_D_FromInt(Expr->IVal);
LOG(("DoConversion 2 new fval: %f\n", Expr->V.FVal.V));
}
/* If this is a floating point constant, convert to integer,
** and warn if precision is discarded.
@ -133,11 +160,13 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
}
Expr->IVal = IVal;
}
/* FIXME: float --- end of new code */
/* Check if the new datatype will have a smaller range. If it
** has a larger range, things are OK, since the value is
** internally already represented by a long.
*/
LOG(("DoConversion 2 NewBits: %d OldBits: %d\n", NewBits, OldBits));
if (NewBits <= OldBits) {
long OldVal = Expr->IVal;
@ -157,6 +186,12 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
}
}
if (IsTypeFloat (NewType)) {
LOG(("DoConversion 2 new fval: %f\n", Expr->V.FVal.V));
} else {
LOG(("DoConversion 2 new ival: %ld\n", Expr->IVal));
}
/* Do the integer constant <-> absolute address conversion if necessary */
if (IsClassPtr (NewType)) {
Expr->Flags &= ~E_MASK_LOC;
@ -167,12 +202,19 @@ static void DoConversion (ExprDesc* Expr, const Type* NewType, int Explicit)
}
} else {
LOG(("DoConversion 3 Old: %s New: %s\n",
(IsTypeFloat (OldType)) ? "float" : "int",
(IsTypeFloat (NewType)) ? "float" : "int"
));
/* The value is not a constant. If the sizes of the types are
** not equal, add conversion code. Be sure to convert chars
** correctly.
*/
if (OldBits != NewBits) {
if ((OldBits != NewBits) ||
/* FIXME: float */
/* when either side is float, emit the call to the conversion code */
(IsTypeFloat (OldType) || IsTypeFloat (NewType))) {
/* Load the value into the primary */
LoadExpr (CF_NONE, Expr);
@ -198,14 +240,17 @@ void TypeConversion (ExprDesc* Expr, const Type* NewType)
** impossible.
*/
{
LOG(("TypeConversion\n"));
#if 0
/* Debugging */
printf ("Expr:\n=======================================\n");
LOG(("=======================================\n"));
LOG(("Expr:\n---------------------------------------\n"));
PrintExprDesc (stdout, Expr);
printf ("Type:\n=======================================\n");
LOG(("\nType:\n---------------------------------------\n"));
PrintType (stdout, NewType);
printf ("\n");
LOG(("\n");
PrintRawType (stdout, NewType);
LOG(("=======================================\n"));
#endif
/* First, do some type checking */
typecmp_t Result = TYPECMP_INITIALIZER;

View File

@ -45,6 +45,7 @@
#include <string.h>
#include <stdint.h>
/* common */
#include "fp.h"
@ -189,7 +190,11 @@ Double FP_D_FromInt (long Val)
return D;
}
long FP_D_ToLong (Double Val)
/* Convert a floating point variable into a long */
{
return (long)Val.V;
}
double FP_D_ToFloat (Double Val)
/* Convert a Double into a native double */
@ -236,3 +241,22 @@ Double FP_D_Div (Double Left, Double Right)
D.V = Left.V / Right.V;
return D;
}
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4244 ) // conversion from double to float
#endif
uint32_t FP_D_As32bitRaw(Double Val)
/* converts double into 32bit (float) and then returns its raw content as a 32bit int */
{
static float f;
uint32_t *lptr;
uint32_t lval;
f = Val.V;
lptr = (uint32_t *)&f;
lval = *lptr;
return lval;
}
#if defined(_MSC_VER)
#pragma warning( pop )
#endif

View File

@ -52,6 +52,7 @@
#include <stddef.h>
#include <stdint.h>
@ -92,7 +93,7 @@ Float FP_F_Make (float Val);
Float FP_F_FromInt (long Val);
/* Convert an integer into a floating point variable */
float FP_F_ToFloat (Float Val);
float FP_F_ToFloat (Float Val); /* FIXME: better name */
/* Convert a Float into a native float */
Float FP_F_Add (Float Left, Float Right);
@ -118,8 +119,9 @@ Double FP_D_Make (double Val);
Double FP_D_FromInt (long Val);
/* Convert an integer into a floating point variable */
long FP_D_ToLong (Double Val);
double FP_D_ToFloat (Double Val);
double FP_D_ToFloat (Double Val); /* FIXME: better name */
/* Convert a Double into a native double */
Double FP_D_Add (Double Left, Double Right);
@ -134,7 +136,8 @@ Double FP_D_Mul (Double Left, Double Right);
Double FP_D_Div (Double Left, Double Right);
/* Divide two floats */
uint32_t FP_D_As32bitRaw(Double Val);
/* converts double into 32bit (float) and then returns its raw content as a 32bit int */
/* End of fp.h */

View File

@ -50,13 +50,28 @@ define PRG_template
$(WORKDIR)/%.$1.$2.prg: %.c | $(WORKDIR)
$(if $(QUIET),echo todo/$$*.$1.$2.prg)
$(CC65) -t sim$2 $$(CC65FLAGS) -$1 -o $$(@:.prg=.s) $$< $(NULLERR)
$(CC65) -t sim$2 $$(CC65FLAGS) --add-source -$1 -o $$(@:.prg=.s) $$< $(NULLERR)
$(CA65) -t sim$2 -o $$(@:.prg=.o) $$(@:.prg=.s) $(NULLERR)
$(LD65) -t sim$2 -o $$@ $$(@:.prg=.o) sim$2.lib $(NULLERR)
$(NOT) $(SIM65) $(SIM65FLAGS) $$@ $(NULLOUT)
endef # PRG_template
# HACK! for some reason the test does NOT fail in this particular config
$(WORKDIR)/inline-asm-1489.Osr.65c02.prg: inline-asm-1489.c | $(WORKDIR)
$(if $(QUIET),echo todo/inline-asm-1489.Osr.65c02.prg)
$(CC65) -t sim65c02 $$(CC65FLAGS) --add-source -Osr -o $(@:.prg=.s) $< $(NULLERR)
$(CA65) -t sim65c02 -o $(@:.prg=.o) $(@:.prg=.s) $(NULLERR)
$(LD65) -t sim65c02 -o $@ $(@:.prg=.o) sim65c02.lib $(NULLERR)
$(SIM65) $(SIM65FLAGS) $@ $(NULLOUT)
$(WORKDIR)/inline-asm-1489.Os.65c02.prg: inline-asm-1489.c | $(WORKDIR)
$(if $(QUIET),echo todo/inline-asm-1489.Os.65c02.prg)
$(CC65) -t sim65c02 $$(CC65FLAGS) --add-source -Os -o $(@:.prg=.s) $< $(NULLERR)
$(CA65) -t sim65c02 -o $(@:.prg=.o) $(@:.prg=.s) $(NULLERR)
$(LD65) -t sim65c02 -o $@ $(@:.prg=.o) sim65c02.lib $(NULLERR)
$(SIM65) $(SIM65FLAGS) $@ $(NULLOUT)
$(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),6502)))
$(foreach option,$(OPTIONS),$(eval $(call PRG_template,$(option),65c02)))

View File

@ -0,0 +1,126 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
void constconst(void)
{
printf("\n*** constant vs constant\n\n");
// addition
printf("\nconstant + constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f + 0.2f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x3e99999a] %s (0.3)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3e99999a");
// substraction
printf("\nconstant - constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f - 0.2f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0xbdcccccd] %s (-0.1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "bdcccccd");
fp3 = 0.3f - 0.1f;
printf("fp3:0x%08lx [0x3e4ccccd] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3e4ccccd");
fp3 = 0.1f - 0.3f;
printf("fp3:0x%08lx [0xbe4ccccd] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "be4ccccd");
// multiplication
printf("\nconstant * constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f * 5.0f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3f000000");
// division
printf("\nconstant / constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f / 0.2f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3f000000");
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-const-const ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
constconst();
WAIT();
printf("\nfloat-basic-const-const (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,131 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
void constintconst(void)
{
printf("\n*** float constant vs int constant\n\n");
// addition
printf("\nconstant + constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.2f + 2;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x400ccccd] %s (2.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "400ccccd");
// substraction
printf("\nconstant - constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f - 2;
printf("fp3:0x%08lx [0xbff33333] %s (-1.9)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "bff33333");
fp3 = 0.3f - 1;
printf("fp3:0x%08lx [0xbf333333] %s (-0.7)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "bf333333");
// multiplication
printf("\nconstant * constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f * 5;
printf("fp3:0x%08lx [0x3f000000] %s (0.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3f000000");
// division
printf("\nconstant / constant\n\n");
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f / 2;
printf("fp3:0x%08lx [0x3d4ccccd] %s (0.05)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3d4ccccd");
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-const-intconst ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
constintconst();
WAIT();
printf("\nfloat-basic-const-intconst (res:%d)\n", result);
return result;
}
#else
int main(void)
{
fp1 = 0.1f;
fp2 = 0.2f;
fp3 = 0.1f - 2; // 2.1
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (0.2)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [?] %s (2.1)\n", *((uint32_t*)&fp3), _ftostr(buf, fp3));
return result;
}
#endif

View File

@ -0,0 +1,109 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
void constintvar(void)
{
printf("\nfloat constant vs int variable\n\n");
var_sint = 64;
fp3 = 16.75f + var_sint;
printf("addition: %s+%d=%s\n", _ftostr(buf, 16.75f), var_sint, _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42a18000] %s (80.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42a18000");
var_sint = 16;
fp3 = 18.5f - var_sint;
printf("substraction: %s-%d=%s\n", _ftostr(buf, 8.5f), var_sint, _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x40200000] %s (2.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40200000");
var_sint = 13;
fp3 = 20.6f - var_sint;
printf("fp3:0x%08lx [0x40f33334] %s (7.6)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40f33334");
var_sint = 13;
fp3 = 10.2f - var_sint;
printf("fp3:0x%08lx [0xc0333334] %s (-2.8)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "c0333334");
var_sint = 2;
fp3 = 16.25f * var_sint;
printf("multiplication: %s*%d=%s\n", _ftostr(buf, 16.25f), var_sint, _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42020000] %s (32.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42020000");
var_sint = 2;
fp3 = 16.2f / var_sint;
printf("division: %s/%d=%s\n", _ftostr(buf, 16.2f), var_sint, _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x4101999a] %s (8.1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "4101999a");
}
int main(void)
{
float fp2 = 43.21f;
printf("float-basic-const-intvar\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
constintvar();
WAIT();
printf("\nfloat-basic-const-intvar (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,111 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
// when making sub tests work, remove them here and uncomment them in val/float-basic.c
void constvar(void)
{
printf("\nconstant vs variable\n\n");
fp2 = 64.25f;
fp3 = 16.75f + fp2;
printf("addition: %s+%s=%s\n", _ftostr(buf, 16.75f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42a20000] %s (81.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42a20000");
fp2 = 16.25f;
fp3 = 8.5f - fp2;
printf("substraction: %s-%s=%s\n", _ftostr(buf, 8.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0xc0f80000] %s (-7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "c0f80000");
fp1 = 0.1f;
fp2 = 0.3f;
fp3 = 0.3f - fp1;
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3e4cccce");
fp3 = 0.1f - fp2;
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "be4cccce");
fp2 = 2.25f;
fp3 = 16.25f * fp2;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42124000] %s (36.5625)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42124000");
fp2 = 2.5f;
fp3 = 16.2f / fp2;
printf("division: %s/%s=%s\n", _ftostr(buf, 16.2f), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x40cf5c2a] %s (6.48)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40cf5c2a");
}
int main(void)
{
float fp2 = 43.21f;
printf("float-basic-const-var\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
constvar();
WAIT();
printf("\nfloat-basic-const-var (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,126 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
void intconstconst(void)
{
printf("\n*** int constant vs constant\n\n");
// addition
printf("\nconstant + constant\n\n");
fp1 = 0.1f;
fp2 = 5;
fp3 = 5 + 0.5f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x40b00000] %s (5.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40b00000");
// substraction
printf("\nconstant - constant\n\n");
fp1 = 0.1f;
fp2 = 5;
fp3 = 5 - 0.2f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x4099999a] %s (4.8)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "4099999a");
fp3 = 5 - 1.1f;
printf("fp3:0x%08lx [0x4079999a] %s (3.9)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "4079999a");
fp3 = 5 - 2.3f;
printf("fp3:0x%08lx [0x402ccccd] %s (2.7)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "402ccccd");
// multiplication
printf("\nconstant * constant\n\n");
fp1 = 0.1f;
fp2 = 5;
fp3 = 5 * 5.0f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x41c80000] %s (25.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "41c80000");
// division
printf("\nconstant / constant\n\n");
fp1 = 0.1f;
fp2 = 5;
fp3 = 5 / 0.2f;
printf(" 0x%08lx [0x3dcccccd] %s (0.1)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf(" 0x%08lx [0x3e4ccccd] %s (5.0)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
printf("fp3:0x%08lx [0x41c80000] %s (25.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "41c80000");
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-intconst-const ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
intconstconst();
WAIT();
printf("\nfloat-basic-intconst-const (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,128 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
int i;
unsigned char var_char;
unsigned int var_int;
float var_float;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]", temp, str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void SKIPPEDtest1(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf(" (SKIPPED:%s:%s)\n", temp, str);
}
void intconstvar(void)
{
var_float = 11.123f;
#if 1
fp1 = 47;
printf("fp1:0x%08lx [?] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [?] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
/* addition */
fp1 = 47 + var_float;
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
fp1 = 47 - var_float;
printf("fp1:0x%08lx [?] %s (35.877)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "420f820c");
#endif
#if 0 // compiles, but wrong result
fp1 = 47 * var_float;
printf("fp1:0x%08lx [?] %s (522.781)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // Internal compiler error
fp1 = 47 / var_float;
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-intconst-var ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
intconstvar();
WAIT();
printf("\nfloat-basic-intconst-var (res:%d)\n", result);
return result;
}
#else
int main(void)
{
// fp1 = 47 * var_float;
// printf("fp1:0x%08lx [?] %s (522.781)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = 47 / var_float;
printf("fp1:0x%08lx [?] %s (58.123)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
return result;
}
#endif

View File

@ -0,0 +1,177 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
int i;
unsigned char var_char;
unsigned int var_int;
float var_float;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]", temp, str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void test2(unsigned int i, unsigned int exp)
{
if (i == exp) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void SKIPPEDtest1(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf(" (SKIPPED:%s:%s)\n", temp, str);
}
void intvarconst(void)
{
var_int = 47;
#if 1
fp1 = var_int;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = 11.123f;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("int var + float const\n");
/* addition */
var_char = 42;
fp1 = var_char + 23.123f;
printf("fp1:0x%08lx [0x42823efa] %s (65.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42823efa");
fp1 = var_int + 11.123f;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
/* subtraction */
#if 1 // gives wrong result
fp1 = var_int - 11.123f;
printf("fp1:0x%08lx [420f820c] %s (35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "420f820c");
#endif
#if 1
/* multiplication */
fp1 = var_int * 11.123f;
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4402b1fc");
/* division */
fp1 = var_int / 11.123f;
printf("fp1:0x%08lx [4087371f] %s (4.2254)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4087371f");
#endif
}
unsigned int i1;
void intvarconst2(void)
{
var_int = 47;
#if 1
i1 = var_int;
printf("i1: %d (47)\n", i1);
#endif
printf("int var X= float const\n");
/* addition */
#if 0 // gives wrong result
i1 = var_int;
i1 += 11.123f;
printf("i1: %d (58)\n", i1);
test2(i1, 58);
#endif
/* subtraction */
#if 0 // gives wrong result
i1 = var_int;
i1 -= 11.123f;
printf("i1: %d (35)\n", i1);
test2(i1, 35);
#endif
#if 0 // internal compiler error
/* multiplication */
i1 = var_int;
i1 *= 11.123f;
printf("i1: %d (522)\n", i1);
test2(i1, 522);
#endif
#if 0 // internal compiler error
/* division */
i1 = var_int;
i1 /= 11.123f;
printf("i1: %d (4)\n", i1);
test2(i1, 4);
#endif
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-intvar-const ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
intvarconst();
intvarconst2();
WAIT();
printf("\nfloat-basic-intvar-const (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,175 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
int i;
unsigned char var_char;
unsigned int var_int;
float var_float;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]", temp, str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void test2(unsigned int i, unsigned int exp)
{
if (i == exp) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void SKIPPEDtest1(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf(" (SKIPPED:%s:%s)\n", temp, str);
}
void intfloat(void)
{
var_int = 47;
var_float = 11.123f;
#if 1
fp1 = var_int;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
/* addition */
fp1 = var_int + var_float;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
fp1 = var_int - var_float;
printf("fp1:0x%08lx [420f820c] %s (35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "420f820c");
#endif
#if 1
fp1 = var_int * var_float;
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4402b1fc");
#endif
#if 1
fp1 = var_int / var_float;
printf("fp1:0x%08lx [4087371f] %s (4.225)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4087371f");
#endif
}
unsigned int i1;
void intfloat2(void)
{
printf("int X= float var\n");
var_int = 47;
var_float = 11.123f;
i1 = var_int;
printf("i1: %d (47)\n", i1);
/* addition */
i1 = var_int;
i1 += var_float;
printf("i1: %d (58)\n", i1);
test2(i1, 58);
#if 1
i1 = var_int;
i1 -= var_float;
printf("i1: %d (36)\n", i1);
test2(i1, 36);
#endif
#if 0 // internal compiler error
i1 = var_int;
i1 *= var_float;
printf("i1: %d (522)\n", i1);
test2(i1, 522);
#endif
#if 0 // internal compiler error
i1 = var_int;
i1 /= var_float;
printf("i1: %d (4)\n", i1);
test2(i1, 4);
#endif
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-intvar-var ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
intfloat();
intfloat2();
WAIT();
printf("\nfloat-basic-intvar-var (res:%d)\n", result);
return result;
}
#else
int main(void)
{
var_int = 47;
var_float = 11.123f;
fp1 = var_int * var_float;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
return result;
}
#endif

View File

@ -0,0 +1,222 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]",temp,str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
#if 1
void varconst(void)
{
printf("\n*** variable vs constant\n\n");
/* addition, variable + constant */
fp1 = 64.75f;
fp3 = fp1 + 2.25f;
printf("addition: %s+%s=%s\n", _ftostr(buf, fp3), _ftostr(buf3, 0.05f), _ftostr(buf2, fp1));
printf(" fp3:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42860000");
/* subtraction, variable - constant */
fp1 = 16.25f;
fp3 = fp1 - 8.5f;
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 8.5f), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40f80000");
fp1 = 0.1f;
fp2 = 0.3f;
fp3 = fp2 - 0.1f;
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3e4cccce");
fp3 = fp1 - 0.3f;
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "be4cccce");
/* multiplication, variable * constant */
fp1 = 16.25f;
fp3 = fp1 * 2.5f;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 2.3f), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42228000");
/* division, variable / constant */
fp1 = 32.5f;
fp3 = fp1 / 2.5f;
printf("division: %s/%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 2.3f), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "41500000");
}
void varconst2(void)
{
printf("\n*** variable vs constant\n\n");
/* addition, variable + constant */
fp1 = 64.75f;
fp1 += 2.25f;
printf("addition: %s+%s=%s\n", _ftostr(buf, 64.75f), _ftostr(buf3, 2.25f), _ftostr(buf2, fp1));
printf(" fp1:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42860000");
/* subtraction, variable - constant */
fp1 = 16.25f;
fp1 -= 8.5f;
printf("substraction: %s-%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 8.5f), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "40f80000");
fp1 = 0.3f;
fp1 -= 0.1f;
printf("fp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "3e4cccce");
fp1 = 0.1f;
fp1 -= 0.3f;
printf("fp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "be4cccce");
/* multiplication, variable * constant */
fp1 = 16.25f;
fp1 *= 2.5f;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 2.5f), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42228000");
/* division, variable / constant */
fp1 = 32.5f;
fp1 /= 2.5f;
printf("division: %s/%s=%s\n", _ftostr(buf, 32.5f), _ftostr(buf2, 2.5f), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "41500000");
}
#endif
void varconst3(void)
{
float localfp3;
float localfp2;
float localfp1;
float localfp4;
float localfp5;
printf("\n*** local variable vs constant\n\n");
#if 1 // compiles, wrong result
/* addition, variable + constant */
localfp1 = 64.75f;
localfp1 += 2.25f;
printf("addition: %s+%s=%s\n", _ftostr(buf, 64.75f), _ftostr(buf3, 2.25f), _ftostr(buf2, localfp1));
printf(" localfp1:0x%08lx [0x42860000] %s (exp:67.0)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "42860000");
#endif
#if 1 // compiles, wrong result
/* subtraction, variable - constant */
localfp1 = 16.25f;
localfp1 -= 8.5f;
printf("substraction: %s-%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 8.5f), _ftostr(buf3, localfp1));
printf(" localfp1:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "40f80000");
localfp1 = 0.3f;
localfp1 -= 0.1f;
printf("localfp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "3e4cccce");
localfp1 = 0.1f;
localfp1 -= 0.3f;
printf("localfp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "be4cccce");
#endif
#if 1
/* multiplication, variable * constant */
localfp1 = 16.25f;
localfp1 *= 2.5f;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, 2.5f), _ftostr(buf3, localfp1));
printf(" localfp1:0x%08lx [0x42228000] %s (exp:40.625)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "42228000");
/* division, variable / constant */
localfp1 = 32.5f;
localfp1 /= 2.5f;
printf("division: %s/%s=%s\n", _ftostr(buf, 32.5f), _ftostr(buf2, 2.5f), _ftostr(buf3, localfp1));
printf(" localfp1:0x%08lx [0x41500000] %s (exp:13.0)", *((uint32_t*)&localfp1), _ftostr(buf, localfp1));
test1(localfp1, "41500000");
#endif
}
int main(void)
{
float fp2 = 43.21f;
printf("float-basic-var-const\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
varconst();
varconst2();
varconst3();
WAIT();
printf("\nfloat-basic-var-const (res:%d)\n", result);
return result;
}
#else
int main(void)
{
fp1 = 16.25f;
fp3 = fp1 - 8.5f;
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, 8.5f), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x40f80000] %s (exp:7.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
return result;
}
#endif

View File

@ -0,0 +1,167 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
int i;
unsigned char var_char;
unsigned int var_int;
float var_float;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]", temp, str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void SKIPPEDtest1(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf(" (SKIPPED:%s:%s)\n", temp, str);
}
void varintconst(void)
{
var_float = 11.123f;
fp1 = 47;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
/* addition */
fp1 = var_float + 47;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#if 1
fp1 = var_float - 47;
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "c20f820c");
#endif
#if 0 // works but gives wrong result
fp1 = var_float * 47;
printf("fp1:0x%08lx [42687df4] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // works but gives wrong result
fp1 = var_float / 47;
printf("fp1:0x%08lx [42687df4] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
}
void varintconst2(void)
{
var_float = 11.123f;
printf("float *= int const\n");
fp1 = 47;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
#if 0 // works but gives wrong result
/* addition */
fp1 = var_float;
fp1 += 47;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // works but gives wrong result
fp1 = var_float;
fp1 -= 47;
printf("fp1:0x%08lx [42687df4] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // works but gives wrong result
fp1 = var_float;
fp1 *= 47;
printf("fp1:0x%08lx [42687df4] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // works but gives wrong result
fp1 = var_float;
fp1 /= 47;
printf("fp1:0x%08lx [42687df4] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-var-intconst ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
varintconst();
varintconst2();
WAIT();
printf("\nfloat-basic-var-intconst (res:%d)\n", result);
return result;
}
#else
int main(void)
{
fp1 = var_float - 47;
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float - 47.0f;
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
return result;
}
#endif

View File

@ -0,0 +1,152 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
int i;
unsigned char var_char;
unsigned int var_int;
float var_float;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf("[%s:%s]", temp, str);
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
} else {
printf(" (failed) !!! ");
result++;
}
printf("result:%d\n", result);
}
void SKIPPEDtest1(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
printf(" (SKIPPED:%s:%s)\n", temp, str);
}
void intvar(void)
{
var_int = 47;
var_float = 11.123f;
fp1 = var_int;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
/* addition */
fp1 = var_float + var_int;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
fp1 = var_float - var_int;
printf("fp1:0x%08lx [c20f820c] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "c20f820c");
fp1 = var_float * var_int;
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4402b1fc");
fp1 = var_float / var_int;
printf("fp1:0x%08lx [3e7256e3] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "3e7256e3");
}
void intvar2(void)
{
var_int = 47;
var_float = 11.123f;
printf("float var *= int var\n");
fp1 = var_int;
printf("fp1:0x%08lx [42687df4] %s (47)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
fp1 = var_float;
printf("fp1:0x%08lx [42687df4] %s (11.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
#if 0 // compiles, but wrong result
/* addition */
fp1 = var_float;
fp1 += var_int;
printf("fp1:0x%08lx [42687df4] %s (58.123)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
#if 0 // compiles, but wrong result
/* subtraction */
fp1 = var_float;
fp1 -= var_int;
printf("fp1:0x%08lx [42687df4] %s (-35.877)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42687df4");
#endif
/* multiplication */
fp1 = var_float;
fp1 *= var_int;
printf("fp1:0x%08lx [4402b1fc] %s (522.781)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "4402b1fc");
/* division */
fp1 = var_float;
fp1 /= var_int;
printf("fp1:0x%08lx [3e7256e3] %s (0.2367)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "3e7256e3");
}
int main(void)
{
float fp2 = 43.21f;
printf("*** float-basic-var-intvar ***\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
intvar();
intvar2();
WAIT();
printf("\nfloat-basic-var-intvar (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,179 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#if 1
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf(" (ok)");
printf("\n");
} else {
printf(" (failed) !!!\n");
result++;
}
}
void varvar(void)
{
printf("\nvariable vs variable\n\n");
/* addition, variable + variable */
fp1 = 16.5f;
fp2 = 64.25f;
fp3 = fp1 + fp2; // = 80.75f
printf("addition: %s+%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x42a18000] %s (exp:80.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "42a18000");
/* subtraction, variable - variable */
fp1 = 64.25f;
fp2 = 16.5f;
fp3 = fp1 - fp2;
printf("substraction: %s-%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x423f0000] %s (exp:47.75)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "423f0000");
fp1 = 0.1f;
fp2 = 0.3f;
fp3 = fp2 - fp1;
printf("fp3:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3e4cccce");
fp3 = fp1 - fp2;
printf("fp3:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "be4cccce");
/* multiplication, variable * variable */
fp1 = 8.5f;
fp2 = 2.25f;
fp3 = fp1 * fp2;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x41990000] %s (exp:19.125)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "41990000");
/* division, variable / variable */
fp1 = 16.25f;
fp2 = 2.5f;
fp3 = fp1 / fp2;
printf("division: %s/%s=%s\n", _ftostr(buf, fp1), _ftostr(buf2, fp2), _ftostr(buf3, fp3));
printf(" fp3:0x%08lx [0x40d00000] %s (exp:6.5)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "40d00000");
}
void varvar2(void)
{
printf("\nvariable vs variable\n\n");
#if 0 // compiles, but wrong result
/* addition, variable + variable */
fp1 = 16.5f;
fp2 = 64.25f;
fp1 += fp2; // = 80.75f
printf("addition: %s+%s=%s\n", _ftostr(buf, 16.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x42a18000] %s (exp:80.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "42a18000");
#endif
#if 0 // compiles, but wrong result
/* subtraction, variable - variable */
fp1 = 64.25f;
fp2 = 16.5f;
fp1 -= fp2;
printf("substraction: %s-%s=%s\n", _ftostr(buf, 64.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x423f0000] %s (exp:47.75)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "423f0000");
fp1 = 0.3f;
fp2 = 0.1f;
fp1 -= fp2;
printf("fp1:0x%08lx [0x3e4cccce] %s (0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "3e4cccce");
fp1 = 0.1f;
fp2 = 0.1f;
fp1 -= fp2;
printf("fp1:0x%08lx [0xbe4cccce] %s (-0.2)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "be4cccce");
#endif
/* multiplication, variable * variable */
fp1 = 8.5f;
fp2 = 2.25f;
fp1 *= fp2;
printf("multiplication: %s*%s=%s\n", _ftostr(buf, 8.5f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x41990000] %s (exp:19.125)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "41990000");
/* division, variable / variable */
fp1 = 16.25f;
fp2 = 2.5f;
fp1 /= fp2;
printf("division: %s/%s=%s\n", _ftostr(buf, 16.25f), _ftostr(buf2, fp2), _ftostr(buf3, fp1));
printf(" fp1:0x%08lx [0x40d00000] %s (exp:6.5)", *((uint32_t*)&fp1), _ftostr(buf, fp1));
test1(fp1, "40d00000");
}
int main(void)
{
float fp2 = 43.21f;
printf("float-basic-var-var\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
varvar();
varvar2();
WAIT();
printf("\nfloat-basic-var-var (res:%d)\n", result);
return result;
}
#else
int main(void)
{
fp1 = 16.5f;
fp2 = 64.25f;
fp1 += fp2; // = 80.75f
return result;
}
#endif

105
test/val/float-bnegate.c Normal file
View File

@ -0,0 +1,105 @@
// test basic arithmetic operations
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <_float.h>
float fp1 = 12.34f;
float fp2; // non initialized
float fp3, fp4 = 55.55f;
char buf[0x20];
char buf2[0x20];
char buf3[0x20];
unsigned long l1,l2;
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
// returns 1 if value in f matches the string
// the string is a hex value without leading "0x"
int compare(float f, char *str)
{
char temp[12];
sprintf(temp, "%08lx", *((uint32_t*)&f));
return (strcmp(temp, str) == 0) ? 1 : 0;
}
void test1(float f, char *str)
{
if (compare(f, str)) {
// printf("(ok)");
printf("\n");
} else {
printf(" (failed)\n");
result++;
}
}
void test2(long n, long val)
{
if (n == val) {
// printf("(ok)");
printf("\n");
} else {
printf(" (failed)\n");
result++;
}
}
int main(void)
{
float fp2 = 43.21f;
printf("float-binary negate (not)\n");
printf("fp1:0x%08lx [0x414570a4] %s (12.340000)\n", *((uint32_t*)&fp1), _ftostr(buf, fp1));
printf("fp2:0x%08lx [0x422cd70a] %s (43.209999)\n", *((uint32_t*)&fp2), _ftostr(buf, fp2));
fp1 = 0.0f;
fp2 = !fp1;
var_sint = !fp1;
fp3 = !fp2;
printf("fp2 0x%08lx [0x3f800000] %s (!0=1) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
test1(fp2, "3f800000");
printf("fp3 0x%08lx [0x00000000] %s (!1=0)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "00000000");
fp1 = 12.6f;
fp2 = !fp1;
var_sint = !fp1;
fp3 = !fp2;
printf("fp2 0x%08lx [0x00000000] %s (!12.6f=0) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
test1(fp2, "00000000");
printf("fp3 0x%08lx [0x3f800000] %s (!0=1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3f800000");
fp1 = -12.6f;
fp2 = !fp1;
var_sint = !fp1;
fp3 = !fp2;
printf("fp2 0x%08lx [0x00000000] %s (!-12.6f=0) %d", *((uint32_t*)&fp2), _ftostr(buf, fp2), var_sint);
test1(fp2, "00000000");
printf("fp3 0x%08lx [0x3f800000] %s (!0=1)", *((uint32_t*)&fp3), _ftostr(buf, fp3));
test1(fp3, "3f800000");
printf("float-binary negate (res:%d)\n", result);
return result;
}

View File

@ -0,0 +1,80 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
void constconst(void)
{
printf("const vs const\n");
expect("1.5f == 1.6f is", 0, (1.5f == 1.6f));
expect("1.6f == 1.5f is", 0, (1.6f == 1.5f));
expect("1.6f == 1.6f is", 1, (1.6f == 1.6f));
expect("1.5f != 1.6f is", 1, (1.5f != 1.6f));
expect("1.6f != 1.5f is", 1, (1.6f != 1.5f));
expect("1.6f != 1.6f is", 0, (1.6f != 1.6f));
expect("1.5f < 1.6f is", 1, (1.5f < 1.6f));
expect("1.6f < 1.5f is", 0, (1.6f < 1.5f));
expect("1.6f < 1.6f is", 0, (1.6f < 1.6f));
expect("1.5f > 1.6f is", 0, (1.5f > 1.6f));
expect("1.6f > 1.5f is", 1, (1.6f > 1.5f));
expect("1.6f > 1.6f is", 0, (1.6f > 1.6f));
expect("1.5f <= 1.6f is", 1, (1.5f <= 1.6f));
expect("1.6f <= 1.5f is", 0, (1.6f <= 1.5f));
expect("1.6f <= 1.6f is", 1, (1.6f <= 1.6f));
expect("1.5f >= 1.6f is", 0, (1.5f >= 1.6f));
expect("1.6f >= 1.5f is", 1, (1.6f >= 1.5f));
expect("1.6f >= 1.6f is", 1, (1.6f >= 1.6f));
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-const-const\n");
constconst();
printf("float-cmp-const-const (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,80 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
void constintconst(void)
{
printf("const vs int const\n");
expect("10.0f == 20 is", 0, (10.0f == 20));
expect("20.0f == 10 is", 0, (20.0f == 10));
expect("20.0f == 20 is", 1, (20.0f == 20));
expect("10.0f != 20 is", 1, (10.0f != 20));
expect("20.0f != 10 is", 1, (20.0f != 10));
expect("20.0f != 20 is", 0, (20.0f != 20));
expect("10.0f < 20 is", 1, (10.0f < 20));
expect("20.0f < 10 is", 0, (20.0f < 10));
expect("20.0f < 20 is", 0, (20.0f < 20));
expect("10.0f > 20 is", 0, (10.0f > 20));
expect("20.0f > 10 is", 1, (20.0f > 10));
expect("20.0f > 20 is", 0, (20.0f > 20));
expect("10.0f <= 20 is", 1, (10.0f <= 20));
expect("20.0f <= 10 is", 0, (20.0f <= 10));
expect("20.0f <= 20 is", 1, (20.0f <= 20));
expect("10.0f >= 20 is", 0, (10.0f >= 20));
expect("20.0f >= 10 is", 1, (20.0f >= 10));
expect("20.0f >= 20 is", 1, (20.0f >= 20));
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-const-intconst\n");
constintconst();
printf("float-cmp-const-intconst (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,85 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
int i1 = 10;
int i2 = 20;
void constintvar(void)
{
printf("const vs int var\n");
#if 0 // compiles but produces wrong results
expect("10.0f == 20 is", 0, (10.0f == i2));
expect("20.0f == 10 is", 0, (20.0f == i1));
expect("20.0f == 20 is", 1, (20.0f == i2));
expect("10.0f != 20 is", 1, (10.0f != i2));
expect("20.0f != 10 is", 1, (20.0f != i1));
expect("20.0f != 20 is", 0, (20.0f != i2));
expect("10.0f < 20 is", 1, (10.0f < i2));
expect("20.0f < 10 is", 0, (20.0f < i1));
expect("20.0f < 20 is", 0, (20.0f < i2));
expect("10.0f > 20 is", 0, (10.0f > i2));
expect("20.0f > 10 is", 1, (20.0f > i1));
expect("20.0f > 20 is", 0, (20.0f > i2));
expect("10.0f <= 20 is", 1, (10.0f <= i2));
expect("20.0f <= 10 is", 0, (20.0f <= i1));
expect("20.0f <= 20 is", 1, (20.0f <= i2));
expect("10.0f >= 20 is", 0, (10.0f >= i2));
expect("20.0f >= 10 is", 1, (20.0f >= i1));
expect("20.0f >= 20 is", 1, (20.0f >= i2));
#endif
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-const-intvar\n");
constintvar();
printf("float-cmp-const-intvar (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,83 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
void constvar(void)
{
printf("const vs var\n");
expect("1.5f == 1.6f is", 0, (1.5f == fp1));
expect("1.6f == 1.5f is", 0, (1.6f == fp2));
expect("1.6f == 1.6f is", 1, (1.6f == fp1));
expect("1.5f != 1.6f is", 1, (1.5f != fp1));
expect("1.6f != 1.5f is", 1, (1.6f != fp2));
expect("1.6f != 1.6f is", 0, (1.6f != fp1));
expect("1.5f < 1.6f is", 1, (1.5f < fp1));
expect("1.6f < 1.5f is", 0, (1.6f < fp2));
expect("1.6f < 1.6f is", 0, (1.6f < fp1));
expect("1.5f > 1.6f is", 0, (1.5f > fp1));
expect("1.6f > 1.5f is", 1, (1.6f > fp2));
expect("1.6f > 1.6f is", 0, (1.6f > fp1));
expect("1.5f <= 1.6f is", 1, (1.5f <= fp1));
expect("1.6f <= 1.5f is", 0, (1.6f <= fp2));
expect("1.6f <= 1.6f is", 1, (1.6f <= fp1));
expect("1.5f >= 1.6f is", 0, (1.5f >= fp1));
expect("1.6f >= 1.5f is", 1, (1.6f >= fp2));
expect("1.6f >= 1.6f is", 1, (1.6f >= fp1));
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-const-var\n");
fp1 = 1.6f;
fp2 = 1.5f;
constvar();
printf("float-cmp-const-var (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,81 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
void intconstconst(void)
{
printf("int const vs const\n");
expect("10 == 20.0f is", 0, (10 == 20.0f));
expect("20 == 10.0f is", 0, (20 == 10.0f));
expect("20 == 20.0f is", 1, (20 == 20.0f));
expect("10 != 20.0f is", 1, (10 != 20.0f));
expect("20 != 10.0f is", 1, (20 != 10.0f));
expect("20 != 20.0f is", 0, (20 != 20.0f));
expect("10 < 20.0f is", 1, (10 < 20.0f));
expect("20 < 10.0f is", 0, (20 < 10.0f));
expect("20 < 20.0f is", 0, (20 < 20.0f));
expect("10 > 20.0f is", 0, (10 > 20.0f));
expect("20 > 10.0f is", 1, (20 > 10.0f));
expect("20 > 20.0f is", 0, (20 > 20.0f));
expect("10 <= 20.0f is", 1, (10 <= 20.0f));
expect("20 <= 10.0f is", 0, (20 <= 10.0f));
expect("20 <= 20.0f is", 1, (20 <= 20.0f));
expect("10 >= 20.0f is", 0, (10 >= 20.0f));
expect("20 >= 10.0f is", 1, (20 >= 10.0f));
expect("20 >= 20.0f is", 1, (20 >= 20.0f));
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-intconst-const\n");
intconstconst();
printf("float-cmp-intconst-const (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,99 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val, fval) \
printf("%s %d:%d:%s%s (is:%d want:%d fval:%s)\n", \
msg, val, exp, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : "", \
val, exp, _ftostr(buf, fval) \
); \
if (exp != val) { \
result++; \
}
//-------------------------------------------------------------------------
void seperate(void)
{
int res;
fp1 = 10.0f;
fp2 = 20.0f;
// res = (20.0f == fp2); // works
res = (20 == fp2); // fails
printf("res:%d\n", res);
}
void intconstvar(void)
{
printf("int const vs var\n");
fp1 = 10.0f;
fp2 = 20.0f;
#if 1
expect("10 == 20 is", 0, (10 == fp2), fp2);
expect("20 == 10 is", 0, (20 == fp1), fp1);
expect("20 == 20 is", 1, (20 == fp2), fp2);
expect("10 != 20 is", 1, (10 != fp2), fp2);
expect("20 != 10 is", 1, (20 != fp1), fp1);
expect("20 != 20 is", 0, (20 != fp2), fp2);
expect("10 < 20 is", 1, (10 < fp2), fp2);
expect("20 < 10 is", 0, (20 < fp1), fp1);
expect("20 < 20 is", 0, (20 < fp2), fp2);
expect("10 > 20 is", 0, (10 > fp2), fp2);
expect("20 > 10 is", 1, (20 > fp1), fp1);
expect("20 > 20 is", 0, (20 > fp2), fp2);
expect("10 <= 20 is", 1, (10 <= fp2), fp2);
expect("20 <= 10 is", 0, (20 <= fp1), fp1);
expect("20 <= 20 is", 1, (20 <= fp2), fp2);
expect("10 >= 20 is", 0, (10 >= fp2), fp2);
expect("20 >= 10 is", 1, (20 >= fp1), fp1);
expect("20 >= 20 is", 1, (20 >= fp2), fp2);
#endif
}
int main(void)
{
printf("float-cmp-intconst-var\n");
seperate();
intconstvar();
printf("float-cmp-intconst-var (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,85 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val) \
printf("%s %s%s\n", \
msg, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : ""); \
if (exp != val) { \
result++; \
}
int i1 = 10;
int i2 = 20;
void intvarconst(void)
{
printf("int var vs const\n");
#if 0 // internal compiler error
expect("10 == 20.0f is", 0, (i1 == 20.0f));
expect("20 == 10.0f is", 0, (i2 == 10.0f));
expect("20 == 20.0f is", 1, (i2 == 20.0f));
expect("10 != 20.0f is", 1, (i1 != 20.0f));
expect("20 != 10.0f is", 1, (i2 != 10.0f));
expect("20 != 20.0f is", 0, (i2 != 20.0f));
expect("10 < 20.0f is", 1, (i1 < 20.0f));
expect("20 < 10.0f is", 0, (i2 < 10.0f));
expect("20 < 20.0f is", 0, (i2 < 20.0f));
expect("10 > 20.0f is", 0, (i1 > 20.0f));
expect("20 > 10.0f is", 1, (i2 > 10.0f));
expect("20 > 20.0f is", 0, (i2 > 20.0f));
expect("10 <= 20.0f is", 1, (i1 <= 20.0f));
expect("20 <= 10.0f is", 0, (i2 <= 10.0f));
expect("20 <= 20.0f is", 1, (i2 <= 20.0f));
expect("10 >= 20.0f is", 0, (i1 >= 20.0f));
expect("20 >= 10.0f is", 1, (i2 >= 10.0f));
expect("20 >= 20.0f is", 1, (i2 >= 20.0f));
#endif
}
//-------------------------------------------------------------------------
int main(void)
{
printf("float-cmp-intvar-const\n");
intvarconst();
printf("float-cmp-intvar-const (res: %d)\n", result);
return result;
}

View File

@ -0,0 +1,102 @@
// test comparison operations
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <_float.h>
#ifdef CONIO
#include <conio.h>
#define WAIT() cgetc()
#else
#define WAIT()
#endif
float fp1, fp2, fp3, fp4;
char buf[0x30];
char buf2[0x30];
char buf3[0x30];
signed char var_schar;
unsigned char var_uchar;
signed int var_sint;
unsigned int var_uint;
signed long var_slong;
unsigned long var_ulong;
int result = 0;
#define expect(msg, exp, val, fval) \
printf("%s %d:%d:%s%s (is:%d want:%d fval:%s)\n", \
msg, val, exp, \
val ? "true" : "false", \
(exp != val) ? " (failed)" : "", \
val, exp, _ftostr(buf, fval) \
); \
if (exp != val) { \
result++; \
}
//-------------------------------------------------------------------------
void seperate(void)
{
int res;
fp1 = 10.0f;
fp2 = 20.0f;
// res = (20.0f == fp2); // works
res = (20 == fp2); // fails
printf("res:%d\n", res);
}
int i1 = 10;
int i2 = 20;
void intvarvar(void)
{
printf("int const vs var\n");
fp1 = 10.0f;
fp2 = 20.0f;
#if 1
expect("10 == 20 is", 0, (i1 == fp2), fp2);
expect("20 == 10 is", 0, (i2 == fp1), fp1);
expect("20 == 20 is", 1, (i2 == fp2), fp2);
expect("10 != 20 is", 1, (i1 != fp2), fp2);
expect("20 != 10 is", 1, (i2 != fp1), fp1);
expect("20 != 20 is", 0, (i2 != fp2), fp2);
expect("10 < 20 is", 1, (i1 < fp2), fp2);
expect("20 < 10 is", 0, (i2 < fp1), fp1);
expect("20 < 20 is", 0, (i2 < fp2), fp2);
expect("10 > 20 is", 0, (i1 > fp2), fp2);
expect("20 > 10 is", 1, (i2 > fp1), fp1);
expect("20 > 20 is", 0, (i2 > fp2), fp2);
expect("10 <= 20 is", 1, (i1 <= fp2), fp2);
expect("20 <= 10 is", 0, (i2 <= fp1), fp1);
expect("20 <= 20 is", 1, (i2 <= fp2), fp2);
expect("10 >= 20 is", 0, (i1 >= fp2), fp2);
expect("20 >= 10 is", 1, (i2 >= fp1), fp1);
expect("20 >= 20 is", 1, (i2 >= fp2), fp2);
#endif
}
int main(void)
{
printf("float-cmp-intvar-var\n");
seperate();
intvarvar();
printf("float-cmp-intvar-var (res: %d)\n", result);
return result;
}

Some files were not shown because too many files have changed in this diff Show More