310 Commits

Author SHA1 Message Date
071cb4fdac replaces unordered_map with flat_hash_map 2025-05-13 08:22:16 +02:00
dd937710a7 adds initial version of intruction cache 2025-05-12 12:19:46 +02:00
047e2e12b0 fixes include issue in LLVM vm_base
vm_base.h needs to be included before gdb_session.h as termios.h (via
boost and gdb_server) has a define which clashes with a variable name in
ConstantRange.h (via iss/llvm/vm_base.h)
2025-05-09 20:14:09 +02:00
fe3ed49519 updates asmjit template, removes lots of comments from IR 2025-04-28 15:04:18 +02:00
1afd77a942 changes aes box functions to extern linkage 2025-04-28 15:02:05 +02:00
cdf5038e59 corrects fp functions for llvm 2025-04-03 09:59:22 +02:00
651897e1e4 corrects another oversight in tcc template wrt floating point 2025-04-03 09:19:02 +02:00
a1803c61c1 even more corrections to tcc template 2025-04-02 13:01:25 +02:00
bfa2182f8e corrects mistakes wrt tcc template 2025-04-02 12:20:42 +02:00
b01c9b27e5 corrects tcc template when using floating point 2025-04-02 12:18:45 +02:00
07f394d5ff corrects tcc template when using floating point 2025-04-02 11:53:55 +02:00
7e97329e78 adds UserProvidedFunctions for NaNBoxing, updates generated files, adapts to new fp API 2025-04-02 10:19:11 +02:00
8f5d666b7d corrects mistake from rebasing, adds newly generated templates 2025-03-31 12:50:05 +02:00
cc123939ce configures logger in main 2025-03-31 10:19:16 +02:00
a2e5405e25 small changes regarding vector template 2025-03-31 10:19:16 +02:00
cd3ec0b79d removes conversion functions in favor of more explicit conversions 2025-03-31 10:19:16 +02:00
0e35a2a8c9 adds complete Zfh support, small rework regarding floating point interface 2025-03-31 10:19:16 +02:00
8220c00a3d small correction for floating point h 2025-03-31 10:19:16 +02:00
ec5fb1e87e increases verbosity for file loading errors 2025-03-31 10:19:16 +02:00
453407568c removes carry_t, moves functionality to own functions 2025-03-31 10:19:16 +02:00
0fe9e6ebc8 corrects error for narrowing fp dispatch 2025-03-31 10:19:16 +02:00
484d9dbe08 removes rounding mode lookup as it is not needes 2025-03-31 10:19:15 +02:00
7a7035f267 adds support for half precision float 2025-03-31 10:19:15 +02:00
d9f1e5d31b small refactor 2025-03-31 10:19:15 +02:00
7b35f45a48 changes to make correct oversighst for XLEN=64 in Vector functions 2025-03-31 10:19:15 +02:00
ece6f7290f small bugfixes, adds some half point functionality 2025-03-31 10:19:15 +02:00
2166a6d81e makes widenning function types more explicit 2025-03-31 10:19:15 +02:00
fe9f2a5455 corrects vectorslide, changes all loop index type 2025-03-31 10:19:15 +02:00
42bf6ee380 corrects errors w.r.t. floating point dispatch 2025-03-31 10:19:15 +02:00
f0b582df6c corrects ambiguity in frsqrt 2025-03-31 10:19:15 +02:00
6fcb3dbb66 adds missing floating point instructions 2025-03-31 10:19:15 +02:00
c01eb39a76 reworks merge instrs, adds fp comparisons 2025-03-31 10:19:15 +02:00
08280a094f allows assigning to mask_view elements 2025-03-31 10:19:15 +02:00
ae90adc854 adds most fp functions 2025-03-31 10:19:15 +02:00
cd358198ad expands floating point functions 2025-03-31 10:19:14 +02:00
8746003d3e adds floating point reduction instrs, widening are untested 2025-03-31 10:19:14 +02:00
60d2b45a81 adds floating point Permutation Instructions 2025-03-31 10:19:14 +02:00
0264c5d66f small cleanup 2025-03-31 10:19:14 +02:00
528c2536af removes unused declarations 2025-03-31 10:19:14 +02:00
19e38ec898 corrects bug 2025-03-31 10:19:14 +02:00
fd11ce18c4 changes order of arguments to reflect assembly 2025-03-31 10:19:14 +02:00
9b7a9fa273 updates indexed load to use vreg_views 2025-03-31 10:19:14 +02:00
e24c1874c4 Changes load_store to use vreg_views aswell 2025-03-31 10:19:14 +02:00
221d2ee38c adds whole register moves 2025-03-31 10:19:14 +02:00
877cad27ba adds gather instructions 2025-03-31 10:19:14 +02:00
a26505cb5c adds more functions, up to slide 2025-03-31 10:19:13 +02:00
c1277b6528 adds mask_mask logical instructions 2025-03-31 10:19:13 +02:00
63889b02e7 adds widening reductions 2025-03-31 10:19:13 +02:00
f049d8cbb3 adds Integer Reduction Instructions 2025-03-31 10:19:13 +02:00
28ac169cfe adds narrowing fixed point instructions 2025-03-31 10:19:13 +02:00
a6f24db83a adds vssrl and vssra 2025-03-31 10:19:13 +02:00
e1911bc450 adds vsmul, widens functions parameters for sat_vector operations 2025-03-31 10:19:13 +02:00
75d96bf18d small cleanup, adds first fixed point instrs 2025-03-31 10:19:13 +02:00
e59458aa0e adds the missing vector csrs to the architectural state 2025-03-31 10:18:51 +02:00
77807fec01 adds merge and move instructions 2025-03-31 10:18:10 +02:00
6852d1d299 adds Vector Widening Integer Multiply-Add Instructions 2025-03-31 10:18:10 +02:00
ac1322d66b changes to ternary functions for Multiply-Add Instructions 2025-03-31 10:18:10 +02:00
9ba9d2432c adds Vector Widening Integer Multiply Instructions 2025-03-31 10:18:10 +02:00
c9b7962cd3 adds Vector Integer Divide Instructions 2025-03-31 10:18:10 +02:00
ab31fd27c9 adds single width integer instructins, also small cleanup 2025-03-31 10:18:10 +02:00
b3f189145f adds funct3 to vector functions 2025-03-31 10:18:10 +02:00
dd4416ab15 adds min/max instructions 2025-03-31 10:18:10 +02:00
0027946f90 renames mask operations to distinguish from vector integer compare instructions 2025-03-31 10:18:09 +02:00
feaff8c4a5 adds support for narrowing shifts 2025-03-31 10:18:09 +02:00
af3e76cc98 adds integer extension and add/substract with carry vector instructions 2025-03-31 10:18:09 +02:00
b1ceac2c2a small correction for vector_functions 2025-03-31 10:18:09 +02:00
b5862039e7 changes order of operands to more closely resemble assembly 2025-03-31 10:18:09 +02:00
51f3802394 adds vector_imm instructions to vector_functions, makes size of all involved registers a template parameter 2025-03-31 10:18:09 +02:00
6ce0d97e81 general improvements to vector_functions, adds functions to process arithmetic instructions (working add) 2025-03-31 10:18:09 +02:00
69c8fda5d2 corrects oversight in vector_functions 2025-03-31 10:18:09 +02:00
c1f9328528 corrects vector_functions 2025-03-31 10:18:09 +02:00
2b85748279 adds load_store_index to vector_functions 2025-03-31 10:18:09 +02:00
f7aa51b12e adds small optimization, clarifies variables in vector_functions 2025-03-31 10:18:09 +02:00
3428745a00 small corrections in vector functions 2025-03-31 10:18:09 +02:00
512b79a3e7 makes elem_count an explicit parameter for the softvector functions rather than calculating it from vtype 2025-03-31 10:18:08 +02:00
7a048f8b93 changes wording of returned index to better reflect what it means, cleans up a bit 2025-03-31 10:18:08 +02:00
6f4daf91ed adds explicit RFS to assertions 2025-03-31 10:18:08 +02:00
947d353bbf adds working vector (unit) stride (segmented) loads and stores 2025-03-31 10:18:08 +02:00
b95f518c91 updates templates for interp to make extension specific includes conditonal 2025-03-31 10:18:08 +02:00
4cef0f57c1 updates templates and adds newly generated files 2025-03-31 10:18:05 +02:00
28af695592 adds vector support to m and mu priv wrapper 2025-03-31 10:16:01 +02:00
f6cdd9d07c adds vector csr to riscv_common 2025-03-31 09:54:26 +02:00
9e390971d4 corrects include guard comment for fp_functions 2025-03-31 09:54:26 +02:00
2bb2e56310 adds dependencies for K ISA (Cryptography) 2025-03-31 09:54:26 +02:00
a0eeae7dd6 corrects template for new arch_if changes 2025-03-30 19:12:22 +02:00
8f491ef36b adds superflous exception throwing 2025-03-21 20:28:37 +01:00
cbe4c2d62f adds comment to indicate purpose of arch state members 2025-03-19 12:03:12 +01:00
31c6bb55f4 applies clang format 2025-03-16 14:38:45 +01:00
63d0162119 adds license header 2025-03-16 13:33:01 +01:00
3b294d9da0 fixes sc_core_adapter wrt refactored memory hierarchy 2025-03-16 12:29:03 +01:00
54233b448d moves mmu related code into mmu unit 2025-03-16 08:50:01 +01:00
e238369e18 cleansup htif call 2025-03-15 06:54:21 +01:00
cfc980a069 Merge branch 'feature/privilege_refactor' into develop 2025-03-14 20:00:07 +01:00
502f3e8df9 fixes htif behavior and instrumentation interface 2025-03-14 19:43:20 +01:00
88475bfa55 changes the io_buf 2025-03-14 12:14:20 +01:00
71260a3ef4 Merge remote-tracking branch 'origin/feature/htif' into develop 2025-03-14 11:32:36 +01:00
23842742a6 factors clic & pmp into separate units 2025-03-13 12:13:41 +01:00
a13b7ac6d3 separates functional memory into separate unit 2025-03-12 09:26:51 +01:00
aaebeaf023 changes the io_buf 2025-03-11 12:00:31 +01:00
fb0f6255e9 replaces virtual functions with memory pointers (kind of) 2025-03-11 08:31:25 +01:00
57d5ea92be moves common functionality to base class 2025-03-10 16:00:26 +01:00
383d762abc applies clang-format and updates SystemC HTIF implementation 2025-03-06 12:10:12 +01:00
03cbd305c6 replaces literal constant with symbolic definition 2025-02-28 19:34:07 +01:00
9f5326c110 extends htif for 32bit systems 2025-02-13 13:39:47 +01:00
f4718c6de3 Merge remote-tracking branch 'origin/feature/htif' into develop 2025-02-13 09:34:31 +01:00
53de21eef9 adds generator changed output 2025-02-12 20:45:04 +01:00
d443c89c87 removes llvm from dbt-rise-tgc build system as it is handled in dbt-rise-core 2024-12-28 13:10:49 +01:00
9a2df32d57 updates templates 2024-12-28 13:07:07 +01:00
be0f783af8 adds cycle increment to tcc 2024-12-28 13:06:46 +01:00
1089800682 updates vm_impls and core.h to work with new vm_base 2024-12-28 08:24:09 +01:00
a6a6f51f0b adds clang-format fixes 2024-12-06 15:50:50 +01:00
21e1f791ad corrects sysc integration template and corresponding file 2024-12-06 09:49:02 +01:00
be6f5791fa adds update to cyclecount after each instr for asmjit 2024-11-26 20:26:18 +01:00
d907dc7f54 corrects tohost functionality and minor cleanup 2024-11-22 17:35:12 +01:00
75e81ce236 copies new tohost implemenation from hart_m_p 2024-11-14 16:51:26 +01:00
82a70efdb8 small reorder to make tohost output more readable 2024-11-14 16:51:26 +01:00
978c3db06e minor improvements to readability 2024-11-14 16:51:26 +01:00
0e88664ff7 adds better tohost writing implementation, allowing the standard riscv-isa-test benchmarks to run 2024-11-14 16:51:26 +01:00
ac818f304d increases verbosity incase elf loading goes wrong 2024-10-21 16:42:58 +02:00
ad60449073 updates generated cores 2024-09-27 20:04:58 +02:00
b45b3589fa updates templates to immediately trap when gen_trap is called 2024-09-27 20:03:51 +02:00
1fb7e8fcea improves logging output 2024-09-24 08:39:34 +02:00
5f9d0beafb corrects softfloat to comply with RVD ACT 2024-09-23 22:22:57 +02:00
4c0d1c75aa adds addr formatting to logging 2024-09-23 12:21:43 +02:00
2f3abf2f76 adds namespaces for ELFIO 2024-09-23 11:55:18 +02:00
62768bf81e applies clang format 2024-09-23 10:05:33 +02:00
f6be8ec006 adds elfio test utility 2024-09-23 09:29:08 +02:00
a8f56b6e27 removes code dupication by unifying elf file read 2024-09-23 09:28:27 +02:00
76ea0db25d adds newest generated vm_impl 2024-08-17 23:19:51 +02:00
ec1b820c18 fixes target xml generation 2024-08-17 19:36:53 +02:00
64329cf0f6 fixes use of icount vs. cycle 2024-08-17 19:36:40 +02:00
9de0aed84d expands some error message 2024-08-17 16:55:49 +02:00
bb4e2766d1 applies clang-format 2024-08-17 16:12:57 +02:00
0996d15bd4 removes debug code 2024-08-17 12:48:48 +02:00
6305efa7c2 implements proper target XML generation incl. CSRs 2024-08-17 12:40:40 +02:00
de79adc50d updates debugger hook to stop before fetching instructions
this relates to https://github.com/Minres/DBT-RISE-RISCV/issues/8 :
Debugger loses control when trap vector fetch fails

and https://github.com/Minres/DBT-RISE-RISCV/issues/7 : Two debugger
single-steps are required at reset vector
2024-08-17 12:39:54 +02:00
0473aa5344 fixes SystemC wrapper wrt. templated core_complex 2024-08-17 12:34:17 +02:00
a45fcd28db updates fn calling generation 2024-08-17 08:22:04 +02:00
0f15032210 removes gen_wait as wait can be called like any other extern function 2024-08-14 15:25:06 +02:00
efc11d87a5 updates template with fcsr check, adds extra braces on If Statements 2024-08-14 14:32:58 +02:00
4a19e27926 adds changes due to generator being more inline with others 2024-08-14 13:52:08 +02:00
c15cdb0955 expands return values of jit creating functions to inhibit endless trapping 2024-08-14 11:49:59 +02:00
6609d12582 adds flimit that gets properly evaluated in interp 2024-08-13 15:22:34 +02:00
b5341700aa updates template and adds braces when using conditions 2024-08-13 08:55:14 +02:00
0b5062d21c adds fp_functions here to remove dependencies in dbt-rise-core 2024-08-09 11:56:32 +02:00
fbca690b3b replaces gen_wait, updates template to include fp_functions when necessary 2024-08-08 12:57:08 +02:00
235a7e6e24 updates template 2024-08-08 11:08:28 +02:00
62d21e1156 updates disass 2024-08-07 09:21:07 +02:00
9c51d6eade improves interp, only calls decode once per instr 2024-08-07 09:20:11 +02:00
2878dca6b5 updates templates 2024-08-06 08:32:05 +02:00
c28e8fd00c removes left-overs 2024-08-04 18:57:20 +02:00
b3cc9d2346 makes core_complex a template 2024-08-04 18:47:32 +02:00
933f08494c removes C++17 dependency from asmjit backend 2024-08-04 17:41:49 +02:00
21f8eab432 adds regenerated tgc5c 2024-08-02 19:18:28 +02:00
6ddb8da07f fixes missing rename 2024-08-02 11:58:51 +02:00
edf456c59f fixes missing braces 2024-08-02 10:33:15 +02:00
42efced1eb fixes FCSR behavior if no floating point is implemented 2024-08-02 08:59:22 +02:00
c376e34b2b applies clang format 2024-08-01 11:02:10 +02:00
f579ec6e48 changes access to rounding mode to fail explicitly instead of unintended behavior 2024-07-31 12:30:41 +02:00
fd20e66f1f changes softfloat API usage, all effected Instrs pass test suite 2024-07-31 12:30:41 +02:00
5d69b79232 reverts patches in softfloat 2024-07-31 12:30:41 +02:00
2edd68d1bd refactors zeroProd branch to allow for better case handling 2024-07-31 12:30:41 +02:00
7ffa7667b6 fixes concerning FMADD_S, FMSUB_S, FNMADD_S, and FNSUB_S
mostly about ensuring correct sign
2024-07-31 12:30:41 +02:00
93d89e07ca removes wrong compile definition 2024-07-31 12:30:41 +02:00
17dcba4b90 updates softfloat to #b51ef8f of softfloat3
https://github.com/ucb-bar/berkeley-softfloat-3/
2024-07-31 12:30:41 +02:00
39d2518fdd checkin: tgc5f builds and runs through 2024-07-31 12:30:41 +02:00
a365110054 fix format 2024-07-30 13:34:23 +02:00
d2efb23ff7 fixes cache behavior for fetches 2024-07-25 19:33:50 +02:00
04b7a09b19 updates date in templates 2024-07-25 17:25:12 +02:00
72b11beac5 moves decoder to dbt-rise-core 2024-07-25 10:13:38 +02:00
e87b7d5fd0 applies clang-format 2024-07-24 14:48:50 +02:00
5a2b96ef3e adds logging categories for ISS 2024-07-24 12:30:07 +02:00
c6b99cd155 introduces new decoder to interp backend 2024-07-24 12:28:35 +02:00
b1306c3a47 improves instruction decoding by avoiding copying, replaces .size() 2024-07-24 08:54:37 +02:00
0d6bf924ed changes jh.globals from map to vector 2024-07-23 15:45:51 +02:00
86de536c8f changes jh globals to seperate riscv specifics 2024-07-23 14:35:31 +02:00
051dd5e2d3 updates templates for decoder in seperate class, adds again generated templates 2024-07-23 13:46:10 +02:00
e3942be776 Introduces decoder in a seperate class 2024-07-23 13:08:53 +02:00
6ee484a771 moves instruction decoder into own class 2024-07-23 11:30:33 +02:00
60808c8649 corrects template since util fns are no longer vm_base members 2024-07-23 11:29:56 +02:00
0432803d82 updates templates and vm impls for better LAST_BRANCH handling 2024-07-22 09:04:17 +02:00
4f5d9214ed adds newly generated instr.yaml 2024-07-18 14:31:36 +02:00
d42d2ce533 corrects illegal instruction for llvm 2024-07-18 14:04:23 +02:00
236d12d7f5 integrates gen_bool for Conditions (was truncation) into llvm 2024-07-18 13:30:42 +02:00
e1b6cab890 removes setting of NEXT_PC to max when trapping in llvm and asmjit, adds default disass to llvm 2024-07-18 12:02:40 +02:00
8361f88718 removes setting of NEXT_PC to max if trap 2024-07-18 11:37:53 +02:00
2ec7ea4b41 removes leftover gen_sync in asmjit 2024-07-17 22:39:12 +02:00
b24965d321 corrects gen_sync update order, improves illegal instruction 2024-07-17 20:52:01 +02:00
244bf6d2f2 corrects gen_sync before trap check, improves illegal_instruction 2024-07-17 20:25:49 +02:00
1a4465a371 changes template: adds correct illegal instruction, reorders gen_sync to allow correct instr id eve when trapping, adds newly generated vm 2024-07-17 19:59:01 +02:00
fa82a50824 fixes typo in templates 2024-07-17 17:24:17 +02:00
6dc17857da updates template 2024-07-17 15:36:08 +02:00
11a30caae8 integrates generator changes to canPrecompute 2024-07-17 15:14:13 +02:00
ac1a26a10c integrates new tval changes into llvm 2024-07-17 14:17:02 +02:00
7a199e122d integrates new tval changes into asmjit 2024-07-17 09:42:12 +02:00
d8c3d2e19c integrates new tval changes into tcc 2024-07-16 17:35:23 +02:00
375755999a integrates new tval changes 2024-07-16 15:32:35 +02:00
9996fd4833 change cache line size to 64 2024-07-11 14:03:58 +02:00
149b3136d2 updates generated files 2024-07-10 12:55:36 +02:00
ac8f8b0539 updates vms with fixed Zc in tgc5c.core_desc 2024-07-10 12:51:59 +02:00
b2cbf90d0b updates generated files 2024-07-10 12:51:59 +02:00
373145478e updats file because of generator changes 2024-07-10 12:51:59 +02:00
55b0cea94f changes vm_base util API 2024-07-10 12:51:59 +02:00
5b17599aa2 allows usage of std::variants 2024-07-10 12:51:59 +02:00
4cfb15c7cd Asmjit and interp working 2024-07-10 12:51:31 +02:00
63da7f8d57 applies clang-format 2024-07-09 13:57:11 +02:00
fb4012fbd1 moves likely annotation 2024-07-09 13:52:10 +02:00
24449f1c0f fixes some elf load issue 2024-07-05 12:18:36 +02:00
fd303c8343 fixes asmjit deprecation warning 2024-07-05 07:51:37 +02:00
346b177a87 extends finishing conditions 2024-07-05 05:52:29 +02:00
d4ec131fa7 change COUNT_LIMIT to ICOUNT_LIMIT 2024-07-04 10:46:24 +02:00
48370a4555 asmjit passes backend with new CoreDSL 2024-06-22 09:28:26 +02:00
36b076774e Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-06-21 13:35:30 +02:00
482a4ec253 fixes semihosting callbacks in templates 2024-06-21 13:35:25 +02:00
2fb28364c5 fixes remaining templates 2024-06-21 10:49:36 +02:00
8460f4ab7f updates templates to re-enable interactive debugging of generator 2024-06-21 10:46:11 +02:00
3fd51cc68c fixes templates 2024-06-14 19:54:33 +02:00
551822916c applies clang-format 2024-06-14 17:43:12 +02:00
37db31fb4b removes repo that should not be checked in 2024-05-31 10:46:19 +02:00
e2da306eee fixes semihosting cb registration 2024-05-31 10:45:28 +02:00
41051f8f34 fixes tohost handling 2024-05-31 10:43:38 +02:00
2a7449fa1e Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-05-31 09:47:52 +02:00
a6c48ceaac Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-05-31 09:42:13 +02:00
1e30b68507 updates min cmake version 2024-05-31 09:37:19 +02:00
ed793471bb adding semhosting 2024-05-31 07:27:47 +02:00
58fb815f32 fixes gen_raise in tcc 2024-05-20 10:34:23 +02:00
3cc8bd0854 adds reformat bc of verilog literals 2024-05-18 21:01:05 +02:00
a27850f841 adds verilog literal and illegal_instr to asmjit 2024-05-18 21:00:21 +02:00
fb330cddea llvm passes act 2024-05-18 19:33:57 +02:00
b76c5bf0d6 adds flush to fence_i 2024-05-11 15:25:49 +02:00
001c6349f7 removes tcc sim stop when writing to tohost 2024-05-11 15:16:46 +02:00
ee6a11dae6 fixes typo 2024-05-09 20:54:30 +02:00
2e27b025cc improves dump-ir comments 2024-05-09 13:47:36 +02:00
f0a004be9d adds information for debugging 2024-05-09 13:42:16 +02:00
3422c7cd5c optimizes writebacks 2024-05-08 15:18:38 +02:00
ad79a28705 wip checkin 2024-04-30 19:21:27 +02:00
9fdbc3ff38 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-04-26 17:07:00 +02:00
602bc6e06a checking: working 2024-04-26 17:06:26 +02:00
6cb76fc256 updates tgc5c according to latest CoreDSL 2024-04-16 13:09:14 +02:00
fbcd389580 fix log macro 2024-04-15 13:03:47 +02:00
b25b7848c6 fix formatting 2024-03-19 11:47:12 +01:00
6c986d38d8 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-03-19 11:02:17 +01:00
a1ebd83d2a adds riscv_hart_common and signature output 2024-03-19 11:02:03 +01:00
8aed551813 Add a new LOG macro in SCC to avoid conflicts with other libraries. 2024-03-14 09:43:08 +01:00
1e6a0086e9 adds disass functionality 2024-03-07 13:58:08 +01:00
119d4a8b43 adds generation if IMEM space 2024-02-21 07:08:24 +01:00
9841b16122 fixes clang-format failures 2024-01-12 11:49:11 +01:00
fbda1424f3 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2024-01-10 16:22:31 +01:00
fe2d5cb2f9 adds semihosting to all backends 2024-01-10 11:47:12 +01:00
3ff59ba45d small refactor, adds baisc functionality 2024-01-10 10:15:05 +01:00
db5765b342 makes softfloat always a static library 2024-01-10 09:36:52 +01:00
075e04249a adds semihosting skeleton 2024-01-09 12:50:41 +01:00
207f778ee6 adds initial semihosting host capabilities 2024-01-08 17:17:59 +01:00
f4f90c5e65 backports clang-format changes to template 2023-12-02 17:42:57 +01:00
bc4ea30815 apply clang-format 10 fixes 2023-12-01 14:50:54 +01:00
e921201f7b applies clang-format fixes 2023-11-30 11:51:49 +01:00
e6aa6e5842 adds handling of variable number of clic interrupts 2023-11-22 11:47:31 +01:00
4418fa7e4f fixes include path of asmjit helpers 2023-11-20 16:07:01 +01:00
adaa7e1c04 updates template 2023-11-20 11:46:19 +01:00
0eb1db0e7e adds functionality, adds working asmjit 2023-11-20 11:45:52 +01:00
e48597b2b7 adds formatting fixes 2023-11-05 17:19:43 +01:00
458c773e19 corrects slow ca configuration of TGC5C 2023-11-05 14:47:24 +01:00
b3f40f9b15 build fixes due to dependencies 2023-11-04 13:05:30 +01:00
6419ad471e updates .gitignore 2023-10-29 17:08:18 +01:00
759061b569 applies clang-format changes 2023-10-29 17:06:56 +01:00
2115e9ceae adds missing include to templates 2023-10-29 14:31:15 +01:00
2bea95c1a7 adds option to disable DMI use 2023-10-28 17:06:50 +02:00
7001b693ae updates templates for SystemC registration 2023-10-27 22:14:11 +02:00
e6f11081eb fixes quantum and quantum break handling 2023-10-27 21:12:49 +02:00
09db0cd35d fixes LLVM backend registration for SystemC 2023-10-26 06:50:54 +02:00
980c8031c3 fixes tohost behavior of SC wrapper and cycle-estimate plugin 2023-10-25 20:37:10 +02:00
b86d7a517d adds dynamic cycle estimation 2023-10-25 17:13:52 +02:00
b7478965ab adds asmjit backend registration for SystemC 2023-10-23 10:18:25 +02:00
bf4a6deb86 fixes dump-ir handling 2023-10-22 23:19:09 +02:00
ffe730219d merge commit 2023-10-22 15:13:25 +02:00
60c926c921 adds asmjit 2023-10-22 15:11:20 +02:00
9371a09b71 adds asmjit 2023-10-22 15:10:55 +02:00
4c3a7386b0 updates generated files 2023-10-22 08:51:08 +02:00
82c26acfc8 does some cleanup of the directory structure 2023-10-21 17:26:09 +02:00
3a86f4f9de does some cleanup of generated files 2023-10-21 17:19:24 +02:00
74ff1d455a fixes install routine 2023-10-20 20:38:59 +02:00
aa12e93177 adds RPATH setting to install 2023-10-18 11:17:20 +02:00
ae4322c1b9 „src/main.cpp“ ändern 2023-10-15 09:03:31 +02:00
9180ad1f9c debugger memory accesses should never lead to traps 2023-10-06 21:39:48 +02:00
ee6a068b06 streamlines backends and reporting 2023-10-01 18:33:14 +02:00
b9b165465d adds some template updates 2023-09-30 22:17:18 +02:00
b97853ff5a update plugins to read YAML file 2023-09-30 22:10:24 +02:00
b7f023756e fixes constructor calls of derived riscv_hart classes 2023-09-27 07:51:49 +02:00
2095ac985b fixes forgotten removal of pctrace in core_complex 2023-09-27 06:19:59 +02:00
3fb8fe765a aligns riscv_hart_msu_vp with riscv_hart_m_p 2023-09-26 20:17:26 +02:00
5fd226b670 moves pctrace 2023-09-25 09:44:51 +02:00
417076f8e6 stops jit block creation in case of ECALL and EBREAK 2023-09-23 11:30:58 +02:00
70839bbbf2 changes templates for correct plugin callback in case of trap 2023-09-23 10:35:21 +02:00
8db0cc5d05 removes clutter 2023-09-23 10:34:58 +02:00
212fb1c8ff adds tracing functionality 2023-09-22 12:40:35 +02:00
f74f98f361 improves readability 2023-09-22 12:40:12 +02:00
f074092a78 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2023-09-20 15:18:05 +02:00
633c0d21a0 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2023-09-20 15:17:43 +02:00
51f6fbe0dd applies newest CoreDSL changes 2023-09-20 15:12:03 +02:00
de45d06878 adds initial working version of llvm backend 2023-09-19 16:26:07 +02:00
c7038cafa5 updates naming in checked-in sources 2023-09-19 12:11:49 +02:00
40f50b0ec0 changes register names to lower case in printing 2023-09-09 18:54:18 +02:00
b360fc2c75 Merge branch 'develop' of https://git.minres.com/DBT-RISE/DBT-RISE-TGC into develop 2023-09-05 10:08:49 +02:00
e21f8dc379 allows functions in interp and updates generated 2023-09-05 10:08:00 +02:00
8ee3ac90f7 adapts name changes 2023-09-04 12:45:45 +02:00
d5763d2f36 fixes option depended compilation 2023-08-30 17:11:50 +02:00
b5d915f389 fixes compile issues from merge 2023-08-30 15:49:28 +02:00
813b40409d Merge branch 'develop' of
https://git.minres.com/DBT-RISE/DBT-RISE-TGC.git into develop
2023-08-30 10:05:42 +02:00
c8a4a4c736 renames core(s) 2023-08-28 07:09:55 +02:00
18e08cfc50 fixes missing template updates 2023-08-08 06:23:38 +02:00
568 changed files with 78645 additions and 63005 deletions

View File

@ -1,4 +1,3 @@
---
Language: Cpp
# BasedOnStyle: LLVM
# should be in line with IndentWidth
@ -13,8 +12,8 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
@ -39,8 +38,8 @@ BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ColumnLimit: 140
CommentPragmas: '^( IWYU pragma:| @suppress)'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 0
ContinuationIndentWidth: 4
@ -76,13 +75,13 @@ PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParens: Never
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false

2
.gitignore vendored
View File

@ -1,5 +1,6 @@
.DS_Store
/*.il
/.settings
/avr-instr.html
/blink.S
/flash.*
@ -14,7 +15,6 @@
/*.ods
/build*/
/*.logs
language.settings.xml
/*.gtkw
/Debug wo LLVM/
/*.txdb

View File

@ -1,73 +0,0 @@
eclipse.preferences.version=1
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return\\")",implicit\=>false}
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused return value\\")"}
org.eclipse.cdt.codan.checkers.nocommentinside=-Error
org.eclipse.cdt.codan.checkers.nocommentinside.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Nesting comments\\")"}
org.eclipse.cdt.codan.checkers.nolinecomment=-Error
org.eclipse.cdt.codan.checkers.nolinecomment.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Line comments\\")"}
org.eclipse.cdt.codan.checkers.noreturn=Error
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No return value\\")",implicit\=>false}
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Abstract class cannot be instantiated\\")"}
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Ambiguous problem\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment in condition\\")"}
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"}
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"No break at end of case\\")",no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false,enable_fallthrough_quickfix_param\=>false}
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Catching by reference is recommended\\")",unknown\=>false,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Circular inheritance\\")"}
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class members should be properly initialized\\")",skip\=>true}
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem=Error
org.eclipse.cdt.codan.internal.checkers.DecltypeAutoProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid 'decltype(auto)' specifier\\")"}
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Field cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid arguments\\")"}
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid template argument\\")"}
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Label statement not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Member declaration not found\\")"}
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Method cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Name convention for function\\")",pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Class has a virtual method and non-virtual destructor\\")"}
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid overload\\")"}
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redeclaration\\")"}
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Invalid redefinition\\")"}
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Return with parenthesis\\")"}
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Format String Vulnerability\\")"}
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Statement has no effect\\")",macro\=>true,exceptions\=>()}
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suggested parenthesis around expression\\")",paramNot\=>false}
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false}
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"}
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused function declaration\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused static function\\")",macro\=>true}
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Unused variable declaration in file scope\\")",macro\=>true,exceptions\=>("@(\#)","$Id")}
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol is not resolved\\")"}

View File

@ -1,13 +0,0 @@
eclipse.preferences.version=1
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
environment/project/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/delimiter=\:
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/operation=append
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LLVM_HOME/value=/usr/lib/llvm-6.0
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/delimiter=\:
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/operation=append
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/LLVM_HOME/value=/usr/lib/llvm-6.0
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
environment/project/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true

View File

@ -1,37 +0,0 @@
eclipse.preferences.version=1
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/CPLUS_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/C_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/CPLUS_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/C_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/CPLUS_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/delimiter=\:
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/C_INCLUDE_PATH/operation=remove
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/delimiter=\:
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/LIBRARY_PATH/operation=remove
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/append=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.debug.1751741082/appendContributed=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/delimiter=\:
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/LIBRARY_PATH/operation=remove
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/append=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171.1259602404/appendContributed=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/delimiter=\:
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/LIBRARY_PATH/operation=remove
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/append=true
environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.exe.release.1745230171/appendContributed=true

View File

@ -1,8 +1,9 @@
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.18)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
###############################################################################
# ##############################################################################
#
###############################################################################
# ##############################################################################
project(dbt-rise-tgc VERSION 1.0.0)
include(GNUInstallDirs)
@ -11,59 +12,76 @@ include(flink)
find_package(elfio QUIET)
find_package(jsoncpp)
find_package(Boost COMPONENTS coroutine REQUIRED)
find_package(absl REQUIRED)
add_subdirectory(softfloat)
set(LIB_SOURCES
src/iss/arch/tgc_c.cpp
src/vm/tcc/vm_tgc_c.cpp
src/vm/interp/vm_tgc_c.cpp
src/vm/fp_functions.cpp
src/iss/plugin/instruction_count.cpp
src/iss/arch/tgc5c.cpp
src/iss/mem/memory_if.cpp
src/vm/interp/vm_tgc5c.cpp
src/vm/fp_functions.cpp
src/vm/vector_functions.cpp
src/iss/debugger/csr_names.cpp
src/iss/semihosting/semihosting.cpp
)
if(WITH_TCC)
list(APPEND LIB_SOURCES
src/vm/tcc/vm_tgc_c.cpp
)
list(APPEND LIB_SOURCES
src/vm/tcc/vm_tgc5c.cpp
)
endif()
if(WITH_LLVM)
list(APPEND LIB_SOURCES
src/vm/llvm/vm_tgc_c.cpp
src/vm/llvm/fp_impl.cpp
)
list(APPEND LIB_SOURCES
src/vm/llvm/vm_tgc5c.cpp
src/vm/llvm/fp_impl.cpp
)
endif()
if(WITH_ASMJIT)
list(APPEND LIB_SOURCES
src/vm/asmjit/vm_tgc5c.cpp
)
endif()
# library files
FILE(GLOB GEN_ISS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/iss/arch/*.cpp)
FILE(GLOB GEN_VM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/interp/vm_*.cpp)
FILE(GLOB GEN_YAML_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/contrib/instr/*.yaml)
list(APPEND LIB_SOURCES ${GEN_ISS_SOURCES} ${GEN_VM_SOURCES})
foreach(FILEPATH ${GEN_ISS_SOURCES})
get_filename_component(CORE ${FILEPATH} NAME_WE)
string(TOUPPER ${CORE} CORE)
list(APPEND LIB_DEFINES CORE_${CORE})
endforeach()
message(STATUS "Core defines are ${LIB_DEFINES}")
if(WITH_LLVM)
FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp)
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
FILE(GLOB LLVM_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/llvm/vm_*.cpp)
list(APPEND LIB_SOURCES ${LLVM_GEN_SOURCES})
endif()
if(WITH_TCC)
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/tcc/vm_*.cpp)
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
endif()
if(TARGET RapidJSON)
if(WITH_ASMJIT)
FILE(GLOB TCC_GEN_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/vm/asmjit/vm_*.cpp)
list(APPEND LIB_SOURCES ${TCC_GEN_SOURCES})
endif()
if(TARGET yaml-cpp::yaml-cpp)
list(APPEND LIB_SOURCES
src/iss/plugin/cycle_estimate.cpp
src/iss/plugin/pctrace.cpp
)
endif()
if(TARGET jsoncpp::jsoncpp)
list(APPEND LIB_SOURCES
src/iss/plugin/instruction_count.cpp
src/iss/plugin/cycle_estimate.cpp
src/iss/plugin/instruction_count.cpp
)
endif()
# Define the library
add_library(${PROJECT_NAME} SHARED ${LIB_SOURCES})
@ -72,53 +90,57 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
target_compile_options(${PROJECT_NAME} PRIVATE /wd4293)
endif()
target_include_directories(${PROJECT_NAME} PUBLIC src)
target_include_directories(${PROJECT_NAME} PUBLIC src-gen)
target_force_link_libraries(${PROJECT_NAME} PRIVATE dbt-rise-core)
# only re-export the include paths
get_target_property(DBT_CORE_INCL dbt-rise-core INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(${PROJECT_NAME} INTERFACE ${DBT_CORE_INCL})
get_target_property(DBT_CORE_DEFS dbt-rise-core INTERFACE_COMPILE_DEFINITIONS)
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine)
if(TARGET jsoncpp::jsoncpp)
target_link_libraries(${PROJECT_NAME} PUBLIC jsoncpp::jsoncpp)
if(NOT(DBT_CORE_DEFS STREQUAL DBT_CORE_DEFS-NOTFOUND))
target_compile_definitions(${PROJECT_NAME} INTERFACE ${DBT_CORE_DEFS})
endif()
if(TARGET lz4::lz4)
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_LZ4)
target_link_libraries(${PROJECT_NAME} PUBLIC lz4::lz4)
endif()
if(TARGET RapidJSON)
target_link_libraries(${PROJECT_NAME} PUBLIC RapidJSON)
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio softfloat scc-util Boost::coroutine abseil::abseil)
if(TARGET yaml-cpp::yaml-cpp)
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_PLUGINS)
target_link_libraries(${PROJECT_NAME} PUBLIC yaml-cpp::yaml-cpp)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE
VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE
)
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/incl/iss COMPONENT ${PROJECT_NAME}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
FILES_MATCHING # install only matched files
PATTERN "*.h" # select header files
)
###############################################################################
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # target directory
FILES_MATCHING # install only matched files
PATTERN "*.h" # select header files
)
install(FILES ${GEN_YAML_SOURCES} DESTINATION share/tgc-vp)
# ##############################################################################
#
###############################################################################
# ##############################################################################
set(CMAKE_INSTALL_RPATH $ORIGIN/../${CMAKE_INSTALL_LIBDIR})
project(tgc-sim)
find_package(Boost COMPONENTS program_options thread REQUIRED)
add_executable(${PROJECT_NAME} src/main.cpp)
if(TARGET ${CORE_NAME}_cpp)
list(APPEND TGC_SOURCES ${${CORE_NAME}_OUTPUT_FILES})
else()
@ -130,21 +152,20 @@ else()
endif()
foreach(F IN LISTS TGC_SOURCES)
if (${F} MATCHES ".*/arch/([^/]*)\.cpp")
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
endif()
endforeach()
#if(WITH_LLVM)
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
#endif()
#if(WITH_TCC)
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
#endif()
# if(WITH_LLVM)
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_LLVM)
# #target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
# endif()
# if(WITH_TCC)
# target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_TCC)
# endif()
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc fmt::fmt)
if(TARGET Boost::program_options)
@ -152,74 +173,91 @@ if(TARGET Boost::program_options)
else()
target_link_libraries(${PROJECT_NAME} PUBLIC ${BOOST_program_options_LIBRARY})
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${CMAKE_DL_LIBS})
if (Tcmalloc_FOUND)
if(Tcmalloc_FOUND)
target_link_libraries(${PROJECT_NAME} PUBLIC ${Tcmalloc_LIBRARIES})
endif(Tcmalloc_FOUND)
install(TARGETS tgc-sim
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME} # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
)
if(BUILD_TESTING)
# ... CMake code to create tests ...
add_test(NAME tgc-sim-interp
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
if(WITH_TCC)
add_test(NAME tgc-sim-tcc
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
endif()
if(WITH_LLVM)
add_test(NAME tgc-sim-llvm
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
endif()
# ... CMake code to create tests ...
add_test(NAME tgc-sim-interp
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend interp)
if(WITH_TCC)
add_test(NAME tgc-sim-tcc
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend tcc)
endif()
if(WITH_LLVM)
add_test(NAME tgc-sim-llvm
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend llvm)
endif()
if(WITH_ASMJIT)
add_test(NAME tgc-sim-asmjit
COMMAND tgc-sim -f ${CMAKE_BINARY_DIR}/../../Firmwares/hello-world/hello --backend asmjit)
endif()
endif()
###############################################################################
# ##############################################################################
#
###############################################################################
# ##############################################################################
if(TARGET scc-sysc)
project(dbt-rise-tgc_sc VERSION 1.0.0)
set(LIB_SOURCES
src/sysc/core_complex.cpp
src/sysc/register_tgc_c.cpp
)
FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp)
list(APPEND LIB_SOURCES ${GEN_SC_SOURCES})
project(dbt-rise-tgc_sc VERSION 1.0.0)
set(LIB_SOURCES
src/sysc/core_complex.cpp
src/sysc/register_tgc_c.cpp
)
FILE(GLOB GEN_SC_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src-gen/sysc/register_*.cpp)
list(APPEND LIB_SOURCES ${GEN_SC_SOURCES})
add_library(${PROJECT_NAME} ${LIB_SOURCES})
target_compile_definitions(${PROJECT_NAME} PUBLIC WITH_SYSTEMC)
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
foreach(F IN LISTS TGC_SOURCES)
if (${F} MATCHES ".*/arch/([^/]*)\.cpp")
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
if(${F} MATCHES ".*/arch/([^/]*)\.cpp")
string(REGEX REPLACE ".*/([^/]*)\.cpp" "\\1" CORE_NAME_LC ${F})
string(TOUPPER ${CORE_NAME_LC} CORE_NAME)
target_compile_definitions(${PROJECT_NAME} PRIVATE CORE_${CORE_NAME})
endif()
endforeach()
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
# if(WITH_LLVM)
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
# endif()
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
target_link_libraries(${PROJECT_NAME} PUBLIC dbt-rise-tgc scc-sysc)
# if(WITH_LLVM)
# target_link_libraries(${PROJECT_NAME} PUBLIC ${llvm_libs})
# endif()
set(LIB_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/sysc/core_complex.h)
set_target_properties(${PROJECT_NAME} PROPERTIES
VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
VERSION ${PROJECT_VERSION}
FRAMEWORK FALSE
PUBLIC_HEADER "${LIB_HEADERS}" # specify the public headers
)
install(TARGETS ${PROJECT_NAME} COMPONENT ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
)
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} # static lib
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # binaries
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/sysc # headers for mac (note the different component -> different package)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # headers
)
endif()
project(elfio-test)
find_package(Boost COMPONENTS program_options thread REQUIRED)
add_executable(${PROJECT_NAME} src/elfio.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC elfio::elfio)

1
contrib/instr/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*.yaml

View File

@ -1,536 +1,623 @@
RV32I:
- LUI:
RVI:
LUI:
index: 0
encoding: 0b00000000000000000000000000110111
mask: 0b00000000000000000000000001111111
size: 32
branch: false
delay: 1
- AUIPC:
AUIPC:
index: 1
encoding: 0b00000000000000000000000000010111
mask: 0b00000000000000000000000001111111
size: 32
branch: false
delay: 1
- JAL:
JAL:
index: 2
encoding: 0b00000000000000000000000001101111
mask: 0b00000000000000000000000001111111
attributes: [[name:no_cont]]
size: 32
branch: true
delay: 1
- JALR:
delay: [1,1]
JALR:
index: 3
encoding: 0b00000000000000000000000001100111
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont]]
size: 32
branch: true
delay: 1
- BEQ:
delay: [1,1]
BEQ:
index: 4
encoding: 0b00000000000000000000000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- BNE:
BNE:
index: 5
encoding: 0b00000000000000000001000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- BLT:
BLT:
index: 6
encoding: 0b00000000000000000100000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- BGE:
BGE:
index: 7
encoding: 0b00000000000000000101000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- BLTU:
BLTU:
index: 8
encoding: 0b00000000000000000110000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- BGEU:
BGEU:
index: 9
encoding: 0b00000000000000000111000001100011
mask: 0b00000000000000000111000001111111
attributes: [[name:no_cont], [name:cond]]
size: 32
branch: true
delay: [1,1]
- LB:
LB:
index: 10
encoding: 0b00000000000000000000000000000011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- LH:
LH:
index: 11
encoding: 0b00000000000000000001000000000011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- LW:
LW:
index: 12
encoding: 0b00000000000000000010000000000011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- LBU:
LBU:
index: 13
encoding: 0b00000000000000000100000000000011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- LHU:
LHU:
index: 14
encoding: 0b00000000000000000101000000000011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SB:
SB:
index: 15
encoding: 0b00000000000000000000000000100011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SH:
SH:
index: 16
encoding: 0b00000000000000000001000000100011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SW:
SW:
index: 17
encoding: 0b00000000000000000010000000100011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- ADDI:
ADDI:
index: 18
encoding: 0b00000000000000000000000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SLTI:
SLTI:
index: 19
encoding: 0b00000000000000000010000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SLTIU:
SLTIU:
index: 20
encoding: 0b00000000000000000011000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- XORI:
XORI:
index: 21
encoding: 0b00000000000000000100000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- ORI:
ORI:
index: 22
encoding: 0b00000000000000000110000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- ANDI:
ANDI:
index: 23
encoding: 0b00000000000000000111000000010011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- SLLI:
SLLI:
index: 24
encoding: 0b00000000000000000001000000010011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SRLI:
SRLI:
index: 25
encoding: 0b00000000000000000101000000010011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SRAI:
SRAI:
index: 26
encoding: 0b01000000000000000101000000010011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- ADD:
ADD:
index: 27
encoding: 0b00000000000000000000000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SUB:
SUB:
index: 28
encoding: 0b01000000000000000000000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SLL:
SLL:
index: 29
encoding: 0b00000000000000000001000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SLT:
SLT:
index: 30
encoding: 0b00000000000000000010000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SLTU:
SLTU:
index: 31
encoding: 0b00000000000000000011000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- XOR:
XOR:
index: 32
encoding: 0b00000000000000000100000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SRL:
SRL:
index: 33
encoding: 0b00000000000000000101000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- SRA:
SRA:
index: 34
encoding: 0b01000000000000000101000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- OR:
OR:
index: 35
encoding: 0b00000000000000000110000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- AND:
AND:
index: 36
encoding: 0b00000000000000000111000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- FENCE:
FENCE:
index: 37
encoding: 0b00000000000000000000000000001111
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- ECALL:
ECALL:
index: 38
encoding: 0b00000000000000000000000001110011
mask: 0b11111111111111111111111111111111
attributes: [[name:no_cont]]
size: 32
branch: false
delay: 1
- EBREAK:
EBREAK:
index: 39
encoding: 0b00000000000100000000000001110011
mask: 0b11111111111111111111111111111111
attributes: [[name:no_cont]]
size: 32
branch: false
delay: 1
- MRET:
MRET:
index: 40
encoding: 0b00110000001000000000000001110011
mask: 0b11111111111111111111111111111111
attributes: [[name:no_cont]]
size: 32
branch: false
delay: 1
- WFI:
WFI:
index: 41
encoding: 0b00010000010100000000000001110011
mask: 0b11111111111111111111111111111111
size: 32
branch: false
delay: 1
Zicsr:
- CSRRW:
CSRRW:
index: 42
encoding: 0b00000000000000000001000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- CSRRS:
CSRRS:
index: 43
encoding: 0b00000000000000000010000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- CSRRC:
CSRRC:
index: 44
encoding: 0b00000000000000000011000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- CSRRWI:
CSRRWI:
index: 45
encoding: 0b00000000000000000101000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- CSRRSI:
CSRRSI:
index: 46
encoding: 0b00000000000000000110000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
- CSRRCI:
CSRRCI:
index: 47
encoding: 0b00000000000000000111000001110011
mask: 0b00000000000000000111000001111111
size: 32
branch: false
delay: 1
Zifencei:
- FENCE_I:
FENCE_I:
index: 48
encoding: 0b00000000000000000001000000001111
mask: 0b00000000000000000111000001111111
attributes: [[name:flush]]
size: 32
branch: false
delay: 1
RV32M:
- MUL:
RVM:
MUL:
index: 49
encoding: 0b00000010000000000000000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- MULH:
MULH:
index: 50
encoding: 0b00000010000000000001000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- MULHSU:
MULHSU:
index: 51
encoding: 0b00000010000000000010000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- MULHU:
MULHU:
index: 52
encoding: 0b00000010000000000011000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- DIV:
DIV:
index: 53
encoding: 0b00000010000000000100000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- DIVU:
DIVU:
index: 54
encoding: 0b00000010000000000101000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- REM:
REM:
index: 55
encoding: 0b00000010000000000110000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
- REMU:
REMU:
index: 56
encoding: 0b00000010000000000111000000110011
mask: 0b11111110000000000111000001111111
size: 32
branch: false
delay: 1
RV32IC:
- CADDI4SPN:
Zca:
C__ADDI4SPN:
index: 57
encoding: 0b0000000000000000
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CLW:
C__LW:
index: 58
encoding: 0b0100000000000000
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CSW:
C__SW:
index: 59
encoding: 0b1100000000000000
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CADDI:
C__ADDI:
index: 60
encoding: 0b0000000000000001
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CNOP:
C__NOP:
index: 61
encoding: 0b0000000000000001
mask: 0b1110111110000011
size: 16
branch: false
delay: 1
- CJAL:
C__JAL:
index: 62
encoding: 0b0010000000000001
mask: 0b1110000000000011
attributes: [[name:no_cont]]
attributes: [[name:enable, value:1]]
size: 16
branch: true
delay: 1
- CLI:
C__LI:
index: 63
encoding: 0b0100000000000001
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CLUI:
C__LUI:
index: 64
encoding: 0b0110000000000001
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CADDI16SP:
C__ADDI16SP:
index: 65
encoding: 0b0110000100000001
mask: 0b1110111110000011
size: 16
branch: false
delay: 1
- CSRLI:
__reserved_clui:
index: 66
encoding: 0b0110000000000001
mask: 0b1111000001111111
size: 16
branch: false
delay: 1
C__SRLI:
index: 67
encoding: 0b1000000000000001
mask: 0b1111110000000011
attributes: [[name:enable, value:1]]
size: 16
branch: false
delay: 1
- CSRAI:
C__SRAI:
index: 68
encoding: 0b1000010000000001
mask: 0b1111110000000011
attributes: [[name:enable, value:1]]
size: 16
branch: false
delay: 1
- CANDI:
C__ANDI:
index: 69
encoding: 0b1000100000000001
mask: 0b1110110000000011
size: 16
branch: false
delay: 1
- CSUB:
C__SUB:
index: 70
encoding: 0b1000110000000001
mask: 0b1111110001100011
size: 16
branch: false
delay: 1
- CXOR:
C__XOR:
index: 71
encoding: 0b1000110000100001
mask: 0b1111110001100011
size: 16
branch: false
delay: 1
- COR:
C__OR:
index: 72
encoding: 0b1000110001000001
mask: 0b1111110001100011
size: 16
branch: false
delay: 1
- CAND:
C__AND:
index: 73
encoding: 0b1000110001100001
mask: 0b1111110001100011
size: 16
branch: false
delay: 1
- CJ:
C__J:
index: 74
encoding: 0b1010000000000001
mask: 0b1110000000000011
attributes: [[name:no_cont]]
size: 16
branch: true
delay: 1
- CBEQZ:
C__BEQZ:
index: 75
encoding: 0b1100000000000001
mask: 0b1110000000000011
attributes: [[name:no_cont], [name:cond]]
size: 16
branch: true
delay: [1,1]
- CBNEZ:
C__BNEZ:
index: 76
encoding: 0b1110000000000001
mask: 0b1110000000000011
attributes: [[name:no_cont], [name:cond]]
size: 16
branch: true
delay: [1,1]
- CSLLI:
C__SLLI:
index: 77
encoding: 0b0000000000000010
mask: 0b1111000000000011
attributes: [[name:enable, value:1]]
size: 16
branch: false
delay: 1
- CLWSP:
C__LWSP:
index: 78
encoding: 0b0100000000000010
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- CMV:
C__MV:
index: 79
encoding: 0b1000000000000010
mask: 0b1111000000000011
size: 16
branch: false
delay: 1
- CJR:
C__JR:
index: 80
encoding: 0b1000000000000010
mask: 0b1111000001111111
attributes: [[name:no_cont]]
size: 16
branch: true
delay: 1
- CADD:
__reserved_cmv:
index: 81
encoding: 0b1000000000000010
mask: 0b1111111111111111
size: 16
branch: false
delay: 1
C__ADD:
index: 82
encoding: 0b1001000000000010
mask: 0b1111000000000011
size: 16
branch: false
delay: 1
- CJALR:
C__JALR:
index: 83
encoding: 0b1001000000000010
mask: 0b1111000001111111
attributes: [[name:no_cont]]
size: 16
branch: true
delay: 1
- CEBREAK:
C__EBREAK:
index: 84
encoding: 0b1001000000000010
mask: 0b1111111111111111
attributes: [[name:no_cont]]
size: 16
branch: false
delay: 1
- CSWSP:
C__SWSP:
index: 85
encoding: 0b1100000000000010
mask: 0b1110000000000011
size: 16
branch: false
delay: 1
- DII:
DII:
index: 86
encoding: 0b0000000000000000
mask: 0b1111111111111111
attributes: [[name:no_cont]]
size: 16
branch: false
delay: 1

View File

@ -0,0 +1,650 @@
RV32I:
ADD:
branch: false
delay: 1
encoding: 51
index: 27
mask: 4261441663
size: 32
ADDI:
branch: false
delay: 1
encoding: 19
index: 18
mask: 28799
size: 32
AND:
branch: false
delay: 1
encoding: 28723
index: 36
mask: 4261441663
size: 32
ANDI:
branch: false
delay: 1
encoding: 28691
index: 23
mask: 28799
size: 32
AUIPC:
branch: false
delay: 1
encoding: 23
index: 1
mask: 127
size: 32
BEQ:
branch: true
delay:
- 1
- 2
encoding: 99
index: 4
mask: 28799
size: 32
BGE:
branch: true
delay:
- 1
- 2
encoding: 20579
index: 7
mask: 28799
size: 32
BGEU:
branch: true
delay:
- 1
- 2
encoding: 28771
index: 9
mask: 28799
size: 32
BLT:
branch: true
delay:
- 1
- 2
encoding: 16483
index: 6
mask: 28799
size: 32
BLTU:
branch: true
delay:
- 1
- 2
encoding: 24675
index: 8
mask: 28799
size: 32
BNE:
branch: true
delay:
- 1
- 2
encoding: 4195
index: 5
mask: 28799
size: 32
EBREAK:
attributes:
- - name:no_cont
branch: false
delay: 3
encoding: 1048691
index: 39
mask: 4294967295
size: 32
ECALL:
attributes:
- - name:no_cont
branch: false
delay: 1
encoding: 115
index: 38
mask: 4294967295
size: 32
FENCE:
branch: false
delay: 1
encoding: 15
index: 37
mask: 28799
size: 32
JAL:
branch: true
delay: 2
encoding: 111
index: 2
mask: 127
size: 32
JALR:
branch: true
delay: 2
encoding: 103
index: 3
mask: 28799
size: 32
LB:
branch: false
delay: 2
encoding: 3
index: 10
mask: 28799
size: 32
LBU:
branch: false
delay: 2
encoding: 16387
index: 13
mask: 28799
size: 32
LH:
branch: false
delay: 2
encoding: 4099
index: 11
mask: 28799
size: 32
LHU:
branch: false
delay: 2
encoding: 20483
index: 14
mask: 28799
size: 32
LUI:
branch: false
delay: 1
encoding: 55
index: 0
mask: 127
size: 32
LW:
branch: false
delay: 2
encoding: 8195
index: 12
mask: 28799
size: 32
MRET:
attributes:
- - name:no_cont
branch: false
delay: 2
encoding: 807403635
index: 40
mask: 4294967295
size: 32
OR:
branch: false
delay: 1
encoding: 24627
index: 35
mask: 4261441663
size: 32
ORI:
branch: false
delay: 1
encoding: 24595
index: 22
mask: 28799
size: 32
SB:
branch: false
delay: 1
encoding: 35
index: 15
mask: 28799
size: 32
SH:
branch: false
delay: 1
encoding: 4131
index: 16
mask: 28799
size: 32
SLL:
branch: false
delay: X_24:20
encoding: 4147
index: 29
mask: 4261441663
size: 32
SLLI:
branch: false
delay: u_24:20
encoding: 4115
index: 24
mask: 4261441663
size: 32
SLT:
branch: false
delay: 1
encoding: 8243
index: 30
mask: 4261441663
size: 32
SLTI:
branch: false
delay: 1
encoding: 8211
index: 19
mask: 28799
size: 32
SLTIU:
branch: false
delay: 1
encoding: 12307
index: 20
mask: 28799
size: 32
SLTU:
branch: false
delay: 1
encoding: 12339
index: 31
mask: 4261441663
size: 32
SRA:
branch: false
delay: X_24:20
encoding: 1073762355
index: 34
mask: 4261441663
size: 32
SRAI:
branch: false
delay: u_24:20
encoding: 1073762323
index: 26
mask: 4261441663
size: 32
SRL:
branch: false
delay: X_24:20
encoding: 20531
index: 33
mask: 4261441663
size: 32
SRLI:
branch: false
delay: u_24:20
encoding: 20499
index: 25
mask: 4261441663
size: 32
SUB:
branch: false
delay: 1
encoding: 1073741875
index: 28
mask: 4261441663
size: 32
SW:
branch: false
delay: 1
encoding: 8227
index: 17
mask: 28799
size: 32
WFI:
branch: false
delay: 1
encoding: 273678451
index: 41
mask: 4294967295
size: 32
XOR:
branch: false
delay: 1
encoding: 16435
index: 32
mask: 4261441663
size: 32
XORI:
branch: false
delay: 1
encoding: 16403
index: 21
mask: 28799
size: 32
RV32M:
DIV:
branch: false
delay: 33
encoding: 33570867
index: 53
mask: 4261441663
size: 32
DIVU:
branch: false
delay: 33
encoding: 33574963
index: 54
mask: 4261441663
size: 32
MUL:
branch: false
delay: 32
encoding: 33554483
index: 49
mask: 4261441663
size: 32
MULH:
branch: false
delay: 32
encoding: 33558579
index: 50
mask: 4261441663
size: 32
MULHSU:
branch: false
delay: 32
encoding: 33562675
index: 51
mask: 4261441663
size: 32
MULHU:
branch: false
delay: 32
encoding: 33566771
index: 52
mask: 4261441663
size: 32
REM:
branch: false
delay: 33
encoding: 33579059
index: 55
mask: 4261441663
size: 32
REMU:
branch: false
delay: 33
encoding: 33583155
index: 56
mask: 4261441663
size: 32
Zca:
C__ADD:
branch: false
delay: 1
encoding: 36866
index: 82
mask: 61443
size: 16
C__ADDI:
branch: false
delay: 1
encoding: 1
index: 60
mask: 57347
size: 16
C__ADDI16SP:
branch: false
delay: 1
encoding: 24833
index: 65
mask: 61315
size: 16
C__ADDI4SPN:
branch: false
delay: 1
encoding: 0
index: 57
mask: 57347
size: 16
C__AND:
branch: false
delay: 1
encoding: 35937
index: 73
mask: 64611
size: 16
C__ANDI:
branch: false
delay: 1
encoding: 34817
index: 69
mask: 60419
size: 16
C__BEQZ:
branch: true
delay:
- 1
- 2
encoding: 49153
index: 75
mask: 57347
size: 16
C__BNEZ:
branch: true
delay:
- 1
- 2
encoding: 57345
index: 76
mask: 57347
size: 16
C__EBREAK:
branch: false
delay: 3
encoding: 36866
index: 84
mask: 65535
size: 16
C__J:
branch: true
delay: 1
encoding: 40961
index: 74
mask: 57347
size: 16
C__JAL:
attributes:
- - name:enable
- value:1
branch: true
delay: 1
encoding: 8193
index: 62
mask: 57347
size: 16
C__JALR:
branch: true
delay: 1
encoding: 36866
index: 83
mask: 61567
size: 16
C__JR:
branch: true
delay: 1
encoding: 32770
index: 80
mask: 61567
size: 16
C__LI:
branch: false
delay: 1
encoding: 16385
index: 63
mask: 57347
size: 16
C__LUI:
branch: false
delay: 1
encoding: 24577
index: 64
mask: 57347
size: 16
C__LW:
branch: false
delay: 2
encoding: 16384
index: 58
mask: 57347
size: 16
C__LWSP:
branch: false
delay: 2
encoding: 16386
index: 78
mask: 57347
size: 16
C__MV:
branch: false
delay: 1
encoding: 32770
index: 79
mask: 61443
size: 16
C__NOP:
branch: false
delay: 1
encoding: 1
index: 61
mask: 61315
size: 16
C__OR:
branch: false
delay: 1
encoding: 35905
index: 72
mask: 64611
size: 16
C__SLLI:
attributes:
- - name:enable
- value:1
branch: false
delay: u_12:12*16+u_6:2
encoding: 2
index: 77
mask: 61443
size: 16
C__SRAI:
attributes:
- - name:enable
- value:1
branch: false
delay: u_12:12*16+u_6:2
encoding: 33793
index: 68
mask: 64515
size: 16
C__SRLI:
attributes:
- - name:enable
- value:1
branch: false
delay: u_12:12*16+u_6:2
encoding: 32769
index: 67
mask: 64515
size: 16
C__SUB:
branch: false
delay: 1
encoding: 35841
index: 70
mask: 64611
size: 16
C__SW:
branch: false
delay: 1
encoding: 49152
index: 59
mask: 57347
size: 16
C__SWSP:
branch: false
delay: 1
encoding: 49154
index: 85
mask: 57347
size: 16
C__XOR:
branch: false
delay: 1
encoding: 35873
index: 71
mask: 64611
size: 16
DII:
branch: false
delay: 1
encoding: 0
index: 86
mask: 65535
size: 16
__reserved_clui:
branch: false
delay: 1
encoding: 24577
index: 66
mask: 61567
size: 16
__reserved_cmv:
branch: false
delay: 1
encoding: 32770
index: 81
mask: 65535
size: 16
Zicsr:
CSRRC:
branch: false
delay: 1
encoding: 12403
index: 44
mask: 28799
size: 32
CSRRCI:
branch: false
delay: 1
encoding: 28787
index: 47
mask: 28799
size: 32
CSRRS:
branch: false
delay: 1
encoding: 8307
index: 43
mask: 28799
size: 32
CSRRSI:
branch: false
delay: 1
encoding: 24691
index: 46
mask: 28799
size: 32
CSRRW:
branch: false
delay: 1
encoding: 4211
index: 42
mask: 28799
size: 32
CSRRWI:
branch: false
delay: 1
encoding: 20595
index: 45
mask: 28799
size: 32
Zifencei:
FENCE_I:
attributes:
- - name:flush
branch: false
delay: 1
encoding: 4111
index: 48
mask: 28799
size: 32

View File

@ -19,7 +19,7 @@ setenv CXX $COWAREHOME/SLS/linux/common/bin/g++
cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \
-DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT}
cmake --build build/PA --target install -j16
cd dbt-rise-tgc/contrib
cd dbt-rise-tgc/contrib/pa
# import the TGC core itself
pct tgc_import_tb.tcl
```
@ -37,7 +37,7 @@ export CXX=$COWAREHOME/SLS/linux/common/bin/g++
cmake -S . -B build/PA -DCMAKE_BUILD_TYPE=Debug -DUSE_CWR_SYSTEMC=ON -DBUILD_SHARED_LIBS=ON \
-DCODEGEN=OFF -DCMAKE_INSTALL_PREFIX=${TGFS_INSTALL_ROOT}
cmake --build build/PA --target install -j16
cd dbt-rise-tgc/contrib
cd dbt-rise-tgc/contrib/pa
# import the TGC core itself
pct tgc_import_tb.tcl
```

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,8 +1,8 @@
import "ISA/RV32I.core_desc"
import "ISA/RVI.core_desc"
import "ISA/RVM.core_desc"
import "ISA/RVC.core_desc"
Core TGC_C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
Core TGC5C provides RV32I, Zicsr, Zifencei, RV32M, RV32IC {
architectural_state {
XLEN=32;
// definitions for the architecture wrapper

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
* Copyright (C) 2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -37,6 +37,7 @@ def getRegisterSizes(){
return regs
}
%>
// clang-format off
#include "${coreDef.name.toLowerCase()}.h"
#include "util/ities.h"
#include <util/logging.h>
@ -46,10 +47,10 @@ def getRegisterSizes(){
using namespace iss::arch;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
constexpr std::array<const char*, ${registers.size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
constexpr std::array<const uint32_t, ${getRegisterSizes().size}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
constexpr std::array<const char*, ${registers.size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_names;
constexpr std::array<const char*, ${registers.size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_aliases;
constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_bit_widths;
constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offsets;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() = default;
@ -73,4 +74,4 @@ uint8_t *${coreDef.name.toLowerCase()}::get_regs_base_ptr() {
${coreDef.name.toLowerCase()}::phys_addr_t ${coreDef.name.toLowerCase()}::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<${coreDef.name.toLowerCase()}>::addr_mask);
}
// clang-format on

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2021 MINRES Technologies GmbH
* Copyright (C) 2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,11 +30,21 @@
*
*******************************************************************************/
<%
def nativeTypeSize(int size){
if(size<=8) return 8; else if(size<=16) return 16; else if(size<=32) return 32; else return 64;
def nativeSize(int size){
if(size<=8) return 8;
if(size<=16) return 16;
if(size<=32) return 32;
if(size<=64) return 64;
if(size<=128) return 128;
if(size<=256) return 256;
if(size<=512) return 512;
if(size<=1024) return 1024;
if(size<=2048) return 2048;
if(size<=4096) return 4096;
throw new IllegalArgumentException("Unsupported size in nativeSize in CORENAME.h.gtl");
}
def getRegisterSizes(){
def regs = registers.collect{nativeTypeSize(it.size)}
def regs = registers.collect{nativeSize(it.size)}
regs+=[32,32, 64, 64, 64, 32, 32] // append TRAP_STATE, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
return regs
}
@ -47,20 +57,14 @@ def getRegisterOffsets(){
}
return offsets
}
def byteSize(int size){
if(size<=8) return 8;
if(size<=16) return 16;
if(size<=32) return 32;
if(size<=64) return 64;
return 128;
}
def getCString(def val){
return val.toString()+'ULL'
}
%>
#ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_
// clang-format off
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
@ -75,15 +79,17 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
constexpr static char const* const core_type = "${coreDef.name}";
static constexpr std::array<const char*, ${registers.size}> reg_names{
{"${registers.collect{it.name}.join('", "')}"}};
static constexpr std::array<const char*, ${registers.size()}> reg_names{
{"${registers.collect{it.name.toLowerCase()}.join('", "')}"}};
static constexpr std::array<const char*, ${registers.size}> reg_aliases{
{"${registers.collect{it.alias}.join('", "')}"}};
static constexpr std::array<const char*, ${registers.size()}> reg_aliases{
{"${registers.collect{it.alias.toLowerCase()}.join('", "')}"}};
enum constants {${constants.collect{c -> c.name+"="+getCString(c.value)}.join(', ')}};
constexpr static unsigned FP_REGS_SIZE = ${constants.find {it.name=='FLEN'}?.value?:0};
constexpr static unsigned V_REGS_SIZE = ${constants.find {it.name=='VLEN'}?.value?:0};
enum reg_e {
${registers.collect{it.name}.join(', ')}, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
@ -99,17 +105,17 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, ${getRegisterSizes().size}> reg_bit_widths{
static constexpr std::array<const uint32_t, ${getRegisterSizes().size()}> reg_bit_widths{
{${getRegisterSizes().join(',')}}};
static constexpr std::array<const uint32_t, ${getRegisterOffsets().size}> reg_byte_offsets{
static constexpr std::array<const uint32_t, ${getRegisterOffsets().size()}> reg_byte_offsets{
{${getRegisterOffsets().join(',')}}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS };
enum mem_type_e { ${spaces.collect{it.name}.join(', ')} };
enum mem_type_e { ${spaces.collect{it.name}.join(', ')}, IMEM = MEM };
enum class opcode_e {<%instructions.eachWithIndex{instr, index -> %>
${instr.instruction.name} = ${index},<%}%>
@ -131,8 +137,6 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
uint8_t* get_regs_base_ptr() override;
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline uint64_t stop_code() { return interrupt_sim; }
@ -141,20 +145,20 @@ struct ${coreDef.name.toLowerCase()}: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline uint32_t get_last_branch() { return reg.last_branch; }
#pragma pack(push, 1)
struct ${coreDef.name}_regs {<%
registers.each { reg -> if(reg.size>0) {%>
uint${byteSize(reg.size)}_t ${reg.name} = 0;<%
registers.each { reg -> if(reg.size>64) {%>
uint8_t ${reg.name}[${reg.size/8}] = {0};<%
}else if(reg.size>0) {%>
uint${nativeSize(reg.size)}_t ${reg.name} = 0;<%
}}%>
uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0;
uint64_t cycle = 0;
uint64_t instret = 0;
uint32_t instruction = 0;
uint32_t last_branch = 0;
uint64_t icount = 0; // counts number of instructions undisturbed
uint64_t cycle = 0; // counts number of cycles, in functional mode equals icount
uint64_t instret = 0; // counts number of instructions, can be reset via CSR write
uint32_t instruction = 0; // holds op code of currently executed instruction
uint32_t last_branch = 0; // indicates if last branch was taken
} reg;
#pragma pack(pop)
std::array<address_type, 4> addr_mode;
@ -168,9 +172,35 @@ if(fcsr != null) {%>
<%} else { %>
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
<%}
def vstart = registers.find {it.name=='vstart'}
def vl = registers.find {it.name=='vl'}
def vtype = registers.find {it.name=='vtype'}
def vxsat = registers.find {it.name=='vxsat'}
def vxrm = registers.find {it.name=='vxrm'}
if(vtype != null) {%>
uint${vstart.size}_t get_vstart(){return reg.vstart;}
void set_vstart(uint${vstart.size}_t val){reg.vstart = val;}
uint${vl.size}_t get_vl(){return reg.vl;}
uint${vtype.size}_t get_vtype(){return reg.vtype;}
uint${vxsat.size}_t get_vxsat(){return reg.vxsat;}
void set_vxsat(uint${vxsat.size}_t val){reg.vxsat = val;}
uint${vxrm.size}_t get_vxrm(){return reg.vxrm;}
void set_vxrm(uint${vxrm.size}_t val){reg.vxrm = val;}
<%} else { %>
uint32_t get_vstart(){return 0;}
void set_vstart(uint32_t val){}
uint32_t get_vl(){return 0;}
uint32_t get_vtype(){return 0;}
uint32_t get_vxsat(){return 0;}
void set_vxsat(uint32_t val){}
uint32_t get_vxrm(){return 0;}
void set_vxrm(uint32_t val){}
<%}%>
};
}
}
#endif /* _${coreDef.name.toUpperCase()}_H_ */
// clang-format on

View File

@ -1,86 +0,0 @@
#include "${coreDef.name.toLowerCase()}.h"
#include <vector>
#include <array>
#include <cstdlib>
#include <algorithm>
namespace iss {
namespace arch {
namespace {
// according to
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
#ifdef __GCC__
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
#elif __cplusplus < 201402L
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
#else
constexpr size_t bit_count(uint32_t u) {
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}
#endif
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_desriptor {
size_t length;
uint32_t value;
uint32_t mask;
opcode_e op;
};
const std::array<instruction_desriptor, ${instructions.size}> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
{${instr.length}, ${instr.encoding}, ${instr.mask}, opcode_e::${instr.instruction.name}},<%}%>
}};
}
template<>
struct instruction_decoder<${coreDef.name.toLowerCase()}> {
using opcode_e = traits<${coreDef.name.toLowerCase()}>::opcode_e;
using code_word_t=traits<${coreDef.name.toLowerCase()}>::code_word_t;
struct instruction_pattern {
uint32_t value;
uint32_t mask;
opcode_e id;
};
std::array<std::vector<instruction_pattern>, 4> qlut;
template<typename T>
unsigned decode_instruction(T);
instruction_decoder() {
for (auto instr : instr_descr) {
auto quadrant = instr.value & 0x3;
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
}
for(auto& lut: qlut){
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
return bit_count(a.mask) < bit_count(b.mask);
});
}
}
};
template<>
unsigned instruction_decoder<${coreDef.name.toLowerCase()}>::decode_instruction<traits<${coreDef.name.toLowerCase()}>::code_word_t>(traits<${coreDef.name.toLowerCase()}>::code_word_t instr){
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
return !((instr&e.mask) ^ e.value );
});
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
}
std::unique_ptr<instruction_decoder<${coreDef.name.toLowerCase()}>> traits<${coreDef.name.toLowerCase()}>::get_decoder(){
return std::make_unique<instruction_decoder<${coreDef.name.toLowerCase()}>>();
}
}
}

View File

@ -8,9 +8,10 @@
instrGroups[groupName]+=it;
}
instrGroups
}%><%getInstructionGroups().each{name, instrList -> %>
${name}: <% instrList.findAll{!it.instruction.name.startsWith("__")}.each { %>
- ${it.instruction.name}:
}%><%int index = 0; getInstructionGroups().each{name, instrList -> %>
${name}: <% instrList.each { %>
${it.instruction.name}:
index: ${index++}
encoding: ${it.encoding}
mask: ${it.mask}<%if(it.attributes.size) {%>
attributes: ${it.attributes}<%}%>

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2023 MINRES Technologies GmbH
* Copyright (C) 2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,46 +29,103 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include "iss_factory.h"
// clang-format off
#include <sysc/iss_factory.h>
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include "sc_core_adapter.h"
#include "core_complex.h"
#include <sysc/sc_core_adapter.h>
#include <sysc/core_complex.h>
#include <array>
<%
def array_count = coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e"? 3 : 2;
%>
namespace iss {
namespace interp {
using namespace sysc;
volatile std::array<bool, 2> ${coreDef.name.toLowerCase()}_init = {
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
}),
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|interp", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#if defined(WITH_LLVM)
namespace llvm {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
}),
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|llvm", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
#if defined(WITH_TCC)
namespace tcc {
using namespace sysc;
volatile std::array<bool, 2> ${coreDef.name.toLowerCase()}_init = {
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
}),
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex*>(data);
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|tcc", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
#if defined(WITH_ASMJIT)
namespace asmjit {
using namespace sysc;
volatile std::array<bool, ${array_count}> ${coreDef.name.toLowerCase()}_init = {
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_m_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
}),
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%if(coreDef.name.toLowerCase()=="tgc5d" || coreDef.name.toLowerCase()=="tgc5e") {%>,
iss_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p_clic_pmp|asmjit", [](unsigned gdb_port, void* data) -> iss_factory::base_t {
auto* cc = reinterpret_cast<sysc::tgfs::core_complex_if*>(data);
auto* cpu = new sc_core_adapter<arch::riscv_hart_mu_p<arch::${coreDef.name.toLowerCase()}, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_EXT_N | iss::arch::FEAT_CLIC)>>(cc);
return {sysc::sc_cpu_ptr{cpu}, vm_ptr{create(static_cast<arch::${coreDef.name.toLowerCase()}*>(cpu), gdb_port)}};
})<%}%>
};
}
#endif
}
// clang-format on

View File

@ -0,0 +1,390 @@
/*******************************************************************************
* Copyright (C) 2017-2024 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
*******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/asmjit/vm_base.h>
#include <asmjit/asmjit.h>
#include <util/logging.h>
#include <iss/instruction_decoder.h>
<%def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%>
#include <vm/fp_functions.h><%}
def aes = functions.find { it.contains('aes') }
if(aes != null) {%>
#include <vm/aes_sbox.h>
<%}%>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
#include <fmt/format.h>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
#ifndef _MSC_VER
using int128_t = __int128;
using uint128_t = unsigned __int128;
namespace std {
template <> struct make_unsigned<__int128> { typedef unsigned __int128 type; };
template <> class __make_unsigned_selector<__int128 unsigned, false, false> {
public:
typedef unsigned __int128 __type;
};
template <> struct is_signed<int128_t> { static constexpr bool value = true; };
template <> struct is_signed<uint128_t> { static constexpr bool value = false; };
template <> struct is_unsigned<int128_t> { static constexpr bool value = false; };
template <> struct is_unsigned<uint128_t> { static constexpr bool value = true; };
} // namespace std
#endif
namespace iss {
namespace asmjit {
namespace ${coreDef.name.toLowerCase()} {
using namespace ::asmjit;
using namespace iss::arch;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::asmjit::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::asmjit::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using mem_type_e = typename super::mem_type_e;
using addr_t = typename super::addr_t;
vm_impl();
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true;
if (vm_base<ARCH>::tgt_adapter == nullptr)
vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm_base<ARCH>::tgt_adapter;
}
protected:
using super::get_ptr_for;
using super::get_reg_for;
using super::get_reg_for_Gp;
using super::load_reg_from_mem;
using super::load_reg_from_mem_Gp;
using super::write_reg_to_mem;
using super::gen_read_mem;
using super::gen_write_mem;
using super::gen_leave;
using super::gen_sync;
using this_class = vm_impl<ARCH>;
using compile_func = continuation_e (this_class::*)(virt_addr_t&, code_word_t, jit_holder&);
continuation_e gen_single_inst_behavior(virt_addr_t&, jit_holder&) override;
enum globals_e {TVAL = 0, GLOBALS_SIZE};
void gen_block_prologue(jit_holder& jh) override;
void gen_block_epilogue(jit_holder& jh) override;
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
<%if(fcsr != null) {%>
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
<%}%>
void gen_instr_prologue(jit_holder& jh);
void gen_instr_epilogue(jit_holder& jh);
inline void gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause);
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type> void gen_set_tval(jit_holder& jh, T new_tval) ;
void gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) ;
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
inline void raise(uint16_t trap_id, uint16_t cause){
auto trap_val = 0x80ULL << 24 | (cause << 16) | trap_id;
this->core.reg.trap_state = trap_val;
}
<%functions.each{ it.eachLine { %>
${it}<%}
}%>
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_descriptor {
uint32_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
}};
//needs to be declared after instr_descr
decoder instr_decoder;
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */
continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){
uint64_t PC = pc.val;
<%instr.fields.eachLine{%>${it}
<%}%>if(this->disass_enabled){
/* generate disass */
<%instr.disass.eachLine{%>
${it}<%}%>
InvokeNode* call_print_disass;
char* mnemonic_ptr = strdup(mnemonic.c_str());
jh.disass_collection.push_back(mnemonic_ptr);
jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build<void, void *, uint64_t, char *>());
call_print_disass->setArg(0, jh.arch_if_ptr);
call_print_disass->setArg(1, pc.val);
call_print_disass->setArg(2, mnemonic_ptr);
}
x86::Compiler& cc = jh.cc;
cc.comment(fmt::format("${instr.name}_{:#x}:",pc.val).c_str());
gen_sync(jh, PRE_SYNC, ${idx});
mov(cc, jh.pc, pc.val);
gen_set_tval(jh, instr);
pc = pc+${instr.length/8};
mov(cc, jh.next_pc, pc.val);
gen_instr_prologue(jh);
/*generate behavior*/
<%instr.behavior.eachLine{%>${it}
<%}%>
gen_sync(jh, POST_SYNC, ${idx});
gen_instr_epilogue(jh);
return returnValue;
}
<%}%>
/****************************************************************************
* end opcode definitions
****************************************************************************/
continuation_e illegal_instruction(virt_addr_t &pc, code_word_t instr, jit_holder& jh ) {
x86::Compiler& cc = jh.cc;
if(this->disass_enabled){
auto mnemonic = std::string("illegal_instruction");
InvokeNode* call_print_disass;
char* mnemonic_ptr = strdup(mnemonic.c_str());
jh.disass_collection.push_back(mnemonic_ptr);
jh.cc.invoke(&call_print_disass, &print_disass, FuncSignature::build<void, void *, uint64_t, char *>());
call_print_disass->setArg(0, jh.arch_if_ptr);
call_print_disass->setArg(1, pc.val);
call_print_disass->setArg(2, mnemonic_ptr);
}
cc.comment(fmt::format("illegal_instruction{:#x}:",pc.val).c_str());
gen_sync(jh, PRE_SYNC, instr_descr.size());
mov(cc, jh.pc, pc.val);
gen_set_tval(jh, instr);
pc = pc + ((instr & 3) == 3 ? 4 : 2);
mov(cc, jh.next_pc, pc.val);
gen_instr_prologue(jh);
gen_raise(jh, 0, 2);
gen_sync(jh, POST_SYNC, instr_descr.size());
gen_instr_epilogue(jh);
return ILLEGAL_INSTR;
}
};
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id)
, instr_decoder([this]() {
std::vector<generic_instruction_descriptor> g_instr_descr;
g_instr_descr.reserve(instr_descr.size());
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
g_instr_descr.push_back(new_instr_descr);
}
return std::move(g_instr_descr);
}()) {}
template <typename ARCH>
continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, jit_holder& jh) {
enum {TRAP_ID=1<<16};
code_word_t instr = 0;
phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&instr;
auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok)
return ILLEGAL_FETCH;
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
return JUMP_TO_SELF;
uint32_t inst_index = instr_decoder.decode_instr(instr);
compile_func f = nullptr;
if(inst_index < instr_descr.size())
f = instr_descr[inst_index].op;
if (f == nullptr)
f = &this_class::illegal_instruction;
return (this->*f)(pc, instr, jh);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_prologue(jit_holder& jh) {
auto& cc = jh.cc;
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
mov(cc, get_ptr_for(jh, traits::PENDING_TRAP), current_trap_state);
cc.comment("//Instruction prologue end");
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_epilogue(jit_holder& jh) {
auto& cc = jh.cc;
cc.comment("//Instruction epilogue begin");
x86_reg_t current_trap_state = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
cmp(cc, current_trap_state, 0);
cc.jne(jh.trap_entry);
cc.inc(get_ptr_for(jh, traits::ICOUNT));
cc.inc(get_ptr_for(jh, traits::CYCLE));
cc.comment("//Instruction epilogue end");
}
template <typename ARCH>
void vm_impl<ARCH>::gen_block_prologue(jit_holder& jh){
jh.pc = load_reg_from_mem_Gp(jh, traits::PC);
jh.next_pc = load_reg_from_mem_Gp(jh, traits::NEXT_PC);
jh.globals.resize(GLOBALS_SIZE);
jh.globals[TVAL] = get_reg_Gp(jh.cc, 64, false);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_block_epilogue(jit_holder& jh){
x86::Compiler& cc = jh.cc;
cc.comment("//block epilogue begin");
cc.ret(jh.next_pc);
cc.bind(jh.trap_entry);
this->write_back(jh);
x86::Gp current_trap_state = get_reg_for_Gp(cc, traits::TRAP_STATE);
mov(cc, current_trap_state, get_ptr_for(jh, traits::TRAP_STATE));
x86::Gp current_pc = get_reg_for_Gp(cc, traits::PC);
mov(cc, current_pc, get_ptr_for(jh, traits::PC));
InvokeNode* call_enter_trap;
cc.invoke(&call_enter_trap, &enter_trap, FuncSignature::build<uint64_t, void*, uint64_t, uint64_t, uint64_t>());
call_enter_trap->setArg(0, jh.arch_if_ptr);
call_enter_trap->setArg(1, current_trap_state);
call_enter_trap->setArg(2, current_pc);
call_enter_trap->setArg(3, jh.globals[TVAL]);
x86_reg_t current_next_pc = get_reg_for(cc, traits::NEXT_PC);
mov(cc, current_next_pc, get_ptr_for(jh, traits::NEXT_PC));
mov(cc, jh.next_pc, current_next_pc);
mov(cc, get_ptr_for(jh, traits::LAST_BRANCH), static_cast<int>(UNKNOWN_JUMP));
cc.ret(jh.next_pc);
}
template <typename ARCH>
inline void vm_impl<ARCH>::gen_raise(jit_holder& jh, uint16_t trap_id, uint16_t cause) {
auto& cc = jh.cc;
auto tmp1 = get_reg_for(cc, traits::TRAP_STATE);
mov(cc, tmp1, 0x80ULL << 24 | (cause << 16) | trap_id);
mov(cc, get_ptr_for(jh, traits::TRAP_STATE), tmp1);
cc.jmp(jh.trap_entry);
}
template <typename ARCH>
template <typename T, typename>
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, T new_tval) {
mov(jh.cc, jh.globals[TVAL], new_tval);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_set_tval(jit_holder& jh, x86_reg_t _new_tval) {
if(nonstd::holds_alternative<x86::Gp>(_new_tval)) {
x86::Gp new_tval = nonstd::get<x86::Gp>(_new_tval);
if(new_tval.size() < 8)
new_tval = gen_ext_Gp(jh.cc, new_tval, 64, false);
mov(jh.cc, jh.globals[TVAL], new_tval);
} else {
throw std::runtime_error("Variant not supported in gen_set_tval");
}
}
} // namespace tgc5c
template <>
std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreDef.name.toLowerCase()} *core, unsigned short port, bool dump) {
auto ret = new ${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace asmjit
} // namespace iss
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|asmjit", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new asmjit::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* Copyright (C) 2017-2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,14 +29,19 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
// vm_base needs to be included before gdb_session as termios.h (via boost and gdb_server) has a define which clashes with a variable
// name in ConstantRange.h
#include <iss/llvm/vm_base.h>
#include <iss/iss.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/llvm/vm_base.h>
#include <iss/instruction_decoder.h>
#include <util/logging.h>
<%def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%>
#include <vm/fp_functions.h><%}%>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
@ -58,6 +63,7 @@ using namespace iss::debugger;
template <typename ARCH> class vm_impl : public iss::llvm::vm_base<ARCH> {
public:
using traits = arch::traits<ARCH>;
using super = typename iss::llvm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
@ -80,237 +86,286 @@ public:
protected:
using vm_base<ARCH>::get_reg_ptr;
inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
<%if(fcsr != null) {%>
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
<%}%>
template <typename T> inline ConstantInt *size(T type) {
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
}
void setup_module(Module* m) override {
super::setup_module(m);
iss::llvm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE, traits<ARCH>::XLEN);
iss::llvm::fp_impl::add_fp_functions_2_module(m, traits::FP_REGS_SIZE, traits::XLEN);
}
inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
}
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, BasicBlock *) override;
void gen_leave_behavior(BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
void gen_leave_trap(unsigned lvl);
void gen_wait(unsigned type);
void set_tval(uint64_t new_tval);
void set_tval(Value* new_tval);
void gen_trap_behavior(BasicBlock *) override;
void gen_trap_check(BasicBlock *bb);
void gen_instr_prologue();
void gen_instr_epilogue(BasicBlock *bb);
inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(this->get_typeptr(i), get_reg_ptr(i), false);
}
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN));
Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits::XLEN, pc.val),
this->get_type(traits::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
}
// some compile time constants
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
enum { LUT_SIZE = 1 << util::bit_count(static_cast<uint64_t>(EXTR_MASK32)), LUT_SIZE_C = 1 << util::bit_count(static_cast<uint64_t>(EXTR_MASK16)) };
using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr,
BasicBlock *bb);
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
template<unsigned W, typename U, typename S = typename std::make_signed<U>::type>
inline S sext(U from) {
auto mask = (1ULL<<W) - 1;
auto sign_mask = 1ULL<<(W-1);
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
<%functions.each{ it.eachLine { %>
${it}<%}
}
if(fcsr != null) {%>
Value* NaNBox16(BasicBlock* bb, Value* NaNBox16_val){
if(static_cast<uint32_t>(traits::FLEN) == 16)
return this->gen_ext(NaNBox16_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 32, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 16), this->gen_ext(NaNBox16_val, traits::FLEN))), traits::FLEN, false);
}
Value* NaNBox32(BasicBlock* bb, Value* NaNBox32_val){
if(static_cast<uint32_t>(traits::FLEN) == 32)
return this->gen_ext(NaNBox32_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 64, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 32), this->gen_ext(NaNBox32_val, traits::FLEN))), traits::FLEN, false);
}
Value* NaNBox64(BasicBlock* bb, Value* NaNBox64_val){
if(static_cast<uint32_t>(traits::FLEN) == 64)
return this->gen_ext(NaNBox64_val, traits::FLEN, false);
auto box = this->builder.CreateNot((this->gen_ext(0, 128, false)));
return this->gen_ext((this->builder.CreateOr(this->builder.CreateShl(this->gen_ext(box, traits::FLEN), 64), this->gen_ext(NaNBox64_val, traits::FLEN))), traits::FLEN, false);
}
<%}%>
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct InstructionDesriptor {
size_t length;
struct instruction_descriptor {
uint32_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
const std::array<InstructionDesriptor, ${instructions.size}> instr_descr = {{
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
/* instruction ${instr.instruction.name} */
{${instr.length}, ${instr.value}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
}};
//needs to be declared after instr_descr
decoder instr_decoder;
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%>
${it}<%}%>
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
uint64_t PC = pc.val;
<%instr.fields.eachLine{%>${it}
<%}%>if(this->disass_enabled){
/* generate console output when executing the command */<%instr.disass.eachLine{%>
${it}<%}%>
std::vector<Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder.CreateGlobalStringPtr(mnemonic),
};
this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
}
bb->setName(fmt::format("${instr.name}_0x{:X}",pc.val));
this->gen_sync(PRE_SYNC,${idx});
this->gen_set_pc(pc, traits::PC);
this->set_tval(instr);
pc=pc+ ${instr.length/8};
this->gen_set_pc(pc, traits::NEXT_PC);
this->gen_instr_prologue();
/*generate behavior*/
<%instr.behavior.eachLine{%>${it}
<%}%>
this->gen_sync(POST_SYNC, ${idx});
this->gen_instr_epilogue(bb);
this->builder.CreateBr(bb);
return returnValue;
}
<%}%>
/****************************************************************************
* end opcode definitions
****************************************************************************/
std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits<ARCH>::NEXT_PC), get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true);
std::tuple<continuation_e, BasicBlock *> illegal_instruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
if(this->disass_enabled){
auto mnemonic = std::string("illegal_instruction");
std::vector<Value*> args {
this->core_ptr,
this->gen_const(64, pc.val),
this->builder.CreateGlobalStringPtr(mnemonic),
};
this->builder.CreateCall(this->mod->getFunction("print_disass"), args);
}
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), true),
get_reg_ptr(traits::PC), true);
this->builder.CreateStore(
this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits<ARCH>::ICOUNT), get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->builder.CreateAdd(this->builder.CreateLoad(this->get_typeptr(traits::ICOUNT), get_reg_ptr(traits::ICOUNT), true),
this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true);
get_reg_ptr(traits::ICOUNT), true);
pc = pc + ((instr & 3) == 3 ? 4 : 2);
this->set_tval(instr);
this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk);
return std::make_tuple(BRANCH, nullptr);
bb = this->leave_blk;
this->gen_instr_epilogue(bb);
this->builder.CreateBr(bb);
return std::make_tuple(ILLEGAL_INSTR, nullptr);
}
};
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
volatile CODE_WORD x = instr;
instr = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data();
qlut[1] = lut_01.data();
qlut[2] = lut_10.data();
qlut[3] = lut_11.data();
for (auto instr : instr_descr) {
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
}
}
: vm_base<ARCH>(core, core_id, cluster_id)
, instr_decoder([this]() {
std::vector<generic_instruction_descriptor> g_instr_descr;
g_instr_descr.reserve(instr_descr.size());
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
g_instr_descr.push_back(new_instr_descr);
}
return std::move(g_instr_descr);
}()) {}
template <typename ARCH>
std::tuple<continuation_e, BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) {
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16};
code_word_t insn = 0;
// const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
code_word_t instr = 0;
// const typename traits::addr_t upper_bits = ~traits::PGMASK;
phys_addr_t paddr(pc);
auto *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc);
//TODO: re-add page handling
// if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
// auto res = this->core.read(paddr, 2, data);
// if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
// if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
// res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
// }
// } else {
auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
// }
if (insn == 0x0000006f || (insn&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack
++inst_cnt;
auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val];
auto *const data = (uint8_t *)&instr;
auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok)
return std::make_tuple(ILLEGAL_FETCH, nullptr);
if (instr == 0x0000006f || (instr&0xffff)==0xa001){
this->builder.CreateBr(this->leave_blk);
return std::make_tuple(JUMP_TO_SELF, nullptr);
}
uint32_t inst_index = instr_decoder.decode_instr(instr);
compile_func f = nullptr;
if(inst_index < instr_descr.size())
f = instr_descr[inst_index].op;
if (f == nullptr) {
f = &this_class::illegal_intruction;
f = &this_class::illegal_instruction;
}
return (this->*f)(pc, insn, this_block);
return (this->*f)(pc, instr, this_block);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
template <typename ARCH>
void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::NEXT_PC), get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
this->builder.CreateRet(this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC),get_reg_ptr(traits::NEXT_PC), false));
}
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
template <typename ARCH>
void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits::TRAP_STATE), true);
this->builder.CreateBr(this->trap_blk);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
template <typename ARCH>
void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(UNKNOWN_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
}
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
template <typename ARCH>
void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
this->builder.CreateCall(this->mod->getFunction("wait"), args);
}
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
template <typename ARCH>
inline void vm_impl<ARCH>::set_tval(uint64_t tval) {
auto tmp_tval = this->gen_const(64, tval);
this->set_tval(tmp_tval);
}
template <typename ARCH>
inline void vm_impl<ARCH>::set_tval(Value* new_tval) {
this->builder.CreateStore(this->gen_ext(new_tval, 64, false), this->tval);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::TRAP_STATE), get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::PC), get_reg_ptr(traits<ARCH>::PC), false))};
auto *trap_state_val = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
auto *cur_pc_val = this->builder.CreateLoad(this->get_typeptr(traits::PC), get_reg_ptr(traits::PC), true);
std::vector<Value *> args{this->core_ptr,
this->adj_to64(trap_state_val),
this->adj_to64(cur_pc_val),
this->adj_to64(this->builder.CreateLoad(this->get_type(64),this->tval))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::NEXT_PC), get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, static_cast<int>(UNKNOWN_JUMP)), get_reg_ptr(traits::LAST_BRANCH), false);
auto *trap_addr_val = this->builder.CreateLoad(this->get_typeptr(traits::NEXT_PC), get_reg_ptr(traits::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val);
}
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_prologue() {
auto* trap_val =
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::PENDING_TRAP), get_reg_ptr(arch::traits<ARCH>::PENDING_TRAP));
this->builder.CreateStore(trap_val, get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), false);
}
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
auto *v = this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::TRAP_STATE), get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
template <typename ARCH>
void vm_impl<ARCH>::gen_instr_epilogue(BasicBlock *bb) {
auto* target_bb = BasicBlock::Create(this->mod->getContext(), "", this->func, bb);
auto *v = this->builder.CreateLoad(this->get_typeptr(traits::TRAP_STATE), get_reg_ptr(traits::TRAP_STATE), true);
this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v,
ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1);
target_bb, this->trap_blk, 1);
this->builder.SetInsertPoint(target_bb);
// update icount
auto* icount_val = this->builder.CreateAdd(
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::ICOUNT), get_reg_ptr(arch::traits<ARCH>::ICOUNT)), this->gen_const(64U, 1));
this->builder.CreateStore(icount_val, get_reg_ptr(arch::traits<ARCH>::ICOUNT), false);
//increment cyclecount
auto* cycle_val = this->builder.CreateAdd(
this->builder.CreateLoad(this->get_typeptr(arch::traits<ARCH>::CYCLE), get_reg_ptr(arch::traits<ARCH>::CYCLE)), this->gen_const(64U, 1));
this->builder.CreateStore(cycle_val, get_reg_ptr(arch::traits<ARCH>::CYCLE), false);
}
} // namespace ${coreDef.name.toLowerCase()}
@ -324,24 +379,33 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
} // namespace llvm
} // namespace iss
#include <iss/factory.h>
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|llvm", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto* vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
auto vm = new llvm::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<std::function<void(arch_if*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*, arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t*)>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2020 MINRES Technologies GmbH
* Copyright (C) 2020-2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,7 +29,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
// clang-format off
#include <iss/arch/${coreDef.name.toLowerCase()}.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
@ -37,7 +37,10 @@
#include <iss/tcc/vm_base.h>
#include <util/logging.h>
#include <sstream>
#include <iss/instruction_decoder.h>
<%def fcsr = registers.find {it.name=='FCSR'}
if(fcsr != null) {%>
#include <vm/fp_functions.h><%}%>
#ifndef FMT_HEADER_ONLY
#define FMT_HEADER_ONLY
#endif
@ -80,16 +83,21 @@ protected:
using vm_base<ARCH>::get_reg_ptr;
using this_class = vm_impl<ARCH>;
using compile_ret_t = std::tuple<continuation_e>;
using compile_ret_t = continuation_e;
using compile_func = compile_ret_t (this_class::*)(virt_addr_t &pc, code_word_t instr, tu_builder&);
inline const char *name(size_t index){return traits::reg_aliases.at(index);}
<%
if(fcsr != null) {%>
inline const char *fname(size_t index){return index < 32?name(index+traits::F0):"illegal";}
<%}%>
void add_prologue(tu_builder& tu) override;
void setup_module(std::string m) override {
super::setup_module(m);
}
compile_ret_t gen_single_inst_behavior(virt_addr_t &, unsigned int &, tu_builder&) override;
compile_ret_t gen_single_inst_behavior(virt_addr_t &, tu_builder&) override;
void gen_trap_behavior(tu_builder& tu) override;
@ -97,7 +105,9 @@ protected:
void gen_leave_trap(tu_builder& tu, unsigned lvl);
void gen_wait(tu_builder& tu, unsigned type);
inline void gen_set_tval(tu_builder& tu, uint64_t new_tval);
inline void gen_set_tval(tu_builder& tu, value new_tval);
inline void gen_trap_check(tu_builder& tu) {
tu("if(*trap_state!=0) goto trap_entry;");
@ -128,47 +138,78 @@ protected:
return (from & mask) | ((from & sign_mask) ? ~mask : 0);
}
<%functions.each{ it.eachLine { %>
${it}<%}
}
if(fcsr != null) {%>
value NaNBox16(tu_builder& tu, value NaNBox16_val){
if(static_cast<uint32_t>(traits::FLEN) == 16)
return tu.ext(NaNBox16_val, traits::FLEN, false);
else {
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 32, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 16), NaNBox16_val)), traits::FLEN, false);
}
}
value NaNBox32(tu_builder& tu, value NaNBox32_val){
if(static_cast<uint32_t>(traits::FLEN) == 32)
return tu.ext(NaNBox32_val, traits::FLEN, false);
else {
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 64, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 32), NaNBox32_val)), traits::FLEN, false);
}
}
value NaNBox64(tu_builder& tu, value NaNBox64_val){
if(static_cast<uint32_t>(traits::FLEN) == 64)
return tu.ext(NaNBox64_val, traits::FLEN, false);
else {
throw new std::runtime_error("tcc does not support Registers wider than 64 bits");
auto box = tu.assignment(tu.logical_neg((tu.ext(0, 128, false))), traits::FLEN) ;
return tu.ext((tu.bitwise_or(tu.shl(box, 64), NaNBox64_val)), traits::FLEN, false);
}
}
<%}%>
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_descriptor {
size_t length;
uint32_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
struct decoding_tree_node{
std::vector<instruction_descriptor> instrs;
std::vector<decoding_tree_node*> children;
uint32_t submask = std::numeric_limits<uint32_t>::max();
uint32_t value;
decoding_tree_node(uint32_t value) : value(value){}
};
decoding_tree_node* root {nullptr};
const std::array<instruction_descriptor, ${instructions.size}> instr_descr = {{
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
/* instruction ${instr.instruction.name}, encoding '${instr.encoding}' */
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
}};
//needs to be declared after instr_descr
decoder instr_decoder;
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
tu("${instr.name}_{:#010x}:", pc.val);
vm_base<ARCH>::gen_sync(tu, PRE_SYNC,${idx});
uint64_t PC = pc.val;
<%instr.fields.eachLine{%>${it}
<%}%>if(this->disass_enabled){
/* generate console output when executing the command */<%instr.disass.eachLine{%>
${it}<%}%>
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, mnemonic);
}
auto cur_pc_val = tu.constant(pc.val, traits::reg_bit_widths[traits::PC]);
pc=pc+ ${instr.length/8};
gen_set_pc(tu, pc, traits::NEXT_PC);
tu.open_scope();<%instr.behavior.eachLine{%>
${it}<%}%>
tu("(*cycle)++;");
tu.open_scope();
this->gen_set_tval(tu, instr);
<%instr.behavior.eachLine{%>${it}
<%}%>
tu("(*icount)++;");
tu("(*instret)++;");
tu.close_scope();
vm_base<ARCH>::gen_sync(tu, POST_SYNC,${idx});
gen_trap_check(tu);
@ -178,66 +219,18 @@ private:
/****************************************************************************
* end opcode definitions
****************************************************************************/
compile_ret_t illegal_intruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) {
compile_ret_t illegal_instruction(virt_addr_t &pc, code_word_t instr, tu_builder& tu) {
vm_impl::gen_sync(tu, iss::PRE_SYNC, instr_descr.size());
if(this->disass_enabled){
/* generate console output when executing the command */
tu("print_disass(core_ptr, {:#x}, \"{}\");", pc.val, std::string("illegal_instruction"));
}
pc = pc + ((instr & 3) == 3 ? 4 : 2);
gen_raise_trap(tu, 0, 2); // illegal instruction trap
gen_raise_trap(tu, 0, static_cast<int32_t>(traits:: RV_CAUSE_ILLEGAL_INSTRUCTION));
this->gen_set_tval(tu, instr);
vm_impl::gen_sync(tu, iss::POST_SYNC, instr_descr.size());
vm_impl::gen_trap_check(tu);
return BRANCH;
}
//decoding functionality
void populate_decoding_tree(decoding_tree_node* root){
//create submask
for(auto instr: root->instrs){
root->submask &= instr.mask;
}
//put each instr according to submask&encoding into children
for(auto instr: root->instrs){
bool foundMatch = false;
for(auto child: root->children){
//use value as identifying trait
if(child->value == (instr.value&root->submask)){
child->instrs.push_back(instr);
foundMatch = true;
}
}
if(!foundMatch){
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
child->instrs.push_back(instr);
root->children.push_back(child);
}
}
root->instrs.clear();
//call populate_decoding_tree for all children
if(root->children.size() >1)
for(auto child: root->children){
populate_decoding_tree(child);
}
else{
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
return instr1.mask > instr2.mask;
});
}
}
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
if(!node->children.size()){
if(node->instrs.size() == 1) return node->instrs[0].op;
for(auto instr : node->instrs){
if((instr.mask&word) == instr.value) return instr.op;
}
}
else{
for(auto child : node->children){
if (child->value == (node->submask&word)){
return decode_instr(child, word);
}
}
}
return nullptr;
return ILLEGAL_INSTR;
}
};
@ -250,54 +243,139 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm_base<ARCH>(core, core_id, cluster_id) {
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
for(auto instr:instr_descr){
root->instrs.push_back(instr);
}
populate_decoding_tree(root);
}
: vm_base<ARCH>(core, core_id, cluster_id)
, instr_decoder([this]() {
std::vector<generic_instruction_descriptor> g_instr_descr;
g_instr_descr.reserve(instr_descr.size());
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
g_instr_descr.push_back(new_instr_descr);
}
return std::move(g_instr_descr);
}()) {}
template <typename ARCH>
std::tuple<continuation_e>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, tu_builder& tu) {
continuation_e
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, tu_builder& tu) {
// we fetch at max 4 byte, alignment is 2
enum {TRAP_ID=1<<16};
code_word_t instr = 0;
phys_addr_t paddr(pc);
paddr = this->core.v2p(pc);
auto res = this->core.read(paddr, 4, reinterpret_cast<uint8_t*>(&instr));
if (res != iss::Ok) throw trap_access(TRAP_ID, pc.val);
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack
++inst_cnt;
auto f = decode_instr(root, instr);
if (res != iss::Ok)
return ILLEGAL_FETCH;
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
return JUMP_TO_SELF;
uint32_t inst_index = instr_decoder.decode_instr(instr);
compile_func f = nullptr;
if(inst_index < instr_descr.size())
f = instr_descr[inst_index].op;
if (f == nullptr) {
f = &this_class::illegal_intruction;
f = &this_class::illegal_instruction;
}
return (this->*f)(pc, instr, tu);
}
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(tu_builder& tu, uint16_t trap_id, uint16_t cause) {
tu(" *trap_state = {:#x};", 0x80 << 24 | (cause << 16) | trap_id);
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(tu_builder& tu, unsigned lvl) {
tu("leave_trap(core_ptr, {});", lvl);
tu.store(traits::NEXT_PC, tu.read_mem(traits::CSR, (lvl << 8) + 0x41, traits::XLEN));
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(), 32));
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP), 32));
}
template <typename ARCH> void vm_impl<ARCH>::gen_wait(tu_builder& tu, unsigned type) {
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, uint64_t new_tval) {
tu(fmt::format("tval = {};", new_tval));
}
template <typename ARCH> void vm_impl<ARCH>::gen_set_tval(tu_builder& tu, value new_tval) {
tu(fmt::format("tval = {};", new_tval.str));
}
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(tu_builder& tu) {
tu("trap_entry:");
tu("enter_trap(core_ptr, *trap_state, *pc, 0);");
tu.store(traits::LAST_BRANCH, tu.constant(std::numeric_limits<uint32_t>::max(),32));
this->gen_sync(tu, POST_SYNC, -1);
tu("enter_trap(core_ptr, *trap_state, *pc, tval);");
tu.store(traits::LAST_BRANCH, tu.constant(static_cast<int>(UNKNOWN_JUMP),32));
tu("return *next_pc;");
}
template <typename ARCH> void vm_impl<ARCH>::add_prologue(tu_builder& tu){
std::ostringstream os;
os << tu.add_reg_ptr("trap_state", arch::traits<ARCH>::TRAP_STATE, this->regs_base_ptr);
os << tu.add_reg_ptr("pending_trap", arch::traits<ARCH>::PENDING_TRAP, this->regs_base_ptr);
os << tu.add_reg_ptr("cycle", arch::traits<ARCH>::CYCLE, this->regs_base_ptr);
<%if(fcsr != null) {
def flen = constants.find { it.name == 'FLEN' }?.value ?: 0
%>
os << "uint32_t (*fget_flags)()=" << (uintptr_t)&fget_flags << ";\\n";
os << "uint16_t (*fadd_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fadd_h << ";\\n";
os << "uint16_t (*fsub_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fsub_h << ";\\n";
os << "uint16_t (*fmul_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fmul_h << ";\\n";
os << "uint16_t (*fdiv_h)(uint16_t v1, uint16_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_h << ";\\n";
os << "uint16_t (*fsqrt_h)(uint16_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_h << ";\\n";
os << "uint16_t (*fcmp_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fcmp_h << ";\\n";
os << "uint16_t (*fmadd_h)(uint16_t v1, uint16_t v2, uint16_t v3, uint16_t op, uint8_t mode)=" << (uintptr_t)&fmadd_h << ";\\n";
os << "uint16_t (*fsel_h)(uint16_t v1, uint16_t v2, uint16_t op)=" << (uintptr_t)&fsel_h << ";\\n";
os << "uint16_t (*fclass_h)(uint16_t v1)=" << (uintptr_t)&fclass_h << ";\\n";
os << "uint16_t (*unbox_h)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_h << ";\\n";
os << "uint32_t (*f16toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi32 << ";\\n";
os << "uint32_t (*f16toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui32 << ";\\n";
os << "uint16_t (*i32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof16 << ";\\n";
os << "uint16_t (*ui32tof16)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof16 << ";\\n";
os << "uint64_t (*f16toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toi64 <<";\\n";
os << "uint64_t (*f16toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f16toui64 <<";\\n";
os << "uint16_t (*i64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof16 <<";\\n";
os << "uint16_t (*ui64tof16)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof16 <<";\\n";
os << "uint32_t (*fadd_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fadd_s << ";\\n";
os << "uint32_t (*fsub_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fsub_s << ";\\n";
os << "uint32_t (*fmul_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fmul_s << ";\\n";
os << "uint32_t (*fdiv_s)(uint32_t v1, uint32_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_s << ";\\n";
os << "uint32_t (*fsqrt_s)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_s << ";\\n";
os << "uint32_t (*fcmp_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fcmp_s << ";\\n";
os << "uint32_t (*fmadd_s)(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_s << ";\\n";
os << "uint32_t (*fsel_s)(uint32_t v1, uint32_t v2, uint32_t op)=" << (uintptr_t)&fsel_s << ";\\n";
os << "uint32_t (*fclass_s)( uint32_t v1 )=" << (uintptr_t)&fclass_s << ";\\n";
os << "uint32_t (*unbox_s)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_s << ";\\n";
os << "uint32_t (*f32toi32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi32 << ";\\n";
os << "uint32_t (*f32toui32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui32 << ";\\n";
os << "uint32_t (*i32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof32 << ";\\n";
os << "uint32_t (*ui32tof32)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof32 << ";\\n";
os << "uint64_t (*f32toi64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toi64 <<";\\n";
os << "uint64_t (*f32toui64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32toui64 <<";\\n";
os << "uint32_t (*i64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof32 <<";\\n";
os << "uint32_t (*ui64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof32 <<";\\n";
<%if(flen > 32) {%>
os << "uint64_t (*fadd_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fadd_d << ";\\n";
os << "uint64_t (*fsub_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fsub_d << ";\\n";
os << "uint64_t (*fmul_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fmul_d << ";\\n";
os << "uint64_t (*fdiv_d)(uint64_t v1, uint64_t v2, uint8_t mode)=" << (uintptr_t)&fdiv_d << ";\\n";
os << "uint64_t (*fsqrt_d)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&fsqrt_d << ";\\n";
os << "uint64_t (*fcmp_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fcmp_d << ";\\n";
os << "uint64_t (*fmadd_d)(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode)=" << (uintptr_t)&fmadd_d << ";\\n";
os << "uint64_t (*fsel_d)(uint64_t v1, uint64_t v2, uint32_t op)=" << (uintptr_t)&fsel_d << ";\\n";
os << "uint64_t (*fclass_d)(uint64_t v1 )=" << (uintptr_t)&fclass_d << ";\\n";
os << "uint64_t (*unbox_d)(uint8_t FLEN, uint64_t v)=" << (uintptr_t)&unbox_d << ";\\n";
os << "uint32_t (*f64tof32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64tof32 << ";\\n";
os << "uint64_t (*f32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&f32tof64 << ";\\n";
os << "uint64_t (*f64toi64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi64 <<";\\n";
os << "uint64_t (*f64toui64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui64 <<";\\n";
os << "uint64_t (*i64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&i64tof64 <<";\\n";
os << "uint64_t (*ui64tof64)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&ui64tof64 <<";\\n";
os << "uint64_t (*i32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&i32tof64 <<";\\n";
os << "uint64_t (*ui32tof64)(uint32_t v1, uint8_t mode)=" << (uintptr_t)&ui32tof64 <<";\\n";
os << "uint32_t (*f64toi32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toi32 <<";\\n";
os << "uint32_t (*f64toui32)(uint64_t v1, uint8_t mode)=" << (uintptr_t)&f64toui32 <<";\\n";
<%}
}%>
tu.add_prologue(os.str());
}
} // namespace ${coreDef.name.toLowerCase()}
@ -310,24 +388,33 @@ std::unique_ptr<vm_if> create<arch::${coreDef.name.toLowerCase()}>(arch::${coreD
} // namesapce tcc
} // namespace iss
#include <iss/factory.h>
#include <iss/arch/riscv_hart_m_p.h>
#include <iss/arch/riscv_hart_mu_p.h>
#include <iss/factory.h>
namespace iss {
namespace {
volatile std::array<bool, 2> dummy = {
core_factory::instance().register_creator<core_factory::CPP>("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|m_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_m_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
}),
core_factory::instance().register_creator<core_factory::CPP>("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void*) -> std::tuple<cpu_ptr, vm_ptr>{
core_factory::instance().register_creator("${coreDef.name.toLowerCase()}|mu_p|tcc", [](unsigned port, void* init_data) -> std::tuple<cpu_ptr, vm_ptr>{
auto* cpu = new iss::arch::riscv_hart_mu_p<iss::arch::${coreDef.name.toLowerCase()}>();
auto vm = new tcc::${coreDef.name.toLowerCase()}::vm_impl<arch::${coreDef.name.toLowerCase()}>(*cpu, false);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(vm, port);
if(init_data){
auto* cb = reinterpret_cast<semihosting_cb_t<arch::traits<arch::${coreDef.name.toLowerCase()}>::reg_t>*>(init_data);
cpu->set_semihosting_callback(*cb);
}
return {cpu_ptr{cpu}, vm_ptr{vm}};
})
};
}
}
// clang-format on

2
softfloat/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/*/*.o
build/*/*.a

View File

@ -327,7 +327,7 @@ set(OTHERS
set(LIB_SOURCES ${PRIMITIVES} ${SPECIALIZE} ${OTHERS})
add_library(softfloat ${LIB_SOURCES})
add_library(softfloat STATIC ${LIB_SOURCES})
set_property(TARGET softfloat PROPERTY C_STANDARD 99)
target_compile_definitions(softfloat PRIVATE
SOFTFLOAT_ROUND_ODD
@ -347,7 +347,7 @@ set_target_properties(softfloat PROPERTIES
install(TARGETS softfloat
EXPORT ${PROJECT_NAME}Targets # for downstream dependencies
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # static lib
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/static COMPONENT libs # static lib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # shared lib
FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libs # for mac
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT devel # headers for mac (note the different component -> different package)

24
softfloat/README.md Normal file
View File

@ -0,0 +1,24 @@
Package Overview for Berkeley SoftFloat Release 3e
==================================================
John R. Hauser<br>
2018 January 20
Berkeley SoftFloat is a software implementation of binary floating-point
that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat
is distributed in the form of C source code. Building the SoftFloat sources
generates a library file (typically `softfloat.a` or `libsoftfloat.a`)
containing the floating-point subroutines.
The SoftFloat package is documented in the following files in the `doc`
subdirectory:
* [SoftFloat.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat.html) Documentation for using the SoftFloat functions.
* [SoftFloat-source.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat-source.html) Documentation for building SoftFloat.
* [SoftFloat-history.html](http://www.jhauser.us/arithmetic/SoftFloat-3/doc/SoftFloat-history.html) History of the major changes to SoftFloat.
Other files in the package comprise the source code for SoftFloat.

View File

@ -0,0 +1,399 @@
#=============================================================================
#
# This Makefile 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.
#
#=============================================================================
SOURCE_DIR ?= ../../source
SPECIALIZE_TYPE ?= RISCV
MARCH ?= rv64gcv_zfh_zfhmin
MABI ?= lp64d
SOFTFLOAT_OPTS ?= \
-DSOFTFLOAT_ROUND_ODD -DINLINE_LEVEL=5 -DSOFTFLOAT_FAST_DIV32TO16 \
-DSOFTFLOAT_FAST_DIV64TO32
DELETE = rm -f
C_INCLUDES = -I. -I$(SOURCE_DIR)/$(SPECIALIZE_TYPE) -I$(SOURCE_DIR)/include
COMPILE_C = \
riscv64-unknown-linux-gnu-gcc -c -march=$(MARCH) -mabi=$(MABI) -Werror-implicit-function-declaration -DSOFTFLOAT_FAST_INT64 \
$(SOFTFLOAT_OPTS) $(C_INCLUDES) -O2 -o $@
MAKELIB = ar crs $@
OBJ = .o
LIB = .a
OTHER_HEADERS = $(SOURCE_DIR)/include/opts-GCC.h
.PHONY: all
all: softfloat$(LIB)
OBJS_PRIMITIVES = \
s_eq128$(OBJ) \
s_le128$(OBJ) \
s_lt128$(OBJ) \
s_shortShiftLeft128$(OBJ) \
s_shortShiftRight128$(OBJ) \
s_shortShiftRightJam64$(OBJ) \
s_shortShiftRightJam64Extra$(OBJ) \
s_shortShiftRightJam128$(OBJ) \
s_shortShiftRightJam128Extra$(OBJ) \
s_shiftRightJam32$(OBJ) \
s_shiftRightJam64$(OBJ) \
s_shiftRightJam64Extra$(OBJ) \
s_shiftRightJam128$(OBJ) \
s_shiftRightJam128Extra$(OBJ) \
s_shiftRightJam256M$(OBJ) \
s_countLeadingZeros8$(OBJ) \
s_countLeadingZeros16$(OBJ) \
s_countLeadingZeros32$(OBJ) \
s_countLeadingZeros64$(OBJ) \
s_add128$(OBJ) \
s_add256M$(OBJ) \
s_sub128$(OBJ) \
s_sub256M$(OBJ) \
s_mul64ByShifted32To128$(OBJ) \
s_mul64To128$(OBJ) \
s_mul128By32$(OBJ) \
s_mul128To256M$(OBJ) \
s_approxRecip_1Ks$(OBJ) \
s_approxRecip32_1$(OBJ) \
s_approxRecipSqrt_1Ks$(OBJ) \
s_approxRecipSqrt32_1$(OBJ) \
OBJS_SPECIALIZE = \
softfloat_raiseFlags$(OBJ) \
s_f16UIToCommonNaN$(OBJ) \
s_commonNaNToF16UI$(OBJ) \
s_propagateNaNF16UI$(OBJ) \
s_bf16UIToCommonNaN$(OBJ) \
s_commonNaNToBF16UI$(OBJ) \
s_f32UIToCommonNaN$(OBJ) \
s_commonNaNToF32UI$(OBJ) \
s_propagateNaNF32UI$(OBJ) \
s_f64UIToCommonNaN$(OBJ) \
s_commonNaNToF64UI$(OBJ) \
s_propagateNaNF64UI$(OBJ) \
extF80M_isSignalingNaN$(OBJ) \
s_extF80UIToCommonNaN$(OBJ) \
s_commonNaNToExtF80UI$(OBJ) \
s_propagateNaNExtF80UI$(OBJ) \
f128M_isSignalingNaN$(OBJ) \
s_f128UIToCommonNaN$(OBJ) \
s_commonNaNToF128UI$(OBJ) \
s_propagateNaNF128UI$(OBJ) \
OBJS_OTHERS = \
s_roundToUI32$(OBJ) \
s_roundToUI64$(OBJ) \
s_roundToI32$(OBJ) \
s_roundToI64$(OBJ) \
s_normSubnormalBF16Sig$(OBJ) \
s_roundPackToBF16$(OBJ) \
s_normSubnormalF16Sig$(OBJ) \
s_roundPackToF16$(OBJ) \
s_normRoundPackToF16$(OBJ) \
s_addMagsF16$(OBJ) \
s_subMagsF16$(OBJ) \
s_mulAddF16$(OBJ) \
s_normSubnormalF32Sig$(OBJ) \
s_roundPackToF32$(OBJ) \
s_normRoundPackToF32$(OBJ) \
s_addMagsF32$(OBJ) \
s_subMagsF32$(OBJ) \
s_mulAddF32$(OBJ) \
s_normSubnormalF64Sig$(OBJ) \
s_roundPackToF64$(OBJ) \
s_normRoundPackToF64$(OBJ) \
s_addMagsF64$(OBJ) \
s_subMagsF64$(OBJ) \
s_mulAddF64$(OBJ) \
s_normSubnormalExtF80Sig$(OBJ) \
s_roundPackToExtF80$(OBJ) \
s_normRoundPackToExtF80$(OBJ) \
s_addMagsExtF80$(OBJ) \
s_subMagsExtF80$(OBJ) \
s_normSubnormalF128Sig$(OBJ) \
s_roundPackToF128$(OBJ) \
s_normRoundPackToF128$(OBJ) \
s_addMagsF128$(OBJ) \
s_subMagsF128$(OBJ) \
s_mulAddF128$(OBJ) \
softfloat_state$(OBJ) \
ui32_to_f16$(OBJ) \
ui32_to_f32$(OBJ) \
ui32_to_f64$(OBJ) \
ui32_to_extF80$(OBJ) \
ui32_to_extF80M$(OBJ) \
ui32_to_f128$(OBJ) \
ui32_to_f128M$(OBJ) \
ui64_to_f16$(OBJ) \
ui64_to_f32$(OBJ) \
ui64_to_f64$(OBJ) \
ui64_to_extF80$(OBJ) \
ui64_to_extF80M$(OBJ) \
ui64_to_f128$(OBJ) \
ui64_to_f128M$(OBJ) \
i32_to_f16$(OBJ) \
i32_to_f32$(OBJ) \
i32_to_f64$(OBJ) \
i32_to_extF80$(OBJ) \
i32_to_extF80M$(OBJ) \
i32_to_f128$(OBJ) \
i32_to_f128M$(OBJ) \
i64_to_f16$(OBJ) \
i64_to_f32$(OBJ) \
i64_to_f64$(OBJ) \
i64_to_extF80$(OBJ) \
i64_to_extF80M$(OBJ) \
i64_to_f128$(OBJ) \
i64_to_f128M$(OBJ) \
bf16_isSignalingNaN$(OBJ) \
bf16_to_f32$(OBJ) \
f16_to_ui32$(OBJ) \
f16_to_ui64$(OBJ) \
f16_to_i32$(OBJ) \
f16_to_i64$(OBJ) \
f16_to_ui32_r_minMag$(OBJ) \
f16_to_ui64_r_minMag$(OBJ) \
f16_to_i32_r_minMag$(OBJ) \
f16_to_i64_r_minMag$(OBJ) \
f16_to_f32$(OBJ) \
f16_to_f64$(OBJ) \
f16_to_extF80$(OBJ) \
f16_to_extF80M$(OBJ) \
f16_to_f128$(OBJ) \
f16_to_f128M$(OBJ) \
f16_roundToInt$(OBJ) \
f16_add$(OBJ) \
f16_sub$(OBJ) \
f16_mul$(OBJ) \
f16_mulAdd$(OBJ) \
f16_div$(OBJ) \
f16_rem$(OBJ) \
f16_sqrt$(OBJ) \
f16_eq$(OBJ) \
f16_le$(OBJ) \
f16_lt$(OBJ) \
f16_eq_signaling$(OBJ) \
f16_le_quiet$(OBJ) \
f16_lt_quiet$(OBJ) \
f16_isSignalingNaN$(OBJ) \
f32_to_ui32$(OBJ) \
f32_to_ui64$(OBJ) \
f32_to_i32$(OBJ) \
f32_to_i64$(OBJ) \
f32_to_ui32_r_minMag$(OBJ) \
f32_to_ui64_r_minMag$(OBJ) \
f32_to_i32_r_minMag$(OBJ) \
f32_to_i64_r_minMag$(OBJ) \
f32_to_bf16$(OBJ) \
f32_to_f16$(OBJ) \
f32_to_f64$(OBJ) \
f32_to_extF80$(OBJ) \
f32_to_extF80M$(OBJ) \
f32_to_f128$(OBJ) \
f32_to_f128M$(OBJ) \
f32_roundToInt$(OBJ) \
f32_add$(OBJ) \
f32_sub$(OBJ) \
f32_mul$(OBJ) \
f32_mulAdd$(OBJ) \
f32_div$(OBJ) \
f32_rem$(OBJ) \
f32_sqrt$(OBJ) \
f32_eq$(OBJ) \
f32_le$(OBJ) \
f32_lt$(OBJ) \
f32_eq_signaling$(OBJ) \
f32_le_quiet$(OBJ) \
f32_lt_quiet$(OBJ) \
f32_isSignalingNaN$(OBJ) \
f64_to_ui32$(OBJ) \
f64_to_ui64$(OBJ) \
f64_to_i32$(OBJ) \
f64_to_i64$(OBJ) \
f64_to_ui32_r_minMag$(OBJ) \
f64_to_ui64_r_minMag$(OBJ) \
f64_to_i32_r_minMag$(OBJ) \
f64_to_i64_r_minMag$(OBJ) \
f64_to_f16$(OBJ) \
f64_to_f32$(OBJ) \
f64_to_extF80$(OBJ) \
f64_to_extF80M$(OBJ) \
f64_to_f128$(OBJ) \
f64_to_f128M$(OBJ) \
f64_roundToInt$(OBJ) \
f64_add$(OBJ) \
f64_sub$(OBJ) \
f64_mul$(OBJ) \
f64_mulAdd$(OBJ) \
f64_div$(OBJ) \
f64_rem$(OBJ) \
f64_sqrt$(OBJ) \
f64_eq$(OBJ) \
f64_le$(OBJ) \
f64_lt$(OBJ) \
f64_eq_signaling$(OBJ) \
f64_le_quiet$(OBJ) \
f64_lt_quiet$(OBJ) \
f64_isSignalingNaN$(OBJ) \
extF80_to_ui32$(OBJ) \
extF80_to_ui64$(OBJ) \
extF80_to_i32$(OBJ) \
extF80_to_i64$(OBJ) \
extF80_to_ui32_r_minMag$(OBJ) \
extF80_to_ui64_r_minMag$(OBJ) \
extF80_to_i32_r_minMag$(OBJ) \
extF80_to_i64_r_minMag$(OBJ) \
extF80_to_f16$(OBJ) \
extF80_to_f32$(OBJ) \
extF80_to_f64$(OBJ) \
extF80_to_f128$(OBJ) \
extF80_roundToInt$(OBJ) \
extF80_add$(OBJ) \
extF80_sub$(OBJ) \
extF80_mul$(OBJ) \
extF80_div$(OBJ) \
extF80_rem$(OBJ) \
extF80_sqrt$(OBJ) \
extF80_eq$(OBJ) \
extF80_le$(OBJ) \
extF80_lt$(OBJ) \
extF80_eq_signaling$(OBJ) \
extF80_le_quiet$(OBJ) \
extF80_lt_quiet$(OBJ) \
extF80_isSignalingNaN$(OBJ) \
extF80M_to_ui32$(OBJ) \
extF80M_to_ui64$(OBJ) \
extF80M_to_i32$(OBJ) \
extF80M_to_i64$(OBJ) \
extF80M_to_ui32_r_minMag$(OBJ) \
extF80M_to_ui64_r_minMag$(OBJ) \
extF80M_to_i32_r_minMag$(OBJ) \
extF80M_to_i64_r_minMag$(OBJ) \
extF80M_to_f16$(OBJ) \
extF80M_to_f32$(OBJ) \
extF80M_to_f64$(OBJ) \
extF80M_to_f128M$(OBJ) \
extF80M_roundToInt$(OBJ) \
extF80M_add$(OBJ) \
extF80M_sub$(OBJ) \
extF80M_mul$(OBJ) \
extF80M_div$(OBJ) \
extF80M_rem$(OBJ) \
extF80M_sqrt$(OBJ) \
extF80M_eq$(OBJ) \
extF80M_le$(OBJ) \
extF80M_lt$(OBJ) \
extF80M_eq_signaling$(OBJ) \
extF80M_le_quiet$(OBJ) \
extF80M_lt_quiet$(OBJ) \
f128_to_ui32$(OBJ) \
f128_to_ui64$(OBJ) \
f128_to_i32$(OBJ) \
f128_to_i64$(OBJ) \
f128_to_ui32_r_minMag$(OBJ) \
f128_to_ui64_r_minMag$(OBJ) \
f128_to_i32_r_minMag$(OBJ) \
f128_to_i64_r_minMag$(OBJ) \
f128_to_f16$(OBJ) \
f128_to_f32$(OBJ) \
f128_to_extF80$(OBJ) \
f128_to_f64$(OBJ) \
f128_roundToInt$(OBJ) \
f128_add$(OBJ) \
f128_sub$(OBJ) \
f128_mul$(OBJ) \
f128_mulAdd$(OBJ) \
f128_div$(OBJ) \
f128_rem$(OBJ) \
f128_sqrt$(OBJ) \
f128_eq$(OBJ) \
f128_le$(OBJ) \
f128_lt$(OBJ) \
f128_eq_signaling$(OBJ) \
f128_le_quiet$(OBJ) \
f128_lt_quiet$(OBJ) \
f128_isSignalingNaN$(OBJ) \
f128M_to_ui32$(OBJ) \
f128M_to_ui64$(OBJ) \
f128M_to_i32$(OBJ) \
f128M_to_i64$(OBJ) \
f128M_to_ui32_r_minMag$(OBJ) \
f128M_to_ui64_r_minMag$(OBJ) \
f128M_to_i32_r_minMag$(OBJ) \
f128M_to_i64_r_minMag$(OBJ) \
f128M_to_f16$(OBJ) \
f128M_to_f32$(OBJ) \
f128M_to_extF80M$(OBJ) \
f128M_to_f64$(OBJ) \
f128M_roundToInt$(OBJ) \
f128M_add$(OBJ) \
f128M_sub$(OBJ) \
f128M_mul$(OBJ) \
f128M_mulAdd$(OBJ) \
f128M_div$(OBJ) \
f128M_rem$(OBJ) \
f128M_sqrt$(OBJ) \
f128M_eq$(OBJ) \
f128M_le$(OBJ) \
f128M_lt$(OBJ) \
f128M_eq_signaling$(OBJ) \
f128M_le_quiet$(OBJ) \
f128M_lt_quiet$(OBJ) \
OBJS_ALL = $(OBJS_PRIMITIVES) $(OBJS_SPECIALIZE) $(OBJS_OTHERS)
$(OBJS_ALL): \
$(OTHER_HEADERS) platform.h $(SOURCE_DIR)/include/primitiveTypes.h \
$(SOURCE_DIR)/include/primitives.h
$(OBJS_SPECIALIZE) $(OBJS_OTHERS): \
$(SOURCE_DIR)/include/softfloat_types.h $(SOURCE_DIR)/include/internals.h \
$(SOURCE_DIR)/$(SPECIALIZE_TYPE)/specialize.h \
$(SOURCE_DIR)/include/softfloat.h
$(OBJS_PRIMITIVES) $(OBJS_OTHERS): %$(OBJ): $(SOURCE_DIR)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$*.c
$(OBJS_SPECIALIZE): %$(OBJ): $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/%.c
$(COMPILE_C) $(SOURCE_DIR)/$(SPECIALIZE_TYPE)/$*.c
softfloat$(LIB): $(OBJS_ALL)
$(DELETE) $@
$(MAKELIB) $^
.PHONY: clean
clean:
$(DELETE) $(OBJS_ALL) softfloat$(LIB)

View File

@ -0,0 +1,54 @@
/*============================================================================
This C header 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.
=============================================================================*/
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define LITTLEENDIAN 1
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#ifdef __GNUC_STDC_INLINE__
#define INLINE inline
#else
#define INLINE extern inline
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define SOFTFLOAT_BUILTIN_CLZ 1
#define SOFTFLOAT_INTRINSIC_INT128 1
#include "opts-GCC.h"

View File

@ -94,6 +94,8 @@ OBJS_SPECIALIZE = \
s_f16UIToCommonNaN$(OBJ) \
s_commonNaNToF16UI$(OBJ) \
s_propagateNaNF16UI$(OBJ) \
s_bf16UIToCommonNaN$(OBJ) \
s_commonNaNToBF16UI$(OBJ) \
s_f32UIToCommonNaN$(OBJ) \
s_commonNaNToF32UI$(OBJ) \
s_propagateNaNF32UI$(OBJ) \
@ -114,6 +116,8 @@ OBJS_OTHERS = \
s_roundToUI64$(OBJ) \
s_roundToI32$(OBJ) \
s_roundToI64$(OBJ) \
s_normSubnormalBF16Sig$(OBJ) \
s_roundPackToBF16$(OBJ) \
s_normSubnormalF16Sig$(OBJ) \
s_roundPackToF16$(OBJ) \
s_normRoundPackToF16$(OBJ) \
@ -172,6 +176,8 @@ OBJS_OTHERS = \
i64_to_extF80M$(OBJ) \
i64_to_f128$(OBJ) \
i64_to_f128M$(OBJ) \
bf16_isSignalingNaN$(OBJ) \
bf16_to_f32$(OBJ) \
f16_to_ui32$(OBJ) \
f16_to_ui64$(OBJ) \
f16_to_i32$(OBJ) \
@ -209,6 +215,7 @@ OBJS_OTHERS = \
f32_to_ui64_r_minMag$(OBJ) \
f32_to_i32_r_minMag$(OBJ) \
f32_to_i64_r_minMag$(OBJ) \
f32_to_bf16$(OBJ) \
f32_to_f16$(OBJ) \
f32_to_f64$(OBJ) \
f32_to_extF80$(OBJ) \

View File

@ -35,11 +35,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
*----------------------------------------------------------------------------*/
#define LITTLEENDIAN 1
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
*----------------------------------------------------------------------------*/
#ifdef __GNUC_STDC_INLINE__
//#define INLINE inline
#define INLINE static
@ -48,10 +48,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
*----------------------------------------------------------------------------*/
#ifdef __GNUC__
#define SOFTFLOAT_BUILTIN_CLZ 1
#define SOFTFLOAT_INTRINSIC_INT128 1
#endif
#include "opts-GCC.h"

View File

@ -115,6 +115,8 @@ OBJS_OTHERS = \
s_roundToUI64$(OBJ) \
s_roundToI32$(OBJ) \
s_roundToI64$(OBJ) \
s_normSubnormalBF16Sig$(OBJ) \
s_roundPackToBF16$(OBJ) \
s_normSubnormalF16Sig$(OBJ) \
s_roundPackToF16$(OBJ) \
s_normRoundPackToF16$(OBJ) \
@ -173,6 +175,8 @@ OBJS_OTHERS = \
i64_to_extF80M$(OBJ) \
i64_to_f128$(OBJ) \
i64_to_f128M$(OBJ) \
bf16_isSignalingNaN$(OBJ) \
bf16_to_f32$(OBJ) \
f16_to_ui32$(OBJ) \
f16_to_ui64$(OBJ) \
f16_to_i32$(OBJ) \
@ -210,6 +214,7 @@ OBJS_OTHERS = \
f32_to_ui64_r_minMag$(OBJ) \
f32_to_i32_r_minMag$(OBJ) \
f32_to_i64_r_minMag$(OBJ) \
f32_to_bf16$(OBJ) \
f32_to_f16$(OBJ) \
f32_to_f64$(OBJ) \
f32_to_extF80$(OBJ) \

View File

@ -508,7 +508,7 @@ significant extra cost.
On computers where the word size is <NOBR>64 bits</NOBR> or larger, both
function versions (<CODE>f128M_add</CODE> and <CODE>f128_add</CODE>) are
provided, because the cost of passing by value is then more reasonable.
Applications that must be portable accross both classes of computers must use
Applications that must be portable across both classes of computers must use
the pointer-based functions, as these are always implemented.
However, if it is known that SoftFloat includes the by-value functions for all
platforms of interest, programmers can use whichever version they prefer.

View File

@ -0,0 +1,59 @@
/*============================================================================
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 "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming `uiA' has the bit pattern of a BF16 NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_bf16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
{
if ( softfloat_isSigNaNBF16UI( uiA ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = uiA>>15;
zPtr->v64 = (uint_fast64_t) uiA<<56;
zPtr->v0 = 0;
}

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 <stdint.h>
#include "platform.h"
#include "specialize.h"
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by `aPtr' into a BF16 NaN, and
| returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToBF16UI( const struct commonNaN *aPtr )
{
return (uint_fast16_t) aPtr->sign<<15 | 0x7FC0 | aPtr->v64>>56;
}

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow 0xFFFFFFFF
#define ui32_fromNegOverflow 0xFFFFFFFF
#define ui32_fromNaN 0xFFFFFFFF
#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN (-0x7FFFFFFF - 1)
#define ui32_fromNaN 0xFFFFFFFF
#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN (-0x7FFFFFFF - 1)
/*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF)
#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
/*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format
@ -92,7 +92,7 @@ struct commonNaN {
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
@ -100,13 +100,13 @@ struct commonNaN {
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
@ -114,8 +114,28 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
/*----------------------------------------------------------------------------
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
| 16-bit brain floating-point (BF16) signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNBF16UI(uiA) ((((uiA)&0x7FC0) == 0x7F80) && ((uiA)&0x003F))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit BF16 floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_bf16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToBF16UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN.
@ -127,7 +147,7 @@ uint_fast16_t
| 32-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
@ -135,13 +155,13 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
@ -149,20 +169,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 )
#define defaultNaNF64UI UINT64_C(0xFFF8000000000000)
/*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
| 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
#define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -170,13 +190,13 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
@ -184,14 +204,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNExtF80UI64 0xFFFF
#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
/*----------------------------------------------------------------------------
| Returns true when the 80-bit unsigned integer formed from concatenating
@ -199,7 +218,8 @@ uint_fast64_t
| floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
@ -215,16 +235,14 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and returns the bit pattern of this value as an unsigned
| integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -235,19 +253,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
#define defaultNaNF128UI0 UINT64_C( 0 )
#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000)
#define defaultNaNF128UI0 UINT64_C(0)
/*----------------------------------------------------------------------------
| Returns true when the 128-bit unsigned integer formed from concatenating
@ -255,7 +267,8 @@ struct uint128
| point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,15 +277,13 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
void
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -283,13 +294,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
#else
@ -304,18 +309,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +324,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
@ -336,7 +332,7 @@ void
#define defaultNaNF128UI96 0xFFFF8000
#define defaultNaNF128UI64 0
#define defaultNaNF128UI32 0
#define defaultNaNF128UI0 0
#define defaultNaNF128UI0 0
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
@ -346,8 +342,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +350,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +360,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
#endif
#endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow 0xFFFFFFFF
#define ui32_fromNegOverflow 0xFFFFFFFF
#define ui32_fromNaN 0xFFFFFFFF
#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN (-0x7FFFFFFF - 1)
#define ui32_fromNaN 0xFFFFFFFF
#define i32_fromPosOverflow (-0x7FFFFFFF - 1)
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN (-0x7FFFFFFF - 1)
/*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNegOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define i64_fromPosOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNaN (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNegOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF)
#define i64_fromPosOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNaN (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
/*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format
@ -92,7 +92,7 @@ struct commonNaN {
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
@ -100,13 +100,13 @@ struct commonNaN {
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN.
@ -127,7 +126,7 @@ uint_fast16_t
| 32-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
@ -135,13 +134,13 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0xFFF8000000000000 )
#define defaultNaNF64UI UINT64_C(0xFFF8000000000000)
/*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
| 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
#define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -170,13 +169,13 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNExtF80UI64 0xFFFF
#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
/*----------------------------------------------------------------------------
| Returns true when the 80-bit unsigned integer formed from concatenating
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
@ -215,16 +214,14 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and returns the bit pattern of this value as an unsigned
| integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
#define defaultNaNF128UI0 UINT64_C( 0 )
#define defaultNaNF128UI64 UINT64_C(0xFFFF800000000000)
#define defaultNaNF128UI0 UINT64_C(0)
/*----------------------------------------------------------------------------
| Returns true when the 128-bit unsigned integer formed from concatenating
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,15 +256,13 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
void
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
#else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
@ -336,7 +311,7 @@ void
#define defaultNaNF128UI96 0xFFFF8000
#define defaultNaNF128UI64 0
#define defaultNaNF128UI32 0
#define defaultNaNF128UI0 0
#define defaultNaNF128UI0 0
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
#endif
#endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -53,27 +53,29 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow 0xFFFFFFFF
#define ui32_fromNegOverflow 0
#define ui32_fromNaN 0
#define i32_fromPosOverflow 0x7FFFFFFF
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN 0
#define ui32_fromNaN 0
#define i32_fromPosOverflow 0x7FFFFFFF
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN 0
/*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNegOverflow 0
#define ui64_fromNaN 0
#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF )
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNaN 0
#define ui64_fromNaN 0
#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF)
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNaN 0
/*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format
| to another.
*----------------------------------------------------------------------------*/
struct commonNaN { char _unused; };
struct commonNaN {
char _unused;
};
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 16-bit floating-point NaN.
@ -85,7 +87,7 @@ struct commonNaN { char _unused; };
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
@ -93,13 +95,15 @@ struct commonNaN { char _unused; };
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_f16UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x0200) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_f16UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x0200)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
#define softfloat_commonNaNToF16UI( aPtr ) ((uint_fast16_t) defaultNaNF16UI)
#define softfloat_commonNaNToF16UI(aPtr) ((uint_fast16_t)defaultNaNF16UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
@ -107,8 +111,7 @@ struct commonNaN { char _unused; };
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN.
@ -120,7 +123,7 @@ uint_fast16_t
| 32-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
@ -128,13 +131,15 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_f32UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & 0x00400000) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_f32UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x00400000)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
#define softfloat_commonNaNToF32UI( aPtr ) ((uint_fast32_t) defaultNaNF32UI)
#define softfloat_commonNaNToF32UI(aPtr) ((uint_fast32_t)defaultNaNF32UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
@ -142,20 +147,20 @@ uint_fast16_t
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
#define defaultNaNF64UI UINT64_C(0x7FF8000000000000)
/*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
| 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
#define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -163,13 +168,15 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_f64UIToCommonNaN( uiA, zPtr ) if ( ! ((uiA) & UINT64_C( 0x0008000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_f64UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&UINT64_C(0x0008000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
#define softfloat_commonNaNToF64UI( aPtr ) ((uint_fast64_t) defaultNaNF64UI)
#define softfloat_commonNaNToF64UI(aPtr) ((uint_fast64_t)defaultNaNF64UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
@ -177,14 +184,13 @@ uint_fast32_t
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNExtF80UI64 0x7FFF
#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
/*----------------------------------------------------------------------------
| Returns true when the 80-bit unsigned integer formed from concatenating
@ -192,7 +198,8 @@ uint_fast64_t
| floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
@ -208,24 +215,25 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_extF80UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA0) & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA0)&UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and returns the bit pattern of this value as an unsigned
| integer.
*----------------------------------------------------------------------------*/
#if defined INLINE && ! defined softfloat_commonNaNToExtF80UI
#if defined INLINE && !defined softfloat_commonNaNToExtF80UI
INLINE
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
{
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) {
struct uint128 uiZ;
uiZ.v64 = defaultNaNExtF80UI64;
uiZ.v0 = defaultNaNExtF80UI0;
uiZ.v0 = defaultNaNExtF80UI0;
return uiZ;
}
#else
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
#endif
/*----------------------------------------------------------------------------
@ -237,19 +245,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 )
#define defaultNaNF128UI0 UINT64_C( 0 )
#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000)
#define defaultNaNF128UI0 UINT64_C(0)
/*----------------------------------------------------------------------------
| Returns true when the 128-bit unsigned integer formed from concatenating
@ -257,7 +259,8 @@ struct uint128
| point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -266,23 +269,24 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
#define softfloat_f128UIToCommonNaN( uiA64, uiA0, zPtr ) if ( ! ((uiA64) & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA64)&UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
#if defined INLINE && ! defined softfloat_commonNaNToF128UI
#if defined INLINE && !defined softfloat_commonNaNToF128UI
INLINE
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
{
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) {
struct uint128 uiZ;
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}
#else
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
#endif
/*----------------------------------------------------------------------------
@ -294,13 +298,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
#else
@ -315,26 +313,23 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_extF80MToCommonNaN( aSPtr, zPtr ) if ( ! ((aSPtr)->signif & UINT64_C( 0x4000000000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \
if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'.
*----------------------------------------------------------------------------*/
#if defined INLINE && ! defined softfloat_commonNaNToExtF80M
#if defined INLINE && !defined softfloat_commonNaNToExtF80M
INLINE
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
{
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) {
zSPtr->signExp = defaultNaNExtF80UI64;
zSPtr->signif = defaultNaNExtF80UI0;
zSPtr->signif = defaultNaNExtF80UI0;
}
#else
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
#endif
/*----------------------------------------------------------------------------
@ -343,12 +338,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
@ -356,7 +346,7 @@ void
#define defaultNaNF128UI96 0x7FFF8000
#define defaultNaNF128UI64 0
#define defaultNaNF128UI32 0
#define defaultNaNF128UI0 0
#define defaultNaNF128UI0 0
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
@ -366,7 +356,9 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
#define softfloat_f128MToCommonNaN( aWPtr, zPtr ) if ( ! ((aWPtr)[indexWordHi( 4 )] & UINT64_C( 0x0000800000000000 )) ) softfloat_raiseFlags( softfloat_flag_invalid )
#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \
if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -374,19 +366,16 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
#if defined INLINE && ! defined softfloat_commonNaNToF128M
#if defined INLINE && !defined softfloat_commonNaNToF128M
INLINE
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
{
zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
}
#else
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
#endif
/*----------------------------------------------------------------------------
@ -397,11 +386,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
#endif
#endif

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -53,21 +53,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow 0xFFFFFFFF
#define ui32_fromNegOverflow 0
#define ui32_fromNaN 0
#define i32_fromPosOverflow 0x7FFFFFFF
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN 0
#define ui32_fromNaN 0
#define i32_fromPosOverflow 0x7FFFFFFF
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN 0
/*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNegOverflow 0
#define ui64_fromNaN 0
#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF )
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1)
#define i64_fromNaN 0
#define ui64_fromNaN 0
#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF)
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNaN 0
/*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format
@ -92,7 +92,7 @@ struct commonNaN {
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
@ -100,13 +100,13 @@ struct commonNaN {
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
void softfloat_f16UIToCommonNaN(uint_fast16_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
uint_fast16_t softfloat_commonNaNToF16UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
@ -114,8 +114,7 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN.
@ -127,7 +126,7 @@ uint_fast16_t
| 32-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
@ -135,13 +134,13 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
void softfloat_f32UIToCommonNaN(uint_fast32_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
uint_fast32_t softfloat_commonNaNToF32UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
@ -149,20 +148,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
#define defaultNaNF64UI UINT64_C(0x7FF8000000000000)
/*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
| 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
#define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -170,13 +169,13 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
void softfloat_f64UIToCommonNaN(uint_fast64_t uiA, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
uint_fast64_t softfloat_commonNaNToF64UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
@ -184,14 +183,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNExtF80UI64 0x7FFF
#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
/*----------------------------------------------------------------------------
| Returns true when the 80-bit unsigned integer formed from concatenating
@ -199,7 +197,8 @@ uint_fast64_t
| floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
@ -215,16 +214,14 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_extF80UIToCommonNaN(uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and returns the bit pattern of this value as an unsigned
| integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -235,19 +232,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI64 UINT64_C( 0x7FFF800000000000 )
#define defaultNaNF128UI0 UINT64_C( 0 )
#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000)
#define defaultNaNF128UI0 UINT64_C(0)
/*----------------------------------------------------------------------------
| Returns true when the 128-bit unsigned integer formed from concatenating
@ -255,7 +246,8 @@ struct uint128
| point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,15 +256,13 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
void
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
void softfloat_f128UIToCommonNaN(uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -283,13 +273,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
#else
@ -304,18 +288,14 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
void softfloat_extF80MToCommonNaN(const struct extFloat80M* aSPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values
@ -323,12 +303,7 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
@ -336,7 +311,7 @@ void
#define defaultNaNF128UI96 0x7FFF8000
#define defaultNaNF128UI64 0
#define defaultNaNF128UI32 0
#define defaultNaNF128UI0 0
#define defaultNaNF128UI0 0
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
@ -346,8 +321,7 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
void softfloat_f128MToCommonNaN(const uint32_t* aWPtr, struct commonNaN* zPtr);
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +329,7 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
/*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +339,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
#endif
#endif

View File

@ -0,0 +1,5 @@
/*----------------------------------------------------------------------------
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/

View File

@ -0,0 +1,5 @@
/*----------------------------------------------------------------------------
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "softfloat_types.h"
#define softfloat_commonNaNToExtF80M softfloat_commonNaNToExtF80M
#include "specialize.h"
/*----------------------------------------------------------------------------
@ -49,8 +50,8 @@ void
const struct commonNaN *aPtr, struct extFloat80M *zSPtr )
{
zSPtr->signExp = packToExtF80UI64( aPtr->sign, 0x7FFF );
zSPtr->signif = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
zSPtr->signExp = defaultNaNExtF80UI64;
zSPtr->signif = defaultNaNExtF80UI0;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "platform.h"
#include "primitives.h"
#include "primitiveTypes.h"
#define softfloat_commonNaNToExtF80UI softfloat_commonNaNToExtF80UI
#include "specialize.h"
/*----------------------------------------------------------------------------
@ -48,8 +49,8 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr )
{
struct uint128 uiZ;
uiZ.v64 = (uint_fast16_t) aPtr->sign<<15 | 0x7FFF;
uiZ.v0 = UINT64_C( 0xC000000000000000 ) | aPtr->v64>>1;
uiZ.v64 = defaultNaNExtF80UI64;
uiZ.v0 = defaultNaNExtF80UI0;
return uiZ;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -36,7 +36,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdint.h>
#include "platform.h"
#include "primitives.h"
#include "primitiveTypes.h"
#define softfloat_commonNaNToF128M softfloat_commonNaNToF128M
#include "specialize.h"
/*----------------------------------------------------------------------------
@ -49,8 +51,10 @@ void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr )
{
softfloat_shortShiftRight128M( (const uint32_t *) &aPtr->v0, 16, zWPtr );
zWPtr[indexWordHi( 4 )] |= (uint32_t) aPtr->sign<<31 | 0x7FFF8000;
zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,9 +34,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "platform.h"
#include "primitives.h"
#include "primitiveTypes.h"
#define softfloat_commonNaNToF128UI softfloat_commonNaNToF128UI
#include "specialize.h"
/*----------------------------------------------------------------------------
@ -47,8 +48,8 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN *aPtr )
{
struct uint128 uiZ;
uiZ = softfloat_shortShiftRight128( aPtr->v64, aPtr->v0, 16 );
uiZ.v64 |= (uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FFF800000000000 );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}

View File

@ -1,51 +1,5 @@
/*============================================================================
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 <stdint.h>
#include "platform.h"
#include "specialize.h"
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by `aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr )
{
return (uint_fast16_t) aPtr->sign<<15 | 0x7E00 | aPtr->v64>>54;
}

View File

@ -1,51 +1,5 @@
/*============================================================================
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 "specialize.h"
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by `aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr )
{
return (uint_fast32_t) aPtr->sign<<31 | 0x7FC00000 | aPtr->v64>>41;
}

View File

@ -1,53 +1,5 @@
/*============================================================================
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 "specialize.h"
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by `aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr )
{
return
(uint_fast64_t) aPtr->sign<<63 | UINT64_C( 0x7FF8000000000000 )
| aPtr->v64>>12;
}

View File

@ -1,62 +1,5 @@
/*============================================================================
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 "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming the 80-bit extended floating-point value pointed to by `aSPtr' is
| a NaN, converts this NaN to the common NaN form, and stores the resulting
| common NaN at the location pointed to by `zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr )
{
if ( extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = signExtF80UI64( aSPtr->signExp );
zPtr->v64 = aSPtr->signif<<1;
zPtr->v0 = 0;
}

View File

@ -1,62 +1,5 @@
/*============================================================================
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 "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
| has the bit pattern of an 80-bit extended floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
{
if ( softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = uiA64>>15;
zPtr->v64 = uiA0<<1;
zPtr->v0 = 0;
}

View File

@ -1,62 +1,5 @@
/*============================================================================
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 "primitives.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by `aWPtr' is a NaN,
| converts this NaN to the common NaN form, and stores the resulting common
| NaN at the location pointed to by `zPtr'. If the NaN is a signaling NaN,
| the invalid exception is raised. Argument `aWPtr' points to an array of
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr )
{
if ( f128M_isSignalingNaN( (const float128_t *) aWPtr ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = aWPtr[indexWordHi( 4 )]>>31;
softfloat_shortShiftLeft128M( aWPtr, 16, (uint32_t *) &zPtr->v0 );
}

View File

@ -1,65 +1,5 @@
/*============================================================================
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 "primitives.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating `uiA64' and `uiA0'
| has the bit pattern of a 128-bit floating-point NaN, converts this NaN to
| the common NaN form, and stores the resulting common NaN at the location
| pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr )
{
struct uint128 NaNSig;
if ( softfloat_isSigNaNF128UI( uiA64, uiA0 ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
NaNSig = softfloat_shortShiftLeft128( uiA64, uiA0, 16 );
zPtr->sign = uiA64>>63;
zPtr->v64 = NaNSig.v64;
zPtr->v0 = NaNSig.v0;
}

View File

@ -1,59 +1,5 @@
/*============================================================================
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 <stdint.h>
#include "platform.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming `uiA' has the bit pattern of a 16-bit floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr )
{
if ( softfloat_isSigNaNF16UI( uiA ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = uiA>>15;
zPtr->v64 = (uint_fast64_t) uiA<<54;
zPtr->v0 = 0;
}

View File

@ -1,59 +1,5 @@
/*============================================================================
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 "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming `uiA' has the bit pattern of a 32-bit floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr )
{
if ( softfloat_isSigNaNF32UI( uiA ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = uiA>>31;
zPtr->v64 = (uint_fast64_t) uiA<<41;
zPtr->v0 = 0;
}

View File

@ -1,59 +1,5 @@
/*============================================================================
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 "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming `uiA' has the bit pattern of a 64-bit floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by `zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
| This file intentionally contains no code.
*----------------------------------------------------------------------------*/
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr )
{
if ( softfloat_isSigNaNF64UI( uiA ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
}
zPtr->sign = uiA>>63;
zPtr->v64 = uiA<<12;
zPtr->v0 = 0;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,10 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "primitiveTypes.h"
#include "specialize.h"
#include "softfloat.h"
@ -54,54 +53,22 @@ void
struct extFloat80M *zSPtr
)
{
bool isSigNaNA;
const struct extFloat80M *sPtr;
bool isSigNaNB;
uint_fast16_t uiB64;
uint64_t uiB0;
uint_fast16_t uiA64;
uint64_t uiA0;
uint_fast16_t uiMagA64, uiMagB64;
uint_fast16_t ui64;
uint_fast64_t ui0;
isSigNaNA = extF80M_isSignalingNaN( (const extFloat80_t *) aSPtr );
sPtr = aSPtr;
if ( ! bSPtr ) {
if ( isSigNaNA ) softfloat_raiseFlags( softfloat_flag_invalid );
goto copy;
}
isSigNaNB = extF80M_isSignalingNaN( (const extFloat80_t *) bSPtr );
if ( isSigNaNA | isSigNaNB ) {
ui64 = aSPtr->signExp;
ui0 = aSPtr->signif;
if (
softfloat_isSigNaNExtF80UI( ui64, ui0 )
|| (bSPtr
&& (ui64 = bSPtr->signExp,
ui0 = bSPtr->signif,
softfloat_isSigNaNExtF80UI( ui64, ui0 )))
) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) {
uiB64 = bSPtr->signExp;
if ( isSigNaNB ) goto returnLargerUIMag;
uiB0 = bSPtr->signif;
if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto copyB;
goto copy;
} else {
uiA64 = aSPtr->signExp;
uiA0 = aSPtr->signif;
if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto copy;
goto copyB;
}
}
uiB64 = bSPtr->signExp;
returnLargerUIMag:
uiA64 = aSPtr->signExp;
uiMagA64 = uiA64 & 0x7FFF;
uiMagB64 = uiB64 & 0x7FFF;
if ( uiMagA64 < uiMagB64 ) goto copyB;
if ( uiMagB64 < uiMagA64 ) goto copy;
uiA0 = aSPtr->signif;
uiB0 = bSPtr->signif;
if ( uiA0 < uiB0 ) goto copyB;
if ( uiB0 < uiA0 ) goto copy;
if ( uiA64 < uiB64 ) goto copy;
copyB:
sPtr = bSPtr;
copy:
zSPtr->signExp = sPtr->signExp;
zSPtr->signif = sPtr->signif | UINT64_C( 0xC000000000000000 );
zSPtr->signExp = defaultNaNExtF80UI64;
zSPtr->signif = defaultNaNExtF80UI0;
}

View File

@ -4,7 +4,7 @@
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, 2018 The Regents of the University of
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
@ -34,17 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "primitiveTypes.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
| 'uiA0' as an 80-bit extended floating-point value, and likewise interpreting
| the unsigned integer formed from concatenating 'uiB64' and 'uiB0' as another
| Interpreting the unsigned integer formed from concatenating `uiA64' and
| `uiA0' as an 80-bit extended floating-point value, and likewise interpreting
| the unsigned integer formed from concatenating `uiB64' and `uiB0' as another
| 80-bit extended 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
@ -58,48 +57,16 @@ struct uint128
uint_fast64_t uiB0
)
{
bool isSigNaNA, isSigNaNB;
uint_fast64_t uiNonsigA0, uiNonsigB0;
uint_fast16_t uiMagA64, uiMagB64;
struct uint128 uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
isSigNaNA = softfloat_isSigNaNExtF80UI( uiA64, uiA0 );
isSigNaNB = softfloat_isSigNaNExtF80UI( uiB64, uiB0 );
/*------------------------------------------------------------------------
| Make NaNs non-signaling.
*------------------------------------------------------------------------*/
uiNonsigA0 = uiA0 | UINT64_C( 0xC000000000000000 );
uiNonsigB0 = uiB0 | UINT64_C( 0xC000000000000000 );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( isSigNaNA | isSigNaNB ) {
if (
softfloat_isSigNaNExtF80UI( uiA64, uiA0 )
|| softfloat_isSigNaNExtF80UI( uiB64, uiB0 )
) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) {
if ( isSigNaNB ) goto returnLargerMag;
if ( isNaNExtF80UI( uiB64, uiB0 ) ) goto returnB;
goto returnA;
} else {
if ( isNaNExtF80UI( uiA64, uiA0 ) ) goto returnA;
goto returnB;
}
}
returnLargerMag:
uiMagA64 = uiA64 & 0x7FFF;
uiMagB64 = uiB64 & 0x7FFF;
if ( uiMagA64 < uiMagB64 ) goto returnB;
if ( uiMagB64 < uiMagA64 ) goto returnA;
if ( uiA0 < uiB0 ) goto returnB;
if ( uiB0 < uiA0 ) goto returnA;
if ( uiA64 < uiB64 ) goto returnA;
returnB:
uiZ.v64 = uiB64;
uiZ.v0 = uiNonsigB0;
return uiZ;
returnA:
uiZ.v64 = uiA64;
uiZ.v0 = uiNonsigA0;
uiZ.v64 = defaultNaNExtF80UI64;
uiZ.v0 = defaultNaNExtF80UI0;
return uiZ;
}

View File

@ -4,8 +4,8 @@
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.
Copyright 2011, 2012, 2013, 2014, 2015, 2018 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:
@ -34,43 +34,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "primitiveTypes.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by
| `aWPtr' and `bWPtr' is a NaN, stores the combined NaN result at the location
| pointed to by `zWPtr'. If either original floating-point value is a
| signaling NaN, the invalid exception is raised. Each of `aWPtr', `bWPtr',
| and `zWPtr' points to an array of four 32-bit elements that concatenate in
| 'aWPtr' and 'bWPtr' is a NaN, stores the combined NaN result at the location
| pointed to by 'zWPtr'. If either original floating-point value is a
| signaling NaN, the invalid exception is raised. Each of 'aWPtr', 'bWPtr',
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr )
{
bool isSigNaNA;
const uint32_t *ptr;
ptr = aWPtr;
isSigNaNA = f128M_isSignalingNaN( (const float128_t *) aWPtr );
if (
isSigNaNA
f128M_isSignalingNaN( (const float128_t *) aWPtr )
|| (bWPtr && f128M_isSignalingNaN( (const float128_t *) bWPtr ))
) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) goto copy;
}
if ( ! softfloat_isNaNF128M( aWPtr ) ) ptr = bWPtr;
copy:
zWPtr[indexWordHi( 4 )] = ptr[indexWordHi( 4 )] | 0x00008000;
zWPtr[indexWord( 4, 2 )] = ptr[indexWord( 4, 2 )];
zWPtr[indexWord( 4, 1 )] = ptr[indexWord( 4, 1 )];
zWPtr[indexWord( 4, 0 )] = ptr[indexWord( 4, 0 )];
zWPtr[indexWord( 4, 3 )] = defaultNaNF128UI96;
zWPtr[indexWord( 4, 2 )] = defaultNaNF128UI64;
zWPtr[indexWord( 4, 1 )] = defaultNaNF128UI32;
zWPtr[indexWord( 4, 0 )] = defaultNaNF128UI0;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,10 +34,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "platform.h"
#include "internals.h"
#include "primitiveTypes.h"
#include "specialize.h"
#include "softfloat.h"
@ -58,23 +57,16 @@ struct uint128
uint_fast64_t uiB0
)
{
bool isSigNaNA;
struct uint128 uiZ;
isSigNaNA = softfloat_isSigNaNF128UI( uiA64, uiA0 );
if ( isSigNaNA || softfloat_isSigNaNF128UI( uiB64, uiB0 ) ) {
if (
softfloat_isSigNaNF128UI( uiA64, uiA0 )
|| softfloat_isSigNaNF128UI( uiB64, uiB0 )
) {
softfloat_raiseFlags( 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 );
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}

View File

@ -4,7 +4,7 @@
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
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
@ -34,10 +34,8 @@ 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"
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB )
{
bool isSigNaNA;
isSigNaNA = softfloat_isSigNaNF16UI( uiA );
if ( isSigNaNA || softfloat_isSigNaNF16UI( uiB ) ) {
if ( softfloat_isSigNaNF16UI( uiA ) || softfloat_isSigNaNF16UI( uiB ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) return uiA | 0x0200;
}
return (isNaNF16UI( uiA ) ? uiA : uiB) | 0x0200;
return defaultNaNF16UI;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,10 +34,8 @@ 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"
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB )
{
bool isSigNaNA;
isSigNaNA = softfloat_isSigNaNF32UI( uiA );
if ( isSigNaNA || softfloat_isSigNaNF32UI( uiB ) ) {
if ( softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) return uiA | 0x00400000;
}
return (isNaNF32UI( uiA ) ? uiA : uiB) | 0x00400000;
return defaultNaNF32UI;
}

View File

@ -4,8 +4,8 @@
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.
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:
@ -34,10 +34,8 @@ 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"
@ -50,14 +48,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB )
{
bool isSigNaNA;
isSigNaNA = softfloat_isSigNaNF64UI( uiA );
if ( isSigNaNA || softfloat_isSigNaNF64UI( uiB ) ) {
if ( softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) ) {
softfloat_raiseFlags( softfloat_flag_invalid );
if ( isSigNaNA ) return uiA | UINT64_C( 0x0008000000000000 );
}
return (isNaNF64UI( uiA ) ? uiA : uiB) | UINT64_C( 0x0008000000000000 );
return defaultNaNF64UI;
}

View File

@ -37,10 +37,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef specialize_h
#define specialize_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#include "softfloat.h"
#include <stdbool.h>
#include <stdint.h>
/*----------------------------------------------------------------------------
| Default value for 'softfloat_detectTininess'.
@ -51,48 +51,50 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| The values to return on conversions to 32-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui32_fromPosOverflow UINT32_C(0xFFFFFFFF)
#define ui32_fromNegOverflow UINT32_C(0x0)
#define ui32_fromNaN UINT32_C(0xFFFFFFFF)
#define i32_fromPosOverflow INT64_C(0x7FFFFFFF)
#define i32_fromNegOverflow (-INT64_C(0x7FFFFFFF)-1)
#define i32_fromNaN INT64_C(0x7FFFFFFF)
#define ui32_fromPosOverflow 0xFFFFFFFF
#define ui32_fromNegOverflow 0
#define ui32_fromNaN 0xFFFFFFFF
#define i32_fromPosOverflow 0x7FFFFFFF
#define i32_fromNegOverflow (-0x7FFFFFFF - 1)
#define i32_fromNaN 0x7FFFFFFF
/*----------------------------------------------------------------------------
| The values to return on conversions to 64-bit integer formats that raise an
| invalid exception.
*----------------------------------------------------------------------------*/
#define ui64_fromPosOverflow UINT64_C( 0xFFFFFFFFFFFFFFFF )
#define ui64_fromNegOverflow UINT64_C( 0x0 )
#define ui64_fromNaN UINT64_C( 0xFFFFFFFFFFFFFFFF)
#define i64_fromPosOverflow INT64_C( 0x7FFFFFFFFFFFFFFF)
#define i64_fromNegOverflow (-INT64_C( 0x7FFFFFFFFFFFFFFF)-1)
#define i64_fromNaN INT64_C( 0x7FFFFFFFFFFFFFFF)
#define ui64_fromPosOverflow UINT64_C(0xFFFFFFFFFFFFFFFF)
#define ui64_fromNegOverflow 0
#define ui64_fromNaN UINT64_C(0xFFFFFFFFFFFFFFFF)
#define i64_fromPosOverflow INT64_C(0x7FFFFFFFFFFFFFFF)
#define i64_fromNegOverflow (-INT64_C(0x7FFFFFFFFFFFFFFF) - 1)
#define i64_fromNaN INT64_C(0x7FFFFFFFFFFFFFFF)
/*----------------------------------------------------------------------------
| "Common NaN" structure, used to transfer NaN representations from one format
| to another.
*----------------------------------------------------------------------------*/
struct commonNaN {
bool sign;
#ifdef LITTLEENDIAN
uint64_t v0, v64;
#else
uint64_t v64, v0;
#endif
char _unused;
};
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 16-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF16UI 0xFE00
#define defaultNaNF16UI 0x7E00
/*----------------------------------------------------------------------------
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
| 16-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF16UI( uiA ) ((((uiA) & 0x7E00) == 0x7C00) && ((uiA) & 0x01FF))
#define softfloat_isSigNaNF16UI(uiA) ((((uiA)&0x7E00) == 0x7C00) && ((uiA)&0x01FF))
/*----------------------------------------------------------------------------
| Returns true when 16-bit unsigned integer 'uiA' has the bit pattern of a
| 16-bit brain floating-point (BF16) signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNBF16UI(uiA) ((((uiA)&0x7FC0) == 0x7F80) && ((uiA)&0x003F))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit floating-point NaN, converts
@ -100,13 +102,25 @@ struct commonNaN {
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f16UIToCommonNaN( uint_fast16_t uiA, struct commonNaN *zPtr );
#define softfloat_f16UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x0200)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 16-bit BF16 floating-point NaN, converts
| this NaN to the common NaN form, and stores the resulting common NaN at the
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
#define softfloat_bf16UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x0040)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
#define softfloat_commonNaNToF16UI(aPtr) ((uint_fast16_t)defaultNaNF16UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 16-bit floating-
@ -114,8 +128,18 @@ uint_fast16_t softfloat_commonNaNToF16UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast16_t
softfloat_propagateNaNF16UI( uint_fast16_t uiA, uint_fast16_t uiB );
uint_fast16_t softfloat_propagateNaNF16UI(uint_fast16_t uiA, uint_fast16_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 16-bit BF16 floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNBF16UI 0x7FC0
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 16-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
#define softfloat_commonNaNToBF16UI(aPtr) ((uint_fast16_t)defaultNaNBF16UI)
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 32-bit floating-point NaN.
@ -127,7 +151,7 @@ uint_fast16_t
| 32-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF32UI( uiA ) ((((uiA) & 0x7FC00000) == 0x7F800000) && ((uiA) & 0x003FFFFF))
#define softfloat_isSigNaNF32UI(uiA) ((((uiA)&0x7FC00000) == 0x7F800000) && ((uiA)&0x003FFFFF))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 32-bit floating-point NaN, converts
@ -135,13 +159,15 @@ uint_fast16_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f32UIToCommonNaN( uint_fast32_t uiA, struct commonNaN *zPtr );
#define softfloat_f32UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&0x00400000)) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 32-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
#define softfloat_commonNaNToF32UI(aPtr) ((uint_fast32_t)defaultNaNF32UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 32-bit floating-
@ -149,20 +175,20 @@ uint_fast32_t softfloat_commonNaNToF32UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast32_t
softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB );
uint_fast32_t softfloat_propagateNaNF32UI(uint_fast32_t uiA, uint_fast32_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 64-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF64UI UINT64_C( 0x7FF8000000000000 )
#define defaultNaNF64UI UINT64_C(0x7FF8000000000000)
/*----------------------------------------------------------------------------
| Returns true when 64-bit unsigned integer 'uiA' has the bit pattern of a
| 64-bit floating-point signaling NaN.
| Note: This macro evaluates its argument more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF64UI( uiA ) ((((uiA) & UINT64_C( 0x7FF8000000000000 )) == UINT64_C( 0x7FF0000000000000 )) && ((uiA) & UINT64_C( 0x0007FFFFFFFFFFFF )))
#define softfloat_isSigNaNF64UI(uiA) \
((((uiA)&UINT64_C(0x7FF8000000000000)) == UINT64_C(0x7FF0000000000000)) && ((uiA)&UINT64_C(0x0007FFFFFFFFFFFF)))
/*----------------------------------------------------------------------------
| Assuming 'uiA' has the bit pattern of a 64-bit floating-point NaN, converts
@ -170,13 +196,15 @@ uint_fast32_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void softfloat_f64UIToCommonNaN( uint_fast64_t uiA, struct commonNaN *zPtr );
#define softfloat_f64UIToCommonNaN(uiA, zPtr) \
if(!((uiA)&UINT64_C(0x0008000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 64-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
#define softfloat_commonNaNToF64UI(aPtr) ((uint_fast64_t)defaultNaNF64UI)
/*----------------------------------------------------------------------------
| Interpreting 'uiA' and 'uiB' as the bit patterns of two 64-bit floating-
@ -184,14 +212,13 @@ uint_fast64_t softfloat_commonNaNToF64UI( const struct commonNaN *aPtr );
| the combined NaN result. If either 'uiA' or 'uiB' has the pattern of a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
uint_fast64_t
softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB );
uint_fast64_t softfloat_propagateNaNF64UI(uint_fast64_t uiA, uint_fast64_t uiB);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 80-bit extended floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNExtF80UI64 0xFFFF
#define defaultNaNExtF80UI0 UINT64_C( 0xC000000000000000 )
#define defaultNaNExtF80UI64 0x7FFF
#define defaultNaNExtF80UI0 UINT64_C(0xC000000000000000)
/*----------------------------------------------------------------------------
| Returns true when the 80-bit unsigned integer formed from concatenating
@ -199,7 +226,8 @@ uint_fast64_t
| floating-point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNExtF80UI( uiA64, uiA0 ) ((((uiA64) & 0x7FFF) == 0x7FFF) && ! ((uiA0) & UINT64_C( 0x4000000000000000 )) && ((uiA0) & UINT64_C( 0x3FFFFFFFFFFFFFFF )))
#define softfloat_isSigNaNExtF80UI(uiA64, uiA0) \
((((uiA64)&0x7FFF) == 0x7FFF) && !((uiA0)&UINT64_C(0x4000000000000000)) && ((uiA0)&UINT64_C(0x3FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
@ -215,16 +243,26 @@ uint_fast64_t
| location pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80UIToCommonNaN(
uint_fast16_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
#define softfloat_extF80UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA0)&UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and returns the bit pattern of this value as an unsigned
| integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
#if defined INLINE && !defined softfloat_commonNaNToExtF80UI
INLINE
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr) {
struct uint128 uiZ;
uiZ.v64 = defaultNaNExtF80UI64;
uiZ.v0 = defaultNaNExtF80UI0;
return uiZ;
}
#else
struct uint128 softfloat_commonNaNToExtF80UI(const struct commonNaN* aPtr);
#endif
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -235,19 +273,13 @@ struct uint128 softfloat_commonNaNToExtF80UI( const struct commonNaN *aPtr );
| result. If either original floating-point value is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNExtF80UI(
uint_fast16_t uiA64,
uint_fast64_t uiA0,
uint_fast16_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNExtF80UI(uint_fast16_t uiA64, uint_fast64_t uiA0, uint_fast16_t uiB64, uint_fast64_t uiB0);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI64 UINT64_C( 0xFFFF800000000000 )
#define defaultNaNF128UI0 UINT64_C( 0 )
#define defaultNaNF128UI64 UINT64_C(0x7FFF800000000000)
#define defaultNaNF128UI0 UINT64_C(0)
/*----------------------------------------------------------------------------
| Returns true when the 128-bit unsigned integer formed from concatenating
@ -255,7 +287,8 @@ struct uint128
| point signaling NaN.
| Note: This macro evaluates its arguments more than once.
*----------------------------------------------------------------------------*/
#define softfloat_isSigNaNF128UI( uiA64, uiA0 ) ((((uiA64) & UINT64_C( 0x7FFF800000000000 )) == UINT64_C( 0x7FFF000000000000 )) && ((uiA0) || ((uiA64) & UINT64_C( 0x00007FFFFFFFFFFF ))))
#define softfloat_isSigNaNF128UI(uiA64, uiA0) \
((((uiA64)&UINT64_C(0x7FFF800000000000)) == UINT64_C(0x7FFF000000000000)) && ((uiA0) || ((uiA64)&UINT64_C(0x00007FFFFFFFFFFF))))
/*----------------------------------------------------------------------------
| Assuming the unsigned integer formed from concatenating 'uiA64' and 'uiA0'
@ -264,15 +297,25 @@ struct uint128
| pointed to by 'zPtr'. If the NaN is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
void
softfloat_f128UIToCommonNaN(
uint_fast64_t uiA64, uint_fast64_t uiA0, struct commonNaN *zPtr );
#define softfloat_f128UIToCommonNaN(uiA64, uiA0, zPtr) \
if(!((uiA64)&UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
| NaN, and returns the bit pattern of this value as an unsigned integer.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
#if defined INLINE && !defined softfloat_commonNaNToF128UI
INLINE
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN* aPtr) {
struct uint128 uiZ;
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}
#else
struct uint128 softfloat_commonNaNToF128UI(const struct commonNaN*);
#endif
/*----------------------------------------------------------------------------
| Interpreting the unsigned integer formed from concatenating 'uiA64' and
@ -283,13 +326,7 @@ struct uint128 softfloat_commonNaNToF128UI( const struct commonNaN * );
| If either original floating-point value is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_propagateNaNF128UI(
uint_fast64_t uiA64,
uint_fast64_t uiA0,
uint_fast64_t uiB64,
uint_fast64_t uiB0
);
struct uint128 softfloat_propagateNaNF128UI(uint_fast64_t uiA64, uint_fast64_t uiA0, uint_fast64_t uiB64, uint_fast64_t uiB0);
#else
@ -304,18 +341,24 @@ struct uint128
| common NaN at the location pointed to by 'zPtr'. If the NaN is a signaling
| NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_extF80MToCommonNaN(
const struct extFloat80M *aSPtr, struct commonNaN *zPtr );
#define softfloat_extF80MToCommonNaN(aSPtr, zPtr) \
if(!((aSPtr)->signif & UINT64_C(0x4000000000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into an 80-bit extended
| floating-point NaN, and stores this NaN at the location pointed to by
| 'zSPtr'.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToExtF80M(
const struct commonNaN *aPtr, struct extFloat80M *zSPtr );
#if defined INLINE && !defined softfloat_commonNaNToExtF80M
INLINE
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr) {
zSPtr->signExp = defaultNaNExtF80UI64;
zSPtr->signif = defaultNaNExtF80UI0;
}
#else
void softfloat_commonNaNToExtF80M(const struct commonNaN* aPtr, struct extFloat80M* zSPtr);
#endif
/*----------------------------------------------------------------------------
| Assuming at least one of the two 80-bit extended floating-point values
@ -323,20 +366,15 @@ void
| at the location pointed to by 'zSPtr'. If either original floating-point
| value is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNExtF80M(
const struct extFloat80M *aSPtr,
const struct extFloat80M *bSPtr,
struct extFloat80M *zSPtr
);
void softfloat_propagateNaNExtF80M(const struct extFloat80M* aSPtr, const struct extFloat80M* bSPtr, struct extFloat80M* zSPtr);
/*----------------------------------------------------------------------------
| The bit pattern for a default generated 128-bit floating-point NaN.
*----------------------------------------------------------------------------*/
#define defaultNaNF128UI96 0xFFFF8000
#define defaultNaNF128UI96 0x7FFF8000
#define defaultNaNF128UI64 0
#define defaultNaNF128UI32 0
#define defaultNaNF128UI0 0
#define defaultNaNF128UI0 0
/*----------------------------------------------------------------------------
| Assuming the 128-bit floating-point value pointed to by 'aWPtr' is a NaN,
@ -346,8 +384,9 @@ void
| four 32-bit elements that concatenate in the platform's normal endian order
| to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_f128MToCommonNaN( const uint32_t *aWPtr, struct commonNaN *zPtr );
#define softfloat_f128MToCommonNaN(aWPtr, zPtr) \
if(!((aWPtr)[indexWordHi(4)] & UINT64_C(0x0000800000000000))) \
softfloat_raiseFlags(softfloat_flag_invalid)
/*----------------------------------------------------------------------------
| Converts the common NaN pointed to by 'aPtr' into a 128-bit floating-point
@ -355,8 +394,17 @@ void
| 'zWPtr' points to an array of four 32-bit elements that concatenate in the
| platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_commonNaNToF128M( const struct commonNaN *aPtr, uint32_t *zWPtr );
#if defined INLINE && !defined softfloat_commonNaNToF128M
INLINE
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr) {
zWPtr[indexWord(4, 3)] = defaultNaNF128UI96;
zWPtr[indexWord(4, 2)] = defaultNaNF128UI64;
zWPtr[indexWord(4, 1)] = defaultNaNF128UI32;
zWPtr[indexWord(4, 0)] = defaultNaNF128UI0;
}
#else
void softfloat_commonNaNToF128M(const struct commonNaN* aPtr, uint32_t* zWPtr);
#endif
/*----------------------------------------------------------------------------
| Assuming at least one of the two 128-bit floating-point values pointed to by
@ -366,11 +414,8 @@ void
| and 'zWPtr' points to an array of four 32-bit elements that concatenate in
| the platform's normal endian order to form a 128-bit floating-point value.
*----------------------------------------------------------------------------*/
void
softfloat_propagateNaNF128M(
const uint32_t *aWPtr, const uint32_t *bWPtr, uint32_t *zWPtr );
void softfloat_propagateNaNF128M(const uint32_t* aWPtr, const uint32_t* bWPtr, uint32_t* zWPtr);
#endif
#endif

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, 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 "platform.h"
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
bool bf16_isSignalingNaN( bfloat16_t a )
{
union ui16_bf16 uA;
uA.f = a;
return softfloat_isSigNaNBF16UI( uA.ui );
}

View File

@ -0,0 +1,90 @@
/*============================================================================
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 bf16_to_f32( bfloat16_t a )
{
union ui16_bf16 uA;
uint_fast16_t uiA;
bool sign;
int_fast16_t exp;
uint_fast16_t frac;
struct commonNaN commonNaN;
uint_fast32_t uiZ;
struct exp8_sig16 normExpSig;
union ui32_f32 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA = uA.ui;
sign = signBF16UI( uiA );
exp = expBF16UI( uiA );
frac = fracBF16UI( uiA );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// NaN or Inf
if ( exp == 0xFF ) {
if ( frac ) {
softfloat_bf16UIToCommonNaN( uiA, &commonNaN );
uiZ = softfloat_commonNaNToF32UI( &commonNaN );
} else {
uiZ = packToF32UI( sign, 0xFF, 0 );
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// packToF32UI simply packs bitfields without any numerical change
// which means it can be used directly for any BF16 to f32 conversions which
// does not require bits manipulation
// (that is everything where the 16-bit are just padded right with 16 zeros, including
// subnormal numbers)
uiZ = packToF32UI( sign, exp, ((uint_fast32_t) frac) <<16 );
uiZ:
uZ.ui = uiZ;
return uZ.f;
}

View File

@ -0,0 +1,105 @@
/*============================================================================
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"
#include <inttypes.h>
#include <stdio.h>
bfloat16_t f32_to_bf16( float32_t a )
{
union ui32_f32 uA;
uint_fast32_t uiA;
bool sign;
int_fast16_t exp;
uint_fast32_t frac;
struct commonNaN commonNaN;
uint_fast16_t uiZ, frac16;
union ui16_bf16 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uA.f = a;
uiA = uA.ui;
sign = signF32UI( uiA );
exp = expF32UI( uiA );
frac = fracF32UI( uiA );
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// infinity or NaN cases
if ( exp == 0xFF ) {
if ( frac ) {
// NaN case
softfloat_f32UIToCommonNaN( uiA, &commonNaN );
uiZ = softfloat_commonNaNToBF16UI( &commonNaN );
} else {
// infinity case
uiZ = packToBF16UI( sign, 0xFF, 0 );
}
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// frac is a 24-bit mantissa, right shifted by 9
// In the normal case, (24-9) = 15 are set
frac16 = frac>>9 | ((frac & 0x1FF) != 0);
if ( ! (exp | frac16) ) {
uiZ = packToBF16UI( sign, 0, 0 );
goto uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// softfloat_roundPackToBF16 exponent argument (2nd argument)
// must correspond to the exponent of fracIn[13] bits
// (fracIn is the 3rd and last argument)
uint_fast32_t mask = exp ? 0x4000 : 0x0; // implicit one mask added if input is a normal number
// exponent for the lowest normal and largest subnormal should be equal
// but is not in IEEE encoding so mantissa must be partially normalized
// (by one bit) for subnormal numbers. Such that (exp - 1) corresponds
// to the exponent of frac16[13]
frac16 = frac16 << (exp ? 0 : 1);
return softfloat_roundPackToBF16( sign, exp - 1, frac16 | mask );
uiZ:
uZ.ui = uiZ;
return uZ.f;
}

View File

@ -72,6 +72,9 @@ float16_t f32_to_f16( float32_t a )
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// frac is a 24-bit significand, the bottom 9 bits LSB are extracted and OR-red
// into a sticky flag, the top 15 MSBs are extracted, the LSB of this top slice
// is OR-red with the sticky
frac16 = frac>>9 | ((frac & 0x1FF) != 0);
if ( ! (exp | frac16) ) {
uiZ = packToF16UI( sign, 0, 0 );

View File

@ -37,242 +37,221 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef internals_h
#define internals_h 1
#include <stdbool.h>
#include <stdint.h>
#include "primitives.h"
#include "softfloat_types.h"
#include <stdbool.h>
#include <stdint.h>
union ui16_f16 { uint16_t ui; float16_t f; };
union ui32_f32 { uint32_t ui; float32_t f; };
union ui64_f64 { uint64_t ui; float64_t f; };
#ifdef SOFTFLOAT_FAST_INT64
union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; };
union ui128_f128 { struct uint128 ui; float128_t f; };
#endif
enum {
softfloat_mulAdd_subC = 1,
softfloat_mulAdd_subProd = 2
union ui16_f16 {
uint16_t ui;
float16_t f;
};
union ui16_bf16 {
uint16_t ui;
bfloat16_t f;
};
union ui32_f32 {
uint32_t ui;
float32_t f;
};
union ui64_f64 {
uint64_t ui;
float64_t f;
};
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool );
#ifdef SOFTFLOAT_FAST_INT64
uint_fast64_t
softfloat_roundToUI64(
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
#else
uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool );
union extF80M_extF80 {
struct extFloat80M fM;
extFloat80_t f;
};
union ui128_f128 {
struct uint128 ui;
float128_t f;
};
#endif
int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool );
enum { softfloat_mulAdd_subC = 1, softfloat_mulAdd_subProd = 2 };
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
uint_fast32_t softfloat_roundToUI32(bool, uint_fast64_t, uint_fast8_t, bool);
#ifdef SOFTFLOAT_FAST_INT64
int_fast64_t
softfloat_roundToI64(
bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool );
uint_fast64_t softfloat_roundToUI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
#else
int_fast64_t softfloat_roundMToI64( bool, uint32_t *, uint_fast8_t, bool );
uint_fast64_t softfloat_roundMToUI64(bool, uint32_t*, uint_fast8_t, bool);
#endif
int_fast32_t softfloat_roundToI32(bool, uint_fast64_t, uint_fast8_t, bool);
#ifdef SOFTFLOAT_FAST_INT64
int_fast64_t softfloat_roundToI64(bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool);
#else
int_fast64_t softfloat_roundMToI64(bool, uint32_t*, uint_fast8_t, bool);
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF16UI( a ) ((bool) ((uint16_t) (a)>>15))
#define expF16UI( a ) ((int_fast8_t) ((a)>>10) & 0x1F)
#define fracF16UI( a ) ((a) & 0x03FF)
#define packToF16UI( sign, exp, sig ) (((uint16_t) (sign)<<15) + ((uint16_t) (exp)<<10) + (sig))
*----------------------------------------------------------------------------*/
#define signF16UI(a) ((bool)((uint16_t)(a) >> 15))
#define expF16UI(a) ((int_fast8_t)((a) >> 10) & 0x1F)
#define fracF16UI(a) ((a)&0x03FF)
#define packToF16UI(sign, exp, sig) (((uint16_t)(sign) << 15) + ((uint16_t)(exp) << 10) + (sig))
#define isNaNF16UI( a ) (((~(a) & 0x7C00) == 0) && ((a) & 0x03FF))
#define isNaNF16UI(a) (((~(a)&0x7C00) == 0) && ((a)&0x03FF))
struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; };
struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t );
struct exp8_sig16 {
int_fast8_t exp;
uint_fast16_t sig;
};
struct exp8_sig16 softfloat_normSubnormalF16Sig(uint_fast16_t);
float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t );
float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t );
float16_t softfloat_roundPackToF16(bool, int_fast16_t, uint_fast16_t);
float16_t softfloat_normRoundPackToF16(bool, int_fast16_t, uint_fast16_t);
float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t );
float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t );
float16_t
softfloat_mulAddF16(
uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t );
float16_t softfloat_addMagsF16(uint_fast16_t, uint_fast16_t);
float16_t softfloat_subMagsF16(uint_fast16_t, uint_fast16_t);
float16_t softfloat_mulAddF16(uint_fast16_t, uint_fast16_t, uint_fast16_t, uint_fast8_t);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF32UI( a ) ((bool) ((uint32_t) (a)>>31))
#define expF32UI( a ) ((int_fast16_t) ((a)>>23) & 0xFF)
#define fracF32UI( a ) ((a) & 0x007FFFFF)
#define packToF32UI( sign, exp, sig ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<23) + (sig))
*----------------------------------------------------------------------------*/
#define signBF16UI(a) ((bool)((uint16_t)(a) >> 15))
#define expBF16UI(a) ((int_fast16_t)((a) >> 7) & 0xFF)
#define fracBF16UI(a) ((a)&0x07F)
#define packToBF16UI(sign, exp, sig) (((uint16_t)(sign) << 15) + ((uint16_t)(exp) << 7) + (sig))
#define isNaNF32UI( a ) (((~(a) & 0x7F800000) == 0) && ((a) & 0x007FFFFF))
#define isNaNBF16UI(a) (((~(a)&0x7FC0) == 0) && ((a)&0x07F))
struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; };
struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t );
float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t );
float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t );
float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t );
float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t );
float32_t
softfloat_mulAddF32(
uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t );
bfloat16_t softfloat_roundPackToBF16(bool, int_fast16_t, uint_fast16_t);
struct exp8_sig16 softfloat_normSubnormalBF16Sig(uint_fast16_t);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF64UI( a ) ((bool) ((uint64_t) (a)>>63))
#define expF64UI( a ) ((int_fast16_t) ((a)>>52) & 0x7FF)
#define fracF64UI( a ) ((a) & UINT64_C( 0x000FFFFFFFFFFFFF ))
#define packToF64UI( sign, exp, sig ) ((uint64_t) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<52) + (sig)))
*----------------------------------------------------------------------------*/
#define signF32UI(a) ((bool)((uint32_t)(a) >> 31))
#define expF32UI(a) ((int_fast16_t)((a) >> 23) & 0xFF)
#define fracF32UI(a) ((a)&0x007FFFFF)
#define packToF32UI(sign, exp, sig) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 23) + (sig))
#define isNaNF64UI( a ) (((~(a) & UINT64_C( 0x7FF0000000000000 )) == 0) && ((a) & UINT64_C( 0x000FFFFFFFFFFFFF )))
#define isNaNF32UI(a) (((~(a)&0x7F800000) == 0) && ((a)&0x007FFFFF))
struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; };
struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t );
struct exp16_sig32 {
int_fast16_t exp;
uint_fast32_t sig;
};
struct exp16_sig32 softfloat_normSubnormalF32Sig(uint_fast32_t);
float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t );
float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t );
float32_t softfloat_roundPackToF32(bool, int_fast16_t, uint_fast32_t);
float32_t softfloat_normRoundPackToF32(bool, int_fast16_t, uint_fast32_t);
float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool );
float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool );
float64_t
softfloat_mulAddF64(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
float32_t softfloat_addMagsF32(uint_fast32_t, uint_fast32_t);
float32_t softfloat_subMagsF32(uint_fast32_t, uint_fast32_t);
float32_t softfloat_mulAddF32(uint_fast32_t, uint_fast32_t, uint_fast32_t, uint_fast8_t);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signExtF80UI64( a64 ) ((bool) ((uint16_t) (a64)>>15))
#define expExtF80UI64( a64 ) ((a64) & 0x7FFF)
#define packToExtF80UI64( sign, exp ) ((uint_fast16_t) (sign)<<15 | (exp))
*----------------------------------------------------------------------------*/
#define signF64UI(a) ((bool)((uint64_t)(a) >> 63))
#define expF64UI(a) ((int_fast16_t)((a) >> 52) & 0x7FF)
#define fracF64UI(a) ((a)&UINT64_C(0x000FFFFFFFFFFFFF))
#define packToF64UI(sign, exp, sig) ((uint64_t)(((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 52) + (sig)))
#define isNaNExtF80UI( a64, a0 ) ((((a64) & 0x7FFF) == 0x7FFF) && ((a0) & UINT64_C( 0x7FFFFFFFFFFFFFFF )))
#define isNaNF64UI(a) (((~(a)&UINT64_C(0x7FF0000000000000)) == 0) && ((a)&UINT64_C(0x000FFFFFFFFFFFFF)))
struct exp16_sig64 {
int_fast16_t exp;
uint_fast64_t sig;
};
struct exp16_sig64 softfloat_normSubnormalF64Sig(uint_fast64_t);
float64_t softfloat_roundPackToF64(bool, int_fast16_t, uint_fast64_t);
float64_t softfloat_normRoundPackToF64(bool, int_fast16_t, uint_fast64_t);
float64_t softfloat_addMagsF64(uint_fast64_t, uint_fast64_t, bool);
float64_t softfloat_subMagsF64(uint_fast64_t, uint_fast64_t, bool);
float64_t softfloat_mulAddF64(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signExtF80UI64(a64) ((bool)((uint16_t)(a64) >> 15))
#define expExtF80UI64(a64) ((a64)&0x7FFF)
#define packToExtF80UI64(sign, exp) ((uint_fast16_t)(sign) << 15 | (exp))
#define isNaNExtF80UI(a64, a0) ((((a64)&0x7FFF) == 0x7FFF) && ((a0)&UINT64_C(0x7FFFFFFFFFFFFFFF)))
#ifdef SOFTFLOAT_FAST_INT64
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
*----------------------------------------------------------------------------*/
struct exp32_sig64 { int_fast32_t exp; uint64_t sig; };
struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t );
struct exp32_sig64 {
int_fast32_t exp;
uint64_t sig;
};
struct exp32_sig64 softfloat_normSubnormalExtF80Sig(uint_fast64_t);
extFloat80_t
softfloat_roundPackToExtF80(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
extFloat80_t
softfloat_normRoundPackToExtF80(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t );
extFloat80_t softfloat_roundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
extFloat80_t softfloat_normRoundPackToExtF80(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
extFloat80_t
softfloat_addMagsExtF80(
uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
extFloat80_t
softfloat_subMagsExtF80(
uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool );
extFloat80_t softfloat_addMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
extFloat80_t softfloat_subMagsExtF80(uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF128UI64( a64 ) ((bool) ((uint64_t) (a64)>>63))
#define expF128UI64( a64 ) ((int_fast32_t) ((a64)>>48) & 0x7FFF)
#define fracF128UI64( a64 ) ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))
#define packToF128UI64( sign, exp, sig64 ) (((uint_fast64_t) (sign)<<63) + ((uint_fast64_t) (exp)<<48) + (sig64))
*----------------------------------------------------------------------------*/
#define signF128UI64(a64) ((bool)((uint64_t)(a64) >> 63))
#define expF128UI64(a64) ((int_fast32_t)((a64) >> 48) & 0x7FFF)
#define fracF128UI64(a64) ((a64)&UINT64_C(0x0000FFFFFFFFFFFF))
#define packToF128UI64(sign, exp, sig64) (((uint_fast64_t)(sign) << 63) + ((uint_fast64_t)(exp) << 48) + (sig64))
#define isNaNF128UI( a64, a0 ) (((~(a64) & UINT64_C( 0x7FFF000000000000 )) == 0) && (a0 || ((a64) & UINT64_C( 0x0000FFFFFFFFFFFF ))))
#define isNaNF128UI(a64, a0) (((~(a64)&UINT64_C(0x7FFF000000000000)) == 0) && (a0 || ((a64)&UINT64_C(0x0000FFFFFFFFFFFF))))
struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; };
struct exp32_sig128
softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t );
struct exp32_sig128 {
int_fast32_t exp;
struct uint128 sig;
};
struct exp32_sig128 softfloat_normSubnormalF128Sig(uint_fast64_t, uint_fast64_t);
float128_t
softfloat_roundPackToF128(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t );
float128_t
softfloat_normRoundPackToF128(
bool, int_fast32_t, uint_fast64_t, uint_fast64_t );
float128_t softfloat_roundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t);
float128_t softfloat_normRoundPackToF128(bool, int_fast32_t, uint_fast64_t, uint_fast64_t);
float128_t
softfloat_addMagsF128(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
float128_t
softfloat_subMagsF128(
uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool );
float128_t
softfloat_mulAddF128(
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast64_t,
uint_fast8_t
);
float128_t softfloat_addMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
float128_t softfloat_subMagsF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool);
float128_t softfloat_mulAddF128(uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast8_t);
#else
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
*----------------------------------------------------------------------------*/
bool
softfloat_tryPropagateNaNExtF80M(
const struct extFloat80M *,
const struct extFloat80M *,
struct extFloat80M *
);
void softfloat_invalidExtF80M( struct extFloat80M * );
bool softfloat_tryPropagateNaNExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*);
void softfloat_invalidExtF80M(struct extFloat80M*);
int softfloat_normExtF80SigM( uint64_t * );
int softfloat_normExtF80SigM(uint64_t*);
void
softfloat_roundPackMToExtF80M(
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
void
softfloat_normRoundPackMToExtF80M(
bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * );
void softfloat_roundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
void softfloat_normRoundPackMToExtF80M(bool, int32_t, uint32_t*, uint_fast8_t, struct extFloat80M*);
void
softfloat_addExtF80M(
const struct extFloat80M *,
const struct extFloat80M *,
struct extFloat80M *,
bool
);
void softfloat_addExtF80M(const struct extFloat80M*, const struct extFloat80M*, struct extFloat80M*, bool);
int
softfloat_compareNonnormExtF80M(
const struct extFloat80M *, const struct extFloat80M * );
int softfloat_compareNonnormExtF80M(const struct extFloat80M*, const struct extFloat80M*);
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#define signF128UI96( a96 ) ((bool) ((uint32_t) (a96)>>31))
#define expF128UI96( a96 ) ((int32_t) ((a96)>>16) & 0x7FFF)
#define fracF128UI96( a96 ) ((a96) & 0x0000FFFF)
#define packToF128UI96( sign, exp, sig96 ) (((uint32_t) (sign)<<31) + ((uint32_t) (exp)<<16) + (sig96))
*----------------------------------------------------------------------------*/
#define signF128UI96(a96) ((bool)((uint32_t)(a96) >> 31))
#define expF128UI96(a96) ((int32_t)((a96) >> 16) & 0x7FFF)
#define fracF128UI96(a96) ((a96)&0x0000FFFF)
#define packToF128UI96(sign, exp, sig96) (((uint32_t)(sign) << 31) + ((uint32_t)(exp) << 16) + (sig96))
bool softfloat_isNaNF128M( const uint32_t * );
bool softfloat_isNaNF128M(const uint32_t*);
bool
softfloat_tryPropagateNaNF128M(
const uint32_t *, const uint32_t *, uint32_t * );
void softfloat_invalidF128M( uint32_t * );
bool softfloat_tryPropagateNaNF128M(const uint32_t*, const uint32_t*, uint32_t*);
void softfloat_invalidF128M(uint32_t*);
int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * );
int softfloat_shiftNormSigF128M(const uint32_t*, uint_fast8_t, uint32_t*);
void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * );
void softfloat_roundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
void softfloat_normRoundPackMToF128M(bool, int32_t, uint32_t*, uint32_t*);
void
softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool );
void
softfloat_mulAddF128M(
const uint32_t *,
const uint32_t *,
const uint32_t *,
uint32_t *,
uint_fast8_t
);
void softfloat_addF128M(const uint32_t*, const uint32_t*, uint32_t*, bool);
void softfloat_mulAddF128M(const uint32_t*, const uint32_t*, const uint32_t*, uint32_t*, uint_fast8_t);
#endif
#endif

View File

@ -39,70 +39,70 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef INLINE
#include <stdint.h>
#include "primitiveTypes.h"
#include <stdint.h>
#ifdef SOFTFLOAT_BUILTIN_CLZ
INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
{ return a ? __builtin_clz( a ) - 16 : 16; }
INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) { return a ? __builtin_clz(a) - 16 : 16; }
#define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16
INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
{ return a ? __builtin_clz( a ) : 32; }
INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) { return a ? __builtin_clz(a) : 32; }
#define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32
INLINE uint_fast8_t softfloat_countLeadingZeros64( uint64_t a )
{ return a ? __builtin_clzll( a ) : 64; }
INLINE uint_fast8_t softfloat_countLeadingZeros64(uint64_t a) { return a ? __builtin_clzll(a) : 64; }
#define softfloat_countLeadingZeros64 softfloat_countLeadingZeros64
#endif
#ifdef SOFTFLOAT_INTRINSIC_INT128
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
{
union { unsigned __int128 ui; struct uint128 s; } uZ;
uZ.ui = (unsigned __int128) a * ((uint_fast64_t) b<<32);
INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
union {
unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = (unsigned __int128)a * ((uint_fast64_t)b << 32);
return uZ.s;
}
#define softfloat_mul64ByShifted32To128 softfloat_mul64ByShifted32To128
INLINE struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b )
{
union { unsigned __int128 ui; struct uint128 s; } uZ;
uZ.ui = (unsigned __int128) a * b;
INLINE struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b) {
union {
unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = (unsigned __int128)a * b;
return uZ.s;
}
#define softfloat_mul64To128 softfloat_mul64To128
INLINE
struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
{
union { unsigned __int128 ui; struct uint128 s; } uZ;
uZ.ui = ((unsigned __int128) a64<<64 | a0) * b;
struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) {
union {
unsigned __int128 ui;
struct uint128 s;
} uZ;
uZ.ui = ((unsigned __int128)a64 << 64 | a0) * b;
return uZ.s;
}
#define softfloat_mul128By32 softfloat_mul128By32
INLINE
void
softfloat_mul128To256M(
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr )
{
void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr) {
unsigned __int128 z0, mid1, mid, z128;
z0 = (unsigned __int128) a0 * b0;
mid1 = (unsigned __int128) a64 * b0;
mid = mid1 + (unsigned __int128) a0 * b64;
z128 = (unsigned __int128) a64 * b64;
z128 += (unsigned __int128) (mid < mid1)<<64 | mid>>64;
z0 = (unsigned __int128)a0 * b0;
mid1 = (unsigned __int128)a64 * b0;
mid = mid1 + (unsigned __int128)a0 * b64;
z128 = (unsigned __int128)a64 * b64;
z128 += (unsigned __int128)(mid < mid1) << 64 | mid >> 64;
mid <<= 64;
z0 += mid;
z128 += (z0 < mid);
zPtr[indexWord( 4, 0 )] = z0;
zPtr[indexWord( 4, 1 )] = z0>>64;
zPtr[indexWord( 4, 2 )] = z128;
zPtr[indexWord( 4, 3 )] = z128>>64;
zPtr[indexWord(4, 0)] = z0;
zPtr[indexWord(4, 1)] = z0 >> 64;
zPtr[indexWord(4, 2)] = z128;
zPtr[indexWord(4, 3)] = z128 >> 64;
}
#define softfloat_mul128To256M softfloat_mul128To256M
@ -111,4 +111,3 @@ void
#endif
#endif

View File

@ -42,13 +42,27 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef SOFTFLOAT_FAST_INT64
#ifdef LITTLEENDIAN
struct uint128 { uint64_t v0, v64; };
struct uint64_extra { uint64_t extra, v; };
struct uint128_extra { uint64_t extra; struct uint128 v; };
struct uint128 {
uint64_t v0, v64;
};
struct uint64_extra {
uint64_t extra, v;
};
struct uint128_extra {
uint64_t extra;
struct uint128 v;
};
#else
struct uint128 { uint64_t v64, v0; };
struct uint64_extra { uint64_t v, extra; };
struct uint128_extra { struct uint128 v; uint64_t extra; };
struct uint128 {
uint64_t v64, v0;
};
struct uint64_extra {
uint64_t v, extra;
};
struct uint128_extra {
struct uint128 v;
uint64_t extra;
};
#endif
#endif
@ -59,27 +73,28 @@ struct uint128_extra { struct uint128 v; uint64_t extra; };
*----------------------------------------------------------------------------*/
#ifdef LITTLEENDIAN
#define wordIncr 1
#define indexWord( total, n ) (n)
#define indexWordHi( total ) ((total) - 1)
#define indexWordLo( total ) 0
#define indexMultiword( total, m, n ) (n)
#define indexMultiwordHi( total, n ) ((total) - (n))
#define indexMultiwordLo( total, n ) 0
#define indexMultiwordHiBut( total, n ) (n)
#define indexMultiwordLoBut( total, n ) 0
#define INIT_UINTM4( v3, v2, v1, v0 ) { v0, v1, v2, v3 }
#define indexWord(total, n) (n)
#define indexWordHi(total) ((total)-1)
#define indexWordLo(total) 0
#define indexMultiword(total, m, n) (n)
#define indexMultiwordHi(total, n) ((total) - (n))
#define indexMultiwordLo(total, n) 0
#define indexMultiwordHiBut(total, n) (n)
#define indexMultiwordLoBut(total, n) 0
#define INIT_UINTM4(v3, v2, v1, v0) \
{ v0, v1, v2, v3 }
#else
#define wordIncr -1
#define indexWord( total, n ) ((total) - 1 - (n))
#define indexWordHi( total ) 0
#define indexWordLo( total ) ((total) - 1)
#define indexMultiword( total, m, n ) ((total) - 1 - (m))
#define indexMultiwordHi( total, n ) 0
#define indexMultiwordLo( total, n ) ((total) - (n))
#define indexMultiwordHiBut( total, n ) 0
#define indexMultiwordLoBut( total, n ) (n)
#define INIT_UINTM4( v3, v2, v1, v0 ) { v3, v2, v1, v0 }
#define indexWord(total, n) ((total)-1 - (n))
#define indexWordHi(total) 0
#define indexWordLo(total) ((total)-1)
#define indexMultiword(total, m, n) ((total)-1 - (m))
#define indexMultiwordHi(total, n) 0
#define indexMultiwordLo(total, n) ((total) - (n))
#define indexMultiwordHiBut(total, n) 0
#define indexMultiwordLoBut(total, n) (n)
#define INIT_UINTM4(v3, v2, v1, v0) \
{ v3, v2, v1, v0 }
#endif
#endif

View File

@ -37,9 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef primitives_h
#define primitives_h 1
#include "primitiveTypes.h"
#include <stdbool.h>
#include <stdint.h>
#include "primitiveTypes.h"
#ifndef softfloat_shortShiftRightJam64
/*----------------------------------------------------------------------------
@ -50,10 +50,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist )
{ return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); }
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist) { return a >> dist | ((a & (((uint_fast64_t)1 << dist) - 1)) != 0); }
#else
uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
uint64_t softfloat_shortShiftRightJam64(uint64_t a, uint_fast8_t dist);
#endif
#endif
@ -68,13 +67,11 @@ uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist );
| is zero or nonzero.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist )
{
return
(dist < 31) ? a>>dist | ((uint32_t) (a<<(-dist & 31)) != 0) : (a != 0);
INLINE uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist) {
return (dist < 31) ? a >> dist | ((uint32_t)(a << (-dist & 31)) != 0) : (a != 0);
}
#else
uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
uint32_t softfloat_shiftRightJam32(uint32_t a, uint_fast16_t dist);
#endif
#endif
@ -89,13 +86,11 @@ uint32_t softfloat_shiftRightJam32( uint32_t a, uint_fast16_t dist );
| is zero or nonzero.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist )
{
return
(dist < 63) ? a>>dist | ((uint64_t) (a<<(-dist & 63)) != 0) : (a != 0);
INLINE uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist) {
return (dist < 63) ? a >> dist | ((uint64_t)(a << (-dist & 63)) != 0) : (a != 0);
}
#else
uint64_t softfloat_shiftRightJam64( uint64_t a, uint_fast32_t dist );
uint64_t softfloat_shiftRightJam64(uint64_t a, uint_fast32_t dist);
#endif
#endif
@ -112,10 +107,9 @@ extern const uint_least8_t softfloat_countLeadingZeros8[256];
| 'a'. If 'a' is zero, 16 is returned.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
{
INLINE uint_fast8_t softfloat_countLeadingZeros16(uint16_t a) {
uint_fast8_t count = 8;
if ( 0x100 <= a ) {
if(0x100 <= a) {
count = 0;
a >>= 8;
}
@ -123,7 +117,7 @@ INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a )
return count;
}
#else
uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
uint_fast8_t softfloat_countLeadingZeros16(uint16_t a);
#endif
#endif
@ -133,22 +127,21 @@ uint_fast8_t softfloat_countLeadingZeros16( uint16_t a );
| 'a'. If 'a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a )
{
INLINE uint_fast8_t softfloat_countLeadingZeros32(uint32_t a) {
uint_fast8_t count = 0;
if ( a < 0x10000 ) {
if(a < 0x10000) {
count = 16;
a <<= 16;
}
if ( a < 0x1000000 ) {
if(a < 0x1000000) {
count += 8;
a <<= 8;
}
count += softfloat_countLeadingZeros8[a>>24];
count += softfloat_countLeadingZeros8[a >> 24];
return count;
}
#else
uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
uint_fast8_t softfloat_countLeadingZeros32(uint32_t a);
#endif
#endif
@ -157,7 +150,7 @@ uint_fast8_t softfloat_countLeadingZeros32( uint32_t a );
| Returns the number of leading 0 bits before the most-significant 1 bit of
| 'a'. If 'a' is zero, 64 is returned.
*----------------------------------------------------------------------------*/
uint_fast8_t softfloat_countLeadingZeros64( uint64_t a );
uint_fast8_t softfloat_countLeadingZeros64(uint64_t a);
#endif
extern const uint16_t softfloat_approxRecip_1k0s[16];
@ -176,9 +169,9 @@ extern const uint16_t softfloat_approxRecip_1k1s[16];
| (units in the last place).
*----------------------------------------------------------------------------*/
#ifdef SOFTFLOAT_FAST_DIV64TO32
#define softfloat_approxRecip32_1( a ) ((uint32_t) (UINT64_C( 0x7FFFFFFFFFFFFFFF ) / (uint32_t) (a)))
#define softfloat_approxRecip32_1(a) ((uint32_t)(UINT64_C(0x7FFFFFFFFFFFFFFF) / (uint32_t)(a)))
#else
uint32_t softfloat_approxRecip32_1( uint32_t a );
uint32_t softfloat_approxRecip32_1(uint32_t a);
#endif
#endif
@ -204,7 +197,7 @@ extern const uint16_t softfloat_approxRecipSqrt_1k1s[16];
| returned is also always within the range 0.5 to 1; thus, the most-
| significant bit of the result is always set.
*----------------------------------------------------------------------------*/
uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
uint32_t softfloat_approxRecipSqrt32_1(unsigned int oddExpA, uint32_t a);
#endif
#ifdef SOFTFLOAT_FAST_INT64
@ -222,10 +215,9 @@ uint32_t softfloat_approxRecipSqrt32_1( unsigned int oddExpA, uint32_t a );
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (1 <= INLINE_LEVEL)
INLINE
bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{ return (a64 == b64) && (a0 == b0); }
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 == b64) && (a0 == b0); }
#else
bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
bool softfloat_eq128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif
#endif
@ -237,10 +229,9 @@ bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{ return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); }
#else
bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
bool softfloat_le128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif
#endif
@ -252,10 +243,9 @@ bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{ return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); }
#else
bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
bool softfloat_lt128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif
#endif
@ -266,17 +256,14 @@ bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
struct uint128
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
struct uint128 z;
z.v64 = a64<<dist | a0>>(-dist & 63);
z.v0 = a0<<dist;
z.v64 = a64 << dist | a0 >> (-dist & 63);
z.v0 = a0 << dist;
return z;
}
#else
struct uint128
softfloat_shortShiftLeft128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
struct uint128 softfloat_shortShiftLeft128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
#endif
#endif
@ -287,17 +274,14 @@ struct uint128
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
struct uint128
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
struct uint128 z;
z.v64 = a64>>dist;
z.v0 = a64<<(-dist & 63) | a0>>dist;
z.v64 = a64 >> dist;
z.v0 = a64 << (-dist & 63) | a0 >> dist;
return z;
}
#else
struct uint128
softfloat_shortShiftRight128( uint64_t a64, uint64_t a0, uint_fast8_t dist );
struct uint128 softfloat_shortShiftRight128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
#endif
#endif
@ -308,19 +292,14 @@ struct uint128
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
struct uint64_extra
softfloat_shortShiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast8_t dist )
{
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist) {
struct uint64_extra z;
z.v = a>>dist;
z.extra = a<<(-dist & 63) | (extra != 0);
z.v = a >> dist;
z.extra = a << (-dist & 63) | (extra != 0);
return z;
}
#else
struct uint64_extra
softfloat_shortShiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast8_t dist );
struct uint64_extra softfloat_shortShiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast8_t dist);
#endif
#endif
@ -334,22 +313,15 @@ struct uint64_extra
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE
struct uint128
softfloat_shortShiftRightJam128(
uint64_t a64, uint64_t a0, uint_fast8_t dist )
{
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist) {
uint_fast8_t negDist = -dist;
struct uint128 z;
z.v64 = a64>>dist;
z.v0 =
a64<<(negDist & 63) | a0>>dist
| ((uint64_t) (a0<<(negDist & 63)) != 0);
z.v64 = a64 >> dist;
z.v0 = a64 << (negDist & 63) | a0 >> dist | ((uint64_t)(a0 << (negDist & 63)) != 0);
return z;
}
#else
struct uint128
softfloat_shortShiftRightJam128(
uint64_t a64, uint64_t a0, uint_fast8_t dist );
struct uint128 softfloat_shortShiftRightJam128(uint64_t a64, uint64_t a0, uint_fast8_t dist);
#endif
#endif
@ -360,21 +332,16 @@ struct uint128
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE
struct uint128_extra
softfloat_shortShiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist )
{
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist) {
uint_fast8_t negDist = -dist;
struct uint128_extra z;
z.v.v64 = a64>>dist;
z.v.v0 = a64<<(negDist & 63) | a0>>dist;
z.extra = a0<<(negDist & 63) | (extra != 0);
z.v.v64 = a64 >> dist;
z.v.v0 = a64 << (negDist & 63) | a0 >> dist;
z.extra = a0 << (negDist & 63) | (extra != 0);
return z;
}
#else
struct uint128_extra
softfloat_shortShiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist );
struct uint128_extra softfloat_shortShiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast8_t dist);
#endif
#endif
@ -397,14 +364,11 @@ struct uint128_extra
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
INLINE
struct uint64_extra
softfloat_shiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast32_t dist )
{
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist) {
struct uint64_extra z;
if ( dist < 64 ) {
z.v = a>>dist;
z.extra = a<<(-dist & 63);
if(dist < 64) {
z.v = a >> dist;
z.extra = a << (-dist & 63);
} else {
z.v = 0;
z.extra = (dist == 64) ? a : (a != 0);
@ -413,9 +377,7 @@ struct uint64_extra
return z;
}
#else
struct uint64_extra
softfloat_shiftRightJam64Extra(
uint64_t a, uint64_t extra, uint_fast32_t dist );
struct uint64_extra softfloat_shiftRightJam64Extra(uint64_t a, uint64_t extra, uint_fast32_t dist);
#endif
#endif
@ -430,8 +392,7 @@ struct uint64_extra
| greater than 128, the result will be either 0 or 1, depending on whether the
| original 128 bits are all zeros.
*----------------------------------------------------------------------------*/
struct uint128
softfloat_shiftRightJam128( uint64_t a64, uint64_t a0, uint_fast32_t dist );
struct uint128 softfloat_shiftRightJam128(uint64_t a64, uint64_t a0, uint_fast32_t dist);
#endif
#ifndef softfloat_shiftRightJam128Extra
@ -452,9 +413,7 @@ struct uint128
| is modified as described above and returned in the 'extra' field of the
| result.)
*----------------------------------------------------------------------------*/
struct uint128_extra
softfloat_shiftRightJam128Extra(
uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist );
struct uint128_extra softfloat_shiftRightJam128Extra(uint64_t a64, uint64_t a0, uint64_t extra, uint_fast32_t dist);
#endif
#ifndef softfloat_shiftRightJam256M
@ -470,9 +429,7 @@ struct uint128_extra
| is greater than 256, the stored result will be either 0 or 1, depending on
| whether the original 256 bits are all zeros.
*----------------------------------------------------------------------------*/
void
softfloat_shiftRightJam256M(
const uint64_t *aPtr, uint_fast32_t dist, uint64_t *zPtr );
void softfloat_shiftRightJam256M(const uint64_t* aPtr, uint_fast32_t dist, uint64_t* zPtr);
#endif
#ifndef softfloat_add128
@ -483,17 +440,14 @@ void
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
struct uint128
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
struct uint128 z;
z.v0 = a0 + b0;
z.v64 = a64 + b64 + (z.v0 < a0);
return z;
}
#else
struct uint128
softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
struct uint128 softfloat_add128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif
#endif
@ -505,9 +459,7 @@ struct uint128
| an array of four 64-bit elements that concatenate in the platform's normal
| endian order to form a 256-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_add256M(
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
void softfloat_add256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
#endif
#ifndef softfloat_sub128
@ -518,9 +470,7 @@ void
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
struct uint128
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 )
{
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0) {
struct uint128 z;
z.v0 = a0 - b0;
z.v64 = a64 - b64;
@ -528,8 +478,7 @@ struct uint128
return z;
}
#else
struct uint128
softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 );
struct uint128 softfloat_sub128(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0);
#endif
#endif
@ -542,9 +491,7 @@ struct uint128
| 64-bit elements that concatenate in the platform's normal endian order to
| form a 256-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_sub256M(
const uint64_t *aPtr, const uint64_t *bPtr, uint64_t *zPtr );
void softfloat_sub256M(const uint64_t* aPtr, const uint64_t* bPtr, uint64_t* zPtr);
#endif
#ifndef softfloat_mul64ByShifted32To128
@ -552,17 +499,16 @@ void
| Returns the 128-bit product of 'a', 'b', and 2^32.
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (3 <= INLINE_LEVEL)
INLINE struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b )
{
INLINE struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b) {
uint_fast64_t mid;
struct uint128 z;
mid = (uint_fast64_t) (uint32_t) a * b;
z.v0 = mid<<32;
z.v64 = (uint_fast64_t) (uint32_t) (a>>32) * b + (mid>>32);
mid = (uint_fast64_t)(uint32_t)a * b;
z.v0 = mid << 32;
z.v64 = (uint_fast64_t)(uint32_t)(a >> 32) * b + (mid >> 32);
return z;
}
#else
struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
struct uint128 softfloat_mul64ByShifted32To128(uint64_t a, uint32_t b);
#endif
#endif
@ -570,7 +516,7 @@ struct uint128 softfloat_mul64ByShifted32To128( uint64_t a, uint32_t b );
/*----------------------------------------------------------------------------
| Returns the 128-bit product of 'a' and 'b'.
*----------------------------------------------------------------------------*/
struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
struct uint128 softfloat_mul64To128(uint64_t a, uint64_t b);
#endif
#ifndef softfloat_mul128By32
@ -581,19 +527,18 @@ struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b );
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (4 <= INLINE_LEVEL)
INLINE
struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b )
{
struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b) {
struct uint128 z;
uint_fast64_t mid;
uint_fast32_t carry;
z.v0 = a0 * b;
mid = (uint_fast64_t) (uint32_t) (a0>>32) * b;
carry = (uint32_t) ((uint_fast32_t) (z.v0>>32) - (uint_fast32_t) mid);
z.v64 = a64 * b + (uint_fast32_t) ((mid + carry)>>32);
mid = (uint_fast64_t)(uint32_t)(a0 >> 32) * b;
carry = (uint32_t)((uint_fast32_t)(z.v0 >> 32) - (uint_fast32_t)mid);
z.v64 = a64 * b + (uint_fast32_t)((mid + carry) >> 32);
return z;
}
#else
struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
struct uint128 softfloat_mul128By32(uint64_t a64, uint64_t a0, uint32_t b);
#endif
#endif
@ -605,9 +550,7 @@ struct uint128 softfloat_mul128By32( uint64_t a64, uint64_t a0, uint32_t b );
| Argument 'zPtr' points to an array of four 64-bit elements that concatenate
| in the platform's normal endian order to form a 256-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_mul128To256M(
uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t *zPtr );
void softfloat_mul128To256M(uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0, uint64_t* zPtr);
#endif
#else
@ -626,7 +569,7 @@ void
| Each of 'aPtr' and 'bPtr' points to an array of three 32-bit elements that
| concatenate in the platform's normal endian order to form a 96-bit integer.
*----------------------------------------------------------------------------*/
int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
int_fast8_t softfloat_compare96M(const uint32_t* aPtr, const uint32_t* bPtr);
#endif
#ifndef softfloat_compare128M
@ -638,8 +581,7 @@ int_fast8_t softfloat_compare96M( const uint32_t *aPtr, const uint32_t *bPtr );
| Each of 'aPtr' and 'bPtr' points to an array of four 32-bit elements that
| concatenate in the platform's normal endian order to form a 128-bit integer.
*----------------------------------------------------------------------------*/
int_fast8_t
softfloat_compare128M( const uint32_t *aPtr, const uint32_t *bPtr );
int_fast8_t softfloat_compare128M(const uint32_t* aPtr, const uint32_t* bPtr);
#endif
#ifndef softfloat_shortShiftLeft64To96M
@ -652,19 +594,14 @@ int_fast8_t
*----------------------------------------------------------------------------*/
#if defined INLINE_LEVEL && (2 <= INLINE_LEVEL)
INLINE
void
softfloat_shortShiftLeft64To96M(
uint64_t a, uint_fast8_t dist, uint32_t *zPtr )
{
zPtr[indexWord( 3, 0 )] = (uint32_t) a<<dist;
void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr) {
zPtr[indexWord(3, 0)] = (uint32_t)a << dist;
a >>= 32 - dist;
zPtr[indexWord( 3, 2 )] = a>>32;
zPtr[indexWord( 3, 1 )] = a;
zPtr[indexWord(3, 2)] = a >> 32;
zPtr[indexWord(3, 1)] = a;
}
#else
void
softfloat_shortShiftLeft64To96M(
uint64_t a, uint_fast8_t dist, uint32_t *zPtr );
void softfloat_shortShiftLeft64To96M(uint64_t a, uint_fast8_t dist, uint32_t* zPtr);
#endif
#endif
@ -678,13 +615,7 @@ void
| that concatenate in the platform's normal endian order to form an N-bit
| integer.
*----------------------------------------------------------------------------*/
void
softfloat_shortShiftLeftM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint_fast8_t dist,
uint32_t *zPtr
);
void softfloat_shortShiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
#endif
#ifndef softfloat_shortShiftLeft96M
@ -692,7 +623,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftLeftM' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftLeft96M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 3, aPtr, dist, zPtr )
#define softfloat_shortShiftLeft96M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(3, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shortShiftLeft128M
@ -700,7 +631,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftLeftM' with
| 'size_words' = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftLeft128M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 4, aPtr, dist, zPtr )
#define softfloat_shortShiftLeft128M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(4, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shortShiftLeft160M
@ -708,7 +639,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftLeftM' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftLeft160M( aPtr, dist, zPtr ) softfloat_shortShiftLeftM( 5, aPtr, dist, zPtr )
#define softfloat_shortShiftLeft160M(aPtr, dist, zPtr) softfloat_shortShiftLeftM(5, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftLeftM
@ -722,13 +653,7 @@ void
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
| greater than N, the stored result will be 0.
*----------------------------------------------------------------------------*/
void
softfloat_shiftLeftM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
void softfloat_shiftLeftM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
#endif
#ifndef softfloat_shiftLeft96M
@ -736,7 +661,7 @@ void
| This function or macro is the same as 'softfloat_shiftLeftM' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_shiftLeft96M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 3, aPtr, dist, zPtr )
#define softfloat_shiftLeft96M(aPtr, dist, zPtr) softfloat_shiftLeftM(3, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftLeft128M
@ -744,7 +669,7 @@ void
| This function or macro is the same as 'softfloat_shiftLeftM' with
| 'size_words' = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_shiftLeft128M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 4, aPtr, dist, zPtr )
#define softfloat_shiftLeft128M(aPtr, dist, zPtr) softfloat_shiftLeftM(4, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftLeft160M
@ -752,7 +677,7 @@ void
| This function or macro is the same as 'softfloat_shiftLeftM' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_shiftLeft160M( aPtr, dist, zPtr ) softfloat_shiftLeftM( 5, aPtr, dist, zPtr )
#define softfloat_shiftLeft160M(aPtr, dist, zPtr) softfloat_shiftLeftM(5, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shortShiftRightM
@ -765,13 +690,7 @@ void
| that concatenate in the platform's normal endian order to form an N-bit
| integer.
*----------------------------------------------------------------------------*/
void
softfloat_shortShiftRightM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint_fast8_t dist,
uint32_t *zPtr
);
void softfloat_shortShiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint_fast8_t dist, uint32_t* zPtr);
#endif
#ifndef softfloat_shortShiftRight128M
@ -779,7 +698,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftRightM' with
| 'size_words' = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftRight128M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 4, aPtr, dist, zPtr )
#define softfloat_shortShiftRight128M(aPtr, dist, zPtr) softfloat_shortShiftRightM(4, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shortShiftRight160M
@ -787,7 +706,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftRightM' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftRight160M( aPtr, dist, zPtr ) softfloat_shortShiftRightM( 5, aPtr, dist, zPtr )
#define softfloat_shortShiftRight160M(aPtr, dist, zPtr) softfloat_shortShiftRightM(5, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shortShiftRightJamM
@ -801,9 +720,7 @@ void
| to a 'size_words'-long array of 32-bit elements that concatenate in the
| platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_shortShiftRightJamM(
uint_fast8_t, const uint32_t *, uint_fast8_t, uint32_t * );
void softfloat_shortShiftRightJamM(uint_fast8_t, const uint32_t*, uint_fast8_t, uint32_t*);
#endif
#ifndef softfloat_shortShiftRightJam160M
@ -811,7 +728,7 @@ void
| This function or macro is the same as 'softfloat_shortShiftRightJamM' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_shortShiftRightJam160M( aPtr, dist, zPtr ) softfloat_shortShiftRightJamM( 5, aPtr, dist, zPtr )
#define softfloat_shortShiftRightJam160M(aPtr, dist, zPtr) softfloat_shortShiftRightJamM(5, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftRightM
@ -825,13 +742,7 @@ void
| The value of 'dist' can be arbitrarily large. In particular, if 'dist' is
| greater than N, the stored result will be 0.
*----------------------------------------------------------------------------*/
void
softfloat_shiftRightM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
void softfloat_shiftRightM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
#endif
#ifndef softfloat_shiftRight96M
@ -839,7 +750,7 @@ void
| This function or macro is the same as 'softfloat_shiftRightM' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_shiftRight96M( aPtr, dist, zPtr ) softfloat_shiftRightM( 3, aPtr, dist, zPtr )
#define softfloat_shiftRight96M(aPtr, dist, zPtr) softfloat_shiftRightM(3, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftRightJamM
@ -856,13 +767,7 @@ void
| is greater than N, the stored result will be either 0 or 1, depending on
| whether the original N bits are all zeros.
*----------------------------------------------------------------------------*/
void
softfloat_shiftRightJamM(
uint_fast8_t size_words,
const uint32_t *aPtr,
uint32_t dist,
uint32_t *zPtr
);
void softfloat_shiftRightJamM(uint_fast8_t size_words, const uint32_t* aPtr, uint32_t dist, uint32_t* zPtr);
#endif
#ifndef softfloat_shiftRightJam96M
@ -870,7 +775,7 @@ void
| This function or macro is the same as 'softfloat_shiftRightJamM' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_shiftRightJam96M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 3, aPtr, dist, zPtr )
#define softfloat_shiftRightJam96M(aPtr, dist, zPtr) softfloat_shiftRightJamM(3, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftRightJam128M
@ -878,7 +783,7 @@ void
| This function or macro is the same as 'softfloat_shiftRightJamM' with
| 'size_words' = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_shiftRightJam128M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 4, aPtr, dist, zPtr )
#define softfloat_shiftRightJam128M(aPtr, dist, zPtr) softfloat_shiftRightJamM(4, aPtr, dist, zPtr)
#endif
#ifndef softfloat_shiftRightJam160M
@ -886,7 +791,7 @@ void
| This function or macro is the same as 'softfloat_shiftRightJamM' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_shiftRightJam160M( aPtr, dist, zPtr ) softfloat_shiftRightJamM( 5, aPtr, dist, zPtr )
#define softfloat_shiftRightJam160M(aPtr, dist, zPtr) softfloat_shiftRightJamM(5, aPtr, dist, zPtr)
#endif
#ifndef softfloat_addM
@ -898,13 +803,7 @@ void
| elements that concatenate in the platform's normal endian order to form an
| N-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_addM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint32_t *zPtr
);
void softfloat_addM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
#endif
#ifndef softfloat_add96M
@ -912,7 +811,7 @@ void
| This function or macro is the same as 'softfloat_addM' with 'size_words'
| = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_add96M( aPtr, bPtr, zPtr ) softfloat_addM( 3, aPtr, bPtr, zPtr )
#define softfloat_add96M(aPtr, bPtr, zPtr) softfloat_addM(3, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_add128M
@ -920,7 +819,7 @@ void
| This function or macro is the same as 'softfloat_addM' with 'size_words'
| = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_add128M( aPtr, bPtr, zPtr ) softfloat_addM( 4, aPtr, bPtr, zPtr )
#define softfloat_add128M(aPtr, bPtr, zPtr) softfloat_addM(4, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_add160M
@ -928,7 +827,7 @@ void
| This function or macro is the same as 'softfloat_addM' with 'size_words'
| = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_add160M( aPtr, bPtr, zPtr ) softfloat_addM( 5, aPtr, bPtr, zPtr )
#define softfloat_add160M(aPtr, bPtr, zPtr) softfloat_addM(5, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_addCarryM
@ -940,14 +839,7 @@ void
| points to a 'size_words'-long array of 32-bit elements that concatenate in
| the platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/
uint_fast8_t
softfloat_addCarryM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint_fast8_t carry,
uint32_t *zPtr
);
uint_fast8_t softfloat_addCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry, uint32_t* zPtr);
#endif
#ifndef softfloat_addComplCarryM
@ -956,14 +848,8 @@ uint_fast8_t
| the value of the unsigned integer pointed to by 'bPtr' is bit-wise completed
| before the addition.
*----------------------------------------------------------------------------*/
uint_fast8_t
softfloat_addComplCarryM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint_fast8_t carry,
uint32_t *zPtr
);
uint_fast8_t softfloat_addComplCarryM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint_fast8_t carry,
uint32_t* zPtr);
#endif
#ifndef softfloat_addComplCarry96M
@ -971,7 +857,7 @@ uint_fast8_t
| This function or macro is the same as 'softfloat_addComplCarryM' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_addComplCarry96M( aPtr, bPtr, carry, zPtr ) softfloat_addComplCarryM( 3, aPtr, bPtr, carry, zPtr )
#define softfloat_addComplCarry96M(aPtr, bPtr, carry, zPtr) softfloat_addComplCarryM(3, aPtr, bPtr, carry, zPtr)
#endif
#ifndef softfloat_negXM
@ -981,7 +867,7 @@ uint_fast8_t
| points to a 'size_words'-long array of 32-bit elements that concatenate in
| the platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/
void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
void softfloat_negXM(uint_fast8_t size_words, uint32_t* zPtr);
#endif
#ifndef softfloat_negX96M
@ -989,7 +875,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_negXM' with 'size_words'
| = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_negX96M( zPtr ) softfloat_negXM( 3, zPtr )
#define softfloat_negX96M(zPtr) softfloat_negXM(3, zPtr)
#endif
#ifndef softfloat_negX128M
@ -997,7 +883,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_negXM' with 'size_words'
| = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_negX128M( zPtr ) softfloat_negXM( 4, zPtr )
#define softfloat_negX128M(zPtr) softfloat_negXM(4, zPtr)
#endif
#ifndef softfloat_negX160M
@ -1005,7 +891,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_negXM' with 'size_words'
| = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_negX160M( zPtr ) softfloat_negXM( 5, zPtr )
#define softfloat_negX160M(zPtr) softfloat_negXM(5, zPtr)
#endif
#ifndef softfloat_negX256M
@ -1013,7 +899,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_negXM' with 'size_words'
| = 8 (N = 256).
*----------------------------------------------------------------------------*/
#define softfloat_negX256M( zPtr ) softfloat_negXM( 8, zPtr )
#define softfloat_negX256M(zPtr) softfloat_negXM(8, zPtr)
#endif
#ifndef softfloat_sub1XM
@ -1024,7 +910,7 @@ void softfloat_negXM( uint_fast8_t size_words, uint32_t *zPtr );
| elements that concatenate in the platform's normal endian order to form an
| N-bit integer.
*----------------------------------------------------------------------------*/
void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
void softfloat_sub1XM(uint_fast8_t size_words, uint32_t* zPtr);
#endif
#ifndef softfloat_sub1X96M
@ -1032,7 +918,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
| = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_sub1X96M( zPtr ) softfloat_sub1XM( 3, zPtr )
#define softfloat_sub1X96M(zPtr) softfloat_sub1XM(3, zPtr)
#endif
#ifndef softfloat_sub1X160M
@ -1040,7 +926,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
| This function or macro is the same as 'softfloat_sub1XM' with 'size_words'
| = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_sub1X160M( zPtr ) softfloat_sub1XM( 5, zPtr )
#define softfloat_sub1X160M(zPtr) softfloat_sub1XM(5, zPtr)
#endif
#ifndef softfloat_subM
@ -1052,13 +938,7 @@ void softfloat_sub1XM( uint_fast8_t size_words, uint32_t *zPtr );
| array of 32-bit elements that concatenate in the platform's normal endian
| order to form an N-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_subM(
uint_fast8_t size_words,
const uint32_t *aPtr,
const uint32_t *bPtr,
uint32_t *zPtr
);
void softfloat_subM(uint_fast8_t size_words, const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
#endif
#ifndef softfloat_sub96M
@ -1066,7 +946,7 @@ void
| This function or macro is the same as 'softfloat_subM' with 'size_words'
| = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_sub96M( aPtr, bPtr, zPtr ) softfloat_subM( 3, aPtr, bPtr, zPtr )
#define softfloat_sub96M(aPtr, bPtr, zPtr) softfloat_subM(3, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_sub128M
@ -1074,7 +954,7 @@ void
| This function or macro is the same as 'softfloat_subM' with 'size_words'
| = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_sub128M( aPtr, bPtr, zPtr ) softfloat_subM( 4, aPtr, bPtr, zPtr )
#define softfloat_sub128M(aPtr, bPtr, zPtr) softfloat_subM(4, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_sub160M
@ -1082,7 +962,7 @@ void
| This function or macro is the same as 'softfloat_subM' with 'size_words'
| = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_sub160M( aPtr, bPtr, zPtr ) softfloat_subM( 5, aPtr, bPtr, zPtr )
#define softfloat_sub160M(aPtr, bPtr, zPtr) softfloat_subM(5, aPtr, bPtr, zPtr)
#endif
#ifndef softfloat_mul64To128M
@ -1092,7 +972,7 @@ void
| elements that concatenate in the platform's normal endian order to form a
| 128-bit integer.
*----------------------------------------------------------------------------*/
void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
void softfloat_mul64To128M(uint64_t a, uint64_t b, uint32_t* zPtr);
#endif
#ifndef softfloat_mul128MTo256M
@ -1104,9 +984,7 @@ void softfloat_mul64To128M( uint64_t a, uint64_t b, uint32_t *zPtr );
| Argument 'zPtr' points to an array of eight 32-bit elements that concatenate
| to form a 256-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_mul128MTo256M(
const uint32_t *aPtr, const uint32_t *bPtr, uint32_t *zPtr );
void softfloat_mul128MTo256M(const uint32_t* aPtr, const uint32_t* bPtr, uint32_t* zPtr);
#endif
#ifndef softfloat_remStepMBy32
@ -1119,15 +997,8 @@ void
| to a 'size_words'-long array of 32-bit elements that concatenate in the
| platform's normal endian order to form an N-bit integer.
*----------------------------------------------------------------------------*/
void
softfloat_remStepMBy32(
uint_fast8_t size_words,
const uint32_t *remPtr,
uint_fast8_t dist,
const uint32_t *bPtr,
uint32_t q,
uint32_t *zPtr
);
void softfloat_remStepMBy32(uint_fast8_t size_words, const uint32_t* remPtr, uint_fast8_t dist, const uint32_t* bPtr, uint32_t q,
uint32_t* zPtr);
#endif
#ifndef softfloat_remStep96MBy32
@ -1135,7 +1006,7 @@ void
| This function or macro is the same as 'softfloat_remStepMBy32' with
| 'size_words' = 3 (N = 96).
*----------------------------------------------------------------------------*/
#define softfloat_remStep96MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 3, remPtr, dist, bPtr, q, zPtr )
#define softfloat_remStep96MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(3, remPtr, dist, bPtr, q, zPtr)
#endif
#ifndef softfloat_remStep128MBy32
@ -1143,7 +1014,7 @@ void
| This function or macro is the same as 'softfloat_remStepMBy32' with
| 'size_words' = 4 (N = 128).
*----------------------------------------------------------------------------*/
#define softfloat_remStep128MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 4, remPtr, dist, bPtr, q, zPtr )
#define softfloat_remStep128MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(4, remPtr, dist, bPtr, q, zPtr)
#endif
#ifndef softfloat_remStep160MBy32
@ -1151,10 +1022,9 @@ void
| This function or macro is the same as 'softfloat_remStepMBy32' with
| 'size_words' = 5 (N = 160).
*----------------------------------------------------------------------------*/
#define softfloat_remStep160MBy32( remPtr, dist, bPtr, q, zPtr ) softfloat_remStepMBy32( 5, remPtr, dist, bPtr, q, zPtr )
#define softfloat_remStep160MBy32(remPtr, dist, bPtr, q, zPtr) softfloat_remStepMBy32(5, remPtr, dist, bPtr, q, zPtr)
#endif
#endif
#endif

View File

@ -34,7 +34,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
/*============================================================================
| Note: If SoftFloat is made available as a general library for programs to
| use, it is strongly recommended that a platform-specific version of this
@ -42,13 +41,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| eliminates all dependencies on compile-time macros.
*============================================================================*/
#ifndef softfloat_h
#define softfloat_h 1
#include "softfloat_types.h"
#include <stdbool.h>
#include <stdint.h>
#include "softfloat_types.h"
#ifndef THREAD_LOCAL
#define THREAD_LOCAL
@ -58,10 +56,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| Software floating-point underflow tininess-detection mode.
*----------------------------------------------------------------------------*/
extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess;
enum {
softfloat_tininess_beforeRounding = 0,
softfloat_tininess_afterRounding = 1
};
enum { softfloat_tininess_beforeRounding = 0, softfloat_tininess_afterRounding = 1 };
/*----------------------------------------------------------------------------
| Software floating-point rounding mode. (Mode "odd" is supported only if
@ -69,175 +64,182 @@ enum {
*----------------------------------------------------------------------------*/
extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode;
enum {
softfloat_round_near_even = 0,
softfloat_round_minMag = 1,
softfloat_round_min = 2,
softfloat_round_max = 3,
softfloat_round_near_even = 0,
softfloat_round_minMag = 1,
softfloat_round_min = 2,
softfloat_round_max = 3,
softfloat_round_near_maxMag = 4,
softfloat_round_odd = 6
softfloat_round_odd = 6
};
/*----------------------------------------------------------------------------
| Software floating-point exception flags.
*----------------------------------------------------------------------------*/
extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags;
enum {
softfloat_flag_inexact = 1,
softfloat_flag_underflow = 2,
softfloat_flag_overflow = 4,
softfloat_flag_infinite = 8,
softfloat_flag_invalid = 16
};
typedef enum {
softfloat_flag_inexact = 1,
softfloat_flag_underflow = 2,
softfloat_flag_overflow = 4,
softfloat_flag_infinite = 8,
softfloat_flag_invalid = 16
} exceptionFlag_t;
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software floating-point exception flags.
*----------------------------------------------------------------------------*/
void softfloat_raiseFlags( uint_fast8_t );
void softfloat_raiseFlags(uint_fast8_t);
/*----------------------------------------------------------------------------
| Integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float16_t ui32_to_f16( uint32_t );
float32_t ui32_to_f32( uint32_t );
float64_t ui32_to_f64( uint32_t );
float16_t ui32_to_f16(uint32_t);
float32_t ui32_to_f32(uint32_t);
float64_t ui32_to_f64(uint32_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t ui32_to_extF80( uint32_t );
float128_t ui32_to_f128( uint32_t );
extFloat80_t ui32_to_extF80(uint32_t);
float128_t ui32_to_f128(uint32_t);
#endif
void ui32_to_extF80M( uint32_t, extFloat80_t * );
void ui32_to_f128M( uint32_t, float128_t * );
float16_t ui64_to_f16( uint64_t );
float32_t ui64_to_f32( uint64_t );
float64_t ui64_to_f64( uint64_t );
void ui32_to_extF80M(uint32_t, extFloat80_t*);
void ui32_to_f128M(uint32_t, float128_t*);
float16_t ui64_to_f16(uint64_t);
float32_t ui64_to_f32(uint64_t);
float64_t ui64_to_f64(uint64_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t ui64_to_extF80( uint64_t );
float128_t ui64_to_f128( uint64_t );
extFloat80_t ui64_to_extF80(uint64_t);
float128_t ui64_to_f128(uint64_t);
#endif
void ui64_to_extF80M( uint64_t, extFloat80_t * );
void ui64_to_f128M( uint64_t, float128_t * );
float16_t i32_to_f16( int32_t );
float32_t i32_to_f32( int32_t );
float64_t i32_to_f64( int32_t );
void ui64_to_extF80M(uint64_t, extFloat80_t*);
void ui64_to_f128M(uint64_t, float128_t*);
float16_t i32_to_f16(int32_t);
float32_t i32_to_f32(int32_t);
float64_t i32_to_f64(int32_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t i32_to_extF80( int32_t );
float128_t i32_to_f128( int32_t );
extFloat80_t i32_to_extF80(int32_t);
float128_t i32_to_f128(int32_t);
#endif
void i32_to_extF80M( int32_t, extFloat80_t * );
void i32_to_f128M( int32_t, float128_t * );
float16_t i64_to_f16( int64_t );
float32_t i64_to_f32( int64_t );
float64_t i64_to_f64( int64_t );
void i32_to_extF80M(int32_t, extFloat80_t*);
void i32_to_f128M(int32_t, float128_t*);
float16_t i64_to_f16(int64_t);
float32_t i64_to_f32(int64_t);
float64_t i64_to_f64(int64_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t i64_to_extF80( int64_t );
float128_t i64_to_f128( int64_t );
extFloat80_t i64_to_extF80(int64_t);
float128_t i64_to_f128(int64_t);
#endif
void i64_to_extF80M( int64_t, extFloat80_t * );
void i64_to_f128M( int64_t, float128_t * );
void i64_to_extF80M(int64_t, extFloat80_t*);
void i64_to_f128M(int64_t, float128_t*);
/*----------------------------------------------------------------------------
| 16-bit (half-precision) floating-point operations.
*----------------------------------------------------------------------------*/
uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool );
uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool );
int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool );
int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool );
uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool );
uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool );
int_fast32_t f16_to_i32_r_minMag( float16_t, bool );
int_fast64_t f16_to_i64_r_minMag( float16_t, bool );
float32_t f16_to_f32( float16_t );
float64_t f16_to_f64( float16_t );
uint_fast32_t f16_to_ui32(float16_t, uint_fast8_t, bool);
uint_fast64_t f16_to_ui64(float16_t, uint_fast8_t, bool);
int_fast32_t f16_to_i32(float16_t, uint_fast8_t, bool);
int_fast64_t f16_to_i64(float16_t, uint_fast8_t, bool);
uint_fast32_t f16_to_ui32_r_minMag(float16_t, bool);
uint_fast64_t f16_to_ui64_r_minMag(float16_t, bool);
int_fast32_t f16_to_i32_r_minMag(float16_t, bool);
int_fast64_t f16_to_i64_r_minMag(float16_t, bool);
float32_t f16_to_f32(float16_t);
float64_t f16_to_f64(float16_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t f16_to_extF80( float16_t );
float128_t f16_to_f128( float16_t );
extFloat80_t f16_to_extF80(float16_t);
float128_t f16_to_f128(float16_t);
#endif
void f16_to_extF80M( float16_t, extFloat80_t * );
void f16_to_f128M( float16_t, float128_t * );
float16_t f16_roundToInt( float16_t, uint_fast8_t, bool );
float16_t f16_add( float16_t, float16_t );
float16_t f16_sub( float16_t, float16_t );
float16_t f16_mul( float16_t, float16_t );
float16_t f16_mulAdd( float16_t, float16_t, float16_t );
float16_t f16_div( float16_t, float16_t );
float16_t f16_rem( float16_t, float16_t );
float16_t f16_sqrt( float16_t );
bool f16_eq( float16_t, float16_t );
bool f16_le( float16_t, float16_t );
bool f16_lt( float16_t, float16_t );
bool f16_eq_signaling( float16_t, float16_t );
bool f16_le_quiet( float16_t, float16_t );
bool f16_lt_quiet( float16_t, float16_t );
bool f16_isSignalingNaN( float16_t );
void f16_to_extF80M(float16_t, extFloat80_t*);
void f16_to_f128M(float16_t, float128_t*);
float16_t f16_roundToInt(float16_t, uint_fast8_t, bool);
float16_t f16_add(float16_t, float16_t);
float16_t f16_sub(float16_t, float16_t);
float16_t f16_mul(float16_t, float16_t);
float16_t f16_mulAdd(float16_t, float16_t, float16_t);
float16_t f16_div(float16_t, float16_t);
float16_t f16_rem(float16_t, float16_t);
float16_t f16_sqrt(float16_t);
bool f16_eq(float16_t, float16_t);
bool f16_le(float16_t, float16_t);
bool f16_lt(float16_t, float16_t);
bool f16_eq_signaling(float16_t, float16_t);
bool f16_le_quiet(float16_t, float16_t);
bool f16_lt_quiet(float16_t, float16_t);
bool f16_isSignalingNaN(float16_t);
/*----------------------------------------------------------------------------
| 16-bit (brain float 16) floating-point operations.
*----------------------------------------------------------------------------*/
float32_t bf16_to_f32(bfloat16_t);
bfloat16_t f32_to_bf16(float32_t);
bool bf16_isSignalingNaN(bfloat16_t);
/*----------------------------------------------------------------------------
| 32-bit (single-precision) floating-point operations.
*----------------------------------------------------------------------------*/
uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool );
uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool );
int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool );
int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool );
uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool );
uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool );
int_fast32_t f32_to_i32_r_minMag( float32_t, bool );
int_fast64_t f32_to_i64_r_minMag( float32_t, bool );
float16_t f32_to_f16( float32_t );
float64_t f32_to_f64( float32_t );
uint_fast32_t f32_to_ui32(float32_t, uint_fast8_t, bool);
uint_fast64_t f32_to_ui64(float32_t, uint_fast8_t, bool);
int_fast32_t f32_to_i32(float32_t, uint_fast8_t, bool);
int_fast64_t f32_to_i64(float32_t, uint_fast8_t, bool);
uint_fast32_t f32_to_ui32_r_minMag(float32_t, bool);
uint_fast64_t f32_to_ui64_r_minMag(float32_t, bool);
int_fast32_t f32_to_i32_r_minMag(float32_t, bool);
int_fast64_t f32_to_i64_r_minMag(float32_t, bool);
float16_t f32_to_f16(float32_t);
float64_t f32_to_f64(float32_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t f32_to_extF80( float32_t );
float128_t f32_to_f128( float32_t );
extFloat80_t f32_to_extF80(float32_t);
float128_t f32_to_f128(float32_t);
#endif
void f32_to_extF80M( float32_t, extFloat80_t * );
void f32_to_f128M( float32_t, float128_t * );
float32_t f32_roundToInt( float32_t, uint_fast8_t, bool );
float32_t f32_add( float32_t, float32_t );
float32_t f32_sub( float32_t, float32_t );
float32_t f32_mul( float32_t, float32_t );
float32_t f32_mulAdd( float32_t, float32_t, float32_t );
float32_t f32_div( float32_t, float32_t );
float32_t f32_rem( float32_t, float32_t );
float32_t f32_sqrt( float32_t );
bool f32_eq( float32_t, float32_t );
bool f32_le( float32_t, float32_t );
bool f32_lt( float32_t, float32_t );
bool f32_eq_signaling( float32_t, float32_t );
bool f32_le_quiet( float32_t, float32_t );
bool f32_lt_quiet( float32_t, float32_t );
bool f32_isSignalingNaN( float32_t );
void f32_to_extF80M(float32_t, extFloat80_t*);
void f32_to_f128M(float32_t, float128_t*);
float32_t f32_roundToInt(float32_t, uint_fast8_t, bool);
float32_t f32_add(float32_t, float32_t);
float32_t f32_sub(float32_t, float32_t);
float32_t f32_mul(float32_t, float32_t);
float32_t f32_mulAdd(float32_t, float32_t, float32_t);
float32_t f32_div(float32_t, float32_t);
float32_t f32_rem(float32_t, float32_t);
float32_t f32_sqrt(float32_t);
bool f32_eq(float32_t, float32_t);
bool f32_le(float32_t, float32_t);
bool f32_lt(float32_t, float32_t);
bool f32_eq_signaling(float32_t, float32_t);
bool f32_le_quiet(float32_t, float32_t);
bool f32_lt_quiet(float32_t, float32_t);
bool f32_isSignalingNaN(float32_t);
/*----------------------------------------------------------------------------
| 64-bit (double-precision) floating-point operations.
*----------------------------------------------------------------------------*/
uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool );
uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool );
int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool );
int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool );
uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool );
uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool );
int_fast32_t f64_to_i32_r_minMag( float64_t, bool );
int_fast64_t f64_to_i64_r_minMag( float64_t, bool );
float16_t f64_to_f16( float64_t );
float32_t f64_to_f32( float64_t );
uint_fast32_t f64_to_ui32(float64_t, uint_fast8_t, bool);
uint_fast64_t f64_to_ui64(float64_t, uint_fast8_t, bool);
int_fast32_t f64_to_i32(float64_t, uint_fast8_t, bool);
int_fast64_t f64_to_i64(float64_t, uint_fast8_t, bool);
uint_fast32_t f64_to_ui32_r_minMag(float64_t, bool);
uint_fast64_t f64_to_ui64_r_minMag(float64_t, bool);
int_fast32_t f64_to_i32_r_minMag(float64_t, bool);
int_fast64_t f64_to_i64_r_minMag(float64_t, bool);
float16_t f64_to_f16(float64_t);
float32_t f64_to_f32(float64_t);
#ifdef SOFTFLOAT_FAST_INT64
extFloat80_t f64_to_extF80( float64_t );
float128_t f64_to_f128( float64_t );
extFloat80_t f64_to_extF80(float64_t);
float128_t f64_to_f128(float64_t);
#endif
void f64_to_extF80M( float64_t, extFloat80_t * );
void f64_to_f128M( float64_t, float128_t * );
float64_t f64_roundToInt( float64_t, uint_fast8_t, bool );
float64_t f64_add( float64_t, float64_t );
float64_t f64_sub( float64_t, float64_t );
float64_t f64_mul( float64_t, float64_t );
float64_t f64_mulAdd( float64_t, float64_t, float64_t );
float64_t f64_div( float64_t, float64_t );
float64_t f64_rem( float64_t, float64_t );
float64_t f64_sqrt( float64_t );
bool f64_eq( float64_t, float64_t );
bool f64_le( float64_t, float64_t );
bool f64_lt( float64_t, float64_t );
bool f64_eq_signaling( float64_t, float64_t );
bool f64_le_quiet( float64_t, float64_t );
bool f64_lt_quiet( float64_t, float64_t );
bool f64_isSignalingNaN( float64_t );
void f64_to_extF80M(float64_t, extFloat80_t*);
void f64_to_f128M(float64_t, float128_t*);
float64_t f64_roundToInt(float64_t, uint_fast8_t, bool);
float64_t f64_add(float64_t, float64_t);
float64_t f64_sub(float64_t, float64_t);
float64_t f64_mul(float64_t, float64_t);
float64_t f64_mulAdd(float64_t, float64_t, float64_t);
float64_t f64_div(float64_t, float64_t);
float64_t f64_rem(float64_t, float64_t);
float64_t f64_sqrt(float64_t);
bool f64_eq(float64_t, float64_t);
bool f64_le(float64_t, float64_t);
bool f64_lt(float64_t, float64_t);
bool f64_eq_signaling(float64_t, float64_t);
bool f64_le_quiet(float64_t, float64_t);
bool f64_lt_quiet(float64_t, float64_t);
bool f64_isSignalingNaN(float64_t);
/*----------------------------------------------------------------------------
| Rounding precision for 80-bit extended double-precision floating-point.
@ -249,124 +251,118 @@ extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision;
| 80-bit extended double-precision floating-point operations.
*----------------------------------------------------------------------------*/
#ifdef SOFTFLOAT_FAST_INT64
uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool );
uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool );
int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool );
int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool );
uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool );
uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool );
int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool );
int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool );
float16_t extF80_to_f16( extFloat80_t );
float32_t extF80_to_f32( extFloat80_t );
float64_t extF80_to_f64( extFloat80_t );
float128_t extF80_to_f128( extFloat80_t );
extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool );
extFloat80_t extF80_add( extFloat80_t, extFloat80_t );
extFloat80_t extF80_sub( extFloat80_t, extFloat80_t );
extFloat80_t extF80_mul( extFloat80_t, extFloat80_t );
extFloat80_t extF80_div( extFloat80_t, extFloat80_t );
extFloat80_t extF80_rem( extFloat80_t, extFloat80_t );
extFloat80_t extF80_sqrt( extFloat80_t );
bool extF80_eq( extFloat80_t, extFloat80_t );
bool extF80_le( extFloat80_t, extFloat80_t );
bool extF80_lt( 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 );
uint_fast32_t extF80_to_ui32(extFloat80_t, uint_fast8_t, bool);
uint_fast64_t extF80_to_ui64(extFloat80_t, uint_fast8_t, bool);
int_fast32_t extF80_to_i32(extFloat80_t, uint_fast8_t, bool);
int_fast64_t extF80_to_i64(extFloat80_t, uint_fast8_t, bool);
uint_fast32_t extF80_to_ui32_r_minMag(extFloat80_t, bool);
uint_fast64_t extF80_to_ui64_r_minMag(extFloat80_t, bool);
int_fast32_t extF80_to_i32_r_minMag(extFloat80_t, bool);
int_fast64_t extF80_to_i64_r_minMag(extFloat80_t, bool);
float16_t extF80_to_f16(extFloat80_t);
float32_t extF80_to_f32(extFloat80_t);
float64_t extF80_to_f64(extFloat80_t);
float128_t extF80_to_f128(extFloat80_t);
extFloat80_t extF80_roundToInt(extFloat80_t, uint_fast8_t, bool);
extFloat80_t extF80_add(extFloat80_t, extFloat80_t);
extFloat80_t extF80_sub(extFloat80_t, extFloat80_t);
extFloat80_t extF80_mul(extFloat80_t, extFloat80_t);
extFloat80_t extF80_div(extFloat80_t, extFloat80_t);
extFloat80_t extF80_rem(extFloat80_t, extFloat80_t);
extFloat80_t extF80_sqrt(extFloat80_t);
bool extF80_eq(extFloat80_t, extFloat80_t);
bool extF80_le(extFloat80_t, extFloat80_t);
bool extF80_lt(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);
#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 );
int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool );
int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool );
uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool );
uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool );
int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool );
int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool );
float16_t extF80M_to_f16( const extFloat80_t * );
float32_t extF80M_to_f32( const extFloat80_t * );
float64_t extF80M_to_f64( const extFloat80_t * );
void extF80M_to_f128M( const extFloat80_t *, float128_t * );
void
extF80M_roundToInt(
const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * );
void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * );
void extF80M_sqrt( const extFloat80_t *, extFloat80_t * );
bool extF80M_eq( const extFloat80_t *, const extFloat80_t * );
bool extF80M_le( const extFloat80_t *, const extFloat80_t * );
bool extF80M_lt( const extFloat80_t *, const extFloat80_t * );
bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * );
bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * );
bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * );
bool extF80M_isSignalingNaN( const extFloat80_t * );
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);
int_fast32_t extF80M_to_i32(const extFloat80_t*, uint_fast8_t, bool);
int_fast64_t extF80M_to_i64(const extFloat80_t*, uint_fast8_t, bool);
uint_fast32_t extF80M_to_ui32_r_minMag(const extFloat80_t*, bool);
uint_fast64_t extF80M_to_ui64_r_minMag(const extFloat80_t*, bool);
int_fast32_t extF80M_to_i32_r_minMag(const extFloat80_t*, bool);
int_fast64_t extF80M_to_i64_r_minMag(const extFloat80_t*, bool);
float16_t extF80M_to_f16(const extFloat80_t*);
float32_t extF80M_to_f32(const extFloat80_t*);
float64_t extF80M_to_f64(const extFloat80_t*);
void extF80M_to_f128M(const extFloat80_t*, float128_t*);
void extF80M_roundToInt(const extFloat80_t*, uint_fast8_t, bool, extFloat80_t*);
void extF80M_add(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_sub(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_mul(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_div(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_rem(const extFloat80_t*, const extFloat80_t*, extFloat80_t*);
void extF80M_sqrt(const extFloat80_t*, extFloat80_t*);
bool extF80M_eq(const extFloat80_t*, const extFloat80_t*);
bool extF80M_le(const extFloat80_t*, const extFloat80_t*);
bool extF80M_lt(const extFloat80_t*, const extFloat80_t*);
bool extF80M_eq_signaling(const extFloat80_t*, const extFloat80_t*);
bool extF80M_le_quiet(const extFloat80_t*, const extFloat80_t*);
bool extF80M_lt_quiet(const extFloat80_t*, const extFloat80_t*);
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_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 );
extFloat80_t f128_to_extF80( 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 );
bool f128_isSignalingNaN( float128_t );
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_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);
extFloat80_t f128_to_extF80(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);
bool f128_isSignalingNaN(float128_t);
#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 );
int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool );
int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool );
uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool );
uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool );
int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool );
int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool );
float16_t f128M_to_f16( const float128_t * );
float32_t f128M_to_f32( const float128_t * );
float64_t f128M_to_f64( const float128_t * );
void f128M_to_extF80M( const float128_t *, extFloat80_t * );
void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * );
void f128M_add( const float128_t *, const float128_t *, float128_t * );
void f128M_sub( const float128_t *, const float128_t *, float128_t * );
void f128M_mul( const float128_t *, const float128_t *, float128_t * );
void
f128M_mulAdd(
const float128_t *, const float128_t *, const float128_t *, float128_t *
);
void f128M_div( const float128_t *, const float128_t *, float128_t * );
void f128M_rem( const float128_t *, const float128_t *, float128_t * );
void f128M_sqrt( const float128_t *, float128_t * );
bool f128M_eq( const float128_t *, const float128_t * );
bool f128M_le( const float128_t *, const float128_t * );
bool f128M_lt( const float128_t *, const float128_t * );
bool f128M_eq_signaling( const float128_t *, const float128_t * );
bool f128M_le_quiet( const float128_t *, const float128_t * );
bool f128M_lt_quiet( const float128_t *, const float128_t * );
bool f128M_isSignalingNaN( const float128_t * );
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);
int_fast32_t f128M_to_i32(const float128_t*, uint_fast8_t, bool);
int_fast64_t f128M_to_i64(const float128_t*, uint_fast8_t, bool);
uint_fast32_t f128M_to_ui32_r_minMag(const float128_t*, bool);
uint_fast64_t f128M_to_ui64_r_minMag(const float128_t*, bool);
int_fast32_t f128M_to_i32_r_minMag(const float128_t*, bool);
int_fast64_t f128M_to_i64_r_minMag(const float128_t*, bool);
float16_t f128M_to_f16(const float128_t*);
float32_t f128M_to_f32(const float128_t*);
float64_t f128M_to_f64(const float128_t*);
void f128M_to_extF80M(const float128_t*, extFloat80_t*);
void f128M_roundToInt(const float128_t*, uint_fast8_t, bool, float128_t*);
void f128M_add(const float128_t*, const float128_t*, float128_t*);
void f128M_sub(const float128_t*, const float128_t*, float128_t*);
void f128M_mul(const float128_t*, const float128_t*, float128_t*);
void f128M_mulAdd(const float128_t*, const float128_t*, const float128_t*, float128_t*);
void f128M_div(const float128_t*, const float128_t*, float128_t*);
void f128M_rem(const float128_t*, const float128_t*, float128_t*);
void f128M_sqrt(const float128_t*, float128_t*);
bool f128M_eq(const float128_t*, const float128_t*);
bool f128M_le(const float128_t*, const float128_t*);
bool f128M_lt(const float128_t*, const float128_t*);
bool f128M_eq_signaling(const float128_t*, const float128_t*);
bool f128M_le_quiet(const float128_t*, const float128_t*);
bool f128M_lt_quiet(const float128_t*, const float128_t*);
bool f128M_isSignalingNaN(const float128_t*);
#endif

View File

@ -47,10 +47,21 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
| the types below may, if desired, be defined as aliases for the native types
| (typically 'float' and 'double', and possibly 'long double').
*----------------------------------------------------------------------------*/
typedef struct { uint16_t v; } float16_t;
typedef struct { uint32_t v; } float32_t;
typedef struct { uint64_t v; } float64_t;
typedef struct { uint64_t v[2]; } float128_t;
typedef struct {
uint16_t v;
} float16_t;
typedef struct {
uint16_t v;
} bfloat16_t;
typedef struct {
uint32_t v;
} float32_t;
typedef struct {
uint64_t v;
} float64_t;
typedef struct {
uint64_t v[2];
} float128_t;
/*----------------------------------------------------------------------------
| The format of an 80-bit extended floating-point number in memory. This
@ -58,9 +69,15 @@ typedef struct { uint64_t v[2]; } float128_t;
| named 'signif'.
*----------------------------------------------------------------------------*/
#ifdef LITTLEENDIAN
struct extFloat80M { uint64_t signif; uint16_t signExp; };
struct extFloat80M {
uint64_t signif;
uint16_t signExp;
};
#else
struct extFloat80M { uint16_t signExp; uint64_t signif; };
struct extFloat80M {
uint16_t signExp;
uint64_t signif;
};
#endif
/*----------------------------------------------------------------------------
@ -78,4 +95,3 @@ struct extFloat80M { uint16_t signExp; uint64_t signif; };
typedef struct extFloat80M extFloat80_t;
#endif

View File

@ -221,4 +221,3 @@ float32_t
return uZ.f;
}

View File

@ -0,0 +1,52 @@
/*============================================================================
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"
struct exp8_sig16 softfloat_normSubnormalBF16Sig( uint_fast16_t sig )
{
int_fast8_t shiftDist;
struct exp8_sig16 z;
shiftDist = softfloat_countLeadingZeros16( sig ) - 8;
z.exp = 1 - shiftDist;
z.sig = sig<<shiftDist;
return z;
}

View File

@ -0,0 +1,114 @@
/*============================================================================
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"
/** sig last significant bit is sig[7], the 7 LSBs will be used for rounding */
bfloat16_t
softfloat_roundPackToBF16( bool sign, int_fast16_t exp, uint_fast16_t sig )
{
uint_fast8_t roundingMode;
bool roundNearEven;
uint_fast8_t roundIncrement, roundBits;
bool isTiny;
uint_fast16_t uiZ;
union ui16_bf16 uZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
roundingMode = softfloat_roundingMode;
roundNearEven = (roundingMode == softfloat_round_near_even);
roundIncrement = 0x40;
if ( ! roundNearEven && (roundingMode != softfloat_round_near_maxMag) ) {
roundIncrement =
(roundingMode
== (sign ? softfloat_round_min : softfloat_round_max))
? 0x7F
: 0;
}
roundBits = sig & 0x7F;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ( 0xFD <= (unsigned int) exp ) {
if ( exp < 0 ) {
/*----------------------------------------------------------------
*----------------------------------------------------------------*/
isTiny =
(softfloat_detectTininess == softfloat_tininess_beforeRounding)
|| (exp < -1) || (sig + roundIncrement < 0x8000);
sig = softfloat_shiftRightJam32( sig, -exp );
exp = 0;
roundBits = sig & 0x7F;
if ( isTiny && roundBits ) {
softfloat_raiseFlags( softfloat_flag_underflow );
}
} else if ( (0xFD < exp) || (0x8000 <= sig + roundIncrement) ) {
/*----------------------------------------------------------------
*----------------------------------------------------------------*/
softfloat_raiseFlags(
softfloat_flag_overflow | softfloat_flag_inexact );
uiZ = packToBF16UI( sign, 0xFF, 0 ) - ! roundIncrement;
goto uiZ;
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig = (sig + roundIncrement)>>7;
if ( roundBits ) {
softfloat_exceptionFlags |= softfloat_flag_inexact;
#ifdef SOFTFLOAT_ROUND_ODD
if ( roundingMode == softfloat_round_odd ) {
sig |= 1;
goto packReturn;
}
#endif
}
sig &= ~(uint_fast16_t) (! (roundBits ^ 0x40) & roundNearEven);
if ( ! sig ) exp = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
packReturn:
uiZ = packToBF16UI( sign, exp, sig );
uiZ:
uZ.ui = uiZ;
return uZ.f;
}

69
src/elfio.cpp Normal file
View File

@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (C) 2024 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifdef _MSC_VER
#define _SCL_SECURE_NO_WARNINGS
#define ELFIO_NO_INTTYPES
#endif
#include <elfio/elfio_dump.hpp>
#include <iostream>
using namespace ELFIO;
int main(int argc, char** argv) {
if(argc != 2) {
printf("Usage: elfdump <file_name>\n");
return 1;
}
elfio reader;
if(!reader.load(argv[1])) {
printf("File %s is not found or it is not an ELF file\n", argv[1]);
return 1;
}
dump::header(std::cout, reader);
dump::section_headers(std::cout, reader);
dump::segment_headers(std::cout, reader);
dump::symbol_tables(std::cout, reader);
dump::notes(std::cout, reader);
dump::modinfo(std::cout, reader);
dump::dynamic_tags(std::cout, reader);
dump::section_datas(std::cout, reader);
dump::segment_datas(std::cout, reader);
return 0;
}

View File

@ -35,6 +35,7 @@
#ifndef _RISCV_HART_M_P_HWL_H
#define _RISCV_HART_M_P_HWL_H
#include "riscv_hart_common.h"
#include <iss/vm_types.h>
namespace iss {
@ -46,49 +47,71 @@ public:
using this_class = hwl<BASE>;
using reg_t = typename BASE::reg_t;
hwl();
hwl(feature_config cfg = feature_config{});
virtual ~hwl() = default;
protected:
iss::status read_custom_csr_reg(unsigned addr, reg_t &val) override;
iss::status write_custom_csr_reg(unsigned addr, reg_t val) override;
iss::status read_custom_csr(unsigned addr, reg_t& val) override;
iss::status write_custom_csr(unsigned addr, reg_t val) override;
};
template<typename BASE>
inline hwl<BASE>::hwl() {
for (unsigned addr = 0x800; addr < 0x803; ++addr){
template <typename BASE>
inline hwl<BASE>::hwl(feature_config cfg)
: BASE(cfg) {
for(unsigned addr = 0x800; addr < 0x803; ++addr) {
this->register_custom_csr_rd(addr);
this->register_custom_csr_wr(addr);
}
for (unsigned addr = 0x804; addr < 0x807; ++addr){
for(unsigned addr = 0x804; addr < 0x807; ++addr) {
this->register_custom_csr_rd(addr);
this->register_custom_csr_wr(addr);
}
}
template<typename BASE>
inline iss::status iss::arch::hwl<BASE>::read_custom_csr_reg(unsigned addr, reg_t &val) {
switch(addr){
case 0x800: val = this->reg.lpstart0; break;
case 0x801: val = this->reg.lpend0; break;
case 0x802: val = this->reg.lpcount0; break;
case 0x804: val = this->reg.lpstart1; break;
case 0x805: val = this->reg.lpend1; break;
case 0x806: val = this->reg.lpcount1; break;
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::read_custom_csr(unsigned addr, reg_t& val) {
switch(addr) {
case 0x800:
val = this->reg.lpstart0;
break;
case 0x801:
val = this->reg.lpend0;
break;
case 0x802:
val = this->reg.lpcount0;
break;
case 0x804:
val = this->reg.lpstart1;
break;
case 0x805:
val = this->reg.lpend1;
break;
case 0x806:
val = this->reg.lpcount1;
break;
}
return iss::Ok;
}
template<typename BASE>
inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg_t val) {
switch(addr){
case 0x800: this->reg.lpstart0 = val; break;
case 0x801: this->reg.lpend0 = val; break;
case 0x802: this->reg.lpcount0 = val; break;
case 0x804: this->reg.lpstart1 = val; break;
case 0x805: this->reg.lpend1 = val; break;
case 0x806: this->reg.lpcount1 = val; break;
template <typename BASE> inline iss::status iss::arch::hwl<BASE>::write_custom_csr(unsigned addr, reg_t val) {
switch(addr) {
case 0x800:
this->reg.lpstart0 = val;
break;
case 0x801:
this->reg.lpend0 = val;
break;
case 0x802:
this->reg.lpcount0 = val;
break;
case 0x804:
this->reg.lpstart1 = val;
break;
case 0x805:
this->reg.lpend1 = val;
break;
case 0x806:
this->reg.lpcount1 = val;
break;
}
return iss::Ok;
}
@ -96,5 +119,4 @@ inline iss::status iss::arch::hwl<BASE>::write_custom_csr_reg(unsigned addr, reg
} // namespace arch
} // namespace iss
#endif /* _RISCV_HART_M_P_H */

233
src/iss/arch/mstatus.h Normal file
View File

@ -0,0 +1,233 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _MSTATUS_TYPE
#define _MSTATUS_TYPE
#include <cstdint>
#include <type_traits>
#include <util/bit_field.h>
#include <util/ities.h>
namespace iss {
namespace arch {
template <class T, class Enable = void> struct status {};
// specialization 32bit
template <typename T> struct status<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
static inline unsigned SD(T v) { return bit_sub<63, 1>(v); }
// value of XLEN for S-mode
static inline unsigned SXL(T v) { return bit_sub<34, 2>(v); };
// value of XLEN for U-mode
static inline unsigned UXL(T v) { return bit_sub<32, 2>(v); };
// Trap SRET
static inline unsigned TSR(T v) { return bit_sub<22, 1>(v); };
// Timeout Wait
static inline unsigned TW(T v) { return bit_sub<21, 1>(v); };
// Trap Virtual Memory
static inline unsigned TVM(T v) { return bit_sub<20, 1>(v); };
// Make eXecutable Readable
static inline unsigned MXR(T v) { return bit_sub<19, 1>(v); };
// permit Supervisor User Memory access
static inline unsigned SUM(T v) { return bit_sub<18, 1>(v); };
// Modify PRiVilege
static inline unsigned MPRV(T v) { return bit_sub<17, 1>(v); };
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
static inline unsigned XS(T v) { return bit_sub<15, 2>(v); };
// floating-point unit status Off/Initial/Clean/Dirty
static inline unsigned FS(T v) { return bit_sub<13, 2>(v); };
// machine previous privilege
static inline unsigned MPP(T v) { return bit_sub<11, 2>(v); };
// supervisor previous privilege
static inline unsigned SPP(T v) { return bit_sub<8, 1>(v); };
// previous machine interrupt-enable
static inline unsigned MPIE(T v) { return bit_sub<7, 1>(v); };
// previous supervisor interrupt-enable
static inline unsigned SPIE(T v) { return bit_sub<5, 1>(v); };
// previous user interrupt-enable
static inline unsigned UPIE(T v) { return bit_sub<4, 1>(v); };
// machine interrupt-enable
static inline unsigned MIE(T v) { return bit_sub<3, 1>(v); };
// supervisor interrupt-enable
static inline unsigned SIE(T v) { return bit_sub<1, 1>(v); };
// user interrupt-enable
static inline unsigned UIE(T v) { return bit_sub<0, 1>(v); };
};
template <typename T> struct status<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public:
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
static inline unsigned SD(T v) { return bit_sub<63, 1>(v); };
// value of XLEN for S-mode
static inline unsigned SXL(T v) { return bit_sub<34, 2>(v); };
// value of XLEN for U-mode
static inline unsigned UXL(T v) { return bit_sub<32, 2>(v); };
// Trap SRET
static inline unsigned TSR(T v) { return bit_sub<22, 1>(v); };
// Timeout Wait
static inline unsigned TW(T v) { return bit_sub<21, 1>(v); };
// Trap Virtual Memory
static inline unsigned TVM(T v) { return bit_sub<20, 1>(v); };
// Make eXecutable Readable
static inline unsigned MXR(T v) { return bit_sub<19, 1>(v); };
// permit Supervisor User Memory access
static inline unsigned SUM(T v) { return bit_sub<18, 1>(v); };
// Modify PRiVilege
static inline unsigned MPRV(T v) { return bit_sub<17, 1>(v); };
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
static inline unsigned XS(T v) { return bit_sub<15, 2>(v); };
// floating-point unit status Off/Initial/Clean/Dirty
static inline unsigned FS(T v) { return bit_sub<13, 2>(v); };
// machine previous privilege
static inline unsigned MPP(T v) { return bit_sub<11, 2>(v); };
// supervisor previous privilege
static inline unsigned SPP(T v) { return bit_sub<8, 1>(v); };
// previous machine interrupt-enable
static inline unsigned MPIE(T v) { return bit_sub<7, 1>(v); };
// previous supervisor interrupt-enable
static inline unsigned SPIE(T v) { return bit_sub<5, 1>(v); };
// previous user interrupt-enable
static inline unsigned UPIE(T v) { return bit_sub<4, 1>(v); };
// machine interrupt-enable
static inline unsigned MIE(T v) { return bit_sub<3, 1>(v); };
// supervisor interrupt-enable
static inline unsigned SIE(T v) { return bit_sub<1, 1>(v); };
// user interrupt-enable
static inline unsigned UIE(T v) { return bit_sub<0, 1>(v); };
};
// primary template
template <class T, class Enable = void> struct hart_state {};
// specialization 32bit
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint32_t>::value>::type> {
public:
BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 31, 1);
// Trap SRET
BF_FIELD(TSR, 22, 1);
// Timeout Wait
BF_FIELD(TW, 21, 1);
// Trap Virtual Memory
BF_FIELD(TVM, 20, 1);
// Make eXecutable Readable
BF_FIELD(MXR, 19, 1);
// permit Supervisor User Memory access
BF_FIELD(SUM, 18, 1);
// Modify PRiVilege
BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2);
// machine previous privilege
BF_FIELD(MPP, 11, 2);
// supervisor previous privilege
BF_FIELD(SPP, 8, 1);
// previous machine interrupt-enable
BF_FIELD(MPIE, 7, 1);
// previous supervisor interrupt-enable
BF_FIELD(SPIE, 5, 1);
// previous user interrupt-enable
BF_FIELD(UPIE, 4, 1);
// machine interrupt-enable
BF_FIELD(MIE, 3, 1);
// supervisor interrupt-enable
BF_FIELD(SIE, 1, 1);
// user interrupt-enable
BF_FIELD(UIE, 0, 1);
END_BF_DECL();
mstatus_t mstatus;
static const T mstatus_reset_val = 0x1800;
};
// specialization 64bit
template <typename T> class hart_state<T, typename std::enable_if<std::is_same<T, uint64_t>::value>::type> {
public:
BEGIN_BF_DECL(mstatus_t, T);
// SD bit is read-only and is set when either the FS or XS bits encode a Dirty state (i.e., SD=((FS==11) OR
// XS==11)))
BF_FIELD(SD, 63, 1);
// value of XLEN for S-mode
BF_FIELD(SXL, 34, 2);
// value of XLEN for U-mode
BF_FIELD(UXL, 32, 2);
// Trap SRET
BF_FIELD(TSR, 22, 1);
// Timeout Wait
BF_FIELD(TW, 21, 1);
// Trap Virtual Memory
BF_FIELD(TVM, 20, 1);
// Make eXecutable Readable
BF_FIELD(MXR, 19, 1);
// permit Supervisor User Memory access
BF_FIELD(SUM, 18, 1);
// Modify PRiVilege
BF_FIELD(MPRV, 17, 1);
// status of additional user-mode extensions and associated state, All off/None dirty or clean, some on/None
// dirty, some clean/Some dirty
BF_FIELD(XS, 15, 2);
// floating-point unit status Off/Initial/Clean/Dirty
BF_FIELD(FS, 13, 2);
// machine previous privilege
BF_FIELD(MPP, 11, 2);
// supervisor previous privilege
BF_FIELD(SPP, 8, 1);
// previous machine interrupt-enable
BF_FIELD(MPIE, 7, 1);
// previous supervisor interrupt-enable
BF_FIELD(SPIE, 5, 1);
// previous user interrupt-enable
BF_FIELD(UPIE, 4, 1);
// machine interrupt-enable
BF_FIELD(MIE, 3, 1);
// supervisor interrupt-enable
BF_FIELD(SIE, 1, 1);
// user interrupt-enable
BF_FIELD(UIE, 0, 1);
END_BF_DECL();
mstatus_t mstatus;
static const T mstatus_reset_val = 0x1800;
};
} // namespace arch
} // namespace iss
#endif // _MSTATUS_TYPE

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017, 2018, 2021 MINRES Technologies GmbH
* Copyright (C) 2017 - 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,15 +35,38 @@
#ifndef _RISCV_HART_COMMON
#define _RISCV_HART_COMMON
#include "iss/arch_if.h"
#include "mstatus.h"
#include "util/delegate.h"
#include <absl/container/flat_hash_map.h>
#include <array>
#include <cstdint>
#include <elfio/elfio.hpp>
#include <fmt/format.h>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/log_categories.h>
#include <iss/mem/memory_if.h>
#include <iss/semihosting/semihosting.h>
#include <iss/vm_types.h>
#include <limits>
#include <sstream>
#include <string>
#include <unordered_map>
#include <util/logging.h>
#include <util/sparse_array.h>
#if defined(__GNUC__)
#define likely(x) ::__builtin_expect(!!(x), 1)
#define unlikely(x) ::__builtin_expect(!!(x), 0)
#else
#define likely(x) x
#define unlikely(x) x
#endif
namespace iss {
namespace arch {
enum { tohost_dflt = 0xF0001000, fromhost_dflt = 0xF0001040 };
enum features_e{FEAT_NONE, FEAT_PMP=1, FEAT_EXT_N=2, FEAT_CLIC=4, FEAT_DEBUG=8, FEAT_TCM=16};
enum features_e { FEAT_NONE, FEAT_EXT_N = 1, FEAT_DEBUG = 2 };
enum riscv_csr {
/* user-level CSR */
@ -51,17 +74,17 @@ enum riscv_csr {
ustatus = 0x000,
uie = 0x004,
utvec = 0x005,
utvt = 0x007, //CLIC
utvt = 0x007, // CLIC
// User Trap Handling
uscratch = 0x040,
uepc = 0x041,
ucause = 0x042,
utval = 0x043,
uip = 0x044,
uxnti = 0x045, //CLIC
uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change
uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change
uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC)
uxnti = 0x045, // CLIC
uintstatus = 0xCB1, // MRW Current interrupt levels (CLIC) - addr subject to change
uintthresh = 0x047, // MRW Interrupt-level threshold (CLIC) - addr subject to change
uscratchcsw = 0x048, // MRW Conditional scratch swap on priv mode change (CLIC)
uscratchcswl = 0x049, // MRW Conditional scratch swap on level change (CLIC)
// User Floating-Point CSRs
fflags = 0x001,
@ -112,17 +135,17 @@ enum riscv_csr {
mie = 0x304,
mtvec = 0x305,
mcounteren = 0x306,
mtvt = 0x307, //CLIC
mtvt = 0x307, // CLIC
// Machine Trap Handling
mscratch = 0x340,
mepc = 0x341,
mcause = 0x342,
mtval = 0x343,
mip = 0x344,
mxnti = 0x345, //CLIC
mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change
mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change
mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC)
mxnti = 0x345, // CLIC
mintstatus = 0xFB1, // MRW Current interrupt levels (CLIC) - addr subject to change
mintthresh = 0x347, // MRW Interrupt-level threshold (CLIC) - addr subject to change
mscratchcsw = 0x348, // MRW Conditional scratch swap on priv mode change (CLIC)
mscratchcswl = 0x349, // MRW Conditional scratch swap on level change (CLIC)
// Physical Memory Protection
pmpcfg0 = 0x3A0,
@ -172,28 +195,20 @@ enum riscv_csr {
dcsr = 0x7B0,
dpc = 0x7B1,
dscratch0 = 0x7B2,
dscratch1 = 0x7B3
dscratch1 = 0x7B3,
// vector CSR
// URW
vstart = 0x008,
vxsat = 0x009,
vxrm = 0x00A,
vcsr = 0x00F,
// URO
vl = 0xC20,
vtype = 0xC21,
vlenb = 0xC22,
};
enum {
PGSHIFT = 12,
PTE_PPN_SHIFT = 10,
// page table entry (PTE) fields
PTE_V = 0x001, // Valid
PTE_R = 0x002, // Read
PTE_W = 0x004, // Write
PTE_X = 0x008, // Execute
PTE_U = 0x010, // User
PTE_G = 0x020, // Global
PTE_A = 0x040, // Accessed
PTE_D = 0x080, // Dirty
PTE_SOFT = 0x300 // Reserved for Software
};
template <typename T> inline bool PTE_TABLE(T PTE) { return (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V); }
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4};
enum { PRIV_U = 0, PRIV_S = 1, PRIV_M = 3, PRIV_D = 4 };
enum {
ISA_A = 1,
@ -211,23 +226,6 @@ enum {
ISA_U = 1 << 20
};
struct vm_info {
int levels;
int idxbits;
int ptesize;
uint64_t ptbase;
bool is_active() { return levels; }
};
struct feature_config {
uint64_t clic_base{0xc0000000};
unsigned clic_int_ctl_bits{4};
unsigned clic_num_irq{16};
unsigned clic_num_trigger{0};
uint64_t tcm_base{0x10000000};
uint64_t tcm_size{0x8000};
};
class trap_load_access_fault : public trap_access {
public:
trap_load_access_fault(uint64_t badaddr)
@ -254,49 +252,663 @@ public:
: trap_access(15 << 16, badaddr) {}
};
inline void read_reg_uint32(uint64_t offs, uint32_t& reg, uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
template <typename WORD_TYPE> struct priv_if {
using rd_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE&)>;
using wr_csr_f = std::function<iss::status(unsigned addr, WORD_TYPE)>;
inline void write_reg_uint32(uint64_t offs, uint32_t& reg, const uint8_t *const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch (offs & 0x3) {
case 0:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for (auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data ;
break;
}
}
std::function<iss::status(unsigned, WORD_TYPE&)> read_csr;
std::function<iss::status(unsigned, WORD_TYPE)> write_csr;
std::function<iss::status(uint8_t const*)> exec_htif;
std::function<void(uint16_t, uint16_t, WORD_TYPE)> raise_trap; // trap_id, cause, fault_data
absl::flat_hash_map<unsigned, rd_csr_f>& csr_rd_cb;
absl::flat_hash_map<unsigned, wr_csr_f>& csr_wr_cb;
hart_state<WORD_TYPE>& state;
uint8_t& PRIV;
WORD_TYPE& PC;
uint64_t& tohost;
uint64_t& fromhost;
unsigned& max_irq;
};
}
}
template <typename BASE, typename LOGCAT = logging::disass> struct riscv_hart_common : public BASE, public mem::memory_elem {
const std::array<const char, 4> lvl = {{'U', 'S', 'H', 'M'}};
const std::array<const char*, 16> trap_str = {{""
"Instruction address misaligned", // 0
"Instruction access fault", // 1
"Illegal instruction", // 2
"Breakpoint", // 3
"Load address misaligned", // 4
"Load access fault", // 5
"Store/AMO address misaligned", // 6
"Store/AMO access fault", // 7
"Environment call from U-mode", // 8
"Environment call from S-mode", // 9
"Reserved", // a
"Environment call from M-mode", // b
"Instruction page fault", // c
"Load page fault", // d
"Reserved", // e
"Store/AMO page fault"}};
const std::array<const char*, 12> irq_str = {{"User software interrupt", "Supervisor software interrupt", "Reserved",
"Machine software interrupt", "User timer interrupt", "Supervisor timer interrupt",
"Reserved", "Machine timer interrupt", "User external interrupt",
"Supervisor external interrupt", "Reserved", "Machine external interrupt"}};
constexpr static unsigned MEM = traits<BASE>::MEM;
using core = BASE;
using this_class = riscv_hart_common<BASE, LOGCAT>;
using phys_addr_t = typename core::phys_addr_t;
using reg_t = typename core::reg_t;
using addr_t = typename core::addr_t;
using rd_csr_f = std::function<iss::status(unsigned addr, reg_t&)>;
using wr_csr_f = std::function<iss::status(unsigned addr, reg_t)>;
#define MK_CSR_RD_CB(FCT) [this](unsigned a, reg_t& r) -> iss::status { return this->FCT(a, r); };
#define MK_CSR_WR_CB(FCT) [this](unsigned a, reg_t r) -> iss::status { return this->FCT(a, r); };
riscv_hart_common()
: state()
, instr_if(*this) {
// reset values
csr[misa] = traits<BASE>::MISA_VAL;
csr[mvendorid] = 0x669;
csr[marchid] = traits<BASE>::MARCHID_VAL;
csr[mimpid] = 1;
if(traits<BASE>::FLEN > 0) {
csr_rd_cb[fcsr] = MK_CSR_RD_CB(read_fcsr);
csr_wr_cb[fcsr] = MK_CSR_WR_CB(write_fcsr);
csr_rd_cb[fflags] = MK_CSR_RD_CB(read_fcsr);
csr_wr_cb[fflags] = MK_CSR_WR_CB(write_fcsr);
csr_rd_cb[frm] = MK_CSR_RD_CB(read_fcsr);
csr_wr_cb[frm] = MK_CSR_WR_CB(write_fcsr);
}
if(traits<BASE>::V_REGS_SIZE > 0) {
csr_rd_cb[vstart] = MK_CSR_RD_CB(read_vstart);
csr_wr_cb[vstart] = MK_CSR_WR_CB(write_vstart);
csr_rd_cb[vxsat] = MK_CSR_RD_CB(read_vxsat);
csr_wr_cb[vxsat] = MK_CSR_WR_CB(write_vxsat);
csr_rd_cb[vxrm] = MK_CSR_RD_CB(read_vxrm);
csr_wr_cb[vxrm] = MK_CSR_WR_CB(write_vxrm);
csr_rd_cb[vcsr] = MK_CSR_RD_CB(read_vcsr);
csr_wr_cb[vcsr] = MK_CSR_WR_CB(write_vcsr);
csr_rd_cb[vl] = MK_CSR_RD_CB(read_vl);
csr_rd_cb[vtype] = MK_CSR_RD_CB(read_vtype);
csr_rd_cb[vlenb] = MK_CSR_RD_CB(read_vlenb);
}
for(unsigned addr = mhpmcounter3; addr <= mhpmcounter31; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
}
if(traits<BASE>::XLEN == 32)
for(unsigned addr = mhpmcounter3h; addr <= mhpmcounter31h; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
}
for(unsigned addr = mhpmevent3; addr <= mhpmevent31; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
csr_wr_cb[addr] = MK_CSR_WR_CB(write_plain);
}
for(unsigned addr = hpmcounter3; addr <= hpmcounter31; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
}
if(traits<BASE>::XLEN == 32)
for(unsigned addr = hpmcounter3h; addr <= hpmcounter31h; ++addr) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_null);
}
// common regs
const std::array<unsigned, 4> roaddrs{{misa, mvendorid, marchid, mimpid}};
for(auto addr : roaddrs) {
csr_rd_cb[addr] = MK_CSR_RD_CB(read_plain);
csr_wr_cb[addr] = MK_CSR_WR_CB(write_null);
}
// special handling & overrides
csr_rd_cb[time] = MK_CSR_RD_CB(read_time);
if(traits<BASE>::XLEN == 32)
csr_rd_cb[timeh] = MK_CSR_RD_CB(read_time);
csr_rd_cb[cycle] = MK_CSR_RD_CB(read_cycle);
if(traits<BASE>::XLEN == 32)
csr_rd_cb[cycleh] = MK_CSR_RD_CB(read_cycle);
csr_rd_cb[instret] = MK_CSR_RD_CB(read_instret);
if(traits<BASE>::XLEN == 32)
csr_rd_cb[instreth] = MK_CSR_RD_CB(read_instret);
csr_rd_cb[mcycle] = MK_CSR_RD_CB(read_cycle);
csr_wr_cb[mcycle] = MK_CSR_WR_CB(write_cycle);
if(traits<BASE>::XLEN == 32)
csr_rd_cb[mcycleh] = MK_CSR_RD_CB(read_cycle);
if(traits<BASE>::XLEN == 32)
csr_wr_cb[mcycleh] = MK_CSR_WR_CB(write_cycle);
csr_rd_cb[minstret] = MK_CSR_RD_CB(read_instret);
csr_wr_cb[minstret] = MK_CSR_WR_CB(write_instret);
if(traits<BASE>::XLEN == 32)
csr_rd_cb[minstreth] = MK_CSR_RD_CB(read_instret);
if(traits<BASE>::XLEN == 32)
csr_wr_cb[minstreth] = MK_CSR_WR_CB(write_instret);
csr_rd_cb[mhartid] = MK_CSR_RD_CB(read_hartid);
};
~riscv_hart_common() {
if(io_buf.str().length()) {
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
}
}
std::unordered_map<std::string, uint64_t> symbol_table;
uint64_t entry_address{0};
uint64_t tohost = std::numeric_limits<uint64_t>::max();
uint64_t fromhost = std::numeric_limits<uint64_t>::max();
std::stringstream io_buf;
void set_semihosting_callback(semihosting_cb_t<reg_t> cb) { semihosting_cb = cb; };
std::pair<uint64_t, bool> load_file(std::string name, int type) {
return std::make_pair(entry_address, read_elf_file(name, sizeof(reg_t) == 4 ? ELFIO::ELFCLASS32 : ELFIO::ELFCLASS64));
}
bool read_elf_file(std::string name, uint8_t expected_elf_class) {
// Create elfio reader
ELFIO::elfio reader;
// Load ELF data
if(reader.load(name)) {
// check elf properties
if(reader.get_class() != expected_elf_class) {
CPPLOG(ERR) << "ISA missmatch, selected XLEN does not match supplied file ";
return false;
}
if(reader.get_type() != ELFIO::ET_EXEC)
return false;
if(reader.get_machine() != ELFIO::EM_RISCV)
return false;
entry_address = reader.get_entry();
for(const auto& pseg : reader.segments) {
const auto fsize = pseg->get_file_size(); // 0x42c/0x0
const auto seg_data = pseg->get_data();
const auto type = pseg->get_type();
if(type == ELFIO::PT_LOAD && fsize > 0) {
auto res = this->write(iss::address_type::PHYSICAL, iss::access_type::DEBUG_WRITE, traits<BASE>::MEM,
pseg->get_physical_address(), fsize, reinterpret_cast<const uint8_t* const>(seg_data));
if(res != iss::Ok)
CPPLOG(ERR) << "problem writing " << fsize << "bytes to 0x" << std::hex << pseg->get_physical_address();
}
}
const auto sym_sec = reader.sections[".symtab"];
if(ELFIO::SHT_SYMTAB == sym_sec->get_type() || ELFIO::SHT_DYNSYM == sym_sec->get_type()) {
ELFIO::symbol_section_accessor symbols(reader, sym_sec);
auto sym_no = symbols.get_symbols_num();
std::string name;
ELFIO::Elf64_Addr value = 0;
ELFIO::Elf_Xword size = 0;
unsigned char bind = 0;
unsigned char type = 0;
ELFIO::Elf_Half section = 0;
unsigned char other = 0;
for(auto i = 0U; i < sym_no; ++i) {
symbols.get_symbol(i, name, value, size, bind, type, section, other);
if(name != "") {
this->symbol_table[name] = value;
#ifndef NDEBUG
CPPLOG(DEBUG) << "Found Symbol " << name;
#endif
}
}
auto to_it = symbol_table.find("tohost");
if(to_it != std::end(symbol_table))
tohost = to_it->second;
auto from_it = symbol_table.find("tohost");
if(from_it != std::end(symbol_table))
tohost = from_it->second;
}
return true;
}
return false;
};
iss::status execute_sys_write(arch_if* aif, const std::array<uint64_t, 8>& loaded_payload, unsigned mem_type) {
uint64_t fd = loaded_payload[1];
uint64_t buf_ptr = loaded_payload[2];
uint64_t len = loaded_payload[3];
std::vector<char> buf(len);
if(aif->read(address_type::PHYSICAL, access_type::DEBUG_READ, mem_type, buf_ptr, len, reinterpret_cast<uint8_t*>(buf.data()))) {
CPPLOG(ERR) << "SYS_WRITE buffer read went wrong";
return iss::Err;
}
// we disregard the fd and just log to stdout
for(size_t i = 0; i < len; i++) {
if(buf[i] == '\n' || buf[i] == '\0') {
CPPLOG(INFO) << "tohost send '" << io_buf.str() << "'";
io_buf.str("");
} else
io_buf << buf[i];
}
// Not sure what the correct return value should be
uint8_t ret_val = 1;
if(fromhost != std::numeric_limits<uint64_t>::max())
if(aif->write(address_type::PHYSICAL, access_type::DEBUG_WRITE, mem_type, fromhost, 1, &ret_val)) {
CPPLOG(ERR) << "Fromhost write went wrong";
return iss::Err;
}
return iss::Ok;
}
constexpr bool has_compressed() { return traits<BASE>::MISA_VAL & 0b0100; }
constexpr reg_t get_pc_mask() { return has_compressed() ? (reg_t)~1 : (reg_t)~3; }
void disass_output(uint64_t pc, const std::string instr) override {
// NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]", pc, instr, lvl[this->reg.PRIV],
// (reg_t)state.mstatus,
// this->reg.cycle + cycle_offset);
NSCLOG(INFO, LOGCAT) << fmt::format("0x{:016x} {:40} [p:{};c:{}]", pc, instr, lvl[this->reg.PRIV],
this->reg.cycle + cycle_offset);
};
void register_csr(unsigned addr, rd_csr_f f) { csr_rd_cb[addr] = f; }
void register_csr(unsigned addr, wr_csr_f f) { csr_wr_cb[addr] = f; }
void register_csr(unsigned addr, rd_csr_f rdf, wr_csr_f wrf) {
csr_rd_cb[addr] = rdf;
csr_wr_cb[addr] = wrf;
}
void unregister_csr_rd(unsigned addr) { csr_rd_cb.erase(addr); }
void unregister_csr_wr(unsigned addr) { csr_wr_cb.erase(addr); }
bool debug_mode_active() { return this->reg.PRIV & 0x4; }
const reg_t& get_mhartid() const { return mhartid_reg; }
void set_mhartid(reg_t mhartid) { mhartid_reg = mhartid; };
iss::status read_csr(unsigned addr, reg_t& val) {
if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data);
auto it = csr_rd_cb.find(addr);
if(it == csr_rd_cb.end() || !it->second) // non existent register
throw illegal_instruction_fault(this->fault_data);
return it->second(addr, val);
}
iss::status write_csr(unsigned addr, reg_t val) {
if(addr >= csr.size())
return iss::Err;
auto req_priv_lvl = (addr >> 8) & 0x3;
if(this->reg.PRIV < req_priv_lvl) // not having required privileges
throw illegal_instruction_fault(this->fault_data);
if((addr & 0xc00) == 0xc00) // writing to read-only region
throw illegal_instruction_fault(this->fault_data);
auto it = csr_wr_cb.find(addr);
if(it == csr_wr_cb.end() || !it->second) // non existent register
throw illegal_instruction_fault(this->fault_data);
return it->second(addr, val);
}
iss::status read_null(unsigned addr, reg_t& val) {
val = 0;
return iss::Ok;
}
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
iss::status read_plain(unsigned addr, reg_t& val) {
val = csr[addr];
return iss::Ok;
}
iss::status write_plain(unsigned addr, reg_t val) {
csr[addr] = val;
return iss::Ok;
}
iss::status read_cycle(unsigned addr, reg_t& val) {
auto cycle_val = this->reg.cycle + cycle_offset;
if(addr == mcycle) {
val = static_cast<reg_t>(cycle_val);
} else if(addr == mcycleh) {
val = static_cast<reg_t>(cycle_val >> 32);
}
return iss::Ok;
}
iss::status write_cycle(unsigned addr, reg_t val) {
if(sizeof(typename traits<BASE>::reg_t) != 4) {
mcycle_csr = static_cast<uint64_t>(val);
} else {
if(addr == mcycle) {
mcycle_csr = (mcycle_csr & 0xffffffff00000000) + val;
} else {
mcycle_csr = (static_cast<uint64_t>(val) << 32) + (mcycle_csr & 0xffffffff);
}
}
cycle_offset = mcycle_csr - this->reg.cycle; // TODO: relying on wrap-around
return iss::Ok;
}
iss::status read_instret(unsigned addr, reg_t& val) {
if((addr & 0xff) == (minstret & 0xff)) {
val = static_cast<reg_t>(this->reg.instret);
} else if((addr & 0xff) == (minstreth & 0xff)) {
val = static_cast<reg_t>(this->reg.instret >> 32);
}
return iss::Ok;
}
iss::status write_instret(unsigned addr, reg_t val) {
if(sizeof(typename traits<BASE>::reg_t) != 4) {
this->reg.instret = static_cast<uint64_t>(val);
} else {
if((addr & 0xff) == (minstret & 0xff)) {
this->reg.instret = (this->reg.instret & 0xffffffff00000000) + val;
} else {
this->reg.instret = (static_cast<uint64_t>(val) << 32) + (this->reg.instret & 0xffffffff);
}
}
this->reg.instret--;
return iss::Ok;
}
iss::status read_time(unsigned addr, reg_t& val) {
uint64_t time_val = this->reg.cycle / (100000000 / 32768 - 1); //-> ~3052;
if(addr == time) {
val = static_cast<reg_t>(time_val);
} else if(addr == timeh) {
if(sizeof(typename traits<BASE>::reg_t) != 4)
return iss::Err;
val = static_cast<reg_t>(time_val >> 32);
}
return iss::Ok;
}
iss::status read_tvec(unsigned addr, reg_t& val) {
val = csr[addr] & ~2;
return iss::Ok;
}
iss::status read_hartid(unsigned addr, reg_t& val) {
val = mhartid_reg;
return iss::Ok;
}
iss::status write_epc(unsigned addr, reg_t val) {
csr[addr] = val & get_pc_mask();
return iss::Ok;
}
iss::status write_dcsr(unsigned addr, reg_t val) {
if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data);
// +-------------- ebreakm
// | +---------- stepi
// | | +++----- cause
// | | ||| +- step
csr[addr] = val & 0b1000100111000100U;
return iss::Ok;
}
iss::status read_debug(unsigned addr, reg_t& val) {
if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data);
val = csr[addr];
return iss::Ok;
}
iss::status write_dscratch(unsigned addr, reg_t val) {
if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data);
csr[addr] = val;
return iss::Ok;
}
iss::status read_dpc(unsigned addr, reg_t& val) {
if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data);
val = this->reg.DPC;
return iss::Ok;
}
iss::status write_dpc(unsigned addr, reg_t val) {
if(!debug_mode_active())
throw illegal_instruction_fault(this->fault_data);
this->reg.DPC = val;
return iss::Ok;
}
iss::status read_fcsr(unsigned addr, reg_t& val) {
switch(addr) {
case 1: // fflags, 4:0
val = bit_sub<0, 5>(this->get_fcsr());
break;
case 2: // frm, 7:5
val = bit_sub<5, 3>(this->get_fcsr());
break;
case 3: // fcsr
val = this->get_fcsr();
break;
default:
return iss::Err;
}
return iss::Ok;
}
iss::status write_fcsr(unsigned addr, reg_t val) {
switch(addr) {
case 1: // fflags, 4:0
this->set_fcsr((this->get_fcsr() & 0xffffffe0) | (val & 0x1f));
break;
case 2: // frm, 7:5
this->set_fcsr((this->get_fcsr() & 0xffffff1f) | ((val & 0x7) << 5));
break;
case 3: // fcsr
this->set_fcsr(val & 0xff);
break;
default:
return iss::Err;
}
return iss::Ok;
}
iss::status read_vstart(unsigned addr, reg_t& val) {
val = this->get_vstart();
return iss::Ok;
}
iss::status write_vstart(unsigned addr, reg_t val) {
this->set_vstart(val);
return iss::Ok;
}
iss::status read_vxsat(unsigned addr, reg_t& val) {
val = this->get_vxsat();
return iss::Ok;
}
iss::status write_vxsat(unsigned addr, reg_t val) {
this->set_vxsat(val & 1);
csr[vcsr] = (~1ULL & csr[vcsr]) | (val & 1);
return iss::Ok;
}
iss::status read_vxrm(unsigned addr, reg_t& val) {
val = this->get_vxrm();
return iss::Ok;
}
iss::status write_vxrm(unsigned addr, reg_t val) {
this->set_vxrm(val & 0b11);
csr[vcsr] = (~0b110ULL & csr[vcsr]) | ((val & 0b11) << 1);
return iss::Ok;
}
iss::status read_vcsr(unsigned addr, reg_t& val) {
val = csr[vcsr];
return iss::Ok;
}
iss::status write_vcsr(unsigned addr, reg_t val) {
csr[vcsr] = val;
return iss::Ok;
}
iss::status read_vl(unsigned addr, reg_t& val) {
val = this->get_vl();
return iss::Ok;
}
iss::status read_vtype(unsigned addr, reg_t& val) {
val = this->get_vtype();
return iss::Ok;
}
iss::status read_vlenb(unsigned addr, reg_t& val) {
val = csr[vlenb];
return iss::Ok;
}
priv_if<reg_t> get_priv_if() {
return priv_if<reg_t>{.read_csr = [this](unsigned addr, reg_t& val) -> iss::status { return read_csr(addr, val); },
.write_csr = [this](unsigned addr, reg_t val) -> iss::status { return write_csr(addr, val); },
.exec_htif = [this](uint8_t const* data) -> iss::status { return execute_htif(data); },
.raise_trap =
[this](uint16_t trap_id, uint16_t cause, reg_t fault_data) {
this->reg.trap_state = 0x80ULL << 24 | (cause << 16) | trap_id;
this->fault_data = fault_data;
},
.csr_rd_cb{this->csr_rd_cb},
.csr_wr_cb{this->csr_wr_cb},
.state{this->state},
.PRIV{this->reg.PRIV},
.PC{this->reg.PC},
.tohost{this->tohost},
.fromhost{this->fromhost},
.max_irq{mcause_max_irq}};
}
iss::status execute_htif(uint8_t const* data) {
reg_t cur_data = *reinterpret_cast<const reg_t*>(data);
// Extract Device (bits 63:56)
uint8_t device = traits<BASE>::XLEN == 32 ? 0 : (cur_data >> 56) & 0xFF;
// Extract Command (bits 55:48)
uint8_t command = traits<BASE>::XLEN == 32 ? 0 : (cur_data >> 48) & 0xFF;
// Extract payload (bits 47:0)
uint64_t payload_addr = cur_data & 0xFFFFFFFFFFFFULL;
if(payload_addr & 1) {
CPPLOG(FATAL) << "this->tohost value is 0x" << std::hex << payload_addr << std::dec << " (" << payload_addr
<< "), stopping simulation";
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
} else if(device == 0 && command == 0) {
std::array<uint64_t, 8> loaded_payload;
if(memory.rd_mem(access_type::DEBUG_READ, payload_addr, 8 * sizeof(uint64_t),
reinterpret_cast<uint8_t*>(loaded_payload.data())) == iss::Err)
CPPLOG(ERR) << "Syscall read went wrong";
uint64_t syscall_num = loaded_payload.at(0);
if(syscall_num == 64) { // SYS_WRITE
return this->execute_sys_write(this, loaded_payload, traits<BASE>::MEM);
} else {
CPPLOG(ERR) << "this->tohost syscall with number 0x" << std::hex << syscall_num << std::dec << " (" << syscall_num
<< ") not implemented";
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
}
} else {
CPPLOG(ERR) << "this->tohost functionality not implemented for device " << device << " and command " << command;
this->reg.trap_state = std::numeric_limits<uint32_t>::max();
this->interrupt_sim = payload_addr;
return iss::Ok;
}
}
mem::memory_hierarchy memories;
mem::memory_if get_mem_if() override {
assert(false || "This function should never be called");
return mem::memory_if{};
}
void set_next(mem::memory_if mem_if) override { memory = mem_if; };
void set_irq_num(unsigned i) { mcause_max_irq = 1 << util::ilog2(i); }
protected:
hart_state<reg_t> state;
static constexpr reg_t get_mstatus_mask_t(unsigned priv_lvl = PRIV_M) {
if(sizeof(reg_t) == 4) {
return priv_lvl == PRIV_U ? 0x80000011UL : // 0b1...0 0001 0001
priv_lvl == PRIV_S ? 0x800de133UL // 0b0...0 0001 1000 1001 1001;
: 0x807ff9ddUL;
} else {
return priv_lvl == PRIV_U ? 0x011ULL : // 0b1...0 0001 0001
priv_lvl == PRIV_S ? 0x000de133ULL
: 0x007ff9ddULL;
}
}
mem::memory_if memory;
struct riscv_instrumentation_if : public iss::instrumentation_if {
riscv_instrumentation_if(riscv_hart_common<BASE, LOGCAT>& arch)
: arch(arch) {}
/**
* get the name of this architecture
*
* @return the name of this architecture
*/
const std::string core_type_name() const override { return traits<BASE>::core_type; }
uint64_t get_pc() override { return arch.reg.PC; }
uint64_t get_next_pc() override { return arch.reg.NEXT_PC; }
uint64_t get_instr_word() override { return arch.reg.instruction; }
uint64_t get_instr_count() override { return arch.reg.icount; }
uint64_t get_pendig_traps() override { return arch.reg.trap_state; }
uint64_t get_total_cycles() override { return arch.reg.cycle + arch.cycle_offset; }
void update_last_instr_cycles(unsigned cycles) override { arch.cycle_offset += cycles - 1; }
bool is_branch_taken() override { return arch.reg.last_branch; }
unsigned get_reg_num() override { return traits<BASE>::NUM_REGS; }
unsigned get_reg_size(unsigned num) override { return traits<BASE>::reg_bit_widths[num]; }
std::unordered_map<std::string, uint64_t> const& get_symbol_table(std::string name) override { return arch.symbol_table; }
riscv_hart_common<BASE, LOGCAT>& arch;
};
friend struct riscv_instrumentation_if;
riscv_instrumentation_if instr_if;
instrumentation_if* get_instrumentation_if() override { return &instr_if; };
using csr_type = util::sparse_array<typename traits<BASE>::reg_t, 1ULL << 12, 12>;
using csr_page_type = typename csr_type::page_type;
csr_type csr;
absl::flat_hash_map<unsigned, rd_csr_f> csr_rd_cb;
absl::flat_hash_map<unsigned, wr_csr_f> csr_wr_cb;
reg_t mhartid_reg{0x0};
uint64_t mcycle_csr{0};
uint64_t minstret_csr{0};
reg_t fault_data;
int64_t cycle_offset{0};
int64_t instret_offset{0};
semihosting_cb_t<reg_t> semihosting_cb;
unsigned mcause_max_irq{16U};
};
} // namespace arch
} // namespace iss
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2020 MINRES Technologies GmbH
* Copyright (C) 2024 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -30,7 +30,8 @@
*
*******************************************************************************/
#include "tgc_c.h"
// clang-format off
#include "tgc5c.h"
#include "util/ities.h"
#include <util/logging.h>
#include <cstdio>
@ -39,18 +40,18 @@
using namespace iss::arch;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc_c>::reg_names;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc_c>::reg_aliases;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc_c>::reg_bit_widths;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc_c>::reg_byte_offsets;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_names;
constexpr std::array<const char*, 36> iss::arch::traits<iss::arch::tgc5c>::reg_aliases;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_bit_widths;
constexpr std::array<const uint32_t, 43> iss::arch::traits<iss::arch::tgc5c>::reg_byte_offsets;
tgc_c::tgc_c() = default;
tgc5c::tgc5c() = default;
tgc_c::~tgc_c() = default;
tgc5c::~tgc5c() = default;
void tgc_c::reset(uint64_t address) {
auto base_ptr = reinterpret_cast<traits<tgc_c>::reg_t*>(get_regs_base_ptr());
for(size_t i=0; i<traits<tgc_c>::NUM_REGS; ++i)
void tgc5c::reset(uint64_t address) {
auto base_ptr = reinterpret_cast<traits<tgc5c>::reg_t*>(get_regs_base_ptr());
for(size_t i=0; i<traits<tgc5c>::NUM_REGS; ++i)
*(base_ptr+i)=0;
reg.PC=address;
reg.NEXT_PC=reg.PC;
@ -59,11 +60,11 @@ void tgc_c::reset(uint64_t address) {
reg.icount=0;
}
uint8_t *tgc_c::get_regs_base_ptr() {
uint8_t *tgc5c::get_regs_base_ptr() {
return reinterpret_cast<uint8_t*>(&reg);
}
tgc_c::phys_addr_t tgc_c::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc_c>::addr_mask);
tgc5c::phys_addr_t tgc5c::virt2phys(const iss::addr_t &addr) {
return phys_addr_t(addr.access, addr.space, addr.val&traits<tgc5c>::addr_mask);
}
// clang-format on

270
src/iss/arch/tgc5c.h Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,261 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017 - 2021 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
*******************************************************************************/
#ifndef _TGC_C_H_
#define _TGC_C_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h>
#include <iss/vm_if.h>
namespace iss {
namespace arch {
struct tgc_c;
template <> struct traits<tgc_c> {
constexpr static char const* const core_type = "TGC_C";
static constexpr std::array<const char*, 36> reg_names{
{"X0", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10", "X11", "X12", "X13", "X14", "X15", "X16", "X17", "X18", "X19", "X20", "X21", "X22", "X23", "X24", "X25", "X26", "X27", "X28", "X29", "X30", "X31", "PC", "NEXT_PC", "PRIV", "DPC"}};
static constexpr std::array<const char*, 36> reg_aliases{
{"ZERO", "RA", "SP", "GP", "TP", "T0", "T1", "T2", "S0", "S1", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "T3", "T4", "T5", "T6", "PC", "NEXT_PC", "PRIV", "DPC"}};
enum constants {MISA_VAL=1073746180ULL, MARCHID_VAL=2147483651ULL, XLEN=32ULL, INSTR_ALIGNMENT=2ULL, RFS=32ULL, fence=0ULL, fencei=1ULL, fencevmal=2ULL, fencevmau=3ULL, CSR_SIZE=4096ULL, MUL_LEN=64ULL};
constexpr static unsigned FP_REGS_SIZE = 0;
enum reg_e {
X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30, X31, PC, NEXT_PC, PRIV, DPC, NUM_REGS, TRAP_STATE=NUM_REGS, PENDING_TRAP, ICOUNT, CYCLE, INSTRET, INSTRUCTION, LAST_BRANCH
};
using reg_t = uint32_t;
using addr_t = uint32_t;
using code_word_t = uint32_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 43> reg_bit_widths{
{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,8,32,32,32,64,64,64,32,32}};
static constexpr std::array<const uint32_t, 43> reg_byte_offsets{
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,137,141,145,149,157,165,173,177}};
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS };
enum mem_type_e { MEM, FENCE, RES, CSR };
enum class opcode_e {
LUI = 0,
AUIPC = 1,
JAL = 2,
JALR = 3,
BEQ = 4,
BNE = 5,
BLT = 6,
BGE = 7,
BLTU = 8,
BGEU = 9,
LB = 10,
LH = 11,
LW = 12,
LBU = 13,
LHU = 14,
SB = 15,
SH = 16,
SW = 17,
ADDI = 18,
SLTI = 19,
SLTIU = 20,
XORI = 21,
ORI = 22,
ANDI = 23,
SLLI = 24,
SRLI = 25,
SRAI = 26,
ADD = 27,
SUB = 28,
SLL = 29,
SLT = 30,
SLTU = 31,
XOR = 32,
SRL = 33,
SRA = 34,
OR = 35,
AND = 36,
FENCE = 37,
ECALL = 38,
EBREAK = 39,
MRET = 40,
WFI = 41,
CSRRW = 42,
CSRRS = 43,
CSRRC = 44,
CSRRWI = 45,
CSRRSI = 46,
CSRRCI = 47,
FENCE_I = 48,
MUL = 49,
MULH = 50,
MULHSU = 51,
MULHU = 52,
DIV = 53,
DIVU = 54,
REM = 55,
REMU = 56,
CADDI4SPN = 57,
CLW = 58,
CSW = 59,
CADDI = 60,
CNOP = 61,
CJAL = 62,
CLI = 63,
CLUI = 64,
CADDI16SP = 65,
__reserved_clui = 66,
CSRLI = 67,
CSRAI = 68,
CANDI = 69,
CSUB = 70,
CXOR = 71,
COR = 72,
CAND = 73,
CJ = 74,
CBEQZ = 75,
CBNEZ = 76,
CSLLI = 77,
CLWSP = 78,
CMV = 79,
CJR = 80,
__reserved_cmv = 81,
CADD = 82,
CJALR = 83,
CEBREAK = 84,
CSWSP = 85,
DII = 86,
MAX_OPCODE
};
};
struct tgc_c: public arch_if {
using virt_addr_t = typename traits<tgc_c>::virt_addr_t;
using phys_addr_t = typename traits<tgc_c>::phys_addr_t;
using reg_t = typename traits<tgc_c>::reg_t;
using addr_t = typename traits<tgc_c>::addr_t;
tgc_c();
~tgc_c();
void reset(uint64_t address=0) override;
uint8_t* get_regs_base_ptr() override;
inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; }
inline uint64_t stop_code() { return interrupt_sim; }
virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline uint32_t get_last_branch() { return reg.last_branch; }
#pragma pack(push, 1)
struct TGC_C_regs {
uint32_t X0 = 0;
uint32_t X1 = 0;
uint32_t X2 = 0;
uint32_t X3 = 0;
uint32_t X4 = 0;
uint32_t X5 = 0;
uint32_t X6 = 0;
uint32_t X7 = 0;
uint32_t X8 = 0;
uint32_t X9 = 0;
uint32_t X10 = 0;
uint32_t X11 = 0;
uint32_t X12 = 0;
uint32_t X13 = 0;
uint32_t X14 = 0;
uint32_t X15 = 0;
uint32_t X16 = 0;
uint32_t X17 = 0;
uint32_t X18 = 0;
uint32_t X19 = 0;
uint32_t X20 = 0;
uint32_t X21 = 0;
uint32_t X22 = 0;
uint32_t X23 = 0;
uint32_t X24 = 0;
uint32_t X25 = 0;
uint32_t X26 = 0;
uint32_t X27 = 0;
uint32_t X28 = 0;
uint32_t X29 = 0;
uint32_t X30 = 0;
uint32_t X31 = 0;
uint32_t PC = 0;
uint32_t NEXT_PC = 0;
uint8_t PRIV = 0;
uint32_t DPC = 0;
uint32_t trap_state = 0, pending_trap = 0;
uint64_t icount = 0;
uint64_t cycle = 0;
uint64_t instret = 0;
uint32_t instruction = 0;
uint32_t last_branch = 0;
} reg;
#pragma pack(pop)
std::array<address_type, 4> addr_mode;
uint64_t interrupt_sim=0;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
};
}
}
#endif /* _TGC_C_H_ */

View File

@ -1,175 +0,0 @@
#include "tgc_c.h"
#include <vector>
#include <array>
#include <cstdlib>
#include <algorithm>
namespace iss {
namespace arch {
namespace {
// according to
// https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation
#ifdef __GCC__
constexpr size_t bit_count(uint32_t u) { return __builtin_popcount(u); }
#elif __cplusplus < 201402L
constexpr size_t uCount(uint32_t u) { return u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111); }
constexpr size_t bit_count(uint32_t u) { return ((uCount(u) + (uCount(u) >> 3)) & 030707070707) % 63; }
#else
constexpr size_t bit_count(uint32_t u) {
size_t uCount = u - ((u >> 1) & 033333333333) - ((u >> 2) & 011111111111);
return ((uCount + (uCount >> 3)) & 030707070707) % 63;
}
#endif
using opcode_e = traits<tgc_c>::opcode_e;
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct instruction_desriptor {
size_t length;
uint32_t value;
uint32_t mask;
opcode_e op;
};
const std::array<instruction_desriptor, 90> instr_descr = {{
/* entries are: size, valid value, valid mask, function ptr */
{32, 0b00000000000000000000000000110111, 0b00000000000000000000000001111111, opcode_e::LUI},
{32, 0b00000000000000000000000000010111, 0b00000000000000000000000001111111, opcode_e::AUIPC},
{32, 0b00000000000000000000000001101111, 0b00000000000000000000000001111111, opcode_e::JAL},
{32, 0b00000000000000000000000001100111, 0b00000000000000000111000001111111, opcode_e::JALR},
{32, 0b00000000000000000000000001100011, 0b00000000000000000111000001111111, opcode_e::BEQ},
{32, 0b00000000000000000001000001100011, 0b00000000000000000111000001111111, opcode_e::BNE},
{32, 0b00000000000000000100000001100011, 0b00000000000000000111000001111111, opcode_e::BLT},
{32, 0b00000000000000000101000001100011, 0b00000000000000000111000001111111, opcode_e::BGE},
{32, 0b00000000000000000110000001100011, 0b00000000000000000111000001111111, opcode_e::BLTU},
{32, 0b00000000000000000111000001100011, 0b00000000000000000111000001111111, opcode_e::BGEU},
{32, 0b00000000000000000000000000000011, 0b00000000000000000111000001111111, opcode_e::LB},
{32, 0b00000000000000000001000000000011, 0b00000000000000000111000001111111, opcode_e::LH},
{32, 0b00000000000000000010000000000011, 0b00000000000000000111000001111111, opcode_e::LW},
{32, 0b00000000000000000100000000000011, 0b00000000000000000111000001111111, opcode_e::LBU},
{32, 0b00000000000000000101000000000011, 0b00000000000000000111000001111111, opcode_e::LHU},
{32, 0b00000000000000000000000000100011, 0b00000000000000000111000001111111, opcode_e::SB},
{32, 0b00000000000000000001000000100011, 0b00000000000000000111000001111111, opcode_e::SH},
{32, 0b00000000000000000010000000100011, 0b00000000000000000111000001111111, opcode_e::SW},
{32, 0b00000000000000000000000000010011, 0b00000000000000000111000001111111, opcode_e::ADDI},
{32, 0b00000000000000000010000000010011, 0b00000000000000000111000001111111, opcode_e::SLTI},
{32, 0b00000000000000000011000000010011, 0b00000000000000000111000001111111, opcode_e::SLTIU},
{32, 0b00000000000000000100000000010011, 0b00000000000000000111000001111111, opcode_e::XORI},
{32, 0b00000000000000000110000000010011, 0b00000000000000000111000001111111, opcode_e::ORI},
{32, 0b00000000000000000111000000010011, 0b00000000000000000111000001111111, opcode_e::ANDI},
{32, 0b00000000000000000001000000010011, 0b11111110000000000111000001111111, opcode_e::SLLI},
{32, 0b00000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRLI},
{32, 0b01000000000000000101000000010011, 0b11111110000000000111000001111111, opcode_e::SRAI},
{32, 0b00000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::ADD},
{32, 0b01000000000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::SUB},
{32, 0b00000000000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::SLL},
{32, 0b00000000000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::SLT},
{32, 0b00000000000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::SLTU},
{32, 0b00000000000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::XOR},
{32, 0b00000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRL},
{32, 0b01000000000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::SRA},
{32, 0b00000000000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::OR},
{32, 0b00000000000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::AND},
{32, 0b00000000000000000000000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE},
{32, 0b00000000000000000000000001110011, 0b11111111111111111111111111111111, opcode_e::ECALL},
{32, 0b00000000000100000000000001110011, 0b11111111111111111111111111111111, opcode_e::EBREAK},
{32, 0b00000000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::URET},
{32, 0b00010000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::SRET},
{32, 0b00110000001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::MRET},
{32, 0b00010000010100000000000001110011, 0b11111111111111111111111111111111, opcode_e::WFI},
{32, 0b01111011001000000000000001110011, 0b11111111111111111111111111111111, opcode_e::DRET},
{32, 0b00000000000000000001000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRW},
{32, 0b00000000000000000010000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRS},
{32, 0b00000000000000000011000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRC},
{32, 0b00000000000000000101000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRWI},
{32, 0b00000000000000000110000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRSI},
{32, 0b00000000000000000111000001110011, 0b00000000000000000111000001111111, opcode_e::CSRRCI},
{32, 0b00000000000000000001000000001111, 0b00000000000000000111000001111111, opcode_e::FENCE_I},
{32, 0b00000010000000000000000000110011, 0b11111110000000000111000001111111, opcode_e::MUL},
{32, 0b00000010000000000001000000110011, 0b11111110000000000111000001111111, opcode_e::MULH},
{32, 0b00000010000000000010000000110011, 0b11111110000000000111000001111111, opcode_e::MULHSU},
{32, 0b00000010000000000011000000110011, 0b11111110000000000111000001111111, opcode_e::MULHU},
{32, 0b00000010000000000100000000110011, 0b11111110000000000111000001111111, opcode_e::DIV},
{32, 0b00000010000000000101000000110011, 0b11111110000000000111000001111111, opcode_e::DIVU},
{32, 0b00000010000000000110000000110011, 0b11111110000000000111000001111111, opcode_e::REM},
{32, 0b00000010000000000111000000110011, 0b11111110000000000111000001111111, opcode_e::REMU},
{16, 0b0000000000000000, 0b1110000000000011, opcode_e::CADDI4SPN},
{16, 0b0100000000000000, 0b1110000000000011, opcode_e::CLW},
{16, 0b1100000000000000, 0b1110000000000011, opcode_e::CSW},
{16, 0b0000000000000001, 0b1110000000000011, opcode_e::CADDI},
{16, 0b0000000000000001, 0b1110111110000011, opcode_e::CNOP},
{16, 0b0010000000000001, 0b1110000000000011, opcode_e::CJAL},
{16, 0b0100000000000001, 0b1110000000000011, opcode_e::CLI},
{16, 0b0110000000000001, 0b1110000000000011, opcode_e::CLUI},
{16, 0b0110000100000001, 0b1110111110000011, opcode_e::CADDI16SP},
{16, 0b0110000000000001, 0b1111000001111111, opcode_e::__reserved_clui},
{16, 0b1000000000000001, 0b1111110000000011, opcode_e::CSRLI},
{16, 0b1000010000000001, 0b1111110000000011, opcode_e::CSRAI},
{16, 0b1000100000000001, 0b1110110000000011, opcode_e::CANDI},
{16, 0b1000110000000001, 0b1111110001100011, opcode_e::CSUB},
{16, 0b1000110000100001, 0b1111110001100011, opcode_e::CXOR},
{16, 0b1000110001000001, 0b1111110001100011, opcode_e::COR},
{16, 0b1000110001100001, 0b1111110001100011, opcode_e::CAND},
{16, 0b1010000000000001, 0b1110000000000011, opcode_e::CJ},
{16, 0b1100000000000001, 0b1110000000000011, opcode_e::CBEQZ},
{16, 0b1110000000000001, 0b1110000000000011, opcode_e::CBNEZ},
{16, 0b0000000000000010, 0b1111000000000011, opcode_e::CSLLI},
{16, 0b0100000000000010, 0b1110000000000011, opcode_e::CLWSP},
{16, 0b1000000000000010, 0b1111000000000011, opcode_e::CMV},
{16, 0b1000000000000010, 0b1111000001111111, opcode_e::CJR},
{16, 0b1000000000000010, 0b1111111111111111, opcode_e::__reserved_cmv},
{16, 0b1001000000000010, 0b1111000000000011, opcode_e::CADD},
{16, 0b1001000000000010, 0b1111000001111111, opcode_e::CJALR},
{16, 0b1001000000000010, 0b1111111111111111, opcode_e::CEBREAK},
{16, 0b1100000000000010, 0b1110000000000011, opcode_e::CSWSP},
{16, 0b0000000000000000, 0b1111111111111111, opcode_e::DII},
}};
}
template<>
struct instruction_decoder<tgc_c> {
using opcode_e = traits<tgc_c>::opcode_e;
using code_word_t=traits<tgc_c>::code_word_t;
struct instruction_pattern {
uint32_t value;
uint32_t mask;
opcode_e id;
};
std::array<std::vector<instruction_pattern>, 4> qlut;
template<typename T>
unsigned decode_instruction(T);
instruction_decoder() {
for (auto instr : instr_descr) {
auto quadrant = instr.value & 0x3;
qlut[quadrant].push_back(instruction_pattern{instr.value, instr.mask, instr.op});
}
for(auto& lut: qlut){
std::sort(std::begin(lut), std::end(lut), [](instruction_pattern const& a, instruction_pattern const& b){
return bit_count(a.mask) > bit_count(b.mask);
});
}
}
};
template<>
unsigned instruction_decoder<tgc_c>::decode_instruction<traits<tgc_c>::code_word_t>(traits<tgc_c>::code_word_t instr){
auto res = std::find_if(std::begin(qlut[instr&0x3]), std::end(qlut[instr&0x3]), [instr](instruction_pattern const& e){
return !((instr&e.mask) ^ e.value );
});
return static_cast<unsigned>(res!=std::end(qlut[instr&0x3])? res->id : opcode_e::MAX_OPCODE);
}
std::unique_ptr<instruction_decoder<tgc_c>> traits<tgc_c>::get_decoder(){
return std::make_unique<instruction_decoder<tgc_c>>();
}
}
}

View File

@ -1,50 +1,85 @@
/*******************************************************************************
* Copyright (C) 2023 - 2025 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _ISS_ARCH_TGC_MAPPER_H
#define _ISS_ARCH_TGC_MAPPER_H
#include "riscv_hart_m_p.h"
#include "tgc_c.h"
using tgc_c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_c>;
#ifdef CORE_TGC_A
#include "tgc5c.h"
using tgc5c_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5c>;
#ifdef CORE_TGC5A
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc_a.h>
using tgc_a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_a>;
#include <iss/arch/tgc5a.h>
using tgc5a_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5a>;
#endif
#ifdef CORE_TGC_B
#ifdef CORE_TGC5B
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc_b.h>
using tgc_b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc_b>;
#include <iss/arch/tgc5b.h>
using tgc5b_plat_type = iss::arch::riscv_hart_m_p<iss::arch::tgc5b>;
#endif
#ifdef CORE_TGC_C_XRB_NN
#include "riscv_hart_m_p.h"
#ifdef CORE_TGC5C_XRB_NN
#include "hwl.h"
#include <iss/arch/tgc_c_xrb_nn.h>
using tgc_c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc_c_xrb_nn>>;
#include "riscv_hart_m_p.h"
#include <iss/arch/tgc5c_xrb_nn.h>
using tgc5c_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_m_p<iss::arch::tgc5c_xrb_nn>>;
#endif
#ifdef CORE_TGC_D
#ifdef CORE_TGC5D
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc_d.h>
using tgc_d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#include <iss/arch/tgc5d.h>
using tgc5d_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC_D_XRB_MAC
#ifdef CORE_TGC5D_XRB_MAC
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc_d_xrb_mac.h>
using tgc_d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_mac, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#include <iss/arch/tgc5d_xrb_mac.h>
using tgc5d_xrb_mac_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_mac(iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC_D_XRB_NN
#include "riscv_hart_mu_p.h"
#ifdef CORE_TGC5D_XRB_NN
#include "hwl.h"
#include <iss/arch/tgc_d_xrb_nn.h>
using tgc_d_xrb_nn_plat_type = iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc_d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>>;
#endif
#ifdef CORE_TGC_E
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc_e.h>
using tgc_e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_e, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N)>;
#include <iss/arch/tgc5d_xrb_nn.h>
using tgc5d_xrb_nn_plat_type =
iss::arch::hwl<iss::arch::riscv_hart_mu_p<iss::arch::tgc5d_xrb_nn, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>>;
#endif
#ifdef CORE_TGC_X
#ifdef CORE_TGC5E
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc_x.h>
using tgc_x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc_x, (iss::arch::features_e)(iss::arch::FEAT_PMP | iss::arch::FEAT_CLIC | iss::arch::FEAT_EXT_N | iss::arch::FEAT_TCM)>;
#include <iss/arch/tgc5e.h>
using tgc5e_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5e, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
#endif
#ifdef CORE_TGC5X
#include "riscv_hart_mu_p.h"
#include <iss/arch/tgc5x.h>
using tgc5x_plat_type = iss::arch::riscv_hart_mu_p<iss::arch::tgc5x, (iss::arch::features_e)(iss::arch::FEAT_EXT_N)>;
#endif
#endif

View File

@ -36,25 +36,27 @@
#define _RISCV_HART_M_P_WT_CACHE_H
#include <iss/vm_types.h>
#include <util/ities.h>
#include <vector>
#include <map>
#include <memory>
#include <util/ities.h>
#include <vector>
namespace iss {
namespace arch {
namespace cache {
enum class state { INVALID, VALID};
enum class state { INVALID, VALID };
struct line {
uint64_t tag_addr{0};
state st{state::INVALID};
std::vector<uint8_t> data;
line(unsigned line_sz): data(line_sz) {}
line(unsigned line_sz)
: data(line_sz) {}
};
struct set {
std::vector<line> ways;
set(unsigned ways_count, line const& l): ways(ways_count, l) {}
set(unsigned ways_count, line const& l)
: ways(ways_count, l) {}
};
struct cache {
std::vector<set> sets;
@ -62,14 +64,14 @@ struct cache {
cache(unsigned size, unsigned line_sz, unsigned ways) {
line const ref_line{line_sz};
set const ref_set{ways, ref_line};
sets.resize(size/(ways*line_sz), ref_set);
sets.resize(size / (ways * line_sz), ref_set);
}
};
struct wt_policy {
bool is_cacheline_hit(cache& c );
bool is_cacheline_hit(cache& c);
};
}
} // namespace cache
// write thru, allocate on read, direct mapped or set-associative with round-robin replacement policy
template <typename BASE> class wt_cache : public BASE {
@ -81,82 +83,81 @@ public:
using mem_write_f = typename BASE::mem_write_f;
using phys_addr_t = typename BASE::phys_addr_t;
wt_cache();
wt_cache(feature_config cfg = feature_config{});
virtual ~wt_cache() = default;
unsigned size{4096};
unsigned line_sz{32};
unsigned line_sz{64};
unsigned ways{1};
uint64_t io_address{0xf0000000};
uint64_t io_addr_mask{0xf0000000};
protected:
iss::status read_cache(phys_addr_t addr, unsigned, uint8_t *const);
iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const *const);
iss::status read_cache(phys_addr_t addr, unsigned, uint8_t* const);
iss::status write_cache(phys_addr_t addr, unsigned, uint8_t const* const);
std::function<mem_read_f> cache_mem_rd_delegate;
std::function<mem_write_f> cache_mem_wr_delegate;
std::unique_ptr<cache::cache> dcache_ptr;
std::unique_ptr<cache::cache> icache_ptr;
size_t get_way_select() {
return 0;
}
size_t get_way_select() { return 0; }
};
template<typename BASE>
inline wt_cache<BASE>::wt_cache() {
template <typename BASE>
inline wt_cache<BASE>::wt_cache(feature_config cfg)
: BASE(cfg)
, io_address{cfg.io_address}
, io_addr_mask{cfg.io_addr_mask} {
auto cb = base_class::replace_mem_access(
[this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l,d);},
[this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l,d);});
[this](phys_addr_t a, unsigned l, uint8_t* const d) -> iss::status { return read_cache(a, l, d); },
[this](phys_addr_t a, unsigned l, uint8_t const* const d) -> iss::status { return write_cache(a, l, d); });
cache_mem_rd_delegate = cb.first;
cache_mem_wr_delegate = cb.second;
}
template<typename BASE>
iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
template <typename BASE> iss::status iss::arch::wt_cache<BASE>::read_cache(phys_addr_t a, unsigned l, uint8_t* const d) {
if(!icache_ptr) {
icache_ptr.reset(new cache::cache(size, line_sz, ways));
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
}
if((a.val&io_addr_mask) != io_address) {
auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways);
auto tag_addr=a.val>>util::ilog2(line_sz);
auto& set = (is_fetch(a.access)?icache_ptr:dcache_ptr)->sets[set_addr];
for(auto& cl: set.ways) {
if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) {
auto start_addr = a.val&(line_sz-1);
for(auto i = 0U; i<l; ++i)
d[i] = cl.data[start_addr+i];
if((a.access & iss::access_type::FETCH) == iss::access_type::FETCH || (a.val & io_addr_mask) != io_address) {
auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways);
auto tag_addr = a.val >> util::ilog2(line_sz);
auto& set = (is_fetch(a.access) ? icache_ptr : dcache_ptr)->sets[set_addr];
for(auto& cl : set.ways) {
if(cl.st == cache::state::VALID && cl.tag_addr == tag_addr) {
auto start_addr = a.val & (line_sz - 1);
for(auto i = 0U; i < l; ++i)
d[i] = cl.data[start_addr + i];
return iss::Ok;
}
}
auto& cl = set.ways[get_way_select()];
phys_addr_t cl_addr{a};
cl_addr.val=tag_addr<<util::ilog2(line_sz);
cl_addr.val = tag_addr << util::ilog2(line_sz);
cache_mem_rd_delegate(cl_addr, line_sz, cl.data.data());
cl.tag_addr=tag_addr;
cl.st=cache::state::VALID;
auto start_addr = a.val&(line_sz-1);
for(auto i = 0U; i<l; ++i)
d[i] = cl.data[start_addr+i];
cl.tag_addr = tag_addr;
cl.st = cache::state::VALID;
auto start_addr = a.val & (line_sz - 1);
for(auto i = 0U; i < l; ++i)
d[i] = cl.data[start_addr + i];
return iss::Ok;
} else
return cache_mem_rd_delegate(a, l, d);
}
template<typename BASE>
iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
template <typename BASE> iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, const uint8_t* const d) {
if(!dcache_ptr)
dcache_ptr.reset(new cache::cache(size, line_sz, ways));
auto res = cache_mem_wr_delegate(a, l, d);
if(res == iss::Ok && ((a.val&io_addr_mask) != io_address)) {
auto set_addr=(a.val&(size-1))>>util::ilog2(line_sz*ways);
auto tag_addr=a.val>>util::ilog2(line_sz);
if(res == iss::Ok && ((a.val & io_addr_mask) != io_address)) {
auto set_addr = (a.val & (size - 1)) >> util::ilog2(line_sz * ways);
auto tag_addr = a.val >> util::ilog2(line_sz);
auto& set = dcache_ptr->sets[set_addr];
for(auto& cl: set.ways) {
if(cl.st==cache::state::VALID && cl.tag_addr==tag_addr) {
auto start_addr = a.val&(line_sz-1);
for(auto i = 0U; i<l; ++i)
cl.data[start_addr+i] = d[i];
for(auto& cl : set.ways) {
if(cl.st == cache::state::VALID && cl.tag_addr == tag_addr) {
auto start_addr = a.val & (line_sz - 1);
for(auto i = 0U; i < l; ++i)
cl.data[start_addr + i] = d[i];
break;
}
}
@ -164,8 +165,6 @@ iss::status iss::arch::wt_cache<BASE>::write_cache(phys_addr_t a, unsigned l, co
return res;
}
} // namespace arch
} // namespace iss

File diff suppressed because it is too large Load Diff

View File

@ -30,8 +30,8 @@
*
*******************************************************************************/
#ifndef _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
#define _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_
#ifndef _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
#define _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_
#include "iss/arch_if.h"
#include <iss/arch/traits.h>
@ -48,25 +48,29 @@
namespace iss {
namespace debugger {
char const* const get_csr_name(unsigned);
constexpr auto csr_offset = 100U;
using namespace iss::arch;
using namespace iss::debugger;
template <typename ARCH> class riscv_target_adapter : public target_adapter_base {
public:
riscv_target_adapter(server_if *srv, iss::arch_if *core)
riscv_target_adapter(server_if* srv, iss::arch_if* core)
: target_adapter_base(srv)
, core(core) {}
/*============== Thread Control ===============================*/
/* Set generic thread */
status set_gen_thread(rp_thread_ref &thread) override;
status set_gen_thread(rp_thread_ref& thread) override;
/* Set control thread */
status set_ctrl_thread(rp_thread_ref &thread) override;
status set_ctrl_thread(rp_thread_ref& thread) override;
/* Get thread status */
status is_thread_alive(rp_thread_ref &thread, bool &alive) override;
status is_thread_alive(rp_thread_ref& thread, bool& alive) override;
/*============= Register Access ================================*/
@ -74,79 +78,83 @@ public:
target byte order. If register is not available
corresponding bytes in avail_buf are 0, otherwise
avail buf is 1 */
status read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) override;
status read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) override;
/* Write all registers. buf is 4-byte aligned and it is in target
byte order */
status write_registers(const std::vector<uint8_t> &data) override;
status write_registers(const std::vector<uint8_t>& data) override;
/* Read one register. buf is 4-byte aligned and it is in
target byte order. If register is not available
corresponding bytes in avail_buf are 0, otherwise
avail buf is 1 */
status read_single_register(unsigned int reg_no, std::vector<uint8_t> &buf,
std::vector<uint8_t> &avail_buf) override;
status read_single_register(unsigned int reg_no, std::vector<uint8_t>& buf, std::vector<uint8_t>& avail_buf) override;
/* Write one register. buf is 4-byte aligned and it is in target byte
order */
status write_single_register(unsigned int reg_no, const std::vector<uint8_t> &buf) override;
status write_single_register(unsigned int reg_no, const std::vector<uint8_t>& buf) override;
/*=================== Memory Access =====================*/
/* Read memory, buf is 4-bytes aligned and it is in target
byte order */
status read_mem(uint64_t addr, std::vector<uint8_t> &buf) override;
status read_mem(uint64_t addr, std::vector<uint8_t>& buf) override;
/* Write memory, buf is 4-bytes aligned and it is in target
byte order */
status write_mem(uint64_t addr, const std::vector<uint8_t> &buf) override;
status write_mem(uint64_t addr, const std::vector<uint8_t>& buf) override;
status process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) override;
status process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) override;
status thread_list_query(int first, const rp_thread_ref &arg, std::vector<rp_thread_ref> &result, size_t max_num,
size_t &num, bool &done) override;
status thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result, size_t max_num, size_t& num,
bool& done) override;
status current_thread_query(rp_thread_ref &thread) override;
status current_thread_query(rp_thread_ref& thread) override;
status offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) override;
status offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) override;
status crc_query(uint64_t addr, size_t len, uint32_t &val) override;
status crc_query(uint64_t addr, size_t len, uint32_t& val) override;
status raw_query(std::string in_buf, std::string &out_buf) override;
status raw_query(std::string in_buf, std::string& out_buf) override;
status threadinfo_query(int first, std::string &out_buf) override;
status threadinfo_query(int first, std::string& out_buf) override;
status threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) override;
status threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) override;
status packetsize_query(std::string &out_buf) override;
status packetsize_query(std::string& out_buf) override;
status add_break(break_type type, uint64_t addr, unsigned int length) override;
status remove_break(break_type type, uint64_t addr, unsigned int length) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) override;
status resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, std::function<void(unsigned)> stop_callback) override;
status target_xml_query(std::string &out_buf) override;
status target_xml_query(std::string& out_buf) override;
protected:
static inline constexpr addr_t map_addr(const addr_t &i) { return i; }
iss::arch_if *core;
static inline constexpr addr_t map_addr(const addr_t& i) { return i; }
std::string csr_xml;
iss::arch_if* core;
rp_thread_ref thread_idx;
};
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref &thread) {
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN != 0, unsigned>::type get_f0_offset() {
return iss::arch::traits<ARCH>::F0;
}
template <typename ARCH> typename std::enable_if<iss::arch::traits<ARCH>::FLEN == 0, unsigned>::type get_f0_offset() { return 0; }
template <typename ARCH> status riscv_target_adapter<ARCH>::set_gen_thread(rp_thread_ref& thread) {
thread_idx = thread;
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref &thread) {
template <typename ARCH> status riscv_target_adapter<ARCH>::set_ctrl_thread(rp_thread_ref& thread) {
thread_idx = thread;
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_thread_ref &thread, bool &alive) {
template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_thread_ref& thread, bool& alive) {
alive = 1;
return Ok;
}
@ -158,10 +166,9 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::is_thread_alive(rp_t
* set if all threads are processed.
*/
template <typename ARCH>
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref &arg,
std::vector<rp_thread_ref> &result, size_t max_num, size_t &num,
bool &done) {
if (first == 0) {
status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_ref& arg, std::vector<rp_thread_ref>& result,
size_t max_num, size_t& num, bool& done) {
if(first == 0) {
result.clear();
result.push_back(thread_idx);
num = 1;
@ -171,80 +178,81 @@ status riscv_target_adapter<ARCH>::thread_list_query(int first, const rp_thread_
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query(rp_thread_ref &thread) {
template <typename ARCH> status riscv_target_adapter<ARCH>::current_thread_query(rp_thread_ref& thread) {
thread = thread_idx;
return Ok;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, std::vector<uint8_t> &avail) {
LOG(TRACE) << "reading target registers";
// return idx<0?:;
template <typename ARCH> status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
CPPLOG(TRACE) << "reading target registers";
data.clear();
avail.clear();
const uint8_t *reg_base = core->get_regs_base_ptr();
auto start_reg=arch::traits<ARCH>::X0;
for (size_t reg_no = start_reg; reg_no < start_reg+33/*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for (size_t j = 0; j < reg_width; ++j) {
data.push_back(*(reg_base + offset + j));
avail.push_back(0xff);
const uint8_t* reg_base = core->get_regs_base_ptr();
auto start_reg = arch::traits<ARCH>::X0;
for(size_t i = 0; i < 33; ++i) {
if(i < arch::traits<ARCH>::RFS || i == arch::traits<ARCH>::PC) {
auto reg_no = i < 32 ? start_reg + i : arch::traits<ARCH>::PC;
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
data.push_back(*(reg_base + offset + j));
avail.push_back(0xff);
}
} else {
for(size_t j = 0; j < arch::traits<ARCH>::XLEN / 8; ++j) {
data.push_back(0);
avail.push_back(0);
}
}
}
if(iss::arch::traits<ARCH>::FLEN > 0) {
auto fstart_reg = get_f0_offset<ARCH>();
for(size_t i = 0; i < 32; ++i) {
auto reg_no = fstart_reg + i;
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for(size_t j = 0; j < reg_width; ++j) {
data.push_back(*(reg_base + offset + j));
avail.push_back(0xff);
}
}
}
// work around fill with F type registers
// if (arch::traits<ARCH>::NUM_REGS < 65) {
// auto reg_width = sizeof(typename arch::traits<ARCH>::reg_t);
// for (size_t reg_no = 0; reg_no < 33; ++reg_no) {
// for (size_t j = 0; j < reg_width; ++j) {
// data.push_back(0x0);
// avail.push_back(0x00);
// }
// // if(arch::traits<ARCH>::XLEN < 64)
// // for(unsigned j=0; j<4; ++j){
// // data.push_back(0x0);
// // avail.push_back(0x00);
// // }
// }
// }
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(const std::vector<uint8_t> &data) {
auto start_reg=arch::traits<ARCH>::X0;
auto *reg_base = core->get_regs_base_ptr();
template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(const std::vector<uint8_t>& data) {
auto start_reg = arch::traits<ARCH>::X0;
auto* reg_base = core->get_regs_base_ptr();
auto iter = data.data();
bool e_ext = arch::traits<ARCH>::PC<32;
for (size_t reg_no = 0; reg_no < start_reg+33/*arch::traits<ARCH>::NUM_REGS*/; ++reg_no) {
if(e_ext && reg_no>15){
if(reg_no==32){
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
std::copy(iter, iter + reg_width, reg_base);
} else {
const uint64_t zero_val=0;
auto reg_width = arch::traits<ARCH>::reg_bit_widths[15] / 8;
auto iter = (uint8_t*)&zero_val;
std::copy(iter, iter + reg_width, reg_base);
}
} else {
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(iter, iter + reg_width, reg_base);
iter += 4;
reg_base += offset;
auto iter_end = data.data() + data.size();
for(size_t i = 0; i < 33 && iter < iter_end; ++i) {
auto reg_width = arch::traits<ARCH>::XLEN / 8;
if(i < arch::traits<ARCH>::RFS) {
auto offset = traits<ARCH>::reg_byte_offsets[start_reg + i];
std::copy(iter, iter + reg_width, reg_base + offset);
} else if(i == 32) {
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
std::copy(iter, iter + reg_width, reg_base + offset);
}
iter += reg_width;
}
if(iss::arch::traits<ARCH>::FLEN > 0) {
auto fstart_reg = get_f0_offset<ARCH>();
auto reg_width = arch::traits<ARCH>::FLEN / 8;
for(size_t i = 0; i < 32 && iter < iter_end; ++i) {
unsigned offset = traits<ARCH>::reg_byte_offsets[fstart_reg + i];
std::copy(iter, iter + reg_width, reg_base + offset);
iter += reg_width;
}
}
return Ok;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t> &data,
std::vector<uint8_t> &avail) {
if (reg_no < 65) {
status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std::vector<uint8_t>& data, std::vector<uint8_t>& avail) {
if(reg_no < csr_offset) {
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8;
auto *reg_base = core->get_regs_base_ptr();
auto* reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
data.resize(reg_width);
avail.resize(reg_width);
@ -252,64 +260,59 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
std::fill(avail.begin(), avail.end(), 0xff);
} else {
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - 65);
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, reg_no - csr_offset);
data.resize(sizeof(typename traits<ARCH>::reg_t));
avail.resize(sizeof(typename traits<ARCH>::reg_t));
std::fill(avail.begin(), avail.end(), 0xff);
core->read(a, data.size(), data.data());
std::fill(avail.begin(), avail.end(), 0xff);
}
return data.size() > 0 ? Ok : Err;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
if (reg_no < 65) {
auto *reg_base = core->get_regs_base_ptr();
template <typename ARCH> status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t>& data) {
if(reg_no < csr_offset) {
auto* reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
} else {
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - csr_offset);
core->write(a, data.size(), data.data());
}
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t> &data) {
template <typename ARCH> status riscv_target_adapter<ARCH>::read_mem(uint64_t addr, std::vector<uint8_t>& data) {
auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
auto f = [&]() -> status { return core->read(a, data.size(), data.data()); };
return srv->execute_syncronized(f);
}
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t> &data) {
auto a = map_addr({iss::access_type::DEBUG_READ, iss::address_type::VIRTUAL, 0, addr});
template <typename ARCH> status riscv_target_adapter<ARCH>::write_mem(uint64_t addr, const std::vector<uint8_t>& data) {
auto a = map_addr({iss::access_type::DEBUG_WRITE, iss::address_type::VIRTUAL, 0, addr});
auto f = [&]() -> status { return core->write(a, data.size(), data.data()); };
return srv->execute_syncronized(f);
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::process_query(unsigned int &mask, const rp_thread_ref &arg, rp_thread_info &info) {
status riscv_target_adapter<ARCH>::process_query(unsigned int& mask, const rp_thread_ref& arg, rp_thread_info& info) {
return NotSupported;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::offsets_query(uint64_t &text, uint64_t &data, uint64_t &bss) {
template <typename ARCH> status riscv_target_adapter<ARCH>::offsets_query(uint64_t& text, uint64_t& data, uint64_t& bss) {
text = 0;
data = 0;
bss = 0;
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t &val) {
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::crc_query(uint64_t addr, size_t len, uint32_t& val) { return NotSupported; }
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string &out_buf) {
return NotSupported;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::string in_buf, std::string& out_buf) { return NotSupported; }
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) {
if (first) {
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string& out_buf) {
if(first) {
out_buf = fmt::format("m{:x}", thread_idx.val);
} else {
out_buf = "l";
@ -317,8 +320,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int
return Ok;
}
template <typename ARCH>
status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &thread, std::string &out_buf) {
template <typename ARCH> status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref& thread, std::string& out_buf) {
std::array<char, 20> buf;
memset(buf.data(), 0, 20);
sprintf(buf.data(), "%02x%02x%02x%02x%02x%02x%02x%02x%02x", 'R', 'u', 'n', 'n', 'a', 'b', 'l', 'e', 0);
@ -326,7 +328,7 @@ status riscv_target_adapter<ARCH>::threadextrainfo_query(const rp_thread_ref &th
return Ok;
}
template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std::string &out_buf) {
template <typename ARCH> status riscv_target_adapter<ARCH>::packetsize_query(std::string& out_buf) {
out_buf = "PacketSize=1000";
return Ok;
}
@ -340,9 +342,9 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::add_break(break_type
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
auto eaddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr + length});
target_adapter_base::bp_lut.addEntry(++target_adapter_base::bp_count, saddr.val, eaddr.val - saddr.val);
LOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex
<< saddr.val << std::dec;
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
CPPLOG(TRACE) << "Adding breakpoint with handle " << target_adapter_base::bp_count << " for addr 0x" << std::hex << saddr.val
<< std::dec;
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok;
}
}
@ -356,15 +358,14 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_t
case HW_EXEC: {
auto saddr = map_addr({iss::access_type::FETCH, iss::address_type::PHYSICAL, 0, addr});
unsigned handle = target_adapter_base::bp_lut.getEntry(saddr.val);
if (handle) {
LOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val
<< std::dec;
if(handle) {
CPPLOG(TRACE) << "Removing breakpoint with handle " << handle << " for addr 0x" << std::hex << saddr.val << std::dec;
// TODO: check length of addr range
target_adapter_base::bp_lut.removeEntry(handle);
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Ok;
}
LOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
CPPLOG(TRACE) << "Now having " << target_adapter_base::bp_lut.size() << " breakpoints";
return Err;
}
}
@ -372,103 +373,67 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::remove_break(break_t
template <typename ARCH>
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) {
auto *reg_base = core->get_regs_base_ptr();
std::function<void(unsigned)> stop_callback) {
auto* reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr);
const uint8_t* iter = reinterpret_cast<const uint8_t*>(&addr);
std::copy(iter, iter + reg_width, reg_base);
return resume_from_current(step, sig, thread, stop_callback);
}
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string &out_buf) {
const std::string res{"<?xml version=\"1.0\"?><!DOCTYPE target SYSTEM \"gdb-target.dtd\">"
"<target><architecture>riscv:rv32</architecture>"
//" <feature name=\"org.gnu.gdb.riscv.rv32i\">\n"
//" <reg name=\"x0\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x1\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x2\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x3\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x4\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x5\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x6\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x7\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x8\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x9\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x10\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x11\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x12\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x13\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x14\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x15\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x16\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x17\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x18\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x19\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x20\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x21\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x22\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x23\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x24\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x25\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x26\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x27\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x28\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x29\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x30\" bitsize=\"32\" group=\"general\"/>\n"
//" <reg name=\"x31\" bitsize=\"32\" group=\"general\"/>\n"
//" </feature>\n"
"</target>"};
out_buf = res;
template <typename ARCH> status riscv_target_adapter<ARCH>::target_xml_query(std::string& out_buf) {
if(!csr_xml.size()) {
std::ostringstream oss;
oss << "<?xml version=\"1.0\"?><!DOCTYPE feature SYSTEM \"gdb-target.dtd\"><target version=\"1.0\">\n";
if(iss::arch::traits<ARCH>::XLEN == 32)
oss << "<architecture>riscv:rv32</architecture>\n";
else if(iss::arch::traits<ARCH>::XLEN == 64)
oss << " <architectureriscv:rv64</architecture>\n";
oss << " <feature name=\"org.gnu.gdb.riscv.cpu\">\n";
auto reg_base_num = iss::arch::traits<ARCH>::X0;
for(auto i = 0U; i < iss::arch::traits<ARCH>::RFS; ++i) {
oss << " <reg name=\"x" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
<< "\" type=\"int\" regnum=\"" << i << "\"/>\n";
}
oss << " <reg name=\"pc\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[iss::arch::traits<ARCH>::PC]
<< "\" type=\"code_ptr\" regnum=\"" << 32U << "\"/>\n";
oss << " </feature>\n";
if(iss::arch::traits<ARCH>::FLEN > 0) {
oss << " <feature name=\"org.gnu.gdb.riscv.fpu\">\n";
auto reg_base_num = get_f0_offset<ARCH>();
auto type = iss::arch::traits<ARCH>::FLEN == 32 ? "ieee_single" : "riscv_double";
for(auto i = 0U; i < 32; ++i) {
oss << " <reg name=\"f" << i << "\" bitsize=\"" << iss::arch::traits<ARCH>::reg_bit_widths[reg_base_num + i]
<< "\" type=\"" << type << "\" regnum=\"" << i + 33 << "\"/>\n";
}
oss << " <reg name=\"fcsr\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"103\" type int/>\n";
oss << " <reg name=\"fflags\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"101\" type int/>\n";
oss << " <reg name=\"frm\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN << "\" regnum=\"102\" type int/>\n";
oss << " </feature>\n";
}
oss << " <feature name=\"org.gnu.gdb.riscv.csr\">\n";
std::vector<uint8_t> data;
std::vector<uint8_t> avail;
data.resize(sizeof(typename traits<ARCH>::reg_t));
avail.resize(sizeof(typename traits<ARCH>::reg_t));
for(auto i = 0U; i < 4096; ++i) {
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_READ, traits<ARCH>::CSR, i);
std::fill(avail.begin(), avail.end(), 0xff);
auto res = core->read(a, data.size(), data.data());
if(res == iss::Ok) {
oss << " <reg name=\"" << get_csr_name(i) << "\" bitsize=\"" << iss::arch::traits<ARCH>::XLEN
<< "\" type=\"int\" regnum=\"" << (i + csr_offset) << "\"/>\n";
}
}
oss << " </feature>\n";
oss << "</target>\n";
csr_xml = oss.str();
}
out_buf = csr_xml;
return Ok;
}
} // namespace debugger
} // namespace iss
/*
*
<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
<architecture>riscv:rv32</architecture>
<feature name="org.gnu.gdb.riscv.rv32i">
<reg name="x0" bitsize="32" group="general"/>
<reg name="x1" bitsize="32" group="general"/>
<reg name="x2" bitsize="32" group="general"/>
<reg name="x3" bitsize="32" group="general"/>
<reg name="x4" bitsize="32" group="general"/>
<reg name="x5" bitsize="32" group="general"/>
<reg name="x6" bitsize="32" group="general"/>
<reg name="x7" bitsize="32" group="general"/>
<reg name="x8" bitsize="32" group="general"/>
<reg name="x9" bitsize="32" group="general"/>
<reg name="x10" bitsize="32" group="general"/>
<reg name="x11" bitsize="32" group="general"/>
<reg name="x12" bitsize="32" group="general"/>
<reg name="x13" bitsize="32" group="general"/>
<reg name="x14" bitsize="32" group="general"/>
<reg name="x15" bitsize="32" group="general"/>
<reg name="x16" bitsize="32" group="general"/>
<reg name="x17" bitsize="32" group="general"/>
<reg name="x18" bitsize="32" group="general"/>
<reg name="x19" bitsize="32" group="general"/>
<reg name="x20" bitsize="32" group="general"/>
<reg name="x21" bitsize="32" group="general"/>
<reg name="x22" bitsize="32" group="general"/>
<reg name="x23" bitsize="32" group="general"/>
<reg name="x24" bitsize="32" group="general"/>
<reg name="x25" bitsize="32" group="general"/>
<reg name="x26" bitsize="32" group="general"/>
<reg name="x27" bitsize="32" group="general"/>
<reg name="x28" bitsize="32" group="general"/>
<reg name="x29" bitsize="32" group="general"/>
<reg name="x30" bitsize="32" group="general"/>
<reg name="x31" bitsize="32" group="general"/>
</feature>
</target>
*/
}
}
#endif /* _ISS_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */
#endif /* _ISS_ARCH_DEBUGGER_RISCV_TARGET_ADAPTER_H_ */

View File

@ -33,21 +33,20 @@
#ifndef _ISS_FACTORY_H_
#define _ISS_FACTORY_H_
#include <algorithm>
#include <functional>
#include <iss/iss.h>
#include <memory>
#include <unordered_map>
#include <functional>
#include <string>
#include <algorithm>
#include <unordered_map>
#include <vector>
namespace iss {
using cpu_ptr = std::unique_ptr<iss::arch_if>;
using vm_ptr= std::unique_ptr<iss::vm_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>;
template<typename PLAT>
std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port){
template <typename PLAT> std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_port) {
using core_type = typename PLAT::core;
core_type* lcpu = new PLAT();
if(backend == "interp")
@ -63,44 +62,45 @@ std::tuple<cpu_ptr, vm_ptr> create_cpu(std::string const& backend, unsigned gdb_
return {nullptr, nullptr};
}
class core_factory {
using cpu_ptr = std::unique_ptr<iss::arch_if>;
using vm_ptr= std::unique_ptr<iss::vm_if>;
using vm_ptr = std::unique_ptr<iss::vm_if>;
using base_t = std::tuple<cpu_ptr, vm_ptr>;
using create_fn = std::function<base_t(unsigned, void*) >;
using registry_t = std::unordered_map<std::string, create_fn> ;
using create_fn = std::function<base_t(unsigned, void*)>;
using registry_t = std::unordered_map<std::string, create_fn>;
registry_t registry;
core_factory() = default;
core_factory(const core_factory &) = delete;
core_factory & operator=(const core_factory &) = delete;
core_factory(const core_factory&) = delete;
core_factory& operator=(const core_factory&) = delete;
public:
static core_factory & instance() { static core_factory bf; return bf; }
static core_factory& instance() {
static core_factory bf;
return bf;
}
bool register_creator(const std::string & className, create_fn const& fn) {
bool register_creator(const std::string& className, create_fn const& fn) {
registry[className] = fn;
return true;
}
base_t create(std::string const& className, unsigned gdb_port=0, void* init_data=nullptr) const {
base_t create(std::string const& className, unsigned gdb_port = 0, void* init_data = nullptr) const {
registry_t::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end())
if(regEntry != registry.end())
return regEntry->second(gdb_port, init_data);
return {nullptr, nullptr};
}
std::vector<std::string> get_names() {
std::vector<std::string> keys{registry.size()};
std::transform(std::begin(registry), std::end(registry), std::begin(keys), [](std::pair<std::string, create_fn> const& p){
return p.first;
});
std::transform(std::begin(registry), std::end(registry), std::begin(keys),
[](std::pair<std::string, create_fn> const& p) { return p.first; });
return keys;
}
};
}
} // namespace iss
#endif /* _ISS_FACTORY_H_ */

285
src/iss/mem/clic.h Normal file
View File

@ -0,0 +1,285 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h"
#include <util/logging.h>
namespace iss {
namespace mem {
struct clic_config {
uint64_t clic_base{0xc0000000};
unsigned clic_int_ctl_bits{4};
unsigned clic_num_irq{16};
unsigned clic_num_trigger{0};
bool nmode{false};
};
inline void read_reg_with_offset(uint32_t reg, uint8_t offs, uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs) {
default:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 1 + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(data + i) = *(reg_ptr + 2 + i);
break;
case 3:
*data = *(reg_ptr + 3);
break;
}
}
inline void write_reg_with_offset(uint32_t& reg, uint8_t offs, const uint8_t* const data, unsigned length) {
auto reg_ptr = reinterpret_cast<uint8_t*>(&reg);
switch(offs) {
default:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + i) = *(data + i);
break;
case 1:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 1 + i) = *(data + i);
break;
case 2:
for(auto i = 0U; i < length; ++i)
*(reg_ptr + 2 + i) = *(data + i);
break;
case 3:
*(reg_ptr + 3) = *data;
break;
}
}
template <typename WORD_TYPE> struct clic : public memory_elem {
using this_class = clic<WORD_TYPE>;
using reg_t = WORD_TYPE;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
clic(arch::priv_if<WORD_TYPE> hart_if, clic_config cfg)
: hart_if(hart_if)
, cfg(cfg) {
clic_int_reg.resize(cfg.clic_num_irq, clic_int_reg_t{.raw = 0});
clic_cfg_reg = 0x30;
clic_mact_lvl = clic_mprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
clic_uact_lvl = clic_uprev_lvl = (1 << (cfg.clic_int_ctl_bits)) - 1;
hart_if.csr_rd_cb[arch::mtvt] = MK_CSR_RD_CB(read_plain);
hart_if.csr_wr_cb[arch::mtvt] = MK_CSR_WR_CB(write_xtvt);
// hart_if.csr_rd_cb[mxnti] = MK_CSR_RD_CB(read_plain(a,r);};
// hart_if.csr_wr_cb[mxnti] = MK_CSR_WR_CB(write_plain(a,r);};
hart_if.csr_rd_cb[arch::mintstatus] = MK_CSR_RD_CB(read_intstatus);
hart_if.csr_wr_cb[arch::mintstatus] = MK_CSR_WR_CB(write_null);
// hart_if.csr_rd_cb[mscratchcsw] = MK_CSR_RD_CB(read_plain(a,r);};
// hart_if.csr_wr_cb[mscratchcsw] = MK_CSR_WR_CB(write_plain(a,r);};
// hart_if.csr_rd_cb[mscratchcswl] = MK_CSR_RD_CB(read_plain(a,r);};
// hart_if.csr_wr_cb[mscratchcswl] = MK_CSR_WR_CB(write_plain(a,r);};
hart_if.csr_rd_cb[arch::mintthresh] = MK_CSR_RD_CB(read_plain);
hart_if.csr_wr_cb[arch::mintthresh] = MK_CSR_WR_CB(write_intthresh);
if(cfg.nmode) {
hart_if.csr_rd_cb[arch::utvt] = MK_CSR_RD_CB(read_plain);
hart_if.csr_wr_cb[arch::utvt] = MK_CSR_WR_CB(write_xtvt);
hart_if.csr_rd_cb[arch::uintstatus] = MK_CSR_RD_CB(read_intstatus);
hart_if.csr_wr_cb[arch::uintstatus] = MK_CSR_WR_CB(write_null);
hart_if.csr_rd_cb[arch::uintthresh] = MK_CSR_RD_CB(read_plain);
hart_if.csr_wr_cb[arch::uintthresh] = MK_CSR_WR_CB(write_intthresh);
}
hart_if.csr[arch::mintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
hart_if.csr[arch::uintthresh] = (1 << (cfg.clic_int_ctl_bits)) - 1;
}
~clic() = default;
memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
void set_next(memory_if mem) override { down_stream_mem = mem; }
std::tuple<uint64_t, uint64_t> get_range() override { return {cfg.clic_base, cfg.clic_base + 0x7fff}; }
private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
return read_clic(addr, length, data);
return down_stream_mem.rd_mem(access, addr, length, data);
}
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
if(addr >= cfg.clic_base && (addr + length) < (cfg.clic_base + 0x8000))
return write_clic(addr, length, data);
return down_stream_mem.wr_mem(access, addr, length, data);
}
iss::status read_clic(uint64_t addr, unsigned length, uint8_t* data);
iss::status write_clic(uint64_t addr, unsigned length, uint8_t const* data);
iss::status write_null(unsigned addr, reg_t val) { return iss::status::Ok; }
iss::status read_plain(unsigned addr, reg_t& val) {
val = hart_if.csr[addr];
return iss::Ok;
}
iss::status write_xtvt(unsigned addr, reg_t val) {
hart_if.csr[addr] = val & ~0x3fULL;
return iss::Ok;
}
iss::status read_cause(unsigned addr, reg_t& val);
iss::status write_cause(unsigned addr, reg_t val);
iss::status read_intstatus(unsigned addr, reg_t& val);
iss::status write_intthresh(unsigned addr, reg_t val);
protected:
arch::priv_if<WORD_TYPE> hart_if;
memory_if down_stream_mem;
clic_config cfg;
uint8_t clic_cfg_reg{0};
std::array<uint32_t, 32> clic_inttrig_reg;
union clic_int_reg_t {
struct {
uint8_t ip;
uint8_t ie;
uint8_t attr;
uint8_t ctl;
};
uint32_t raw;
};
std::vector<clic_int_reg_t> clic_int_reg;
uint8_t clic_mprev_lvl{0}, clic_uprev_lvl{0};
uint8_t clic_mact_lvl{0}, clic_uact_lvl{0};
};
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_clic(uint64_t addr, unsigned length, uint8_t* const data) {
if(addr == cfg.clic_base) { // cliccfg
*data = clic_cfg_reg;
for(auto i = 1; i < length; ++i)
*(data + i) = 0;
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4;
read_reg_with_offset(clic_inttrig_reg[offset], addr & 0x3, data, length);
} else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
read_reg_with_offset(clic_int_reg[offset].raw, addr & 0x3, data, length);
} else {
for(auto i = 0U; i < length; ++i)
*(data + i) = 0;
}
return iss::Ok;
}
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_clic(uint64_t addr, unsigned length, const uint8_t* const data) {
if(addr == cfg.clic_base) { // cliccfg
clic_cfg_reg = (clic_cfg_reg & ~0x1e) | (*data & 0x1e);
} else if(addr >= (cfg.clic_base + 0x40) && (addr + length) <= (cfg.clic_base + 0x40 + cfg.clic_num_trigger * 4)) { // clicinttrig
auto offset = ((addr & 0x7fff) - 0x40) / 4;
write_reg_with_offset(clic_inttrig_reg[offset], addr & 0x3, data, length);
} else if(addr >= (cfg.clic_base + 0x1000) &&
(addr + length) <= (cfg.clic_base + 0x1000 + cfg.clic_num_irq * 4)) { // clicintip/clicintie/clicintattr/clicintctl
auto offset = ((addr & 0x7fff) - 0x1000) / 4;
write_reg_with_offset(clic_int_reg[offset].raw, addr & 0x3, data, length);
clic_int_reg[offset].raw &= 0xf0c70101; // clicIntCtlBits->0xf0, clicintattr->0xc7, clicintie->0x1, clicintip->0x1
}
return iss::Ok;
}
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_cause(unsigned addr, reg_t& val) {
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
val = hart_if.csr[addr] & (1UL << (sizeof(reg_t) * 8) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
auto mode = (addr >> 8) & 0x3;
switch(mode) {
case 0:
val |= clic_uprev_lvl << 16;
val |= hart_if.state.mstatus.UPIE << 27;
break;
default:
val |= clic_mprev_lvl << 16;
val |= hart_if.state.mstatus.MPIE << 27;
val |= hart_if.state.mstatus.MPP << 28;
break;
}
} else
val = hart_if.csr[addr] & ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
return iss::Ok;
}
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_cause(unsigned addr, reg_t val) {
if((hart_if.csr[arch::mtvec] & 0x3) == 3) {
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1) | (0xfUL << 16));
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
auto mode = (addr >> 8) & 0x3;
switch(mode) {
case 0:
clic_uprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.state.mstatus.UPIE = (val >> 27) & 0x1;
break;
default:
clic_mprev_lvl = ((val >> 16) & 0xff) | (1 << (8 - cfg.clic_int_ctl_bits)) - 1;
hart_if.state.mstatus.MPIE = (val >> 27) & 0x1;
hart_if.state.mstatus.MPP = (val >> 28) & 0x3;
break;
}
} else {
auto mask = ((1UL << (sizeof(WORD_TYPE) * 8 - 1)) | (hart_if.mcause_max_irq - 1));
hart_if.csr[addr] = (val & mask) | (hart_if.csr[addr] & ~mask);
}
return iss::Ok;
}
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::read_intstatus(unsigned addr, reg_t& val) {
auto mode = (addr >> 8) & 0x3;
val = clic_uact_lvl & 0xff;
if(mode == 0x3)
val += (clic_mact_lvl & 0xff) << 24;
return iss::Ok;
}
template <typename WORD_TYPE> iss::status clic<WORD_TYPE>::write_intthresh(unsigned addr, reg_t val) {
hart_if.csr[addr] = (val & 0xff) | (1 << (cfg.clic_int_ctl_bits)) - 1;
return iss::Ok;
}
} // namespace mem
} // namespace iss

101
src/iss/mem/memory_if.cpp Normal file
View File

@ -0,0 +1,101 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#include "memory_if.h"
#include <algorithm>
namespace iss {
namespace mem {
void memory_hierarchy::root(memory_elem& e) {
hierarchy.push_front(&e);
root_set = true;
update_chain();
}
void memory_hierarchy::prepend(memory_elem& e) {
if(root_set)
hierarchy.insert(hierarchy.begin() + 1, &e);
else
hierarchy.push_front(&e);
update_chain();
}
void memory_hierarchy::append(memory_elem& e) {
hierarchy.push_back(&e);
update_chain();
}
void memory_hierarchy::insert_before(memory_elem&) {}
void memory_hierarchy::insert_after(memory_elem&) {}
void memory_hierarchy::replace_last(memory_elem& e) {
auto old = hierarchy.back();
auto it = std::find_if(std::begin(owned_elems), std::end(owned_elems),
[old](std::unique_ptr<memory_elem> const& p) { return p.get() == old; });
hierarchy.pop_back();
if(it != std::end(owned_elems))
owned_elems.erase(it);
hierarchy.push_back(&e);
update_chain();
}
void memory_hierarchy::update_chain() {
bool tail = false;
for(size_t i = 1; i < hierarchy.size(); ++i) {
hierarchy[i - 1]->set_next(hierarchy[i]->get_mem_if());
}
}
void memory_hierarchy::prepend(std::unique_ptr<memory_elem>&& p) {
prepend(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::append(std::unique_ptr<memory_elem>&& p) {
append(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::insert_before(std::unique_ptr<memory_elem>&& p) {
insert_before(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::insert_after(std::unique_ptr<memory_elem>&& p) {
insert_after(*p);
owned_elems.push_back(std::move(p));
}
void memory_hierarchy::replace_last(std::unique_ptr<memory_elem>&& p) {
replace_last(*p);
owned_elems.push_back(std::move(p));
}
} // namespace mem
} // namespace iss

View File

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (C) 2017 - 2023, MINRES Technologies GmbH
* Copyright (C) 2025 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -29,73 +29,58 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* eyck@minres.com - initial API and implementation
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _ISS_PLUGIN_COV_H_
#define _ISS_PLUGIN_COV_H_
#include <iss/vm_plugin.h>
#include "iss/instrumentation_if.h"
#include <string>
#include <fstream>
#ifndef _MEMORY_MEMORY_IF_
#define _MEMORY_MEMORY_IF_
#include "iss/vm_types.h"
#include <deque>
#include <functional>
#include <limits>
#include <memory>
#include <util/delegate.h>
#include <vector>
namespace iss {
namespace plugin {
class lz4compress_steambuf;
class pctrace : public iss::vm_plugin {
struct instr_delay {
std::string instr_name;
size_t size;
size_t not_taken_delay;
size_t taken_delay;
};
BEGIN_BF_DECL(instr_desc, uint32_t)
BF_FIELD(taken, 24, 8)
BF_FIELD(not_taken, 16, 8)
BF_FIELD(is_branch, 8, 8)
BF_FIELD(size, 0, 8)
instr_desc(uint32_t size, uint32_t taken, uint32_t not_taken, bool branch): instr_desc() {
this->size=size;
this->taken=taken;
this->not_taken=not_taken;
this->is_branch=branch;
}
END_BF_DECL();
namespace mem {
public:
using rd_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t*);
using wr_mem_func_sig = iss::status(iss::access_type, uint64_t, unsigned, uint8_t const*);
pctrace(const pctrace &) = delete;
pctrace(const pctrace &&) = delete;
pctrace(std::string const &);
virtual ~pctrace();
pctrace &operator=(const pctrace &) = delete;
pctrace &operator=(const pctrace &&) = delete;
bool registration(const char *const version, vm_if &arch) override;
sync_type get_sync() override { return POST_SYNC; };
void callback(instr_info_t) override;
private:
iss::instrumentation_if *instr_if {nullptr};
std::ofstream output;
#ifdef WITH_LZ4
std::unique_ptr<lz4compress_steambuf> strbuf;
std::ostream ostr;
#endif
std::string filename;
std::vector<instr_desc> delays;
bool jumped{false}, first{true};
struct memory_if {
util::delegate<iss::status(access_type, uint64_t, unsigned, uint8_t*)> rd_mem;
util::delegate<iss::status(access_type, uint64_t, unsigned, uint8_t const*)> wr_mem;
};
}
}
#endif /* _ISS_PLUGIN_COV_H_ */
struct memory_elem {
virtual ~memory_elem() = default;
virtual memory_if get_mem_if() = 0;
virtual void set_next(memory_if) = 0;
virtual std::tuple<uint64_t, uint64_t> get_range() { return {0, std::numeric_limits<uint64_t>::max()}; }
};
struct memory_hierarchy {
void root(memory_elem&);
void prepend(memory_elem&);
void append(memory_elem&);
void insert_before(memory_elem&);
void insert_after(memory_elem&);
void replace_last(memory_elem&);
void prepend(std::unique_ptr<memory_elem>&&);
void append(std::unique_ptr<memory_elem>&&);
void insert_before(std::unique_ptr<memory_elem>&&);
void insert_after(std::unique_ptr<memory_elem>&&);
void replace_last(std::unique_ptr<memory_elem>&&);
protected:
void update_chain();
std::deque<memory_elem*> hierarchy;
std::vector<std::unique_ptr<memory_elem>> owned_elems;
bool root_set{false};
};
} // namespace mem
} // namespace iss
#endif

View File

@ -0,0 +1,90 @@
/*******************************************************************************
* Copyright (C) 2025 MINRES Technologies GmbH
* 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
*
* Contributors:
* eyck@minres.com - initial implementation
******************************************************************************/
#ifndef _MEMORY_WITH_HTIF_
#define _MEMORY_WITH_HTIF_
#include "memory_if.h"
#include "iss/arch/riscv_hart_common.h"
#include "iss/vm_types.h"
#include <util/logging.h>
#include <util/sparse_array.h>
namespace iss {
namespace mem {
template <typename WORD_TYPE> struct memory_with_htif : public memory_elem {
using this_class = memory_with_htif<WORD_TYPE>;
constexpr static unsigned WORD_LEN = sizeof(WORD_TYPE) * 8;
memory_with_htif(arch::priv_if<WORD_TYPE> hart_if)
: hart_if(hart_if) {}
~memory_with_htif() = default;
memory_if get_mem_if() override {
return memory_if{.rd_mem{util::delegate<rd_mem_func_sig>::from<this_class, &this_class::read_mem>(this)},
.wr_mem{util::delegate<wr_mem_func_sig>::from<this_class, &this_class::write_mem>(this)}};
}
void set_next(memory_if) override {
// intenrionally left empty, leaf element
}
private:
iss::status read_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t* data) {
for(auto offs = 0U; offs < length; ++offs) {
*(data + offs) = mem[(addr + offs) % mem.size()];
}
return iss::Ok;
}
iss::status write_mem(iss::access_type access, uint64_t addr, unsigned length, uint8_t const* data) {
mem_type::page_type& p = mem(addr / mem.page_size);
std::copy(data, data + length, p.data() + (addr & mem.page_addr_mask));
// this->tohost handling in case of riscv-test
// according to https://github.com/riscv-software-src/riscv-isa-sim/issues/364#issuecomment-607657754:
if(access && iss::access_type::FUNC && addr == hart_if.tohost) {
return hart_if.exec_htif(data);
}
return iss::Ok;
}
protected:
using mem_type = util::sparse_array<uint8_t, 1ULL << 32>;
mem_type mem;
arch::priv_if<WORD_TYPE> hart_if;
};
} // namespace mem
} // namespace iss
#endif // _MEMORY_WITH_HTIF_

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