Compare commits

...
172 Commits
Author SHA1 Message Date
Ryan Houdek ee4ef0fe87 Docs: Update for release FEX-2505 2025-05-05 11:37:17 -07:00
LC 1dff7073de Merge pull request #4554 from Sonicadvance1/remove_unused_argument
NFC: FEXCore: Removes unused argument on CreateThread
2025-05-05 14:30:24 -04:00
Ryan Houdek 92a82c3134 FEXCore: Removes unused argument on CreateThread
ParentTID is purely a Linux construct and has been moved entirely to the
frontend at this point. Remove this argument which is now unused.
2025-05-05 11:17:02 -07:00
Ryan Houdek a6a203c483 Merge pull request #4553 from neobrain/fix_align16b 2025-05-05 10:35:55 -07:00
Tony Wasserka cdaa65f6fd Arm64Emitter: Fix overalignment in Align16B
Previously, 16 additional bytes were emitted if the buffer was already
aligned.
2025-05-05 16:02:42 +02:00
Ryan Houdek 31e5f706b8 Merge pull request #4551 from OFFTKP/fadvise64
Fix 32-bit fadvise64
2025-05-02 18:37:55 -07:00
offtkp 00e05558ce Formatting 2025-05-03 04:28:23 +03:00
offtkp c02b88baff Fix 32-bit fadvise64 2025-05-03 03:56:16 +03:00
Ryan Houdek 794c80edad Merge pull request #4549 from OFFTKP/patch-2
Marshal freeram in sysinfo
2025-05-02 17:34:52 -07:00
Paris Oplopoios fb939600e2 Marshal freeram in sysinfo 2025-05-03 03:23:18 +03:00
Ryan Houdek 9dbbd44d09 Merge pull request #4544 from Sonicadvance1/fhu_ring_buffer
FHU: Add a non-block thread local ringbuffer
2025-05-02 11:22:39 -07:00
Ryan Houdek afcd93fe5f Merge pull request #4547 from Sonicadvance1/dont_go_chasing_sigsegv_waterfalls
Linux/SMCTracking: Stop calling mprotect on a memory region times the number of threads
2025-05-02 11:22:30 -07:00
Ryan Houdek 118faa5380 FHU: Add a non-block thread local ringbuffer
I keep rewriting this thing when I want to see some history on
something. Throw it in a FHU utility so I can stop wasting my time.
2025-05-02 01:19:00 -07:00
Ryan Houdek 7ed17f68c5 FEXCore: Remove unused InvalidateGuestCodeRange with callback 2025-05-02 01:15:50 -07:00
Ryan Houdek 96363143de Linux/SMCTracking: Stop calling mprotect on a memory region times the number of threads
I noticed this cascade of mprotects when poking at Crypt of the
Necrodancer, since it consistently is invalidating code. I saw us
calling mprotect on the same page 32 times in a tight loop and thought
surely this isn't FEX doing this.

Turns out we were calling the callback after invalidating each thread.
It should instead be done once at the end of invalidating the thread's
caches while still holding the locks.

Fixes this weird cascade of mprotects that equal the number of FEX
threads.
2025-05-01 21:14:05 -07:00
Ryan Houdek cf5fcb2371 Merge pull request #4546 from OFFTKP/shmdt
Make shmdt reset the unmapped pages in the 32-bit allocator
2025-05-01 20:17:50 -07:00
offtkp 7d3699050e Make shmdt reset the unmapped pages in the 32-bit allocator 2025-05-02 02:49:39 +03:00
LC 40e0a71f49 Merge pull request #4545 from Sonicadvance1/fix_fexserver_with_images
FEXServer: Fixes squashfs/erofs with newer fuse releases
2025-05-01 17:55:57 -04:00
Ryan Houdek cdbcdfe397 FEXServer: Fixes squashfs/erofs with newer fuse releases
Newer fuse releases changed how they are waiting on child processes to
exit. Setting the signal action to SIG_IGN would cause
erofsfuse/squashfuse to inherit the ignored action and cause their
internal `wait4` syscalls to fail with ECHLD.

Set the action back to default inside the FEXServer because our original
reasoning for setting the ignoring is no longer valid. FEXInterpreter
still ignores SIGCHLD while launching FEXServer.

Maybe fixes the muvm thing people have been complaining about.

Also fixes accidental comma delimiter usage.
2025-05-01 13:47:46 -07:00
LC 4f2d2e646e Merge pull request #4542 from Sonicadvance1/fexcore_reconstructions_getting_saved_today
FEXCore/JIT: Switch over to new vl64pair for RIP reconstruction
2025-05-01 13:28:16 -04:00
LC f97cd24647 Merge pull request #4543 from Sonicadvance1/fix_my_reducing_of_x87_today
FEXCore: Fixes x87 reduced precision
2025-05-01 13:25:30 -04:00
Ryan Houdek e5e75ad1ef InstcountCI: Update 2025-04-30 17:54:55 -07:00
Ryan Houdek fc052efb91 FEXCore: Fixes x87 reduced precision
With the change from #4538 I had accidentally broken x87 reduced
precision.

This is due to the fact that we accidentally lost ABI information about
interpreter fallbacks supporting `preserve_all` or not. So now instead
of having some ABI callbacks supporting it and some not, just force
usage of `preserve_all` if it is supported by the compiler entirely.

Fixes Steam when x87 reduced precision is enabled.
2025-04-30 17:37:10 -07:00
Ryan Houdek c5754145c5 FEXCore/JIT: Switch over to new vl64pair for RIP reconstruction
As said in the implementation of this struct commit message. This new
pair struct optimizes specific cases of small forward only increments
that can fit in to 8-bit space, and small forward or backward jump cases
that fit in to 16-bit space.

Some stats of this change:
- Steam: 5.88MB down to 4.34MB. 73.8% the space consumed
- Steamwebhelper: 15.8MB down to 13.24MB. 83.8% space consumed
- Sonic Mania: 3.6MB down to 2.58MB. 71.6% space consumed

As for absolute stats when compared to all code buffer size:
- Steam: 86MB of code buffer to 5.88MB -> 4.34MB of RIP reconstruction.
  - 6.8% -> 5% code buffer space used for RIP reconstruction
- Steamwebhelper: 285MB of code buffer to 17MB -> 14.26MB of RIP reconstruction.
  - 5.9% -> 4.9% code buffer space used for RIP reconstruction
- Sonic Mania: 48.53MB of code buffer to 3.55MB -> 2.53MB of RIP reconstruction.
  - 7.3% -> 5.2% code buffer space used for RIP reconstruction
2025-04-30 15:41:43 -07:00
Ryan Houdek 9986e69622 FEXCore/APITests: Extend tests for vl64pair 2025-04-30 15:41:20 -07:00
Ryan Houdek 00acf4d327 FEXCore/Utils: Implement a new VL64Pair struct type
This new variable length pair of integer implementation is taking direct
advantage of the most common aspects of FEX's JIT in that most x86
instructions are <= 8-bytes in length, and the ARM implementations of
those are /usually/ 16 instructions in length or less. Also only
unsigned offsets in this implementation since the common case is forward
incrementing.

This converts a majority of 16-bit vl encodings in to an 8-bit encoding
instead, shaving space off the RIP reconstruction data.

An additional optimization is for the 16-bit pair of integers, we
continue this optimization through but with more bits and changing over
to signed. This captures the second most common cases of /slightly/
larger increments and small loops.

Pairs of 32-bit and 64-bit integers are unoptimized since they are
uncommon.
2025-04-30 15:36:49 -07:00
Ryan Houdek 00ff549044 Merge pull request #4538 from Sonicadvance1/fex_interpreters_are_dancing
JIT: Move interpreter ABI handlers in to the dispatcher
2025-04-30 11:51:29 -07:00
Ryan Houdek 75a39c8939 InstcountCI: Update 2025-04-29 22:35:39 -07:00
Ryan Houdek 5b9354cc74 JIT: Move interpreter ABI handlers in to the dispatcher
Fixes #4535

A handful of improvements on this.
* Reduces codegen around interpreter fallbacks
* Keeps ABI handling code in common Dispatcher code
* Improves I$ hitrate by most of the heavy code staying in Dispatcher

This cuts the amount of codegen inside the JIT for most interpreter
fallbacks by 1/2 or 1/3, by only doing the minimal amount of work in the
code blocks and doing most things in the dispatcher. The cost of which
is an additional branch per operation.

This should bring marginal performance improvements, but it should also
basically fall within noise. The bigger thing to care about here is a
smaller amount of code being generated for x87 blocks.
2025-04-29 22:35:39 -07:00
Ryan Houdek f7049a6478 Arm64Emitter: On spill return stack used and stop clobbering TMP4
TMP4 was used before we passed in a tmp register. Now use that temp
register.

Also return the amount of stack used on the push function. This will be
used in a bit.
2025-04-29 22:31:35 -07:00
Ryan Houdek e1d032b5a6 Merge pull request #4540 from pmatos/MProtectLastPage
mprotect last page of CodeBuffer
2025-04-27 11:07:14 -07:00
LC f99691b0eb Merge pull request #4541 from Sonicadvance1/f80_cephes_softfloat_prep
80-bit cephes prep work
2025-04-26 09:18:57 -04:00
Ryan Houdek 10d18f2f17 Softfloat-3e: Adds missing extF80_le file 2025-04-25 17:30:18 -07:00
Ryan Houdek a236700c55 cephes_128bit: Rename a bunch of variables
These are going to conflict with the 80-bit implementation otherwise.
2025-04-25 17:30:18 -07:00
Ryan Houdek 34d62fcea6 cephes: Split 128-bit to its own folder
We are soon going to learn how to operate in f80.
2025-04-25 17:30:18 -07:00
Paulo Matos 791502afef Protect last page of CodeBuffer
protects last page of codebuffer. This should cause a
SIGSEGV if we try to access it. Until now it was possible to go over
and access out of bounds.

In addition, there a couple of clang-tidy fixes which should be NFC.
2025-04-25 20:41:18 +02:00
Ryan Houdek 99114e1fc2 Merge pull request #4528 from neobrain/feature_unlink_threadsafe
JIT: Make code patching during (un-/)linking thread-safe
2025-04-25 08:22:38 -07:00
Ryan Houdek 3c8bb53d1a Merge pull request #4539 from cjacek/mincore
Link to mincore instead of kernelbase on ARM64EC
2025-04-25 08:22:19 -07:00
Jacek Caban bd0682b518 Link to mincore instead of kernelbase on ARM64EC
The kernelbase import library is not available in upstream mingw-w64. Instead, similar to MSVC,
we can use mincore, which allows importing the relevant functions via apisets.
2025-04-25 11:38:16 +02:00
Tony Wasserka e89a913b69 JIT: Make memory write visible to other threads reading the same location 2025-04-25 09:47:13 +02:00
Tony Wasserka 293d77d412 JIT: Make code patching during (un-/)linking thread-safe 2025-04-25 09:21:09 +02:00
Ryan Houdek 6beb4b0f8b Merge pull request #4533 from Sonicadvance1/align_tail_in_the_pale_moonlight
JIT: Align JITCodeTail to native alignment
2025-04-24 16:18:45 -07:00
LC 23a8462688 Merge pull request #4536 from Sonicadvance1/eternal_sunshine_of_a_vectorless_mind
JIT: Moves VPCMPESTRX handler to use vectors
2025-04-24 13:35:33 -04:00
LC 02f90fbc66 Merge pull request #4534 from Sonicadvance1/spaaaaaaace
CodeEmitter: Fix clang-format
2025-04-24 13:34:19 -04:00
Ryan Houdek 8cc23d0cf8 Merge pull request #4537 from sdpoueme/main
updated Dockerfile to reflect latest FEX-Emu releases
2025-04-24 10:28:24 -07:00
Serge Poueme 60b5b1414d updated Dockerfile to reflect latest FEX-Emu releases
Add multi-stage Dockerfile for FEX emulator build

- Stage 1 (Builder): Sets up build environment with Ubuntu 22.04
  - Installs development tools and dependencies
  - Builds FEX using clang-13 with optimized settings
  - Configures cmake with LTO enabled and tests disabled

- Stage 2 (Runner): Creates minimal runtime image
  - Includes only necessary runtime libraries
  - Copies built binaries from builder stage
2025-04-24 10:13:04 -07:00
Ryan Houdek cbab344822 InstcountCI: Update 2025-04-24 10:11:25 -07:00
Ryan Houdek 32764ddf81 JIT: Moves VPCMPESTRX handler to use vectors
I pushed this off from the previous changes that were converting things
to vector as less important. It has now become more important to keep
these in vector registers until beyond the ABI boundary.

This will reduce burden on our JIT backend and just changes where the
movement in to GPRs occurs. Necessary for #4535
2025-04-24 10:09:26 -07:00
Ryan Houdek e31127e39e CodeEmitter: Fix clang-format 2025-04-24 08:41:23 -07:00
Ryan Houdek 735f537846 JIT: Align JITCodeTail to native alignment
Removes UB
2025-04-24 08:40:43 -07:00
Ryan Houdek b7790e10e9 Merge pull request #4532 from pmatos/X87StateBlockReset
X87 state block reset
2025-04-24 08:37:32 -07:00
Ryan Houdek 3f7ad04054 Merge pull request #4531 from Sonicadvance1/instcountci_change_size
InstcountCI: Changes how code size is calculated
2025-04-24 08:35:33 -07:00
Paulo Matos 670ddf9cd8 instcountci: Reset MMXState to X87 at the start of each block 2025-04-24 15:02:46 +02:00
Paulo Matos d377e26106 Reset MMXState to X87 at the start of each block
Ensures that blocks always start with the same state independently of predecessors
which allows independent compilation of blocks.
Starting in the X87 state is better than starting in MMX state because
MMX state is more work to initialize.
2025-04-24 15:02:41 +02:00
Ryan Houdek 674f939690 Merge pull request #4523 from bylaws/maptrack
Improve tracking of executable mappings
2025-04-23 13:08:12 -07:00
Ryan Houdek 64abfb1afe InstcountCI: Update 2025-04-23 12:56:46 -07:00
Ryan Houdek adcefe62cf InstcountCI: Changes how code size is calculated
Due to how jit block tail padding is working, there's no real good way
to determine the true "implementation size" of an instruction without
the backend being aware of wanting to investigate it.

Trying to inject another instruction, or another IR operation actually
subtly changes codegen in a way that gives invalid results. The only
real way to get around this is to inject a known token in to the
instruction stream as we `ExitFunction`.

So inject a `udf #0x420f`, and change the scanning behaviour to find the
first one and cut everything else off afterwards.

This already scoops out some code in some game blocks that were
accidentally landing ExitFunction code in the json.

This also has been tested to work with #4528 with its InstCountCI
specific changes reverted.

This means we don't need to play subtle padding tricks in the JIT to get
the information we want in InstcountCI.
2025-04-23 12:56:46 -07:00
Ryan Houdek bf77fa4275 unittests/Emitter: Adds udf test 2025-04-23 12:53:36 -07:00
Ryan Houdek e7fce2de40 CodeEmitter: Adds udf support 2025-04-23 12:14:44 -07:00
Ryan Houdek 8864637602 Merge pull request #4465 from Sonicadvance1/ubsan_fixes
Various: UBSAN fixes around unaligned accesses
2025-04-23 00:54:49 -07:00
Ryan Houdek 1a0d97d5f7 Various: UBSAN fixes around unaligned accesses 2025-04-23 00:31:09 -07:00
Ryan Houdek 9ba46e395d Merge pull request #4530 from neobrain/fix_instcountci_script
Scripts/InstCountCI: Restrict git-add to relevant JSON files only
2025-04-22 06:10:43 -07:00
Tony Wasserka be99fa0b05 Scripts/InstCountCI: Restrict git-add to relevant JSON files only 2025-04-22 13:34:28 +02:00
Ryan Houdek c42b1858c5 Merge pull request #4529 from lioncash/tests
ASIMD_Tests: Enable PMULL/PMULL2 tests
2025-04-21 19:03:01 -07:00
Lioncache cc11de16bf ASIMD_Tests: Enable PMULL/PMULL2 tests
vixl now supports these. We can also get rid of the invalid data sizes,
since only halfword and 128-bit variants are defined.
2025-04-21 20:03:37 -04:00
Ryan Houdek 3ea7c2b014 Merge pull request #4522 from bylaws/persona
LinuxEmulation: Copy the host persona on thread startup
2025-04-21 00:59:01 -07:00
Ryan Houdek e0e9f5aa16 Merge pull request #4527 from lioncash/concept
CodeEmitter/ASIMDOps: Constrain Q and D register requirements with concept
2025-04-20 18:14:15 -07:00
Lioncache 63a2d1e1db CodeEmitter/ASIMDOps: Move three emitter helpers to private section
These don't need to be public.
2025-04-20 15:55:53 -04:00
Lioncache 644263a764 CodeEmitter/ASIMDOps: Constrain Q and D register requirements with concept
Pulls these out into a single concept instead of having the same lengthy
requirements clause.
2025-04-20 15:55:49 -04:00
Ryan Houdek f912295690 Merge pull request #4524 from bylaws/faulto
X86Tables: Set FLAGS_BLOCK_END for more faulting ops
2025-04-19 19:02:09 -07:00
Ryan Houdek 79e57c320c Merge pull request #4525 from lioncash/pac
CodeEmitter/LoadstoreOps: Add Load/store register (PAC) group
2025-04-19 18:29:18 -07:00
Lioncache 4e6f183f77 CodeEmitter/LoadstoreOps: Add Load/store register (PAC) group
Eh, what the heck. Gets rid of the last TODO marker in the base load-stores.
2025-04-19 13:00:00 -04:00
Billy Laws 23017af874 TestHarnessRunner: Call the frontend mapping callback for created mappings 2025-04-19 15:29:23 +01:00
LC 4d02126b77 Merge pull request #4517 from Sonicadvance1/ruining_another_set_of_memory_leaks
LinuxEmulation: Fixes remaining memory leak on pthread teardown
2025-04-19 09:44:26 -04:00
Billy Laws 30fefbd57d X86Tables: Set FLAGS_BLOCK_END for more faulting ops 2025-04-19 14:19:19 +01:00
Billy Laws 38304fa63a LinuxEmulation: Copy the host persona on thread startup 2025-04-19 14:10:55 +01:00
Billy Laws 6525b8dd14 VDSO_Emulation: Map the VDSO thunk as executable 2025-04-19 14:09:48 +01:00
Billy Laws 0155719b1a VDSO_Emulation: Ensure the 32 bit sigreturn mapping is tracked as executable 2025-04-19 14:09:48 +01:00
Billy Laws 966dce6e95 SyscallsSMCTracking: Handle shmat SHM_EXEC flag 2025-04-19 14:09:48 +01:00
Billy Laws e3088686db InvalidationTracker: Track executable mappings 2025-04-19 14:09:48 +01:00
Billy Laws 771162cf14 InvalidationTracker: Track the protection of regions mapped at startup
Code can be injected into a process by e.g. the chromium sandbox before
FEX is loaded.
2025-04-19 14:09:48 +01:00
Billy Laws 1a2398d2ce Windows: Call the protection callback for executable FEX mappings 2025-04-19 14:09:48 +01:00
Billy Laws 0f0e969d8f Windows: Call the image map callback for ntdll 2025-04-19 14:09:48 +01:00
Ryan Houdek c8371087e6 Merge pull request #4519 from neobrain/fix_fexconfig_layout
FEXConfig: Fix layout issues on Qt 6.9
2025-04-18 09:25:08 -07:00
Ryan Houdek 3da6fc3972 Merge pull request #4518 from neobrain/refactor_warn_fixes
JIT: Fix warning about unused variable
2025-04-18 09:24:49 -07:00
Ryan Houdek 0cbbd91e72 Merge pull request #4521 from lioncash/mem
CodeEmitter/LoadStoreOps: Add Memory Copy and Memory Set category
2025-04-18 09:24:24 -07:00
Lioncache d71aca9e9b CodeEmitter/LoadStoreOps: Add Memory Copy and Memory Set category
Adds all of the memory facilities in FEAT_MOPS to the emitter.
2025-04-18 10:53:38 -04:00
Tony Wasserka 63035fd5f3 FEXConfig: Fix layout issues on Qt 6.9 2025-04-18 11:17:51 +02:00
Tony Wasserka 0fe28129a0 JIT: Fix warning about unused variable 2025-04-18 11:16:46 +02:00
Ryan Houdek c44d8eed35 LinuxEmulation: Fixes remaining memory leak on pthread teardown
With the previous stack leak fix, RUINER reduced its memory leaking down
to around 50MB/s. The remaining memory leaks come from the pthread stack
that we are required to allocate (128KB per thread) and some internal
DTV tracking structures.

The problems come in the fact that glibc/pthread only tears down its
internal state for these if the pthread function actually returns! We
can **technically** switch the initial stack over to a "user" stack but
that introduces more problems around internal dtv tracking that we
already fixed months ago, so we can't actually do that in practice.

This leaves us no choice, we effectively are mandated to return from the
pthread function in order to free the memory from glibc. The only way we
can safely do this is with a long jump and deferring some data structure
management until that case.

This is all incredibly sucky but it's necessary to work. With these
changes, RUINER is no longer leaking memory (Hovering at around 3GB used
while in-game) and even Steam is consuming less memory.

It doesn't solve the problem that thread creation and teardown could
likely be faster, but not many applications are creating 720
threads/second.
2025-04-17 18:16:32 -07:00
Ryan Houdek 6f5588f71e Merge pull request #4504 from pmatos/NoStrictAliasing
Enable -fno-strict-aliasing
2025-04-17 17:27:33 -07:00
Ryan Houdek 68f8c244b4 Merge pull request #4516 from lioncash/radd
CodeEmitter/ASIMDOps: Support RADDHN{2}/RSUBHN{2}
2025-04-17 17:27:22 -07:00
Lioncache d7a08fc7d4 CodeEmitter/ASIMDOps: Support RADDHN{2}/RSUBHN{2}
These are trivial enough to just drop right in.
2025-04-17 20:13:30 -04:00
LC 572d6e0395 Merge pull request #4509 from Sonicadvance1/in_the_twilight_of_the_pale_blue_moon
A couple of barrier and timing fixes.
2025-04-17 17:30:03 -04:00
LC 156b6745a2 Merge pull request #4513 from Sonicadvance1/fix_stack_leak
LinuxSyscalls: Fixes a major stack memory leak
2025-04-17 17:27:15 -04:00
Ryan Houdek b4eb38e2b7 Merge pull request #4515 from lioncash/scalar
CodeEmitter/ScalarOps: Add two more instruction categories
2025-04-17 14:10:04 -07:00
Lioncache bafcc8762b CodeEmitter/ScalarOps: Handle ASIMD scalar x indexed element group 2025-04-17 14:47:38 -04:00
Lioncache ec6ff7899d CodeEmitter/ScalarOps: Remove implemented TODO
These scalar ops are already implemented and this was accidentally left in.
2025-04-17 08:14:10 -04:00
Lioncache 6330b398a5 CodeEmitter/ScalarOps: Handle ASIMD scalar three same extra group
These are trivial enough to drop in.
2025-04-17 08:09:42 -04:00
Ryan Houdek 86c492da13 LinuxSyscalls: Fixes a major stack memory leak
Fixes an issue where a thread that exits with the `exit` syscall never
actually frees its pivot stack. This is common practice and it was
missed when I was fixing the previous stack pivot leak.

This was uncovered when looking at the game
[RUINER](https://store.steampowered.com/agecheck/app/464060/?curator_clanid=4777282)
for timing bugs. Turns out the Linux build of the game creates and
destroys a VLC object every tick of the engine. Creating this VLC
object creates six threads behind the scenes. At what I assume the
default tick of the engine is of 120Hz(?) this would mean it is
attempting to create and destroy 720 threads per second, quickly
leading to memory exhaustion under FEX.

While this hits the biggest memory leak we have around thread creation,
this game is still hitting thread creation so hard that I can see other
leaks that I need to track down still.
2025-04-16 19:47:56 -07:00
Ryan Houdek 8ff7497d59 Merge pull request #4501 from JunChi1022/mask_signal_at_defer
LinuxSyscalls: Update signal mask at deferring time
2025-04-16 10:56:40 -07:00
Ryan Houdek 73593ad4f1 Merge pull request #4499 from bylaws/x87fix
OpcodeDispatcher: Mark NZCV as dirty when clobbering in FCOMIF64
2025-04-16 10:32:13 -07:00
Ryan Houdek 572a58ed27 Merge pull request #4512 from lioncash/internal
Arm64: Mark several functions as internally linked
2025-04-16 10:31:06 -07:00
Ryan Houdek d7df4be379 Merge pull request #4511 from lioncash/test
ASIMD_Tests: Re-enable tests disabled due to dissassembly bugs
2025-04-16 10:30:25 -07:00
Ryan Houdek f227722898 Merge pull request #4503 from pmatos/UBSANflags
Add no-sanitize flags to UBSAN
2025-04-16 10:29:02 -07:00
JustinChi f371bf2bc4 LinuxSyscalls: Update signal mask at deferring time
In regular x86 programs, when a signal occurs, the signal will not be handled within the signal handler. However, under FEX's defer signal mechanism, the signal is not immediately masked when it is deferred. When returning to the location that receives the signal and continues processing, the signal might be received again, causing inconsistency between the emulation and the actual program.

Here is an unit test for this patch from ltp:
https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/syscalls/timer_settime/timer_settime03.c
2025-04-16 21:39:53 +08:00
Lioncache e6841ea46d Arm64_stubs: Remove non-public functions
These aren't exposed in the public interface anymore, so they can be removed.
2025-04-16 09:21:51 -04:00
Lioncache edbfe45a20 Arm64: Mark several functions as internally linked
These aren't directly used outside of the translation unit.
2025-04-16 09:16:44 -04:00
Lioncache 5f83e89be5 ASIMD_Tests: Re-enable tests disabled due to dissassembly bugs
These issues seem to be resolved now.
2025-04-16 08:47:18 -04:00
Billy Laws 5850b26de5 Update InstCountCI 2025-04-16 13:16:07 +01:00
Billy Laws 416267a238 OpcodeDispatcher: Safely clobber NZCV in FCOMIF64
Also fix a small typo that broke the !flagm2 path.
2025-04-16 13:06:37 +01:00
LC 94499ed8fc Merge pull request #4510 from Sonicadvance1/fix_space
CodeEmitter: Fixes misaligned function
2025-04-15 19:58:40 -04:00
Ryan Houdek da1868288d CodeEmitter: Fixes misaligned function 2025-04-15 15:47:31 -07:00
Ryan Houdek c8d6b39585 EmulatedFiles: Match bogomips calculation
Instead of hardcoding the bogomips calculation, more closely match what
the Linux kernel does for bogomips. There are some applications out
there that use bogomips for silly timing calculations, so this is a
better version.
2025-04-15 15:42:52 -07:00
Ryan Houdek 00f8181c3a OpcodeDispatcher: Fix CPUID being a instruction fence
It is common practice for games to use CPUID as an instruction barrier
for various reasons. Ensure that we respect this by adding support for
an instruction barrier.
2025-04-15 15:42:43 -07:00
Ryan Houdek 60565cc2ef OpcodeDispatcher: Implement support for self-synchronizing cycle counter
FEAT_ECV added a new synchronizing cycle counter instruction that
restrict speculation across the cycle counter access. Because it
restricts speculation, it effectively acts like an isb and load dsb.

Luckily for us, this actually matches behaviour for what rdtscp does, so
we can take advantage of it if the host supports FEAT_ECV.
2025-04-15 15:42:43 -07:00
Ryan Houdek bfee39ae70 HostFeatures: Passthrough if the host supports ECV 2025-04-15 15:38:00 -07:00
Ryan Houdek 753c5e72be CodeEmitter: Implement support for CNTVCTSS_EL0 2025-04-15 15:37:02 -07:00
Ryan Houdek 571a533543 Merge pull request #4508 from lioncash/crypto
Emitter: Add missing ASIMD crypto operations
2025-04-15 11:24:51 -07:00
Lioncache 222fcfd70e CodeEmitter/ASIMDOps: Add crypto two-register SHA512 category 2025-04-15 11:48:30 -04:00
Lioncache 95c8a70ce6 CodeEmitter/ASIMDOps: Add crypto four-reg category 2025-04-15 11:41:07 -04:00
Lioncache 0f6bec4d5e CodeEmitter/ASIMDOps: Add crypto three-reg SHA512 category 2025-04-15 11:31:00 -04:00
Lioncache 5fb0522c78 CodeEmitter/ASIMDOps: Add crypto three-reg imm2 category 2025-04-15 11:15:21 -04:00
Tony Wasserka 7c0bc2d972 Merge pull request #4506 from pmatos/CastFixValidateCode
Fix cast in ValidateCode impl
2025-04-15 14:07:51 +02:00
Paulo Matos cb972e165b Fix cast in ValidateCode impl 2025-04-15 09:35:46 +02:00
Paulo Matos fb319a352a Enable -fno-strict-aliasing 2025-04-14 09:29:15 +02:00
Paulo Matos e10646b436 Add no-sanitize flags to UBSAN
See discussion in https://github.com/FEX-Emu/FEX/pull/4494 for context.
2025-04-14 09:10:28 +02:00
Ryan Houdek 211bec65d2 Merge pull request #4492 from bylaws/badencodings
Frontend: Be more tolerant of bad instruction encodings
2025-04-13 19:09:07 -07:00
Ryan Houdek 66807539ce Merge pull request #4500 from bylaws/arm64ec-fixes-etc
Windows: Misc cleanups and fixes
2025-04-13 19:03:17 -07:00
Ryan Houdek 2919c32a8f Merge pull request #4497 from pmatos/CleanupGCCTests
Cleanup info test files for 32bits
2025-04-11 17:43:09 -07:00
Billy Laws 05be9e9c37 Windows: Process cross-process notifications before code compilation 2025-04-11 12:07:16 +01:00
Billy Laws 039aaae041 FEXCore: Add a pre-compilation frontend callback to SyscallHandler 2025-04-11 12:07:16 +01:00
Billy Laws 890653ae39 WOW64: Handle the image mapped callback 2025-04-11 12:07:16 +01:00
Billy Laws 8644fdd595 ARM64EC: Slight cleanup 2025-04-11 12:07:16 +01:00
Billy Laws 4fca8fb8e6 AllocatorHooks: Correctly restore the region protection in VirtualDontNeed 2025-04-11 12:07:16 +01:00
Billy Laws 9625201cbf Frontend: Remove asserts on invalid instruction encodings 2025-04-11 12:06:01 +01:00
Paulo Matos e7dea56adf NFC: Cleanup info test files for 32bits
No point in duplicating test info between Disabled and Known Failures.

Leaving tests known to fail in Known_Failures. Flakes / Unreliable tests go into Disabled_Tests.
2025-04-11 10:50:41 +02:00
LC 5b802d17d1 Merge pull request #4498 from Sonicadvance1/fix_llseek
LinuxSyscalls: Fixes 32-bit llseek result
2025-04-10 16:18:54 -04:00
Ryan Houdek a43ddba87c LinuxSyscalls: Fixes 32-bit llseek result
`llseek` returns only ever 0 or errno in the return register. This is in
contrast to `lseek` which returns the result (or errno) in the return
register.

We were accidentally returning the result on non-error conditions which
could freak out some software. Thanks to
[OFFTKP](https://github.com/OFFTKP) for pointing out this issue
2025-04-10 13:08:06 -07:00
Tony Wasserka f1d007ca4c Merge pull request #4495 from pmatos/CleanupCompWarn
Cleanup compile warnings
2025-04-10 16:40:46 +02:00
Paulo Matos c2111e7384 Cleanup compile warnings 2025-04-10 08:49:51 +02:00
Billy Laws a1c6378317 Frontend: Only accept POP opcodes with a 0 ModRM.reg field 2025-04-09 23:04:11 +01:00
Billy Laws f064013b9a Frontend: Enforce FLAGS_SF_MOD_MEM_ONLY/FLAGS_SF_MOD_REG_ONLY 2025-04-09 23:02:09 +01:00
Billy Laws d4480c3566 X86Tables: Mark VMOVNTDQ as FLAGS_SF_MOD_MEM_ONLY 2025-04-09 23:01:26 +01:00
Billy Laws b3a4de7aa8 X86Tables: Mark MASKMOVQ as FLAGS_SF_MOD_REG_ONLY 2025-04-09 23:01:26 +01:00
Billy Laws 60d8131a4d X86Tables: Drop FLAGS_SF_MOD_MEM_ONLY from (V)MOV(L/H)PS
These encodings are shared with MOVLHPS/MOVHLPS and FEX handles both variants.
2025-04-09 23:01:26 +01:00
Billy Laws 6d78aefa13 Frontend: Ignore REX register extension for MMX registers 2025-04-09 23:01:26 +01:00
Billy Laws badd953600 unittests: Test for REX.B being ignored with MMX registers 2025-04-09 23:01:26 +01:00
LC 5d385c540d Merge pull request #4489 from Sonicadvance1/reduce_stack_cpu_count
FEXCore: Reduce stack usage in CalculateNumberOfCPUs
2025-04-09 12:40:52 -04:00
Ryan Houdek 52351902ee Merge pull request #4488 from pmatos/EnableUBSAN
Add option to enable UBSAN
2025-04-09 00:13:29 -07:00
Paulo Matos 6e697e5ec1 Add option to enable UBSAN 2025-04-09 08:58:24 +02:00
Ryan Houdek c55c8979f1 AOTGen: Only calculate number of CPU cores once
Removes some per-iteration string processing and file IO.
2025-04-08 22:55:55 -07:00
Ryan Houdek 7ca757bb6d FEXCore: Move CPUInfo to FEX
This is only ever used in the frontend now.
2025-04-08 22:54:43 -07:00
Ryan Houdek c2d59b02bd FEXCore: Reduce stack usage in CalculateNumberOfCPUs
Nothing crazy, just recalculate the maximum string length rather than
use PATH_MAX.
2025-04-08 22:54:43 -07:00
LC 45b638fc45 Merge pull request #4491 from Sonicadvance1/push_pop_callee
FEXCore/Emitter: Stop creating a vector on the heap
2025-04-09 01:46:34 -04:00
Ryan Houdek 5767c61a91 FEXCore/Emitter: Stop creating a vector on the heap
In the Push/Pop CalleeSavedRegisters these vectors were getting created
on the heap, allocating memory and then just iterating them.

Just use a std::array which makes it stop allocating memory and saves
the number of instructions.
2025-04-08 18:36:47 -07:00
LC e3f8a817e0 Merge pull request #4490 from Sonicadvance1/remove_old_workaround
FEXCore/Allocator: Removes old workaround for kernel 4.17
2025-04-08 21:34:47 -04:00
Ryan Houdek 4377603d7e FEXCore/Allocator: Removes old workaround for kernel 4.17
This was only used for working around our old CI machines and now that
our minimum kernel requirement is 5.15 this isn't required anymore.
2025-04-08 18:22:39 -07:00
LC bc72239181 Merge pull request #4485 from Sonicadvance1/softfloat-3e_potara_cephes
cephes: Rewrite to use softfloat-3e 128-bit
2025-04-08 11:26:01 -04:00
Ryan Houdek 2d7f37386e Softfloat: Remove warnings
These precision warnings are no longer true!
2025-04-07 15:22:24 -07:00
Ryan Houdek dffba2d83c unittests/ASM: Enable x87 tests under simulator
Since the x86 simulator is now handling these instructions at 128-bit
precision, these now just work.
2025-04-07 15:13:04 -07:00
Ryan Houdek 0fbb6aa02f cephes: Rewrite to use softfloat-3e 128-bit
And also use it at the same time, since the function signatures changed.

Instead of relying on the host libc math libraries for `long double` ALU
operations, rewrite the entire thing to use softfloat-3e fixed width
float128_t types.

This is a very invasive change in cephes but is a necessary requirement
for getting the precision we require in environments that map `long
  double` to be the same as `double`, like Win32 and MacOS.

This fixes the precision issue in transcendental operations when running
under WINE.
2025-04-07 15:13:04 -07:00
Ryan Houdek 7364affd69 Softfloat-3e: Adds some missing files and passes state through 2025-04-07 14:57:48 -07:00
LC 09e622d5a0 Merge pull request #4482 from Sonicadvance1/softfloat_3e
Softfloat-3e: Add support for f128
2025-04-06 18:03:35 -04:00
Ryan Houdek 21ccaf56e6 Softfloat-3e: Add support for f128
This is going to be necessary soon.
2025-04-05 17:48:57 -07:00
Ryan Houdek d8cd807520 Softfloat-3e: Moves to Externals 2025-04-05 17:26:15 -07:00
LC 6069d05aa9 Merge pull request #4481 from Sonicadvance1/instcountci_ensure_consistent_rip
InstcountCI: Ensure RIP of blocks is consistent
2025-04-05 19:04:39 -04:00
Ryan Houdek 09a3d4851a InstcountCI: Update 2025-04-05 15:55:08 -07:00
Ryan Houdek d41374c55a InstcountCI: Ensure RIP of blocks is consistent
This changes the instcountCI code to consistently load test data in to
RIP 0x1'0000 so we don't have any spurious changes due to json changes.

This has been a minor annoyance where if a test was added, it had the
potential to shift the rest of the data in the tests. This now ensures
it is consistent.
2025-04-05 15:55:08 -07:00
LC dd8a1f00fc Merge pull request #4468 from Sonicadvance1/thats_the_softfloat_guarantee
FEXCore/Softfloat: Wire up cephes math library for transcendental operations
2025-04-04 19:11:55 -04:00
Ryan Houdek ffca27cbde FEXCore/Softfloat: Wire up cephes math library for transcendental operations
This is solving a different problem than what #4411 is specifically
trying to solve.

For our transcendental operations, we can't currently guarantee that
these functions will actually operate at the 128-bit softfloat
precision. While this is true with glibc, this is /not/ true for musl
and likely more libraries.

Instead of relying on our libc implementation to implement these,
instead include the cephes math library directly which is what most
people use for this. Including musl even, but not for all operations.

With this we are no longer beholden to the standard libraries for
providing a correct implementation.
2025-04-04 16:03:09 -07:00
Ryan Houdek 82edd901fe FEXCore/Common: Adds cephes math library
Only the few transcendental functions that FEX needs.
Disabled when building on x86-64.
2025-04-04 16:03:09 -07:00
252 changed files with 47422 additions and 174651 deletions

No files matched your search

-2
View File
@@ -3,8 +3,6 @@
# Ignore all files in the External directory
External/*
# SoftFloat-3e code doesn't belong to us
FEXCore/Source/Common/SoftFloat-3e/*
Source/Common/cpp-optparse/*
# Files with human-indented tables for readability - don't mess with these
+16
View File
@@ -13,6 +13,7 @@ option(ENABLE_IWYU "Enables include what you use program" FALSE)
option(ENABLE_LTO "Enable LTO with compilation" TRUE)
option(ENABLE_XRAY "Enable building with LLVM X-Ray" FALSE)
set(USE_LINKER "" CACHE STRING "Allow overriding the linker path directly")
option(ENABLE_UBSAN "Enables Clang UBSAN" FALSE)
option(ENABLE_ASAN "Enables Clang ASAN" FALSE)
option(ENABLE_TSAN "Enables Clang TSAN" FALSE)
option(ENABLE_COVERAGE "Enables Coverage" FALSE)
@@ -228,6 +229,19 @@ if (NOT ENABLE_OFFLINE_TELEMETRY)
add_definitions(-DFEX_DISABLE_TELEMETRY=1)
endif()
if (ENABLE_UBSAN)
# See https://github.com/FEX-Emu/FEX/pull/4494#issuecomment-2800608944
# and related discussion for the use of -fno-sanitize=alignment -fno-sanitize=function
# with UBSAN.
# alignment: we don't follow a strict alignment policy, for example IR uses packed structs
# that are regularly access unaligned.
# function: syscalls cast function pointers to void (*)(unsigned long...), causing warnings
# related to this access.
add_definitions(-DENABLE_UBSAN=1)
add_compile_options(-fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=function -fno-sanitize-recover=undefined)
link_libraries(-fno-omit-frame-pointer -fsanitize=undefined -fno-sanitize=alignment -fno-sanitize=function -fno-sanitize-recover=undefined)
endif()
if (ENABLE_ASAN)
add_definitions(-DENABLE_ASAN=1)
add_compile_options(-fno-omit-frame-pointer -fsanitize=address -fsanitize-address-use-after-scope)
@@ -440,6 +454,8 @@ if (BUILD_TESTS)
set(TEST_JOB_FLAG "-j${TEST_JOB_COUNT}")
endif()
add_subdirectory(External/SoftFloat-3e/)
add_subdirectory(External/cephes/)
add_subdirectory(FEXHeaderUtils/)
add_subdirectory(CodeEmitter/)
add_subdirectory(FEXCore/)
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -47,13 +47,13 @@ public:
CurrentOffset += StringLength;
}
void Align() {
// Align the buffer to instruction size
auto CurrentAlignment = reinterpret_cast<uint64_t>(CurrentOffset) & 0b11;
void Align(size_t Size = 4) {
// Align the buffer to provided size.
auto CurrentAlignment = reinterpret_cast<uint64_t>(CurrentOffset) & (Size - 1);
if (!CurrentAlignment) {
return;
}
CurrentOffset += 4 - CurrentAlignment;
CurrentOffset += Size - CurrentAlignment;
}
template<typename T>
+5
View File
@@ -355,6 +355,7 @@ enum class SystemRegister : uint32_t {
TPIDRRO_EL0 = GenSystemReg<0b11, 0b011, 0b1101, 0b0000, 0b011>,
CNTFRQ_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b000>,
CNTVCT_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b010>,
CNTVCTSS_EL0 = GenSystemReg<0b11, 0b011, 0b1110, 0b0000, 0b110>,
};
template<uint32_t op1, uint32_t CRm, uint32_t op2>
@@ -572,6 +573,10 @@ enum class Rotation : uint32_t {
template<typename T>
concept IsXOrWRegister = std::is_same_v<T, XRegister> || std::is_same_v<T, WRegister>;
// Concept for contraining some instructions to accept only a QRegister or DRegister.
template<typename T>
concept IsQOrDRegister = std::is_same_v<T, QRegister> || std::is_same_v<T, DRegister>;
// Whether or not a given set of vector registers are sequential
// in increasing order as far as the register file is concerned (modulo its size)
//
+412 -10
View File
@@ -416,8 +416,7 @@ public:
0;
ASIMDSTLD<size, true, 1>(Op, Opcode, rt, Index, rn, Reg::r0);
}
template<SubRegSize size, typename T>
requires (std::is_same_v<QRegister, T> || std::is_same_v<DRegister, T>)
template<SubRegSize size, IsQOrDRegister T>
void ld1r(T rt, Register rn) {
constexpr uint32_t Op = 0b0000'1101'000 << 21;
constexpr uint32_t Opcode = 0b110;
@@ -435,8 +434,7 @@ public:
0;
ASIMDSTLD<size, true, 2>(Op, Opcode, rt, Index, rn, Reg::r0);
}
template<SubRegSize size, typename T>
requires (std::is_same_v<QRegister, T> || std::is_same_v<DRegister, T>)
template<SubRegSize size, IsQOrDRegister T>
void ld2r(T rt, T rt2, Register rn) {
LOGMAN_THROW_A_FMT(AreVectorsSequential(rt, rt2), "rt and rt2 must be sequential");
constexpr uint32_t Op = 0b0000'1101'000 << 21;
@@ -455,8 +453,7 @@ public:
0;
ASIMDSTLD<size, true, 3>(Op, Opcode, rt, Index, rn, Reg::r0);
}
template<SubRegSize size, typename T>
requires (std::is_same_v<QRegister, T> || std::is_same_v<DRegister, T>)
template<SubRegSize size, IsQOrDRegister T>
void ld3r(T rt, T rt2, T rt3, Register rn) {
LOGMAN_THROW_A_FMT(AreVectorsSequential(rt, rt2, rt3), "rt, rt2, and rt3 must be sequential");
constexpr uint32_t Op = 0b0000'1101'000 << 21;
@@ -475,8 +472,7 @@ public:
0;
ASIMDSTLD<size, true, 4>(Op, Opcode, rt, Index, rn, Reg::r0);
}
template<SubRegSize size, typename T>
requires (std::is_same_v<QRegister, T> || std::is_same_v<DRegister, T>)
template<SubRegSize size, IsQOrDRegister T>
void ld4r(T rt, T rt2, T rt3, T rt4, Register rn) {
LOGMAN_THROW_A_FMT(AreVectorsSequential(rt, rt2, rt3, rt4), "rt, rt2, rt3, and rt4 must be sequential");
constexpr uint32_t Op = 0b0000'1101'000 << 21;
@@ -2136,7 +2132,370 @@ public:
}
// Memory copy/set
// TODO
void cpyfp(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0000, rs, rn, rd);
}
void cpyfm(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0000, rs, rn, rd);
}
void cpyfe(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0000, rs, rn, rd);
}
void cpyfpwt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0001, rs, rn, rd);
}
void cpyfmwt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0001, rs, rn, rd);
}
void cpyfewt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0001, rs, rn, rd);
}
void cpyfprt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0010, rs, rn, rd);
}
void cpyfmrt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0010, rs, rn, rd);
}
void cpyfert(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0010, rs, rn, rd);
}
void cpyfpt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0011, rs, rn, rd);
}
void cpyfmt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0011, rs, rn, rd);
}
void cpyfet(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0011, rs, rn, rd);
}
void cpyfpwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0100, rs, rn, rd);
}
void cpyfmwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0100, rs, rn, rd);
}
void cpyfewn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0100, rs, rn, rd);
}
void cpyfpwtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0101, rs, rn, rd);
}
void cpyfmwtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0101, rs, rn, rd);
}
void cpyfewtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0101, rs, rn, rd);
}
void cpyfprtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0110, rs, rn, rd);
}
void cpyfmrtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0110, rs, rn, rd);
}
void cpyfertwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0110, rs, rn, rd);
}
void cpyfptwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b0111, rs, rn, rd);
}
void cpyfmtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b0111, rs, rn, rd);
}
void cpyfetwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b0111, rs, rn, rd);
}
void cpyfprn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1000, rs, rn, rd);
}
void cpyfmrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1000, rs, rn, rd);
}
void cpyfern(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1000, rs, rn, rd);
}
void cpyfpwtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1001, rs, rn, rd);
}
void cpyfmwtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1001, rs, rn, rd);
}
void cpyfewtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1001, rs, rn, rd);
}
void cpyfprtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1010, rs, rn, rd);
}
void cpyfmrtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1010, rs, rn, rd);
}
void cpyfertrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1010, rs, rn, rd);
}
void cpyfptrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1011, rs, rn, rd);
}
void cpyfmtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1011, rs, rn, rd);
}
void cpyfetrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1011, rs, rn, rd);
}
void cpyfpn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1100, rs, rn, rd);
}
void cpyfmn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1100, rs, rn, rd);
}
void cpyfen(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1100, rs, rn, rd);
}
void cpyfpwtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1101, rs, rn, rd);
}
void cpyfmwtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1101, rs, rn, rd);
}
void cpyfewtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1101, rs, rn, rd);
}
void cpyfprtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1110, rs, rn, rd);
}
void cpyfmrtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1110, rs, rn, rd);
}
void cpyfertn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1110, rs, rn, rd);
}
void cpyfptn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b00, 0b1111, rs, rn, rd);
}
void cpyfmtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b01, 0b1111, rs, rn, rd);
}
void cpyfetn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 0, 0b10, 0b1111, rs, rn, rd);
}
void setp(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0000, rs, rn, rd);
}
void setm(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0100, rs, rn, rd);
}
void sete(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b1000, rs, rn, rd);
}
void setpt(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0001, rs, rn, rd);
}
void setmt(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0101, rs, rn, rd);
}
void setet(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b1001, rs, rn, rd);
}
void setpn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0010, rs, rn, rd);
}
void setmn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0110, rs, rn, rd);
}
void seten(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b1010, rs, rn, rd);
}
void setptn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0011, rs, rn, rd);
}
void setmtn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b0111, rs, rn, rd);
}
void setetn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 0, 0b11, 0b1011, rs, rn, rd);
}
void cpyp(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0000, rs, rn, rd);
}
void cpym(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0000, rs, rn, rd);
}
void cpye(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0000, rs, rn, rd);
}
void cpypwt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0001, rs, rn, rd);
}
void cpymwt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0001, rs, rn, rd);
}
void cpyewt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0001, rs, rn, rd);
}
void cpyprt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0010, rs, rn, rd);
}
void cpymrt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0010, rs, rn, rd);
}
void cpyert(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0010, rs, rn, rd);
}
void cpypt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0011, rs, rn, rd);
}
void cpymt(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0011, rs, rn, rd);
}
void cpyet(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0011, rs, rn, rd);
}
void cpypwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0100, rs, rn, rd);
}
void cpymwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0100, rs, rn, rd);
}
void cpyewn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0100, rs, rn, rd);
}
void cpypwtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0101, rs, rn, rd);
}
void cpymwtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0101, rs, rn, rd);
}
void cpyewtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0101, rs, rn, rd);
}
void cpyprtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0110, rs, rn, rd);
}
void cpymrtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0110, rs, rn, rd);
}
void cpyertwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0110, rs, rn, rd);
}
void cpyptwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b0111, rs, rn, rd);
}
void cpymtwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b0111, rs, rn, rd);
}
void cpyetwn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b0111, rs, rn, rd);
}
void cpyprn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1000, rs, rn, rd);
}
void cpymrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1000, rs, rn, rd);
}
void cpyern(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1000, rs, rn, rd);
}
void cpypwtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1001, rs, rn, rd);
}
void cpymwtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1001, rs, rn, rd);
}
void cpyewtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1001, rs, rn, rd);
}
void cpyprtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1010, rs, rn, rd);
}
void cpymrtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1010, rs, rn, rd);
}
void cpyertrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1010, rs, rn, rd);
}
void cpyptrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1011, rs, rn, rd);
}
void cpymtrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1011, rs, rn, rd);
}
void cpyetrn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1011, rs, rn, rd);
}
void cpypn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1100, rs, rn, rd);
}
void cpymn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1100, rs, rn, rd);
}
void cpyen(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1100, rs, rn, rd);
}
void cpypwtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1101, rs, rn, rd);
}
void cpymwtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1101, rs, rn, rd);
}
void cpyewtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1101, rs, rn, rd);
}
void cpyprtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1110, rs, rn, rd);
}
void cpymrtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1110, rs, rn, rd);
}
void cpyertn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1110, rs, rn, rd);
}
void cpyptn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b00, 0b1111, rs, rn, rd);
}
void cpymtn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b01, 0b1111, rs, rn, rd);
}
void cpyetn(Register rd, Register rs, Register rn) {
MemoryCopyAndMemorySet(0, 1, 0b10, 0b1111, rs, rn, rd);
}
void setgp(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0000, rs, rn, rd);
}
void setgm(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0100, rs, rn, rd);
}
void setge(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b1000, rs, rn, rd);
}
void setgpt(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0001, rs, rn, rd);
}
void setgmt(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0101, rs, rn, rd);
}
void setget(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b1001, rs, rn, rd);
}
void setgpn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0010, rs, rn, rd);
}
void setgmn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0110, rs, rn, rd);
}
void setgen(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b1010, rs, rn, rd);
}
void setgptn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0011, rs, rn, rd);
}
void setgmtn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b0111, rs, rn, rd);
}
void setgetn(Register rd, Register rn, Register rs) {
MemoryCopyAndMemorySet(0, 1, 0b11, 0b1011, rs, rn, rd);
}
// Loadstore no-allocate pair
void stnp(ARMEmitter::WRegister rt, ARMEmitter::WRegister rt2, ARMEmitter::Register rn, int32_t Imm) {
LOGMAN_THROW_A_FMT(Imm >= -256 && Imm <= 252 && ((Imm & 0b11) == 0), "Unscaled offset too large");
@@ -3819,7 +4178,12 @@ public:
}
// Loadstore PAC
// TODO
void ldraa(XRegister rt, XRegister rn, IndexType type, int32_t offset = 0) {
LoadStorePAC(0b11, 0, 0, offset, type, rn, rt);
}
void ldrab(XRegister rt, XRegister rn, IndexType type, int32_t offset = 0) {
LoadStorePAC(0b11, 0, 1, offset, type, rn, rt);
}
// Loadstore unsigned immediate
// Maximum values of unsigned immediate offsets for particular data sizes.
@@ -3968,6 +4332,20 @@ private:
dc32(Instr);
}
void MemoryCopyAndMemorySet(uint32_t sz, uint32_t o0, uint32_t op1, uint32_t op2, Register rs, Register rn, Register rd) {
uint32_t Instr = 0b0001'1001'0000'0000'0000'0100'0000'0000;
Instr |= sz << 30;
Instr |= o0 << 26;
Instr |= op1 << 22;
Instr |= rs.Idx() << 16;
Instr |= op2 << 12;
Instr |= rn.Idx() << 5;
Instr |= rd.Idx();
dc32(Instr);
}
// Loadstore no-allocate pair
template<typename T>
void LoadStoreNoAllocate(uint32_t Op, T rt, T rt2, ARMEmitter::Register rn, uint32_t Imm) {
@@ -4034,6 +4412,30 @@ private:
dc32(Instr);
}
void LoadStorePAC(uint32_t size, uint32_t VR, uint32_t M, int32_t imm, IndexType type, Register rn, Register rt) {
LOGMAN_THROW_A_FMT((imm % 8) == 0, "Immediate ({}) must be divisible by 8", imm);
LOGMAN_THROW_A_FMT(imm >= -4096 && imm <= 4088, "Immediate ({}) must be within [-4096, 4088]", imm);
LOGMAN_THROW_A_FMT(type == IndexType::OFFSET || type == IndexType::PRE, "PAC may only use offset or pre-indexed values");
// The immediate is scaled down in order to fit within the available 10 immediate bits.
const auto scaled_imm = static_cast<uint32_t>(imm / 8);
const auto imm9 = scaled_imm & 0b1'1111'1111;
const auto S = (scaled_imm >> 9) & 1;
const auto W = type == IndexType::OFFSET ? 0U : 1U;
uint32_t Instr = 0b0011'1000'0010'0000'0000'0100'0000'0000;
Instr |= size << 30;
Instr |= VR << 26;
Instr |= M << 23;
Instr |= S << 22;
Instr |= imm9 << 12;
Instr |= W << 11;
Instr |= rn.Idx() << 5;
Instr |= rt.Idx();
dc32(Instr);
}
// Loadstore unsigned immediate
template<typename T>
void LoadStoreUnsigned(uint32_t size, uint32_t V, uint32_t opc, T rt, Register rn, uint32_t Imm) {
+106 -7
View File
@@ -137,7 +137,15 @@ public:
}
// Advanced SIMD scalar three same extra
// XXX:
void sqrdmlah(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm) {
LOGMAN_THROW_A_FMT(size == ScalarRegSize::i16Bit || size == ScalarRegSize::i32Bit, "Only supports 16/32-bit");
ASIMDScalarThreeSameExtra(1, size, 0b0000, rm, rn, rd);
}
void sqrdmlsh(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm) {
LOGMAN_THROW_A_FMT(size == ScalarRegSize::i16Bit || size == ScalarRegSize::i32Bit, "Only supports 16/32-bit");
ASIMDScalarThreeSameExtra(1, size, 0b0001, rm, rn, rd);
}
// Advanced SIMD scalar two-register miscellaneous
void suqadd(ScalarRegSize size, VRegister rd, VRegister rn) {
ASIMDScalar2RegMisc(0, 0, size, 0b00011, rd, rn);
@@ -744,10 +752,51 @@ public:
const uint32_t immb = InvertedShift & 0b111;
ASIMDScalarShiftByImm(1, immh, immb, 0b10011, rd, rn);
}
// TODO: UCVTF, FCVTZU
// Advanced SIMD scalar x indexed element
// XXX:
//
void sqdmlal(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(0, size, 0b0011, rm, rn, rd, index);
}
void sqdmlsl(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(0, size, 0b0111, rm, rn, rd, index);
}
void sqdmull(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(0, size, 0b1011, rm, rn, rd, index);
}
void sqdmulh(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(0, size, 0b1100, rm, rn, rd, index);
}
void sqrdmulh(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(0, size, 0b1101, rm, rn, rd, index);
}
void fmla(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
ASIMDScalarXIndexedElement(0, size, 0b0001, rm, rn, rd, index);
}
void fmls(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
ASIMDScalarXIndexedElement(0, size, 0b0101, rm, rn, rd, index);
}
void fmul(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
ASIMDScalarXIndexedElement(0, size, 0b1001, rm, rn, rd, index);
}
void sqrdmlah(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(1, size, 0b1101, rm, rn, rd, index);
}
void sqrdmlsh(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i64Bit, "Scalar size must not be 64-bit");
ASIMDScalarXIndexedElement(1, size, 0b1111, rm, rn, rd, index);
}
void fmulx(ScalarRegSize size, VRegister rd, VRegister rn, VRegister rm, uint32_t index) {
ASIMDScalarXIndexedElement(1, size, 0b1001, rm, rn, rd, index);
}
// Floating-point data-processing (1 source)
void fmov(ScalarRegSize size, VRegister rd, VRegister rn) {
Float1Source(size, 0, 0, 0b000000, rd, rn);
@@ -1269,7 +1318,17 @@ private:
}
// Advanced SIMD scalar three same extra
// XXX:
void ASIMDScalarThreeSameExtra(uint32_t U, ScalarRegSize size, uint32_t opcode, VRegister rm, VRegister rn, VRegister rd) {
uint32_t Instr = 0b0101'1110'0000'0000'1000'0100'0000'0000;
Instr |= U << 29;
Instr |= FEXCore::ToUnderlying(size) << 22;
Instr |= rm.Idx() << 16;
Instr |= opcode << 11;
Instr |= rn.Idx() << 5;
Instr |= rd.Idx();
dc32(Instr);
}
// Advanced SIMD scalar two-register miscellaneous
void ASIMDScalar2RegMisc(uint32_t b20, uint32_t U, ScalarRegSize size, uint32_t opcode, VRegister rd, VRegister rn) {
uint32_t Instr = 0b0101'1110'0010'0000'0000'1000'0000'0000;
@@ -1283,8 +1342,6 @@ private:
dc32(Instr);
}
// Advanced SIMD scalar pairwise
// XXX:
// Advanced SIMD scalar three different
void ASIMD3RegDifferent(uint32_t U, ScalarRegSize size, uint32_t opcode, VRegister rd, VRegister rn, VRegister rm) {
uint32_t Instr = 0b0101'1110'0010'0000'0000'0000'0000'0000;
@@ -1321,8 +1378,50 @@ private:
Instr |= Encode_rd(rd);
dc32(Instr);
}
// Advanced SIMD scalar x indexed element
// XXX:
void ASIMDScalarXIndexedElement(uint32_t U, ScalarRegSize size, uint32_t opcode, VRegister rm, VRegister rn, VRegister rd, uint32_t index) {
LOGMAN_THROW_A_FMT(size != ScalarRegSize::i8Bit, "Scalar size must not be 8-bit");
[[maybe_unused]] const auto invalid_bound = 16U >> FEXCore::ToUnderlying(size);
LOGMAN_THROW_A_FMT(index < invalid_bound, "Index ({}) must be within [0-{}]", index, invalid_bound - 1);
uint32_t Instr = 0b0101'1111'0000'0000'0000'0000'0000'0000;
// FMUL/FMLA/FMLS indexed variants deal with size differently.
if (opcode == 0b0001 || opcode == 0b0101 || opcode == 0b1001) {
// Unlike other instructions in the group, 16-bit is encoded as zero
// and 32/64-bit are encoded with the top bit always set to one.
if (size != ScalarRegSize::i16Bit) {
Instr |= (0b10 | (FEXCore::ToUnderlying(size) & 1)) << 22;
}
} else {
Instr |= FEXCore::ToUnderlying(size) << 22;
}
uint32_t H = 0;
uint32_t LM = 0;
if (size == ScalarRegSize::i16Bit) {
LOGMAN_THROW_A_FMT(rm <= VReg::v15, "rm ({}) must be within [v0-v15]", rm.Idx());
H = (index >> 2) & 1;
LM = index & 0b11;
} else if (size == ScalarRegSize::i32Bit) {
H = (index >> 1) & 1;
LM = (index & 0b01) << 1;
} else {
H = index & 1;
}
Instr |= U << 29;
Instr |= LM << 20;
Instr |= rm.Idx() << 16;
Instr |= opcode << 12;
Instr |= H << 11;
Instr |= rn.Idx() << 5;
Instr |= rd.Idx();
dc32(Instr);
}
// Floating-point data-processing (1 source)
void Float1Source(uint32_t M, uint32_t S, uint32_t ptype, uint32_t opcode, VRegister rd, VRegister rn) {
uint32_t Instr = 0b0001'1110'0010'0000'0100'0000'0000'0000;
+6
View File
@@ -13,6 +13,12 @@ struct EmitterOps : Emitter {
#endif
public:
// Reserved
void udf(uint32_t Imm) {
LOGMAN_THROW_A_FMT(Imm < 0x1'0000, "Immediate needs to be 16-bit");
dc32(Imm);
}
// System with result
// TODO: SYSL
// System Instruction
+14 -14
View File
@@ -1,31 +1,31 @@
# --- Stage 1: Builder ---
FROM ubuntu:20.04 as builder
FROM ubuntu:22.04 as builder
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
RUN DEBIAN_FRONTEND="noninteractive" apt install -y cmake \
clang-10 llvm-10 nasm ninja-build pkg-config \
clang-13 llvm-13 nasm ninja-build pkg-config \
libcap-dev libglfw3-dev libepoxy-dev python3-dev libsdl2-dev \
python3 linux-headers-generic \
git
python3 linux-headers-generic \
git qtbase5-dev qtdeclarative5-dev lld
RUN git clone --recurse-submodules https://github.com/FEX-Emu/FEX.git
WORKDIR /FEX
RUN mkdir build
CMD [ "mkdir /opt/FEX/build" ]
WORKDIR /opt/FEX/build
ARG CC=clang-10
ARG CXX=clang++-10
RUN cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release
ARG CC=clang-13
ARG CXX=clang++-13
RUN cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DUSE_LINKER=lld -DENABLE_LTO=True -DBUILD_TESTS=False -DENABLE_ASSERTIONS=False -G Ninja .
RUN ninja
WORKDIR /FEX/build
# --- Stage 2: Runner ---
FROM ubuntu:20.04
FROM builder as runner
RUN DEBIAN_FRONTEND="noninteractive" apt-get update
RUN DEBIAN_FRONTEND="noninteractive" apt install -y \
libcap-dev libglfw3-dev libepoxy-dev
COPY --from=builder /opt/FEX/build/Bin/* /usr/bin/
COPY --from=builder /FEX/Bin/* /usr/bin/
WORKDIR /root
WORKDIR /
+98
View File
@@ -0,0 +1,98 @@
set (SRCS
# F80 support
src/extF80_add.c
src/extF80_div.c
src/extF80_sub.c
src/extF80_mul.c
src/extF80_rem.c
src/extF80_sqrt.c
src/extF80_le.c
src/extF80_to_i32.c
src/extF80_to_i64.c
src/extF80_to_ui64.c
src/extF80_to_f32.c
src/extF80_to_f64.c
src/i32_to_extF80.c
src/ui64_to_extF80.c
src/extF80_to_f128.c
src/f128_to_extF80.c
# F128 support
src/f128_add.c
src/f128_div.c
src/f128_eq.c
src/f128_eq_signaling.c
src/f128_isSignalingNaN.c
src/f128_le.c
src/f128_le_quiet.c
src/f128_lt.c
src/f128_lt_quiet.c
src/f128_mulAdd.c
src/f128_mul.c
src/f128_rem.c
src/f128_sqrt.c
src/f128_sub.c
src/f128_to_f16.c
src/f128_to_f32.c
src/f128_to_f64.c
src/f128_to_i32.c
src/f128_to_i64.c
src/f128_to_ui32.c
src/f128_to_ui64.c
src/s_addMagsF128.c
src/s_subMagsF128.c
src/s_normRoundPackToF128.c
src/s_roundPackToF128.c
src/s_propagateNaNF128UI.c
# Conversion
src/f32_to_f128.c
src/i32_to_f128.c
src/s_roundToUI64.c
src/s_f128UIToCommonNaN.c
src/s_commonNaNToF128UI.c
src/s_normSubnormalF128Sig.c
src/s_roundToI32.c
src/s_roundToI64.c
src/s_roundPackToF32.c
src/s_addMagsExtF80.c
src/s_extF80UIToCommonNaN.c
src/s_commonNaNToF32UI.c
src/s_commonNaNToF64UI.c
src/s_roundPackToF64.c
src/s_propagateNaNExtF80UI.c
src/s_roundPackToExtF80.c
src/s_normSubnormalExtF80Sig.c
src/s_subMagsExtF80.c
src/s_shiftRightJam128.c
src/s_shiftRightJam128Extra.c
src/s_normRoundPackToExtF80.c
src/s_approxRecip_1Ks.c
src/s_approxRecipSqrt32_1.c
src/s_approxRecipSqrt_1Ks.c
src/softfloat_raiseFlags.c
src/f64_to_extF80.c
src/s_commonNaNToExtF80UI.c
src/s_normSubnormalF64Sig.c
src/s_f64UIToCommonNaN.c
src/extF80_roundToInt.c
src/extF80_eq.c
src/extF80_lt.c
src/f32_to_extF80.c
src/s_normSubnormalF32Sig.c
src/s_f32UIToCommonNaN.c)
if (_M_ARM_64 AND HAS_CLANG_PRESERVE_ALL)
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=__attribute__((preserve_all));-DFEXCORE_HAS_PRESERVE_ALL_ATTR=1")
else()
list(APPEND DEFINES "-DFEXCORE_PRESERVE_ALL_ATTR=;-DFEXCORE_HAS_PRESERVE_ALL_ATTR=0")
endif()
list(APPEND DEFINES "-DSOFTFLOAT_BUILTIN_CLZ=1;-DINLINE=static inline;-DINLINE_LEVEL=4;-DSOFTFLOAT_FAST_INT64=1;-DSOFTFLOAT_FAST_DIV32TO16=1;-DSOFTFLOAT_FAST_DIV64TO32=1")
add_library(softfloat_3e STATIC ${SRCS})
target_include_directories(softfloat_3e PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/)
target_include_directories(softfloat_3e PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include/SoftFloat-3e/)
target_compile_definitions(softfloat_3e PUBLIC ${DEFINES})
@@ -149,7 +149,7 @@ float64_t f32_to_f64( float32_t );
#ifdef SOFTFLOAT_FAST_INT64
FEXCORE_PRESERVE_ALL_ATTR
extFloat80_t f32_to_extF80( struct softfloat_state *, float32_t );
float128_t f32_to_f128( float32_t );
float128_t f32_to_f128( struct softfloat_state *, float32_t );
#endif
void f32_to_extF80M( float32_t, extFloat80_t * );
void f32_to_f128M( float32_t, float128_t * );
@@ -243,13 +243,17 @@ FEXCORE_PRESERVE_ALL_ATTR
extFloat80_t extF80_sqrt( struct softfloat_state *, extFloat80_t );
FEXCORE_PRESERVE_ALL_ATTR
bool extF80_eq( struct softfloat_state *, extFloat80_t, extFloat80_t );
bool extF80_le( extFloat80_t, extFloat80_t );
bool extF80_le( struct softfloat_state *, extFloat80_t, extFloat80_t );
FEXCORE_PRESERVE_ALL_ATTR
bool extF80_lt( struct softfloat_state *, extFloat80_t, extFloat80_t );
bool extF80_eq_signaling( extFloat80_t, extFloat80_t );
bool extF80_le_quiet( extFloat80_t, extFloat80_t );
bool extF80_lt_quiet( extFloat80_t, extFloat80_t );
bool extF80_isSignalingNaN( extFloat80_t );
static inline extFloat80_t extF80_complement_sign(extFloat80_t a) {
a.signExp ^= 1ULL << 15;
return a;
}
#endif
uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool );
uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool );
@@ -284,34 +288,38 @@ bool extF80M_isSignalingNaN( const extFloat80_t * );
| 128-bit (quadruple-precision) floating-point operations.
*----------------------------------------------------------------------------*/
#ifdef SOFTFLOAT_FAST_INT64
uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool );
uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool );
int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool );
int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool );
uint_fast32_t f128_to_ui32( struct softfloat_state *, float128_t, uint_fast8_t, bool );
uint_fast64_t f128_to_ui64( struct softfloat_state *, float128_t, uint_fast8_t, bool );
int_fast32_t f128_to_i32( struct softfloat_state *, float128_t, uint_fast8_t, bool );
int_fast64_t f128_to_i64( struct softfloat_state *, float128_t, uint_fast8_t, bool );
uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool );
uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool );
int_fast32_t f128_to_i32_r_minMag( float128_t, bool );
int_fast64_t f128_to_i64_r_minMag( float128_t, bool );
float16_t f128_to_f16( float128_t );
float32_t f128_to_f32( float128_t );
float64_t f128_to_f64( float128_t );
float16_t f128_to_f16( struct softfloat_state *, float128_t );
float32_t f128_to_f32( struct softfloat_state *, float128_t );
float64_t f128_to_f64( struct softfloat_state *, float128_t );
FEXCORE_PRESERVE_ALL_ATTR
extFloat80_t f128_to_extF80( struct softfloat_state *, float128_t );
float128_t f128_roundToInt( float128_t, uint_fast8_t, bool );
float128_t f128_add( float128_t, float128_t );
float128_t f128_sub( float128_t, float128_t );
float128_t f128_mul( float128_t, float128_t );
float128_t f128_mulAdd( float128_t, float128_t, float128_t );
float128_t f128_div( float128_t, float128_t );
float128_t f128_rem( float128_t, float128_t );
float128_t f128_sqrt( float128_t );
bool f128_eq( float128_t, float128_t );
bool f128_le( float128_t, float128_t );
bool f128_lt( float128_t, float128_t );
bool f128_eq_signaling( float128_t, float128_t );
bool f128_le_quiet( float128_t, float128_t );
bool f128_lt_quiet( float128_t, float128_t );
float128_t f128_add( struct softfloat_state *, float128_t, float128_t );
float128_t f128_sub( struct softfloat_state *, float128_t, float128_t );
float128_t f128_mul( struct softfloat_state *, float128_t, float128_t );
float128_t f128_mulAdd( struct softfloat_state *, float128_t, float128_t, float128_t );
float128_t f128_div( struct softfloat_state *, float128_t, float128_t );
float128_t f128_rem( struct softfloat_state *, float128_t, float128_t );
float128_t f128_sqrt( struct softfloat_state *, float128_t );
bool f128_eq( struct softfloat_state *, float128_t, float128_t );
bool f128_le( struct softfloat_state *, float128_t, float128_t );
bool f128_lt( struct softfloat_state *, float128_t, float128_t );
bool f128_eq_signaling( struct softfloat_state *, float128_t, float128_t );
bool f128_le_quiet( struct softfloat_state *, float128_t, float128_t );
bool f128_lt_quiet( struct softfloat_state *, float128_t, float128_t );
bool f128_isSignalingNaN( float128_t );
static inline float128_t f128_complement_sign(float128_t a) {
a.v[1] ^= 1ULL << 63;
return a;
}
#endif
uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool );
uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool );
File renamed without changes.
File renamed without changes.
File renamed without changes.
+73
View File
@@ -0,0 +1,73 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool extF80_le( struct softfloat_state *state, extFloat80_t a, extFloat80_t b )
{
union { struct extFloat80M s; extFloat80_t f; } uA;
uint_fast16_t uiA64;
uint_fast64_t uiA0;
union { struct extFloat80M s; extFloat80_t f; } uB;
uint_fast16_t uiB64;
uint_fast64_t uiB0;
bool signA, signB;
uA.f = a;
uiA64 = uA.s.signExp;
uiA0 = uA.s.signif;
uB.f = b;
uiB64 = uB.s.signExp;
uiB0 = uB.s.signif;
if ( isNaNExtF80UI( uiA64, uiA0 ) || isNaNExtF80UI( uiB64, uiB0 ) ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return false;
}
signA = signExtF80UI64( uiA64 );
signB = signExtF80UI64( uiB64 );
return
(signA != signB)
? signA || ! (((uiA64 | uiB64) & 0x7FFF) | uiA0 | uiB0)
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+78
View File
@@ -0,0 +1,78 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
float128_t f128_add( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
float128_t
(*magsFuncPtr)(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
#endif
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
signB = signF128UI64( uiB64 );
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
if ( signA == signB ) {
return softfloat_addMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
} else {
return softfloat_subMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
}
#else
magsFuncPtr =
(signA == signB) ? softfloat_addMagsF128 : softfloat_subMagsF128;
return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
#endif
}
+199
View File
@@ -0,0 +1,199 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_div( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
int_fast32_t expA;
struct uint128 sigA;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signB;
int_fast32_t expB;
struct uint128 sigB;
bool signZ;
struct exp32_sig128 normExpSig;
int_fast32_t expZ;
struct uint128 rem;
uint_fast32_t recip32;
int ix;
uint_fast64_t q64;
uint_fast32_t q;
struct uint128 term;
uint_fast32_t qs[3];
uint_fast64_t sigZExtra;
struct uint128 sigZ, uiZ;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
expA = expF128UI64( uiA64 );
sigA.v64 = fracF128UI64( uiA64 );
sigA.v0 = uiA0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
signB = signF128UI64( uiB64 );
expB = expF128UI64( uiB64 );
sigB.v64 = fracF128UI64( uiB64 );
sigB.v0 = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( expA == 0x7FFF ) {
if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
if ( expB == 0x7FFF ) {
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
goto invalid;
}
goto infinity;
}
if ( expB == 0x7FFF ) {
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
goto zero;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ! expB ) {
if ( ! (sigB.v64 | sigB.v0) ) {
if ( ! (expA | sigA.v64 | sigA.v0) ) goto invalid;
softfloat_raiseFlags( state, softfloat_flag_infinite );
goto infinity;
}
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
if ( ! expA ) {
if ( ! (sigA.v64 | sigA.v0) ) goto zero;
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA - expB + 0x3FFE;
sigA.v64 |= UINT64_C( 0x0001000000000000 );
sigB.v64 |= UINT64_C( 0x0001000000000000 );
rem = sigA;
if ( softfloat_lt128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 ) ) {
--expZ;
rem = softfloat_add128( sigA.v64, sigA.v0, sigA.v64, sigA.v0 );
}
recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
ix = 3;
for (;;) {
q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
q = (q64 + 0x80000000)>>32;
--ix;
if ( ix < 0 ) break;
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
--q;
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
}
qs[ix] = q;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ((q + 1) & 7) < 2 ) {
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
--q;
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
} else if ( softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 ) ) {
++q;
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
}
if ( rem.v64 | rem.v0 ) q |= 1;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sigZExtra = (uint64_t) ((uint_fast64_t) q<<60);
term = softfloat_shortShiftLeft128( 0, qs[1], 54 );
sigZ =
softfloat_add128(
(uint_fast64_t) qs[2]<<19, ((uint_fast64_t) qs[0]<<25) + (q>>4),
term.v64, term.v0
);
return
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
goto uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags( state, softfloat_flag_invalid );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
goto uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infinity:
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
goto uiZ0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
uiZ.v64 = packToF128UI64( signZ, 0, 0 );
uiZ0:
uiZ.v0 = 0;
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+73
View File
@@ -0,0 +1,73 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool f128_eq( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
if (
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
}
return false;
}
return
(uiA0 == uiB0)
&& ( (uiA64 == uiB64)
|| (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
);
}
+67
View File
@@ -0,0 +1,67 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
bool f128_eq_signaling( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return false;
}
return
(uiA0 == uiB0)
&& ( (uiA64 == uiB64)
|| (! uiA0 && ! ((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
);
}
+51
View File
@@ -0,0 +1,51 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool f128_isSignalingNaN( float128_t a )
{
union ui128_f128 uA;
uA.f = a;
return softfloat_isSigNaNF128UI( uA.ui.v64, uA.ui.v0 );
}
+72
View File
@@ -0,0 +1,72 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
bool f128_le( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signA, signB;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return false;
}
signA = signF128UI64( uiA64 );
signB = signF128UI64( uiB64 );
return
(signA != signB)
? signA
|| ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
| uiA0 | uiB0)
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
}
+78
View File
@@ -0,0 +1,78 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool f128_le_quiet( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signA, signB;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
if (
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
}
return false;
}
signA = signF128UI64( uiA64 );
signB = signF128UI64( uiB64 );
return
(signA != signB)
? signA
|| ! (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
| uiA0 | uiB0)
: ((uiA64 == uiB64) && (uiA0 == uiB0))
|| (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
}
+72
View File
@@ -0,0 +1,72 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
bool f128_lt( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signA, signB;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return false;
}
signA = signF128UI64( uiA64 );
signB = signF128UI64( uiB64 );
return
(signA != signB)
? signA
&& (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
| uiA0 | uiB0)
: ((uiA64 != uiB64) || (uiA0 != uiB0))
&& (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
}
+78
View File
@@ -0,0 +1,78 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool f128_lt_quiet( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signA, signB;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
if ( isNaNF128UI( uiA64, uiA0 ) || isNaNF128UI( uiB64, uiB0 ) ) {
if (
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
}
return false;
}
signA = signF128UI64( uiA64 );
signB = signF128UI64( uiB64 );
return
(signA != signB)
? signA
&& (((uiA64 | uiB64) & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
| uiA0 | uiB0)
: ((uiA64 != uiB64) || (uiA0 != uiB0))
&& (signA ^ softfloat_lt128( uiA64, uiA0, uiB64, uiB0 ));
}
+163
View File
@@ -0,0 +1,163 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_mul( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
int_fast32_t expA;
struct uint128 sigA;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signB;
int_fast32_t expB;
struct uint128 sigB;
bool signZ;
uint_fast64_t magBits;
struct exp32_sig128 normExpSig;
int_fast32_t expZ;
uint64_t sig256Z[4];
uint_fast64_t sigZExtra;
struct uint128 sigZ;
struct uint128_extra sig128Extra;
struct uint128 uiZ;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
expA = expF128UI64( uiA64 );
sigA.v64 = fracF128UI64( uiA64 );
sigA.v0 = uiA0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
signB = signF128UI64( uiB64 );
expB = expF128UI64( uiB64 );
sigB.v64 = fracF128UI64( uiB64 );
sigB.v0 = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( expA == 0x7FFF ) {
if (
(sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
) {
goto propagateNaN;
}
magBits = expB | sigB.v64 | sigB.v0;
goto infArg;
}
if ( expB == 0x7FFF ) {
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
magBits = expA | sigA.v64 | sigA.v0;
goto infArg;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ! expA ) {
if ( ! (sigA.v64 | sigA.v0) ) goto zero;
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if ( ! expB ) {
if ( ! (sigB.v64 | sigB.v0) ) goto zero;
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x4000;
sigA.v64 |= UINT64_C( 0x0001000000000000 );
sigB = softfloat_shortShiftLeft128( sigB.v64, sigB.v0, 16 );
softfloat_mul128To256M( sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z );
sigZExtra = sig256Z[indexWord( 4, 1 )] | (sig256Z[indexWord( 4, 0 )] != 0);
sigZ =
softfloat_add128(
sig256Z[indexWord( 4, 3 )], sig256Z[indexWord( 4, 2 )],
sigA.v64, sigA.v0
);
if ( UINT64_C( 0x0002000000000000 ) <= sigZ.v64 ) {
++expZ;
sig128Extra =
softfloat_shortShiftRightJam128Extra(
sigZ.v64, sigZ.v0, sigZExtra, 1 );
sigZ = sig128Extra.v;
sigZExtra = sig128Extra.extra;
}
return
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
goto uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if ( ! magBits ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
goto uiZ;
}
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
goto uiZ0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
uiZ.v64 = packToF128UI64( signZ, 0, 0 );
uiZ0:
uiZ.v0 = 0;
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+63
View File
@@ -0,0 +1,63 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
float128_t f128_mulAdd( struct softfloat_state *state, float128_t a, float128_t b, float128_t c )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
union ui128_f128 uC;
uint_fast64_t uiC64, uiC0;
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
uC.f = c;
uiC64 = uC.ui.v64;
uiC0 = uC.ui.v0;
return softfloat_mulAddF128( uiA64, uiA0, uiB64, uiB0, uiC64, uiC0, 0 );
}
+190
View File
@@ -0,0 +1,190 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_rem( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
int_fast32_t expA;
struct uint128 sigA;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
int_fast32_t expB;
struct uint128 sigB;
struct exp32_sig128 normExpSig;
struct uint128 rem;
int_fast32_t expDiff;
uint_fast32_t q, recip32;
uint_fast64_t q64;
struct uint128 term, altRem, meanRem;
bool signRem;
struct uint128 uiZ;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
expA = expF128UI64( uiA64 );
sigA.v64 = fracF128UI64( uiA64 );
sigA.v0 = uiA0;
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
expB = expF128UI64( uiB64 );
sigB.v64 = fracF128UI64( uiB64 );
sigB.v0 = uiB0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( expA == 0x7FFF ) {
if (
(sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))
) {
goto propagateNaN;
}
goto invalid;
}
if ( expB == 0x7FFF ) {
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
return a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ! expB ) {
if ( ! (sigB.v64 | sigB.v0) ) goto invalid;
normExpSig = softfloat_normSubnormalF128Sig( sigB.v64, sigB.v0 );
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
if ( ! expA ) {
if ( ! (sigA.v64 | sigA.v0) ) return a;
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sigA.v64 |= UINT64_C( 0x0001000000000000 );
sigB.v64 |= UINT64_C( 0x0001000000000000 );
rem = sigA;
expDiff = expA - expB;
if ( expDiff < 1 ) {
if ( expDiff < -1 ) return a;
if ( expDiff ) {
--expB;
sigB = softfloat_add128( sigB.v64, sigB.v0, sigB.v64, sigB.v0 );
q = 0;
} else {
q = softfloat_le128( sigB.v64, sigB.v0, rem.v64, rem.v0 );
if ( q ) {
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
}
}
} else {
recip32 = softfloat_approxRecip32_1( sigB.v64>>17 );
expDiff -= 30;
for (;;) {
q64 = (uint_fast64_t) (uint32_t) (rem.v64>>19) * recip32;
if ( expDiff < 0 ) break;
q = (q64 + 0x80000000)>>32;
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
rem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
}
expDiff -= 29;
}
/*--------------------------------------------------------------------
| (`expDiff' cannot be less than -29 here.)
*--------------------------------------------------------------------*/
q = (uint32_t) (q64>>32)>>(~expDiff & 31);
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, expDiff + 30 );
term = softfloat_mul128By32( sigB.v64, sigB.v0, q );
rem = softfloat_sub128( rem.v64, rem.v0, term.v64, term.v0 );
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
altRem = softfloat_add128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
goto selectRem;
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
do {
altRem = rem;
++q;
rem = softfloat_sub128( rem.v64, rem.v0, sigB.v64, sigB.v0 );
} while ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) );
selectRem:
meanRem = softfloat_add128( rem.v64, rem.v0, altRem.v64, altRem.v0 );
if (
(meanRem.v64 & UINT64_C( 0x8000000000000000 ))
|| (! (meanRem.v64 | meanRem.v0) && (q & 1))
) {
rem = altRem;
}
signRem = signA;
if ( rem.v64 & UINT64_C( 0x8000000000000000 ) ) {
signRem = ! signRem;
rem = softfloat_sub128( 0, 0, rem.v64, rem.v0 );
}
return softfloat_normRoundPackToF128( state, signRem, expB - 1, rem.v64, rem.v0 );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
goto uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags( state, softfloat_flag_invalid );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+201
View File
@@ -0,0 +1,201 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_sqrt( struct softfloat_state *state, float128_t a )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
int_fast32_t expA;
struct uint128 sigA, uiZ;
struct exp32_sig128 normExpSig;
int_fast32_t expZ;
uint_fast32_t sig32A, recipSqrt32, sig32Z;
struct uint128 rem;
uint32_t qs[3];
uint_fast32_t q;
uint_fast64_t x64, sig64Z;
struct uint128 y, term;
uint_fast64_t sigZExtra;
struct uint128 sigZ;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
expA = expF128UI64( uiA64 );
sigA.v64 = fracF128UI64( uiA64 );
sigA.v0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( expA == 0x7FFF ) {
if ( sigA.v64 | sigA.v0 ) {
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, 0, 0 );
goto uiZ;
}
if ( ! signA ) return a;
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( signA ) {
if ( ! (expA | sigA.v64 | sigA.v0) ) return a;
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ! expA ) {
if ( ! (sigA.v64 | sigA.v0) ) return a;
normExpSig = softfloat_normSubnormalF128Sig( sigA.v64, sigA.v0 );
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
| (`sig32Z' is guaranteed to be a lower bound on the square root of
| `sig32A', which makes `sig32Z' also a lower bound on the square root of
| `sigA'.)
*------------------------------------------------------------------------*/
expZ = ((expA - 0x3FFF)>>1) + 0x3FFE;
expA &= 1;
sigA.v64 |= UINT64_C( 0x0001000000000000 );
sig32A = sigA.v64>>17;
recipSqrt32 = softfloat_approxRecipSqrt32_1( expA, sig32A );
sig32Z = ((uint_fast64_t) sig32A * recipSqrt32)>>32;
if ( expA ) {
sig32Z >>= 1;
rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 12 );
} else {
rem = softfloat_shortShiftLeft128( sigA.v64, sigA.v0, 13 );
}
qs[2] = sig32Z;
rem.v64 -= (uint_fast64_t) sig32Z * sig32Z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
q = ((uint32_t) (rem.v64>>2) * (uint_fast64_t) recipSqrt32)>>32;
x64 = (uint_fast64_t) sig32Z<<32;
sig64Z = x64 + ((uint_fast64_t) q<<3);
y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
/*------------------------------------------------------------------------
| (Repeating this loop is a rare occurrence.)
*------------------------------------------------------------------------*/
for (;;) {
term = softfloat_mul64ByShifted32To128( x64 + sig64Z, q );
rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
--q;
sig64Z -= 1<<3;
}
qs[1] = q;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
q = ((rem.v64>>2) * recipSqrt32)>>32;
y = softfloat_shortShiftLeft128( rem.v64, rem.v0, 29 );
sig64Z <<= 1;
/*------------------------------------------------------------------------
| (Repeating this loop is a rare occurrence.)
*------------------------------------------------------------------------*/
for (;;) {
term = softfloat_shortShiftLeft128( 0, sig64Z, 32 );
term = softfloat_add128( term.v64, term.v0, 0, (uint_fast64_t) q<<6 );
term = softfloat_mul128By32( term.v64, term.v0, q );
rem = softfloat_sub128( y.v64, y.v0, term.v64, term.v0 );
if ( ! (rem.v64 & UINT64_C( 0x8000000000000000 )) ) break;
--q;
}
qs[0] = q;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
term = softfloat_shortShiftLeft128( 0, qs[1], 53 );
sigZ =
softfloat_add128(
(uint_fast64_t) qs[2]<<18, ((uint_fast64_t) qs[0]<<24) + (q>>5),
term.v64, term.v0
);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( (q & 0xF) <= 2 ) {
q &= ~3;
sigZExtra = (uint64_t) ((uint_fast64_t) q<<59);
y = softfloat_shortShiftLeft128( sigZ.v64, sigZ.v0, 6 );
y.v0 |= sigZExtra>>58;
term = softfloat_sub128( y.v64, y.v0, 0, q );
y = softfloat_mul64ByShifted32To128( term.v0, q );
term = softfloat_mul64ByShifted32To128( term.v64, q );
term = softfloat_add128( term.v64, term.v0, 0, y.v64 );
rem = softfloat_shortShiftLeft128( rem.v64, rem.v0, 20 );
term = softfloat_sub128( term.v64, term.v0, rem.v64, rem.v0 );
/*--------------------------------------------------------------------
| The concatenation of `term' and `y.v0' is now the negative remainder
| (3 words altogether).
*--------------------------------------------------------------------*/
if ( term.v64 & UINT64_C( 0x8000000000000000 ) ) {
sigZExtra |= 1;
} else {
if ( term.v64 | term.v0 | y.v0 ) {
if ( sigZExtra ) {
--sigZExtra;
} else {
sigZ = softfloat_sub128( sigZ.v64, sigZ.v0, 0, 1 );
sigZExtra = ~0;
}
}
}
}
return softfloat_roundPackToF128( state, 0, expZ, sigZ.v64, sigZ.v0, sigZExtra );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags( state, softfloat_flag_invalid );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+78
View File
@@ -0,0 +1,78 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
float128_t f128_sub( struct softfloat_state *state, float128_t a, float128_t b )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool signA;
union ui128_f128 uB;
uint_fast64_t uiB64, uiB0;
bool signB;
#if ! defined INLINE_LEVEL || (INLINE_LEVEL < 2)
float128_t
(*magsFuncPtr)(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
#endif
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
signA = signF128UI64( uiA64 );
uB.f = b;
uiB64 = uB.ui.v64;
uiB0 = uB.ui.v0;
signB = signF128UI64( uiB64 );
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
if ( signA == signB ) {
return softfloat_subMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
} else {
return softfloat_addMagsF128( state, uiA64, uiA0, uiB64, uiB0, signA );
}
#else
magsFuncPtr =
(signA == signB) ? softfloat_subMagsF128 : softfloat_addMagsF128;
return (*magsFuncPtr)( uiA64, uiA0, uiB64, uiB0, signA );
#endif
}
+95
View File
@@ -0,0 +1,95 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float16_t f128_to_f16( struct softfloat_state *state, float128_t a )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t frac64;
struct commonNaN commonNaN;
uint_fast16_t uiZ, frac16;
union ui16_f16 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp == 0x7FFF ) {
if ( frac64 ) {
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
uiZ = softfloat_commonNaNToF16UI( &commonNaN );
} else {
uiZ = packToF16UI( sign, 0x1F, 0 );
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
frac16 = softfloat_shortShiftRightJam64( frac64, 34 );
if ( ! (exp | frac16) ) {
uiZ = packToF16UI( sign, 0, 0 );
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3FF1;
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
if ( exp < -0x40 ) exp = -0x40;
}
return softfloat_roundPackToF16( sign, exp, frac16 | 0x4000 );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+95
View File
@@ -0,0 +1,95 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float32_t f128_to_f32( struct softfloat_state *state, float128_t a )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t frac64;
struct commonNaN commonNaN;
uint_fast32_t uiZ, frac32;
union ui32_f32 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
frac64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp == 0x7FFF ) {
if ( frac64 ) {
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
uiZ = softfloat_commonNaNToF32UI( &commonNaN );
} else {
uiZ = packToF32UI( sign, 0xFF, 0 );
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
frac32 = softfloat_shortShiftRightJam64( frac64, 18 );
if ( ! (exp | frac32) ) {
uiZ = packToF32UI( sign, 0, 0 );
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3F81;
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
if ( exp < -0x1000 ) exp = -0x1000;
}
return softfloat_roundPackToF32( state, sign, exp, frac32 | 0x40000000 );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+100
View File
@@ -0,0 +1,100 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float64_t f128_to_f64( struct softfloat_state *state, float128_t a )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t frac64, frac0;
struct commonNaN commonNaN;
uint_fast64_t uiZ;
struct uint128 frac128;
union ui64_f64 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
frac64 = fracF128UI64( uiA64 );
frac0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp == 0x7FFF ) {
if ( frac64 | frac0 ) {
softfloat_f128UIToCommonNaN( state, uiA64, uiA0, &commonNaN );
uiZ = softfloat_commonNaNToF64UI( &commonNaN );
} else {
uiZ = packToF64UI( sign, 0x7FF, 0 );
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
frac128 = softfloat_shortShiftLeft128( frac64, frac0, 14 );
frac64 = frac128.v64 | (frac128.v0 != 0);
if ( ! (exp | frac64) ) {
uiZ = packToF64UI( sign, 0, 0 );
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3C01;
if ( sizeof (int_fast16_t) < sizeof (int_fast32_t) ) {
if ( exp < -0x1000 ) exp = -0x1000;
}
return
softfloat_roundPackToF64(
state, sign, exp, frac64 | UINT64_C( 0x4000000000000000 ) );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+85
View File
@@ -0,0 +1,85 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int_fast32_t f128_to_i32( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t sig64, sig0;
int_fast32_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
sig64 = fracF128UI64( uiA64 );
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
if ( (exp == 0x7FFF) && (sig64 | sig0) ) {
#if (i32_fromNaN == i32_fromPosOverflow)
sign = 0;
#elif (i32_fromNaN == i32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags( softfloat_flag_invalid );
return i32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
sig64 |= (sig0 != 0);
shiftDist = 0x4023 - exp;
if ( 0 < shiftDist ) sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
return softfloat_roundToI32( state, sign, sig64, roundingMode, exact );
}
+95
View File
@@ -0,0 +1,95 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int_fast64_t f128_to_i64( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t sig64, sig0;
int_fast32_t shiftDist;
struct uint128 sig128;
struct uint64_extra sigExtra;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
sig64 = fracF128UI64( uiA64 );
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if ( shiftDist <= 0 ) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if ( shiftDist < -15 ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return
(exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C( 0x0001000000000000 );
if ( shiftDist ) {
sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
sig64 = sig128.v64;
sig0 = sig128.v0;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
sig64 = sigExtra.v;
sig0 = sigExtra.extra;
}
return softfloat_roundToI64( state, sign, sig64, sig0, roundingMode, exact );
}
+86
View File
@@ -0,0 +1,86 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint_fast32_t
f128_to_ui32( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t sig64;
int_fast32_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
sig64 = fracF128UI64( uiA64 ) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
if ( (exp == 0x7FFF) && sig64 ) {
#if (ui32_fromNaN == ui32_fromPosOverflow)
sign = 0;
#elif (ui32_fromNaN == ui32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags( softfloat_flag_invalid );
return ui32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
shiftDist = 0x4023 - exp;
if ( 0 < shiftDist ) {
sig64 = softfloat_shiftRightJam64( sig64, shiftDist );
}
return softfloat_roundToUI32( sign, sig64, roundingMode, exact );
}
+96
View File
@@ -0,0 +1,96 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint_fast64_t
f128_to_ui64( struct softfloat_state *state, float128_t a, uint_fast8_t roundingMode, bool exact )
{
union ui128_f128 uA;
uint_fast64_t uiA64, uiA0;
bool sign;
int_fast32_t exp;
uint_fast64_t sig64, sig0;
int_fast32_t shiftDist;
struct uint128 sig128;
struct uint64_extra sigExtra;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA64 = uA.ui.v64;
uiA0 = uA.ui.v0;
sign = signF128UI64( uiA64 );
exp = expF128UI64( uiA64 );
sig64 = fracF128UI64( uiA64 );
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if ( shiftDist <= 0 ) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if ( shiftDist < -15 ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
return
(exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C( 0x0001000000000000 );
if ( shiftDist ) {
sig128 = softfloat_shortShiftLeft128( sig64, sig0, -shiftDist );
sig64 = sig128.v64;
sig0 = sig128.v0;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if ( exp ) sig64 |= UINT64_C( 0x0001000000000000 );
sigExtra = softfloat_shiftRightJam64Extra( sig64, sig0, shiftDist );
sig64 = sigExtra.v;
sig0 = sigExtra.extra;
}
return softfloat_roundToUI64( state, sign, sig64, sig0, roundingMode, exact );
}
+96
View File
@@ -0,0 +1,96 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f32_to_f128( struct softfloat_state *state, float32_t a )
{
union ui32_f32 uA;
uint_fast32_t uiA;
bool sign;
int_fast16_t exp;
uint_fast32_t frac;
struct commonNaN commonNaN;
struct uint128 uiZ;
struct exp16_sig32 normExpSig;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA = uA.ui;
sign = signF32UI( uiA );
exp = expF32UI( uiA );
frac = fracF32UI( uiA );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( exp == 0xFF ) {
if ( frac ) {
softfloat_f32UIToCommonNaN( state, uiA, &commonNaN );
uiZ = softfloat_commonNaNToF128UI( &commonNaN );
} else {
uiZ.v64 = packToF128UI64( sign, 0x7FFF, 0 );
uiZ.v0 = 0;
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( ! exp ) {
if ( ! frac ) {
uiZ.v64 = packToF128UI64( sign, 0, 0 );
uiZ.v0 = 0;
goto uiZ;
}
normExpSig = softfloat_normSubnormalF32Sig( frac );
exp = normExpSig.exp - 1;
frac = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ.v64 = packToF128UI64( sign, exp + 0x3F80, (uint_fast64_t) frac<<25 );
uiZ.v0 = 0;
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
+64
View File
@@ -0,0 +1,64 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
float128_t i32_to_f128( int32_t a )
{
uint_fast64_t uiZ64;
bool sign;
uint_fast32_t absA;
int_fast8_t shiftDist;
union ui128_f128 uZ;
uiZ64 = 0;
if ( a ) {
sign = (a < 0);
absA = sign ? -(uint_fast32_t) a : (uint_fast32_t) a;
shiftDist = softfloat_countLeadingZeros32( absA ) + 17;
uiZ64 =
packToF128UI64(
sign, 0x402E - shiftDist, (uint_fast64_t) absA<<shiftDist );
}
uZ.ui.v64 = uiZ64;
uZ.ui.v0 = 0;
return uZ.f;
}
@@ -196,16 +196,20 @@ struct exp32_sig128
float128_t
softfloat_roundPackToF128(
struct softfloat_state *,
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t );
float128_t
softfloat_normRoundPackToF128(
struct softfloat_state *,
bool, int_fast32_t, uint_fast64_t, uint_fast64_t );
float128_t
softfloat_addMagsF128(
struct softfloat_state *,
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
float128_t
softfloat_subMagsF128(
struct softfloat_state *,
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
float128_t
softfloat_mulAddF128(
File renamed without changes.
File renamed without changes.
+155
View File
@@ -0,0 +1,155 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
float128_t
softfloat_addMagsF128(
struct softfloat_state *state,
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0,
bool signZ
)
{
int_fast32_t expA;
struct uint128 sigA;
int_fast32_t expB;
struct uint128 sigB;
int_fast32_t expDiff;
struct uint128 uiZ, sigZ;
int_fast32_t expZ;
uint_fast64_t sigZExtra;
struct uint128_extra sig128Extra;
union ui128_f128 uZ;
expA = expF128UI64( uiA64 );
sigA.v64 = fracF128UI64( uiA64 );
sigA.v0 = uiA0;
expB = expF128UI64( uiB64 );
sigB.v64 = fracF128UI64( uiB64 );
sigB.v0 = uiB0;
expDiff = expA - expB;
if ( ! expDiff ) {
if ( expA == 0x7FFF ) {
if ( sigA.v64 | sigA.v0 | sigB.v64 | sigB.v0 ) goto propagateNaN;
uiZ.v64 = uiA64;
uiZ.v0 = uiA0;
goto uiZ;
}
sigZ = softfloat_add128( sigA.v64, sigA.v0, sigB.v64, sigB.v0 );
if ( ! expA ) {
uiZ.v64 = packToF128UI64( signZ, 0, sigZ.v64 );
uiZ.v0 = sigZ.v0;
goto uiZ;
}
expZ = expA;
sigZ.v64 |= UINT64_C( 0x0002000000000000 );
sigZExtra = 0;
goto shiftRight1;
}
if ( expDiff < 0 ) {
if ( expB == 0x7FFF ) {
if ( sigB.v64 | sigB.v0 ) goto propagateNaN;
uiZ.v64 = packToF128UI64( signZ, 0x7FFF, 0 );
uiZ.v0 = 0;
goto uiZ;
}
expZ = expB;
if ( expA ) {
sigA.v64 |= UINT64_C( 0x0001000000000000 );
} else {
++expDiff;
sigZExtra = 0;
if ( ! expDiff ) goto newlyAligned;
}
sig128Extra =
softfloat_shiftRightJam128Extra( sigA.v64, sigA.v0, 0, -expDiff );
sigA = sig128Extra.v;
sigZExtra = sig128Extra.extra;
} else {
if ( expA == 0x7FFF ) {
if ( sigA.v64 | sigA.v0 ) goto propagateNaN;
uiZ.v64 = uiA64;
uiZ.v0 = uiA0;
goto uiZ;
}
expZ = expA;
if ( expB ) {
sigB.v64 |= UINT64_C( 0x0001000000000000 );
} else {
--expDiff;
sigZExtra = 0;
if ( ! expDiff ) goto newlyAligned;
}
sig128Extra =
softfloat_shiftRightJam128Extra( sigB.v64, sigB.v0, 0, expDiff );
sigB = sig128Extra.v;
sigZExtra = sig128Extra.extra;
}
newlyAligned:
sigZ =
softfloat_add128(
sigA.v64 | UINT64_C( 0x0001000000000000 ),
sigA.v0,
sigB.v64,
sigB.v0
);
--expZ;
if ( sigZ.v64 < UINT64_C( 0x0002000000000000 ) ) goto roundAndPack;
++expZ;
shiftRight1:
sig128Extra =
softfloat_shortShiftRightJam128Extra(
sigZ.v64, sigZ.v0, sigZExtra, 1 );
sigZ = sig128Extra.v;
sigZExtra = sig128Extra.extra;
roundAndPack:
return
softfloat_roundPackToF128( state, signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra );
propagateNaN:
uiZ = softfloat_propagateNaNF128UI( state, uiA64, uiA0, uiB64, uiB0 );
uiZ:
uZ.ui = uiZ;
return uZ.f;
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
+82
View File
@@ -0,0 +1,82 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
float128_t
softfloat_normRoundPackToF128(
struct softfloat_state *state,
bool sign, int_fast32_t exp, uint_fast64_t sig64, uint_fast64_t sig0 )
{
int_fast8_t shiftDist;
struct uint128 sig128;
union ui128_f128 uZ;
uint_fast64_t sigExtra;
struct uint128_extra sig128Extra;
if ( ! sig64 ) {
exp -= 64;
sig64 = sig0;
sig0 = 0;
}
shiftDist = softfloat_countLeadingZeros64( sig64 ) - 15;
exp -= shiftDist;
if ( 0 <= shiftDist ) {
if ( shiftDist ) {
sig128 = softfloat_shortShiftLeft128( sig64, sig0, shiftDist );
sig64 = sig128.v64;
sig0 = sig128.v0;
}
if ( (uint32_t) exp < 0x7FFD ) {
uZ.ui.v64 = packToF128UI64( sign, sig64 | sig0 ? exp : 0, sig64 );
uZ.ui.v0 = sig0;
return uZ.f;
}
sigExtra = 0;
} else {
sig128Extra =
softfloat_shortShiftRightJam128Extra( sig64, sig0, 0, -shiftDist );
sig64 = sig128Extra.v.v64;
sig0 = sig128Extra.v.v0;
sigExtra = sig128Extra.extra;
}
return softfloat_roundPackToF128( state, sign, exp, sig64, sig0, sigExtra );
}
+82
View File
@@ -0,0 +1,82 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating `uiA64' and
| `uiA0' as a 128-bit floating-point value, and likewise interpreting the
| unsigned integer formed from concatenating `uiB64' and `uiB0' as another
| 128-bit floating-point value, and assuming at least on of these floating-
| point values is a NaN, returns the bit pattern of the combined NaN result.
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
struct softfloat_state *state,
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
)
{
bool isSigNaNA;
struct uint128 uiZ;
isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
softfloat_raiseFlags( state, softfloat_flag_invalid );
if ( isSigNaNA ) goto returnNonsigA;
}
if ( isNaNF128UI( uiA64, uiA0 ) ) {
returnNonsigA:
uiZ.v64 = uiA64;
uiZ.v0 = uiA0;
} else {
uiZ.v64 = uiB64;
uiZ.v0 = uiB0;
}
uiZ.v64 |= UINT64_C( 0x0000800000000000 );
return uiZ;
}
+171
View File
@@ -0,0 +1,171 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat.h"
float128_t
softfloat_roundPackToF128(
struct softfloat_state *state,
bool sign,
int_fast32_t exp,
uint_fast64_t sig64,
uint_fast64_t sig0,
uint_fast64_t sigExtra
)
{
uint_fast8_t roundingMode;
bool roundNearEven, doIncrement, isTiny;
struct uint128_extra sig128Extra;
uint_fast64_t uiZ64, uiZ0;
struct uint128 sig128;
union ui128_f128 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
roundingMode = state->roundingMode;
roundNearEven = (roundingMode == softfloat_round_near_even);
doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
doIncrement =
(roundingMode
== (sign ? softfloat_round_min : softfloat_round_max))
&& sigExtra;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( 0x7FFD <= (uint32_t) exp ) {
if ( exp < 0 ) {
/*----------------------------------------------------------------
*----------------------------------------------------------------*/
isTiny =
(state->detectTininess
== softfloat_tininess_beforeRounding)
|| (exp < -1)
|| ! doIncrement
|| softfloat_lt128(
sig64,
sig0,
UINT64_C( 0x0001FFFFFFFFFFFF ),
UINT64_C( 0xFFFFFFFFFFFFFFFF )
);
sig128Extra =
softfloat_shiftRightJam128Extra( sig64, sig0, sigExtra, -exp );
sig64 = sig128Extra.v.v64;
sig0 = sig128Extra.v.v0;
sigExtra = sig128Extra.extra;
exp = 0;
if ( isTiny && sigExtra ) {
softfloat_raiseFlags( state, softfloat_flag_underflow );
}
doIncrement = (UINT64_C( 0x8000000000000000 ) <= sigExtra);
if (
! roundNearEven
&& (roundingMode != softfloat_round_near_maxMag)
) {
doIncrement =
(roundingMode
== (sign ? softfloat_round_min : softfloat_round_max))
&& sigExtra;
}
} else if (
(0x7FFD < exp)
|| ((exp == 0x7FFD)
&& softfloat_eq128(
sig64,
sig0,
UINT64_C( 0x0001FFFFFFFFFFFF ),
UINT64_C( 0xFFFFFFFFFFFFFFFF )
)
&& doIncrement)
) {
/*----------------------------------------------------------------
*----------------------------------------------------------------*/
softfloat_raiseFlags(
state, softfloat_flag_overflow | softfloat_flag_inexact );
if (
roundNearEven
|| (roundingMode == softfloat_round_near_maxMag)
|| (roundingMode
== (sign ? softfloat_round_min : softfloat_round_max))
) {
uiZ64 = packToF128UI64( sign, 0x7FFF, 0 );
uiZ0 = 0;
} else {
uiZ64 =
packToF128UI64(
sign, 0x7FFE, UINT64_C( 0x0000FFFFFFFFFFFF ) );
uiZ0 = UINT64_C( 0xFFFFFFFFFFFFFFFF );
}
goto uiZ;
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( sigExtra ) {
state->exceptionFlags |= softfloat_flag_inexact;
#ifdef SOFTFLOAT_ROUND_ODD
if ( roundingMode == softfloat_round_odd ) {
sig0 |= 1;
goto packReturn;
}
#endif
}
if ( doIncrement ) {
sig128 = softfloat_add128( sig64, sig0, 0, 1 );
sig64 = sig128.v64;
sig0 =
sig128.v0
& ~(uint64_t)
(! (sigExtra & UINT64_C( 0x7FFFFFFFFFFFFFFF ))
& roundNearEven);
} else {
if ( ! (sig64 | sig0) ) exp = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ64 = packToF128UI64( sign, exp, sig64 );
uiZ0 = sig0;
uiZ:
uZ.ui.v64 = uiZ64;
uZ.ui.v0 = uiZ0;
return uZ.f;
}
File renamed without changes.
File renamed without changes.
Loaded 100 of 252 files, more files were not shown because too many files have changed in this diff. Show more