├── .build-qemu.sh ├── .cargo └── config ├── .fast-setup.sh ├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile.in ├── README.md ├── aclocal.m4 ├── bbl ├── bbl.ac ├── bbl.c ├── bbl.h ├── bbl.lds ├── bbl.mk.in ├── logo.c ├── payload.S ├── raw_logo.S └── riscv_logo.txt ├── config.h.in ├── configure ├── configure.ac ├── dummy_payload ├── dummy_entry.S ├── dummy_payload.ac ├── dummy_payload.c ├── dummy_payload.lds └── dummy_payload.mk.in ├── hash └── sm_expected_hash.h ├── machine ├── atomic.h ├── bits.h ├── disabled_hart_mask.h ├── emulation.c ├── emulation.h ├── encoding.h ├── fdt.c ├── fdt.h ├── finisher.c ├── finisher.h ├── flush_icache.c ├── fp_asm.S ├── fp_emulation.c ├── fp_emulation.h ├── fp_ldst.c ├── htif.c ├── htif.h ├── machine.ac ├── machine.mk.in ├── mcall.h ├── mentry.S ├── minit.c ├── misaligned_ldst.c ├── mtrap.c ├── mtrap.h ├── muldiv_emulation.c ├── uart.c ├── uart.h ├── uart16550.c ├── uart16550.h ├── unprivileged_memory.h └── vm.h ├── pk ├── boot.h ├── console.c ├── elf.c ├── elf.h ├── entry.S ├── file.c ├── file.h ├── frontend.c ├── frontend.h ├── handlers.c ├── mmap.c ├── mmap.h ├── pk.ac ├── pk.c ├── pk.h ├── pk.lds ├── pk.mk.in ├── syscall.c └── syscall.h ├── riscv64gc-unknown-linux-gnuhf.json ├── riscv64gc-unknown-none-elfhf.json ├── scripts ├── config.guess ├── config.sub ├── install.sh ├── mk-install-dirs.sh ├── qemu-riscv64 └── vcs-version.sh ├── sm ├── attest.c ├── cpu.c ├── cpu.h ├── crypto.c ├── crypto.h ├── ed25519 │ ├── ed25519.h │ ├── fe.c │ ├── fe.h │ ├── fixedint.h │ ├── ge.c │ ├── ge.h │ ├── keypair.c │ ├── precomp_data.h │ ├── sc.c │ ├── sc.h │ └── sign.c ├── enclave.c ├── enclave.h ├── hkdf_sha3_512 │ ├── hkdf_sha3_512.c │ └── hkdf_sha3_512.h ├── hmac_sha3 │ ├── hmac_sha3.c │ └── hmac_sha3.h ├── mprv.S ├── mprv.h ├── page.h ├── platform.h ├── platform │ ├── default │ │ ├── default.c │ │ └── default.h │ └── fu540 │ │ ├── fu540.c │ │ ├── fu540.h │ │ ├── fu540_internal.c │ │ ├── waymasks.c │ │ └── waymasks.h ├── plugins │ ├── multimem.c │ ├── multimem.h │ ├── plugins.c │ └── plugins.h ├── pmp.c ├── pmp.h ├── safe_math_util.h ├── sha3 │ ├── sha3.c │ └── sha3.h ├── sm-sbi.c ├── sm-sbi.h ├── sm.ac ├── sm.c ├── sm.h ├── sm.mk.in ├── tests │ ├── CMakeLists.txt │ ├── cmocka │ │ ├── cmocka.h │ │ ├── cmocka_pbc.h │ │ ├── cmocka_private.h │ │ ├── libcmocka-static-32.a │ │ └── libcmocka-static.a │ ├── mock │ │ ├── machine.c │ │ ├── mprv.c │ │ └── secure_boot.c │ ├── test_enclave.c │ └── test_pmp.c ├── thread.c ├── thread.h └── trap.S ├── sm_rs ├── Cargo.toml ├── attest.rs ├── bindings.h ├── build.rs ├── cpu.h ├── cpu.rs ├── crypto.h ├── crypto.rs ├── ed25519 │ ├── ed25519.h │ ├── fe.c │ ├── fe.h │ ├── fixedint.h │ ├── ge.c │ ├── ge.h │ ├── keypair.c │ ├── precomp_data.h │ ├── sc.c │ ├── sc.h │ └── sign.c ├── enclave.h ├── enclave.rs ├── hkdf_sha3_512 │ ├── hkdf_sha3_512.c │ └── hkdf_sha3_512.h ├── hmac_sha3 │ ├── hmac_sha3.c │ └── hmac_sha3.h ├── lib.rs ├── mprv.S ├── mprv.rs ├── page.h ├── platform.h ├── platform │ ├── default │ │ ├── default.c │ │ └── default.h │ └── fu540 │ │ ├── fu540.c │ │ ├── fu540.h │ │ ├── fu540_internal.c │ │ ├── waymasks.c │ │ └── waymasks.h ├── plugins │ ├── multimem.c │ ├── multimem.h │ ├── plugins.c │ └── plugins.h ├── pmp.c ├── pmp.h ├── pmp.rs ├── safe_math_util.h ├── sha3 │ ├── sha3.c │ └── sha3.h ├── sm-sbi.c ├── sm-sbi.h ├── sm.h ├── sm.rs ├── sm_rs.ac ├── sm_rs.mk.in ├── tests │ ├── mock │ │ ├── Cargo.toml │ │ ├── lib.rs │ │ ├── machine.c │ │ └── secure_boot.c │ └── test_pmp.c ├── thread.c ├── thread.h └── trap.S ├── softfloat ├── 8086 │ ├── OLD-specialize.c │ ├── OLD-specialize.h │ ├── platform.h │ ├── s_commonNaNToF32UI.c │ ├── s_commonNaNToF64UI.c │ ├── s_f32UIToCommonNaN.c │ ├── s_f64UIToCommonNaN.c │ ├── s_isSigNaNF32UI.c │ ├── s_isSigNaNF64UI.c │ ├── s_propagateNaNF32UI.c │ ├── s_propagateNaNF64UI.c │ ├── softfloat_raiseFlags.c │ ├── softfloat_types.h │ └── specialize.h ├── f32_add.c ├── f32_classify.c ├── f32_div.c ├── f32_eq.c ├── f32_eq_signaling.c ├── f32_isSignalingNaN.c ├── f32_le.c ├── f32_le_quiet.c ├── f32_lt.c ├── f32_lt_quiet.c ├── f32_mul.c ├── f32_mulAdd.c ├── f32_rem.c ├── f32_roundToInt.c ├── f32_sqrt.c ├── f32_sub.c ├── f32_to_f64.c ├── f32_to_i32.c ├── f32_to_i32_r_minMag.c ├── f32_to_i64.c ├── f32_to_i64_r_minMag.c ├── f32_to_ui32.c ├── f32_to_ui32_r_minMag.c ├── f32_to_ui64.c ├── f32_to_ui64_r_minMag.c ├── f64_add.c ├── f64_classify.c ├── f64_div.c ├── f64_eq.c ├── f64_eq_signaling.c ├── f64_isSignalingNaN.c ├── f64_le.c ├── f64_le_quiet.c ├── f64_lt.c ├── f64_lt_quiet.c ├── f64_mul.c ├── f64_mulAdd.c ├── f64_rem.c ├── f64_roundToInt.c ├── f64_sqrt.c ├── f64_sub.c ├── f64_to_f32.c ├── f64_to_i32.c ├── f64_to_i32_r_minMag.c ├── f64_to_i64.c ├── f64_to_i64_r_minMag.c ├── f64_to_ui32.c ├── f64_to_ui32_r_minMag.c ├── f64_to_ui64.c ├── f64_to_ui64_r_minMag.c ├── i32_to_f32.c ├── i32_to_f64.c ├── i64_to_f32.c ├── i64_to_f64.c ├── internals.h ├── platform.h ├── primitives.h ├── s_add128.c ├── s_add192.c ├── s_addMagsF32.c ├── s_addMagsF64.c ├── s_commonNaNToF32UI.c ├── s_commonNaNToF64UI.c ├── s_countLeadingZeros32.c ├── s_countLeadingZeros64.c ├── s_countLeadingZeros8.c ├── s_eq128.c ├── s_estimateDiv128To64.c ├── s_estimateSqrt32.c ├── s_f32UIToCommonNaN.c ├── s_f64UIToCommonNaN.c ├── s_isSigNaNF32UI.c ├── s_isSigNaNF64UI.c ├── s_le128.c ├── s_lt128.c ├── s_mul128By64To192.c ├── s_mul128To256.c ├── s_mul64To128.c ├── s_mulAddF32.c ├── s_mulAddF64.c ├── s_normRoundPackToF32.c ├── s_normRoundPackToF64.c ├── s_normSubnormalF32Sig.c ├── s_normSubnormalF64Sig.c ├── s_propagateNaNF32UI.c ├── s_propagateNaNF64UI.c ├── s_roundPackToF32.c ├── s_roundPackToF64.c ├── s_roundPackToI32.c ├── s_roundPackToI64.c ├── s_roundPackToUI32.c ├── s_roundPackToUI64.c ├── s_shift128ExtraRightJam.c ├── s_shift128RightJam.c ├── s_shift32RightJam.c ├── s_shift64ExtraRightJam.c ├── s_shift64RightJam.c ├── s_shortShift128ExtraRightJam.c ├── s_shortShift128Left.c ├── s_shortShift128Right.c ├── s_shortShift192Left.c ├── s_shortShift32Right1Jam.c ├── s_shortShift64ExtraRightJam.c ├── s_shortShift64RightJam.c ├── s_sub128.c ├── s_sub192.c ├── s_subMagsF32.c ├── s_subMagsF64.c ├── softfloat.ac ├── softfloat.h ├── softfloat.mk.in ├── softfloat_raiseFlags.c ├── softfloat_types.h ├── specialize.h ├── ui32_to_f32.c ├── ui32_to_f64.c ├── ui64_to_f32.c └── ui64_to_f64.c ├── test-sm.sh └── util ├── Cargo.toml ├── bitfield.rs ├── lib.rs ├── snprintf.c ├── string.c ├── util.ac └── util.mk.in /.build-qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is only for Travis test. Do not run in your local repository 4 | git clone --shallow-since=2018-05-01 https://github.com/qemu/qemu riscv-qemu 5 | cd riscv-qemu; git checkout v4.0.0; cd .. 6 | cd riscv-qemu; ./configure --target-list=riscv64-linux-user; make -j$(nproc); cd .. 7 | mkdir -p riscv/bin 8 | cp riscv-qemu/riscv64-linux-user/qemu-riscv64 ./riscv/bin 9 | -------------------------------------------------------------------------------- /.cargo/config: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "riscv64gc-unknown-none-elfhf.json" 3 | 4 | [target.riscv64gc-unknown-linux-gnuhf] 5 | runner = "./scripts/qemu-riscv64" 6 | -------------------------------------------------------------------------------- /.fast-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script is only for Travis test. Do not run in your local repository 4 | echo "Starting..." 5 | if ( $(command -v riscv64-unknown-linux-gnu-gcc > /dev/null) && 6 | $(command -v riscv64-unknown-elf-gcc > /dev/null) ) 7 | then 8 | echo "RISCV tools are already installed" 9 | else 10 | echo "Downloading Prebuilt RISC-V Toolchain... " 11 | 12 | # The 1.0 version expected libmpfr.so.4, modern Ubuntu has .6 13 | TOOL_VER=1.0 14 | if [[ $(ldconfig -p | grep "libmpfr.so.6") ]]; then 15 | echo "Downloading tools v2.0 (support for libmpfr.so.6)" 16 | TOOL_VER=2.0 17 | fi 18 | 19 | export RISCV=$(pwd)/riscv 20 | export PATH=$PATH:$RISCV/bin 21 | wget https://github.com/keystone-enclave/firesim-riscv-tools-prebuilt/archive/${TOOL_VER}.tar.gz 22 | tar -xzvf ${TOOL_VER}.tar.gz 23 | cd firesim-riscv-tools-prebuilt-${TOOL_VER} 24 | ./installrelease.sh > riscv-tools-install.log 25 | mv distrib riscv 26 | cp -R riscv ../ 27 | cd .. 28 | echo "Toolchain has been installed in $RISCV" 29 | fi 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #========================================================================= 2 | # Git Ignore Files 3 | #========================================================================= 4 | # We explicitly ignore a default build directory and the autoconf 5 | # generated autom4te.cache directory. This makes it easy to do a clean 6 | # build under the source directory and still have it appear clean to git. 7 | 8 | build/ 9 | autom4te.cache/ 10 | *.swp 11 | *~ 12 | target/ 13 | Cargo.lock 14 | test-build/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - nightly 4 | 5 | dist: xenial 6 | cache: 7 | apt: true 8 | cargo: true 9 | timeout: 1000 #In seconds 10 | directories: 11 | - $TRAVIS_BUILD_DIR/riscv 12 | 13 | git: 14 | submodules: false 15 | depth: 1 16 | 17 | env: 18 | - RISCV=$TRAVIS_BUILD_DIR/riscv PATH=$PATH:$RISCV/bin 19 | 20 | addons: 21 | apt: 22 | sources: 23 | - sourceline: 'deb http://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main' 24 | key_url: https://apt.llvm.org/llvm-snapshot.gpg.key 25 | packages: 26 | - autoconf 27 | - automake 28 | - autotools-dev 29 | - build-essential 30 | - gcc 31 | - git 32 | - llvm-9 33 | 34 | branches: 35 | only: 36 | - keystone 37 | - sm_rs 38 | 39 | before_install: 40 | - rustup target add riscv64gc-unknown-none-elf 41 | - rustup component add rust-src 42 | - cargo install cargo-xbuild || true 43 | - ./.fast-setup.sh 44 | 45 | jobs: 46 | include: 47 | - stage: build everything (C) 48 | script: 49 | - mkdir build 50 | - cd build 51 | - ../configure 52 | --enable-logo 53 | --host=riscv64-unknown-elf 54 | --enable-sm 55 | - make 56 | 57 | - stage: build everything (Rust) 58 | script: 59 | - ln -snf sm_rs sm 60 | - mkdir build 61 | - cd build 62 | - ../configure 63 | --enable-logo 64 | --host=riscv64-unknown-elf 65 | --enable-sm 66 | - make 67 | 68 | - stage: test (Rust) 69 | script: 70 | - ln -snf sm_rs sm 71 | - if [ -f riscv/bin/qemu-riscv64 ]; then ls riscv; else ./.build-qemu.sh; fi 72 | - ./test-sm.sh 73 | 74 | - stage: test (C) 75 | script: 76 | - if [ -f riscv/bin/qemu-riscv64 ]; then ls riscv; else ./.build-qemu.sh; fi 77 | - mkdir build 78 | - cd build 79 | - ../configure 80 | - cd ../sm/tests 81 | - mkdir build 82 | - cd build 83 | - cmake ..; make 84 | - make test CTEST_OUTPUT_ON_FAILURE=TRUE ARGS="--verbose" 85 | - cd $TRAVIS_BUILD_DIR 86 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, The Regents of the University of California (Regents). 2 | All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the Regents nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 16 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 17 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 18 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 23 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 24 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RISC-V Proxy Kernel and Boot Loader + Keystone SM 2 | ================================================= 3 | 4 | About 5 | --------- 6 | 7 | The RISC-V Proxy Kernel, `pk`, is a lightweight application execution 8 | environment that can host statically-linked RISC-V ELF binaries. It is 9 | designed to support tethered RISC-V implementations with limited I/O 10 | capability and and thus handles I/O-related system calls by proxying them to 11 | a host computer. 12 | 13 | This package also contains the Berkeley Boot Loader, `bbl`, which is a 14 | supervisor execution environment for tethered RISC-V systems. It is 15 | designed to host the RISC-V Linux port. 16 | 17 | This also contains the Keystone Security Monitor (SM) in `sm`. 18 | 19 | Build Steps 20 | --------------- 21 | 22 | We suggest building the bbl image using the top-level build in 23 | [keystone](https://github.com/keystone-enclave/keystone). 24 | 25 | If you wish to build the bbl independently, either: 26 | follow the build instructions 27 | [here](http://docs.keystone-enclave.org/en/dev/Getting-Started/Running-Keystone-with-QEMU.html#build-berkeley-bootloader-bbl-with-keystone-security-monitor) 28 | or follow the flow in the Makefile in 29 | [keystone](https://github.com/keystone-enclave/keystone). 30 | 31 | The top-level Makefile will always be the most up-to-date build 32 | instructions. 33 | 34 | Test 35 | -------------- 36 | 37 | Make sure that `qemu-riscv64` is in your PATH. 38 | `qemu-riscv64` can be compiled from the upstream [qemu source](https://github.com/qemu/qemu) v4.0.0 (try `./configure --target-list=riscv64-linux-user`). 39 | 40 | Current test only covers the security monitor, and exists as a separate build system. 41 | 42 | ``` 43 | cd sm/tests 44 | mkdir build; cd build 45 | cmake .. 46 | make 47 | ``` 48 | 49 | ... and run tests! 50 | 51 | ``` 52 | make test 53 | ``` 54 | 55 | To see the why your test fails the test, you should try 56 | 57 | ``` 58 | make test CTEST_OUTPUT_ON_FAILURE=TRUE 59 | ``` 60 | -------------------------------------------------------------------------------- /bbl/bbl.ac: -------------------------------------------------------------------------------- 1 | AC_ARG_ENABLE([logo], AS_HELP_STRING([--enable-logo], [Enable boot logo])) 2 | AS_IF([test "x$enable_logo" == "xyes"], [ 3 | AC_DEFINE([PK_ENABLE_LOGO],,[Define if the RISC-V logo is to be displayed]) 4 | ]) 5 | 6 | AC_ARG_WITH([payload], AS_HELP_STRING([--with-payload], [Set ELF payload for bbl]), 7 | [AC_SUBST([BBL_PAYLOAD], $with_payload, [Kernel payload for bbl])], 8 | [AC_SUBST([BBL_PAYLOAD], [dummy_payload], [Kernel payload for bbl])]) 9 | 10 | AC_ARG_WITH([logo], AS_HELP_STRING([--with-logo], [Specify a better logo]), 11 | [AC_SUBST([BBL_LOGO_FILE], $with_logo, [Logo for bbl])], 12 | [AC_SUBST([BBL_LOGO_FILE], [riscv_logo.txt], [Logo for bbl])]) 13 | -------------------------------------------------------------------------------- /bbl/bbl.c: -------------------------------------------------------------------------------- 1 | #include "bbl.h" 2 | #include "mtrap.h" 3 | #include "atomic.h" 4 | #include "vm.h" 5 | #include "bits.h" 6 | #include "config.h" 7 | #include "fdt.h" 8 | #include 9 | 10 | static const void* entry_point; 11 | long disabled_hart_mask; 12 | 13 | static uintptr_t dtb_output() 14 | { 15 | extern char _payload_end; 16 | uintptr_t end = (uintptr_t) &_payload_end; 17 | return (end + MEGAPAGE_SIZE - 1) / MEGAPAGE_SIZE * MEGAPAGE_SIZE; 18 | } 19 | 20 | static void filter_dtb(uintptr_t source) 21 | { 22 | uintptr_t dest = dtb_output(); 23 | uint32_t size = fdt_size(source); 24 | memcpy((void*)dest, (void*)source, size); 25 | 26 | // Remove information from the chained FDT 27 | filter_harts(dest, &disabled_hart_mask); 28 | filter_plic(dest); 29 | filter_compat(dest, "riscv,clint0"); 30 | filter_compat(dest, "riscv,debug-013"); 31 | } 32 | 33 | void boot_other_hart(uintptr_t unused __attribute__((unused))) 34 | { 35 | const void* entry; 36 | do { 37 | entry = entry_point; 38 | mb(); 39 | } while (!entry); 40 | 41 | long hartid = read_csr(mhartid); 42 | if ((1 << hartid) & disabled_hart_mask) { 43 | while (1) { 44 | __asm__ volatile("wfi"); 45 | #ifdef __riscv_div 46 | __asm__ volatile("div x0, x0, x0"); 47 | #endif 48 | } 49 | } 50 | 51 | enter_supervisor_mode(entry, hartid, dtb_output()); 52 | } 53 | 54 | void boot_loader(uintptr_t dtb) 55 | { 56 | extern char _payload_start; 57 | filter_dtb(dtb); 58 | #ifdef PK_ENABLE_LOGO 59 | print_logo(); 60 | #endif 61 | #ifdef PK_PRINT_DEVICE_TREE 62 | fdt_print(dtb_output()); 63 | #endif 64 | mb(); 65 | entry_point = &_payload_start; 66 | boot_other_hart(0); 67 | } 68 | -------------------------------------------------------------------------------- /bbl/bbl.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _BBL_H 4 | #define _BBL_H 5 | 6 | #ifndef __ASSEMBLER__ 7 | 8 | #include 9 | #include 10 | 11 | void print_logo(); 12 | 13 | #endif // !__ASSEMBLER__ 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /bbl/bbl.mk.in: -------------------------------------------------------------------------------- 1 | bbl_subproject_deps = \ 2 | sm \ 3 | util \ 4 | machine \ 5 | dummy_payload \ 6 | 7 | bbl_hdrs = \ 8 | bbl.h \ 9 | 10 | bbl_c_srcs = \ 11 | logo.c \ 12 | 13 | bbl_asm_srcs = \ 14 | payload.S \ 15 | raw_logo.S \ 16 | 17 | payload.o: bbl_payload 18 | 19 | bbl_payload: $(BBL_PAYLOAD) 20 | if $(READELF) -h $< 2> /dev/null > /dev/null; then $(OBJCOPY) -O binary $< $@; else cp $< $@; fi 21 | 22 | raw_logo.o: bbl_logo_file 23 | 24 | bbl_logo_file: @BBL_LOGO_FILE@ 25 | cat $^ | sed 's/$$/\r/' > $@ 26 | 27 | bbl_test_srcs = 28 | 29 | bbl_install_prog_srcs = \ 30 | bbl.c \ 31 | -------------------------------------------------------------------------------- /bbl/logo.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mtrap.h" 3 | 4 | extern const char logo[]; 5 | 6 | void print_logo() 7 | { 8 | putstring(logo); 9 | } 10 | -------------------------------------------------------------------------------- /bbl/payload.S: -------------------------------------------------------------------------------- 1 | #include "encoding.h" 2 | 3 | .section ".payload","a",@progbits 4 | .align RISCV_PGSHIFT + RISCV_PGLEVEL_BITS 5 | 6 | .globl _payload_start, _payload_end 7 | _payload_start: 8 | .incbin BBL_PAYLOAD 9 | _payload_end: 10 | -------------------------------------------------------------------------------- /bbl/raw_logo.S: -------------------------------------------------------------------------------- 1 | #include "encoding.h" 2 | 3 | .section .rodata 4 | .globl logo 5 | logo: 6 | .incbin BBL_LOGO_FILE 7 | .byte 0 8 | -------------------------------------------------------------------------------- /bbl/riscv_logo.txt: -------------------------------------------------------------------------------- 1 | vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 2 | vvvvvvvvvvvvvvvvvvvvvvvvvvvv 3 | rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvvvv 4 | rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv 5 | rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv 6 | rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv 7 | rrrrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvvvv 8 | rrrrrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv 9 | rrrrrrrrrrrrr vvvvvvvvvvvvvvvvvvvvvv 10 | rr vvvvvvvvvvvvvvvvvvvvvv 11 | rr vvvvvvvvvvvvvvvvvvvvvvvv rr 12 | rrrr vvvvvvvvvvvvvvvvvvvvvvvvvv rrrr 13 | rrrrrr vvvvvvvvvvvvvvvvvvvvvv rrrrrr 14 | rrrrrrrr vvvvvvvvvvvvvvvvvv rrrrrrrr 15 | rrrrrrrrrr vvvvvvvvvvvvvv rrrrrrrrrr 16 | rrrrrrrrrrrr vvvvvvvvvv rrrrrrrrrrrr 17 | rrrrrrrrrrrrrr vvvvvv rrrrrrrrrrrrrr 18 | rrrrrrrrrrrrrrrr vv rrrrrrrrrrrrrrrr 19 | rrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrr 20 | rrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrr 21 | rrrrrrrrrrrrrrrrrrrrrr rrrrrrrrrrrrrrrrrrrrrr 22 | 23 | INSTRUCTION SETS WANT TO BE FREE 24 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 4 | #undef BBL_ENABLED 5 | 6 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 7 | #undef DUMMY_PAYLOAD_ENABLED 8 | 9 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 10 | #undef MACHINE_ENABLED 11 | 12 | /* Define to the address where bug reports for this package should be sent. */ 13 | #undef PACKAGE_BUGREPORT 14 | 15 | /* Define to the full name of this package. */ 16 | #undef PACKAGE_NAME 17 | 18 | /* Define to the full name and version of this package. */ 19 | #undef PACKAGE_STRING 20 | 21 | /* Define to the one symbol short name of this package. */ 22 | #undef PACKAGE_TARNAME 23 | 24 | /* Define to the home page for this package. */ 25 | #undef PACKAGE_URL 26 | 27 | /* Define to the version of this package. */ 28 | #undef PACKAGE_VERSION 29 | 30 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 31 | #undef PK_ENABLED 32 | 33 | /* Define if floating-point emulation is enabled */ 34 | #undef PK_ENABLE_FP_EMULATION 35 | 36 | /* Define if the RISC-V logo is to be displayed */ 37 | #undef PK_ENABLE_LOGO 38 | 39 | /* Define if virtual memory support is enabled */ 40 | #undef PK_ENABLE_VM 41 | 42 | /* Define if the DTS is to be displayed */ 43 | #undef PK_PRINT_DEVICE_TREE 44 | 45 | /* Enable multimem plugin */ 46 | #undef PLUGIN_ENABLE_MULTIMEM 47 | 48 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 49 | #undef SM_ENABLED 50 | 51 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 52 | #undef SOFTFLOAT_ENABLED 53 | 54 | /* Define to 1 if you have the ANSI C header files. */ 55 | #undef STDC_HEADERS 56 | 57 | /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ 58 | #undef UTIL_ENABLED 59 | -------------------------------------------------------------------------------- /dummy_payload/dummy_entry.S: -------------------------------------------------------------------------------- 1 | #include "mcall.h" 2 | 3 | .section ".text.init" 4 | .globl _start 5 | _start: 6 | la s0, str 7 | 1: 8 | lbu a0, (s0) 9 | beqz a0, 1f 10 | li a7, SBI_CONSOLE_PUTCHAR 11 | ecall 12 | add s0, s0, 1 13 | j 1b 14 | 15 | 1: 16 | li a7, SBI_SHUTDOWN 17 | ecall 18 | 19 | .data 20 | str: 21 | .asciz "This is bbl's dummy_payload. To boot a real kernel, reconfigure\n\ 22 | bbl with the flag --with-payload=PATH, then rebuild bbl.\n" 23 | -------------------------------------------------------------------------------- /dummy_payload/dummy_payload.ac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/dummy_payload/dummy_payload.ac -------------------------------------------------------------------------------- /dummy_payload/dummy_payload.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/dummy_payload/dummy_payload.c -------------------------------------------------------------------------------- /dummy_payload/dummy_payload.lds: -------------------------------------------------------------------------------- 1 | ENTRY(_start) 2 | 3 | SECTIONS { 4 | . = -0x80000000; 5 | 6 | .text.init : { *(.text.init) } 7 | } 8 | -------------------------------------------------------------------------------- /dummy_payload/dummy_payload.mk.in: -------------------------------------------------------------------------------- 1 | dummy_payload_subproject_deps = \ 2 | 3 | dummy_payload_hdrs = \ 4 | 5 | dummy_payload_c_srcs = \ 6 | 7 | dummy_payload_asm_srcs = \ 8 | dummy_entry.S \ 9 | 10 | dummy_payload_test_srcs = 11 | 12 | dummy_payload_install_prog_srcs = \ 13 | dummy_payload.c \ 14 | -------------------------------------------------------------------------------- /hash/sm_expected_hash.h: -------------------------------------------------------------------------------- 1 | unsigned char sm_expected_hash[] = { 2 | 0x99, 0x39, 0x61, 0xf9, 0x78, 0xd2, 0x03, 0xa1, 0x1a, 0xfa, 0x50, 0x2d, 3 | 0xa5, 0x18, 0x23, 0xf0, 0x00, 0x92, 0x12, 0xe8, 0x2c, 0xd5, 0xfe, 0x82, 4 | 0x21, 0x56, 0xf2, 0x75, 0x48, 0x02, 0x2b, 0x6e, 0xb4, 0x85, 0xe0, 0x8d, 5 | 0xcd, 0xd3, 0xbc, 0x69, 0x65, 0x96, 0xc6, 0x2b, 0xb8, 0x8f, 0xd7, 0xf2, 6 | 0xb0, 0x51, 0x8b, 0xe7, 0xa5, 0xbf, 0xbf, 0x66, 0x28, 0x02, 0x48, 0x27, 7 | 0xa9, 0x2a, 0x2e, 0x06 8 | }; 9 | unsigned int sm_expected_hash_len = 64; 10 | -------------------------------------------------------------------------------- /machine/bits.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_BITS_H 2 | #define _RISCV_BITS_H 3 | 4 | #define likely(x) __builtin_expect((x), 1) 5 | #define unlikely(x) __builtin_expect((x), 0) 6 | 7 | #define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) 8 | #define ROUNDDOWN(a, b) ((a)/(b)*(b)) 9 | 10 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 11 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 12 | #define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) 13 | 14 | #define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) 15 | #define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) 16 | 17 | #define STR(x) XSTR(x) 18 | #define XSTR(x) #x 19 | 20 | #if __riscv_xlen == 64 21 | # define SLL32 sllw 22 | # define STORE sd 23 | # define LOAD ld 24 | # define LWU lwu 25 | # define LOG_REGBYTES 3 26 | #else 27 | # define SLL32 sll 28 | # define STORE sw 29 | # define LOAD lw 30 | # define LWU lw 31 | # define LOG_REGBYTES 2 32 | #endif 33 | #define REGBYTES (1 << LOG_REGBYTES) 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /machine/disabled_hart_mask.h: -------------------------------------------------------------------------------- 1 | #ifndef DISABLED_HART_MASK_H 2 | #define DISABLED_HART_MASK_H 3 | extern long disabled_hart_mask; 4 | #endif 5 | -------------------------------------------------------------------------------- /machine/finisher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "finisher.h" 3 | #include "fdt.h" 4 | 5 | volatile uint32_t* finisher; 6 | 7 | void finisher_exit(uint16_t code) 8 | { 9 | if (!finisher) return; 10 | if (code == 0) { 11 | *finisher = FINISHER_PASS; 12 | } else { 13 | *finisher = code << 16 | FINISHER_FAIL; 14 | } 15 | } 16 | 17 | struct finisher_scan 18 | { 19 | int compat; 20 | uint64_t reg; 21 | }; 22 | 23 | static void finisher_open(const struct fdt_scan_node *node, void *extra) 24 | { 25 | struct finisher_scan *scan = (struct finisher_scan *)extra; 26 | memset(scan, 0, sizeof(*scan)); 27 | } 28 | 29 | static void finisher_prop(const struct fdt_scan_prop *prop, void *extra) 30 | { 31 | struct finisher_scan *scan = (struct finisher_scan *)extra; 32 | if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,test0")) { 33 | scan->compat = 1; 34 | } else if (!strcmp(prop->name, "reg")) { 35 | fdt_get_address(prop->node->parent, prop->value, &scan->reg); 36 | } 37 | } 38 | 39 | static void finisher_done(const struct fdt_scan_node *node, void *extra) 40 | { 41 | struct finisher_scan *scan = (struct finisher_scan *)extra; 42 | if (!scan->compat || !scan->reg || finisher) return; 43 | finisher = (uint32_t*)(uintptr_t)scan->reg; 44 | } 45 | 46 | void query_finisher(uintptr_t fdt) 47 | { 48 | struct fdt_cb cb; 49 | struct finisher_scan scan; 50 | 51 | memset(&cb, 0, sizeof(cb)); 52 | cb.open = finisher_open; 53 | cb.prop = finisher_prop; 54 | cb.done = finisher_done; 55 | cb.extra = &scan; 56 | 57 | fdt_scan(fdt, &cb); 58 | } 59 | -------------------------------------------------------------------------------- /machine/finisher.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_FINISHER_H 2 | #define _RISCV_FINISHER_H 3 | 4 | #include 5 | 6 | #define FINISHER_REG_FINISH 0 7 | #define FINISHER_FAIL 0x3333 8 | #define FINISHER_PASS 0x5555 9 | 10 | void finisher_exit(uint16_t code); 11 | void query_finisher(uintptr_t fdt); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /machine/flush_icache.c: -------------------------------------------------------------------------------- 1 | void __riscv_flush_icache(void) { 2 | __asm__ volatile ("fence.i"); 3 | } 4 | -------------------------------------------------------------------------------- /machine/fp_ldst.c: -------------------------------------------------------------------------------- 1 | #include "fp_emulation.h" 2 | #include "unprivileged_memory.h" 3 | 4 | #define punt_to_misaligned_handler(align, handler) \ 5 | if (addr % (align) != 0) \ 6 | return write_csr(mbadaddr, addr), (handler)(regs, mcause, mepc) 7 | 8 | DECLARE_EMULATION_FUNC(emulate_float_load) 9 | { 10 | uintptr_t addr = GET_RS1(insn, regs) + IMM_I(insn); 11 | 12 | // if FPU is disabled, punt back to the OS 13 | if (unlikely((mstatus & MSTATUS_FS) == 0)) 14 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 15 | 16 | switch (insn & MASK_FUNCT3) 17 | { 18 | case MATCH_FLW & MASK_FUNCT3: 19 | punt_to_misaligned_handler(4, misaligned_load_trap); 20 | SET_F32_RD(insn, regs, load_int32_t((void *)addr, mepc)); 21 | break; 22 | 23 | case MATCH_FLD & MASK_FUNCT3: 24 | punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_load_trap); 25 | SET_F64_RD(insn, regs, load_uint64_t((void *)addr, mepc)); 26 | break; 27 | 28 | default: 29 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 30 | } 31 | } 32 | 33 | DECLARE_EMULATION_FUNC(emulate_float_store) 34 | { 35 | uintptr_t addr = GET_RS1(insn, regs) + IMM_S(insn); 36 | 37 | // if FPU is disabled, punt back to the OS 38 | if (unlikely((mstatus & MSTATUS_FS) == 0)) 39 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 40 | 41 | switch (insn & MASK_FUNCT3) 42 | { 43 | case MATCH_FSW & MASK_FUNCT3: 44 | punt_to_misaligned_handler(4, misaligned_store_trap); 45 | store_uint32_t((void *)addr, GET_F32_RS2(insn, regs), mepc); 46 | break; 47 | 48 | case MATCH_FSD & MASK_FUNCT3: 49 | punt_to_misaligned_handler(sizeof(uintptr_t), misaligned_store_trap); 50 | store_uint64_t((void *)addr, GET_F64_RS2(insn, regs), mepc); 51 | break; 52 | 53 | default: 54 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /machine/htif.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_HTIF_H 2 | #define _RISCV_HTIF_H 3 | 4 | #include 5 | 6 | #if __riscv_xlen == 64 7 | # define TOHOST_CMD(dev, cmd, payload) \ 8 | (((uint64_t)(dev) << 56) | ((uint64_t)(cmd) << 48) | (uint64_t)(payload)) 9 | #else 10 | # define TOHOST_CMD(dev, cmd, payload) ({ \ 11 | if ((dev) || (cmd)) __builtin_trap(); \ 12 | (payload); }) 13 | #endif 14 | #define FROMHOST_DEV(fromhost_value) ((uint64_t)(fromhost_value) >> 56) 15 | #define FROMHOST_CMD(fromhost_value) ((uint64_t)(fromhost_value) << 8 >> 56) 16 | #define FROMHOST_DATA(fromhost_value) ((uint64_t)(fromhost_value) << 16 >> 16) 17 | 18 | extern uintptr_t htif; 19 | void query_htif(uintptr_t dtb); 20 | void htif_console_putchar(uint8_t); 21 | int htif_console_getchar(); 22 | void htif_poweroff() __attribute__((noreturn)); 23 | void htif_syscall(uintptr_t); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /machine/machine.ac: -------------------------------------------------------------------------------- 1 | AC_ARG_ENABLE([fp-emulation], AS_HELP_STRING([--disable-fp-emulation], [Disable floating-point emulation])) 2 | AS_IF([test "x$enable_fp_emulation" != "xno"], [ 3 | AC_DEFINE([PK_ENABLE_FP_EMULATION],,[Define if floating-point emulation is enabled]) 4 | ]) 5 | -------------------------------------------------------------------------------- /machine/machine.mk.in: -------------------------------------------------------------------------------- 1 | machine_subproject_deps = \ 2 | sm \ 3 | 4 | machine_hdrs = \ 5 | atomic.h \ 6 | bits.h \ 7 | fdt.h \ 8 | emulation.h \ 9 | encoding.h \ 10 | htif.h \ 11 | mcall.h \ 12 | mtrap.h \ 13 | uart.h \ 14 | uart16550.h \ 15 | finisher.h \ 16 | unprivileged_memory.h \ 17 | vm.h \ 18 | 19 | machine_c_srcs = \ 20 | fdt.c \ 21 | mtrap.c \ 22 | minit.c \ 23 | htif.c \ 24 | emulation.c \ 25 | muldiv_emulation.c \ 26 | fp_ldst.c \ 27 | uart.c \ 28 | uart16550.c \ 29 | finisher.c \ 30 | misaligned_ldst.c \ 31 | flush_icache.c \ 32 | 33 | machine_asm_srcs = \ 34 | mentry.S \ 35 | fp_asm.S \ 36 | -------------------------------------------------------------------------------- /machine/mcall.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_SBI_H 2 | #define _RISCV_SBI_H 3 | 4 | #define SBI_SET_TIMER 0 5 | #define SBI_CONSOLE_PUTCHAR 1 6 | #define SBI_CONSOLE_GETCHAR 2 7 | #define SBI_CLEAR_IPI 3 8 | #define SBI_SEND_IPI 4 9 | #define SBI_REMOTE_FENCE_I 5 10 | #define SBI_REMOTE_SFENCE_VMA 6 11 | #define SBI_REMOTE_SFENCE_VMA_ASID 7 12 | #define SBI_SHUTDOWN 8 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /machine/muldiv_emulation.c: -------------------------------------------------------------------------------- 1 | #include "emulation.h" 2 | 3 | #ifndef __riscv_muldiv 4 | 5 | #if __riscv_xlen == 64 6 | typedef __int128 double_int; 7 | #else 8 | typedef int64_t double_int; 9 | #endif 10 | 11 | // These routines rely on the compiler to turn these operations into libcalls 12 | // when not natively supported. So work on making those go fast. 13 | 14 | DECLARE_EMULATION_FUNC(emulate_mul_div) 15 | { 16 | uintptr_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs), val; 17 | 18 | if ((insn & MASK_MUL) == MATCH_MUL) 19 | val = rs1 * rs2; 20 | else if ((insn & MASK_DIV) == MATCH_DIV) 21 | val = (intptr_t)rs1 / (intptr_t)rs2; 22 | else if ((insn & MASK_DIVU) == MATCH_DIVU) 23 | val = rs1 / rs2; 24 | else if ((insn & MASK_REM) == MATCH_REM) 25 | val = (intptr_t)rs1 % (intptr_t)rs2; 26 | else if ((insn & MASK_REMU) == MATCH_REMU) 27 | val = rs1 % rs2; 28 | else if ((insn & MASK_MULH) == MATCH_MULH) 29 | val = ((double_int)(intptr_t)rs1 * (double_int)(intptr_t)rs2) >> (8 * sizeof(rs1)); 30 | else if ((insn & MASK_MULHU) == MATCH_MULHU) 31 | val = ((double_int)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); 32 | else if ((insn & MASK_MULHSU) == MATCH_MULHSU) 33 | val = ((double_int)(intptr_t)rs1 * (double_int)rs2) >> (8 * sizeof(rs1)); 34 | else 35 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 36 | 37 | SET_RD(insn, regs, val); 38 | } 39 | 40 | #if __riscv_xlen == 64 41 | 42 | DECLARE_EMULATION_FUNC(emulate_mul_div32) 43 | { 44 | uint32_t rs1 = GET_RS1(insn, regs), rs2 = GET_RS2(insn, regs); 45 | int32_t val; 46 | 47 | if ((insn & MASK_MULW) == MATCH_MULW) 48 | val = rs1 * rs2; 49 | else if ((insn & MASK_DIVW) == MATCH_DIVW) 50 | val = (int32_t)rs1 / (int32_t)rs2; 51 | else if ((insn & MASK_DIVUW) == MATCH_DIVUW) 52 | val = rs1 / rs2; 53 | else if ((insn & MASK_REMW) == MATCH_REMW) 54 | val = (int32_t)rs1 % (int32_t)rs2; 55 | else if ((insn & MASK_REMUW) == MATCH_REMUW) 56 | val = rs1 % rs2; 57 | else 58 | return truly_illegal_insn(regs, mcause, mepc, mstatus, insn); 59 | 60 | SET_RD(insn, regs, val); 61 | } 62 | 63 | #endif 64 | #endif 65 | -------------------------------------------------------------------------------- /machine/uart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "uart.h" 3 | #include "fdt.h" 4 | 5 | volatile uint32_t* uart; 6 | 7 | void uart_putchar(uint8_t ch) 8 | { 9 | #ifdef __riscv_atomic 10 | int32_t r; 11 | do { 12 | __asm__ __volatile__ ( 13 | "amoor.w %0, %2, %1\n" 14 | : "=r" (r), "+A" (uart[UART_REG_TXFIFO]) 15 | : "r" (ch)); 16 | } while (r < 0); 17 | #else 18 | volatile uint32_t *tx = uart + UART_REG_TXFIFO; 19 | while ((int32_t)(*tx) < 0); 20 | *tx = ch; 21 | #endif 22 | } 23 | 24 | int uart_getchar() 25 | { 26 | int32_t ch = uart[UART_REG_RXFIFO]; 27 | if (ch < 0) return -1; 28 | return ch; 29 | } 30 | 31 | struct uart_scan 32 | { 33 | int compat; 34 | uint64_t reg; 35 | }; 36 | 37 | static void uart_open(const struct fdt_scan_node *node, void *extra) 38 | { 39 | struct uart_scan *scan = (struct uart_scan *)extra; 40 | memset(scan, 0, sizeof(*scan)); 41 | } 42 | 43 | static void uart_prop(const struct fdt_scan_prop *prop, void *extra) 44 | { 45 | struct uart_scan *scan = (struct uart_scan *)extra; 46 | if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "sifive,uart0")) { 47 | scan->compat = 1; 48 | } else if (!strcmp(prop->name, "reg")) { 49 | fdt_get_address(prop->node->parent, prop->value, &scan->reg); 50 | } 51 | } 52 | 53 | static void uart_done(const struct fdt_scan_node *node, void *extra) 54 | { 55 | struct uart_scan *scan = (struct uart_scan *)extra; 56 | if (!scan->compat || !scan->reg || uart) return; 57 | 58 | // Enable Rx/Tx channels 59 | uart = (void*)(uintptr_t)scan->reg; 60 | uart[UART_REG_TXCTRL] = UART_TXEN; 61 | uart[UART_REG_RXCTRL] = UART_RXEN; 62 | } 63 | 64 | void query_uart(uintptr_t fdt) 65 | { 66 | struct fdt_cb cb; 67 | struct uart_scan scan; 68 | 69 | memset(&cb, 0, sizeof(cb)); 70 | cb.open = uart_open; 71 | cb.prop = uart_prop; 72 | cb.done = uart_done; 73 | cb.extra = &scan; 74 | 75 | fdt_scan(fdt, &cb); 76 | } 77 | -------------------------------------------------------------------------------- /machine/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_UART_H 2 | #define _RISCV_UART_H 3 | 4 | #include 5 | 6 | extern volatile uint32_t* uart; 7 | 8 | #define UART_REG_TXFIFO 0 9 | #define UART_REG_RXFIFO 1 10 | #define UART_REG_TXCTRL 2 11 | #define UART_REG_RXCTRL 3 12 | #define UART_REG_DIV 4 13 | 14 | #define UART_TXEN 0x1 15 | #define UART_RXEN 0x1 16 | 17 | void uart_putchar(uint8_t ch); 18 | int uart_getchar(); 19 | void query_uart(uintptr_t dtb); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /machine/uart16550.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "uart16550.h" 3 | #include "fdt.h" 4 | 5 | volatile uint8_t* uart16550; 6 | 7 | #define UART_REG_QUEUE 0 8 | #define UART_REG_LINESTAT 5 9 | #define UART_REG_STATUS_RX 0x01 10 | #define UART_REG_STATUS_TX 0x20 11 | 12 | void uart16550_putchar(uint8_t ch) 13 | { 14 | while ((uart16550[UART_REG_LINESTAT] & UART_REG_STATUS_TX) == 0); 15 | uart16550[UART_REG_QUEUE] = ch; 16 | } 17 | 18 | int uart16550_getchar() 19 | { 20 | if (uart16550[UART_REG_LINESTAT] & UART_REG_STATUS_RX) 21 | return uart16550[UART_REG_QUEUE]; 22 | return -1; 23 | } 24 | 25 | struct uart16550_scan 26 | { 27 | int compat; 28 | uint64_t reg; 29 | }; 30 | 31 | static void uart16550_open(const struct fdt_scan_node *node, void *extra) 32 | { 33 | struct uart16550_scan *scan = (struct uart16550_scan *)extra; 34 | memset(scan, 0, sizeof(*scan)); 35 | } 36 | 37 | static void uart16550_prop(const struct fdt_scan_prop *prop, void *extra) 38 | { 39 | struct uart16550_scan *scan = (struct uart16550_scan *)extra; 40 | if (!strcmp(prop->name, "compatible") && !strcmp((const char*)prop->value, "ns16550a")) { 41 | scan->compat = 1; 42 | } else if (!strcmp(prop->name, "reg")) { 43 | fdt_get_address(prop->node->parent, prop->value, &scan->reg); 44 | } 45 | } 46 | 47 | static void uart16550_done(const struct fdt_scan_node *node, void *extra) 48 | { 49 | struct uart16550_scan *scan = (struct uart16550_scan *)extra; 50 | if (!scan->compat || !scan->reg || uart16550) return; 51 | 52 | uart16550 = (void*)(uintptr_t)scan->reg; 53 | // http://wiki.osdev.org/Serial_Ports 54 | uart16550[1] = 0x00; // Disable all interrupts 55 | uart16550[3] = 0x80; // Enable DLAB (set baud rate divisor) 56 | uart16550[0] = 0x03; // Set divisor to 3 (lo byte) 38400 baud 57 | uart16550[1] = 0x00; // (hi byte) 58 | uart16550[3] = 0x03; // 8 bits, no parity, one stop bit 59 | uart16550[2] = 0xC7; // Enable FIFO, clear them, with 14-byte threshold 60 | } 61 | 62 | void query_uart16550(uintptr_t fdt) 63 | { 64 | struct fdt_cb cb; 65 | struct uart16550_scan scan; 66 | 67 | memset(&cb, 0, sizeof(cb)); 68 | cb.open = uart16550_open; 69 | cb.prop = uart16550_prop; 70 | cb.done = uart16550_done; 71 | cb.extra = &scan; 72 | 73 | fdt_scan(fdt, &cb); 74 | } 75 | -------------------------------------------------------------------------------- /machine/uart16550.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_16550_H 2 | #define _RISCV_16550_H 3 | 4 | #include 5 | 6 | extern volatile uint8_t* uart16550; 7 | 8 | void uart16550_putchar(uint8_t ch); 9 | int uart16550_getchar(); 10 | void query_uart16550(uintptr_t dtb); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /machine/vm.h: -------------------------------------------------------------------------------- 1 | #ifndef _VM_H 2 | #define _VM_H 3 | 4 | #include "encoding.h" 5 | #include 6 | 7 | #define MEGAPAGE_SIZE ((uintptr_t)(RISCV_PGSIZE << RISCV_PGLEVEL_BITS)) 8 | #if __riscv_xlen == 64 9 | # define SATP_MODE_CHOICE INSERT_FIELD(0, SATP64_MODE, SATP_MODE_SV39) 10 | # define VA_BITS 39 11 | # define GIGAPAGE_SIZE (MEGAPAGE_SIZE << RISCV_PGLEVEL_BITS) 12 | #else 13 | # define SATP_MODE_CHOICE INSERT_FIELD(0, SATP32_MODE, SATP_MODE_SV32) 14 | # define VA_BITS 32 15 | #endif 16 | 17 | typedef uintptr_t pte_t; 18 | extern pte_t* root_page_table; 19 | 20 | static inline void flush_tlb() 21 | { 22 | asm volatile ("sfence.vma"); 23 | } 24 | 25 | static inline pte_t pte_create(uintptr_t ppn, int type) 26 | { 27 | return (ppn << PTE_PPN_SHIFT) | PTE_V | type; 28 | } 29 | 30 | static inline pte_t ptd_create(uintptr_t ppn) 31 | { 32 | return pte_create(ppn, PTE_V); 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /pk/boot.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _BOOT_H 4 | #define _BOOT_H 5 | 6 | #ifndef __ASSEMBLER__ 7 | 8 | #include 9 | 10 | typedef struct { 11 | int phent; 12 | int phnum; 13 | int is_supervisor; 14 | size_t phdr; 15 | size_t phdr_size; 16 | size_t bias; 17 | size_t entry; 18 | size_t brk_min; 19 | size_t brk; 20 | size_t brk_max; 21 | size_t mmap_max; 22 | size_t stack_top; 23 | size_t time0; 24 | size_t cycle0; 25 | size_t instret0; 26 | } elf_info; 27 | 28 | extern elf_info current; 29 | 30 | void load_elf(const char* fn, elf_info* info); 31 | 32 | #endif // !__ASSEMBLER__ 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /pk/console.c: -------------------------------------------------------------------------------- 1 | #include "pk.h" 2 | #include "file.h" 3 | #include "frontend.h" 4 | #include 5 | #include 6 | 7 | static void vprintk(const char* s, va_list vl) 8 | { 9 | char out[256]; // XXX 10 | int res = vsnprintf(out, sizeof(out), s, vl); 11 | file_write(stderr, out, res < sizeof(out) ? res : sizeof(out)); 12 | } 13 | 14 | void printk(const char* s, ...) 15 | { 16 | va_list vl; 17 | va_start(vl, s); 18 | 19 | vprintk(s, vl); 20 | 21 | va_end(vl); 22 | } 23 | 24 | void dump_tf(trapframe_t* tf) 25 | { 26 | static const char* regnames[] = { 27 | "z ", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 28 | "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 29 | "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 30 | "s8", "s9", "sA", "sB", "t3", "t4", "t5", "t6" 31 | }; 32 | 33 | tf->gpr[0] = 0; 34 | 35 | for(int i = 0; i < 32; i+=4) 36 | { 37 | for(int j = 0; j < 4; j++) 38 | printk("%s %lx%c",regnames[i+j],tf->gpr[i+j],j < 3 ? ' ' : '\n'); 39 | } 40 | printk("pc %lx va %lx insn %x sr %lx\n", tf->epc, tf->badvaddr, 41 | (uint32_t)tf->insn, tf->status); 42 | } 43 | 44 | void do_panic(const char* s, ...) 45 | { 46 | va_list vl; 47 | va_start(vl, s); 48 | 49 | vprintk(s, vl); 50 | shutdown(-1); 51 | 52 | va_end(vl); 53 | } 54 | 55 | void kassert_fail(const char* s) 56 | { 57 | register uintptr_t ra asm ("ra"); 58 | do_panic("assertion failed @ %p: %s\n", ra, s); 59 | } 60 | -------------------------------------------------------------------------------- /pk/file.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _FILE_H 4 | #define _FILE_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct file 11 | { 12 | int kfd; // file descriptor on the host side of the HTIF 13 | uint32_t refcnt; 14 | } file_t; 15 | 16 | extern file_t files[]; 17 | #define stdin (files + 0) 18 | #define stdout (files + 1) 19 | #define stderr (files + 2) 20 | 21 | file_t* file_get(int fd); 22 | file_t* file_open(const char* fn, int flags, int mode); 23 | void file_decref(file_t*); 24 | void file_incref(file_t*); 25 | int file_dup(file_t*); 26 | 27 | file_t* file_openat(int dirfd, const char* fn, int flags, int mode); 28 | ssize_t file_pwrite(file_t* f, const void* buf, size_t n, off_t off); 29 | ssize_t file_pread(file_t* f, void* buf, size_t n, off_t off); 30 | ssize_t file_write(file_t* f, const void* buf, size_t n); 31 | ssize_t file_read(file_t* f, void* buf, size_t n); 32 | ssize_t file_lseek(file_t* f, size_t ptr, int dir); 33 | int file_truncate(file_t* f, off_t len); 34 | int file_stat(file_t* f, struct stat* s); 35 | int fd_close(int fd); 36 | 37 | void file_init(); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /pk/frontend.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #include "pk.h" 4 | #include "atomic.h" 5 | #include "frontend.h" 6 | #include "syscall.h" 7 | #include "htif.h" 8 | #include 9 | 10 | long frontend_syscall(long n, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6) 11 | { 12 | static volatile uint64_t magic_mem[8]; 13 | 14 | static spinlock_t lock = SPINLOCK_INIT; 15 | spinlock_lock(&lock); 16 | 17 | magic_mem[0] = n; 18 | magic_mem[1] = a0; 19 | magic_mem[2] = a1; 20 | magic_mem[3] = a2; 21 | magic_mem[4] = a3; 22 | magic_mem[5] = a4; 23 | magic_mem[6] = a5; 24 | magic_mem[7] = a6; 25 | 26 | htif_syscall((uintptr_t)magic_mem); 27 | 28 | long ret = magic_mem[0]; 29 | 30 | spinlock_unlock(&lock); 31 | return ret; 32 | } 33 | 34 | void shutdown(int code) 35 | { 36 | frontend_syscall(SYS_exit, code, 0, 0, 0, 0, 0, 0); 37 | while (1); 38 | } 39 | 40 | void copy_stat(struct stat* dest, struct frontend_stat* src) 41 | { 42 | dest->st_dev = src->dev; 43 | dest->st_ino = src->ino; 44 | dest->st_mode = src->mode; 45 | dest->st_nlink = src->nlink; 46 | dest->st_uid = src->uid; 47 | dest->st_gid = src->gid; 48 | dest->st_rdev = src->rdev; 49 | dest->st_size = src->size; 50 | dest->st_blksize = src->blksize; 51 | dest->st_blocks = src->blocks; 52 | dest->st_atime = src->atime; 53 | dest->st_mtime = src->mtime; 54 | dest->st_ctime = src->ctime; 55 | } 56 | -------------------------------------------------------------------------------- /pk/frontend.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _RISCV_FRONTEND_H 4 | #define _RISCV_FRONTEND_H 5 | 6 | #include 7 | #include 8 | 9 | void shutdown(int) __attribute__((noreturn)); 10 | long frontend_syscall(long n, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t a6); 11 | 12 | struct frontend_stat { 13 | uint64_t dev; 14 | uint64_t ino; 15 | uint32_t mode; 16 | uint32_t nlink; 17 | uint32_t uid; 18 | uint32_t gid; 19 | uint64_t rdev; 20 | uint64_t __pad1; 21 | uint64_t size; 22 | uint32_t blksize; 23 | uint32_t __pad2; 24 | uint64_t blocks; 25 | uint64_t atime; 26 | uint64_t __pad3; 27 | uint64_t mtime; 28 | uint64_t __pad4; 29 | uint64_t ctime; 30 | uint64_t __pad5; 31 | uint32_t __unused4; 32 | uint32_t __unused5; 33 | }; 34 | 35 | void copy_stat(struct stat* dest, struct frontend_stat* src); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /pk/mmap.h: -------------------------------------------------------------------------------- 1 | #ifndef _MMAP_H 2 | #define _MMAP_H 3 | 4 | #include "vm.h" 5 | #include "syscall.h" 6 | #include "encoding.h" 7 | #include "file.h" 8 | #include "mtrap.h" 9 | #include 10 | 11 | #define PROT_NONE 0 12 | #define PROT_READ 1 13 | #define PROT_WRITE 2 14 | #define PROT_EXEC 4 15 | 16 | #define MAP_PRIVATE 0x2 17 | #define MAP_FIXED 0x10 18 | #define MAP_ANONYMOUS 0x20 19 | #define MAP_POPULATE 0x8000 20 | #define MREMAP_FIXED 0x2 21 | 22 | extern int demand_paging; 23 | uintptr_t pk_vm_init(); 24 | int handle_page_fault(uintptr_t vaddr, int prot); 25 | void populate_mapping(const void* start, size_t size, int prot); 26 | void __map_kernel_range(uintptr_t va, uintptr_t pa, size_t len, int prot); 27 | int __valid_user_range(uintptr_t vaddr, size_t len); 28 | uintptr_t __do_mmap(uintptr_t addr, size_t length, int prot, int flags, file_t* file, off_t offset); 29 | uintptr_t do_mmap(uintptr_t addr, size_t length, int prot, int flags, int fd, off_t offset); 30 | int do_munmap(uintptr_t addr, size_t length); 31 | uintptr_t do_mremap(uintptr_t addr, size_t old_size, size_t new_size, int flags); 32 | uintptr_t do_mprotect(uintptr_t addr, size_t length, int prot); 33 | uintptr_t do_brk(uintptr_t addr); 34 | 35 | #define va2pa(va) ({ uintptr_t __va = (uintptr_t)(va); \ 36 | extern uintptr_t first_free_paddr; \ 37 | __va >= DRAM_BASE ? __va : __va + first_free_paddr; }) 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /pk/pk.ac: -------------------------------------------------------------------------------- 1 | AC_ARG_ENABLE([vm], AS_HELP_STRING([--disable-vm], [Disable virtual memory])) 2 | AS_IF([test "x$enable_vm" != "xno"], [ 3 | AC_DEFINE([PK_ENABLE_VM],,[Define if virtual memory support is enabled]) 4 | ]) 5 | -------------------------------------------------------------------------------- /pk/pk.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _PK_H 4 | #define _PK_H 5 | 6 | #ifndef __ASSEMBLER__ 7 | 8 | #include "encoding.h" 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct 14 | { 15 | long gpr[32]; 16 | long status; 17 | long epc; 18 | long badvaddr; 19 | long cause; 20 | long insn; 21 | } trapframe_t; 22 | 23 | #define panic(s,...) do { do_panic(s"\n", ##__VA_ARGS__); } while(0) 24 | #define kassert(cond) do { if(!(cond)) kassert_fail(""#cond); } while(0) 25 | void do_panic(const char* s, ...) __attribute__((noreturn)); 26 | void kassert_fail(const char* s) __attribute__((noreturn)); 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | void printk(const char* s, ...); 33 | void printm(const char* s, ...); 34 | int vsnprintf(char* out, size_t n, const char* s, va_list vl); 35 | int snprintf(char* out, size_t n, const char* s, ...); 36 | void start_user(trapframe_t* tf) __attribute__((noreturn)); 37 | void dump_tf(trapframe_t*); 38 | 39 | static inline int insn_len(long insn) 40 | { 41 | return (insn & 0x3) < 0x3 ? 2 : 4; 42 | } 43 | 44 | #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif // !__ASSEMBLER__ 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /pk/pk.mk.in: -------------------------------------------------------------------------------- 1 | pk_subproject_deps = \ 2 | sm \ 3 | util \ 4 | machine \ 5 | 6 | pk_hdrs = \ 7 | boot.h \ 8 | elf.h \ 9 | file.h \ 10 | frontend.h \ 11 | mmap.h \ 12 | pk.h \ 13 | syscall.h \ 14 | 15 | pk_c_srcs = \ 16 | file.c \ 17 | syscall.c \ 18 | handlers.c \ 19 | frontend.c \ 20 | elf.c \ 21 | console.c \ 22 | mmap.c \ 23 | 24 | pk_asm_srcs = \ 25 | entry.S \ 26 | 27 | pk_test_srcs = 28 | 29 | pk_install_prog_srcs = \ 30 | pk.c \ 31 | -------------------------------------------------------------------------------- /pk/syscall.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _PK_SYSCALL_H 4 | #define _PK_SYSCALL_H 5 | 6 | #define SYS_exit 93 7 | #define SYS_exit_group 94 8 | #define SYS_getpid 172 9 | #define SYS_kill 129 10 | #define SYS_read 63 11 | #define SYS_write 64 12 | #define SYS_openat 56 13 | #define SYS_close 57 14 | #define SYS_lseek 62 15 | #define SYS_brk 214 16 | #define SYS_linkat 37 17 | #define SYS_unlinkat 35 18 | #define SYS_mkdirat 34 19 | #define SYS_renameat 38 20 | #define SYS_chdir 49 21 | #define SYS_getcwd 17 22 | #define SYS_fstat 80 23 | #define SYS_fstatat 79 24 | #define SYS_faccessat 48 25 | #define SYS_pread 67 26 | #define SYS_pwrite 68 27 | #define SYS_uname 160 28 | #define SYS_getuid 174 29 | #define SYS_geteuid 175 30 | #define SYS_getgid 176 31 | #define SYS_getegid 177 32 | #define SYS_mmap 222 33 | #define SYS_munmap 215 34 | #define SYS_mremap 216 35 | #define SYS_mprotect 226 36 | #define SYS_prlimit64 261 37 | #define SYS_getmainvars 2011 38 | #define SYS_rt_sigaction 134 39 | #define SYS_writev 66 40 | #define SYS_gettimeofday 169 41 | #define SYS_times 153 42 | #define SYS_fcntl 25 43 | #define SYS_ftruncate 46 44 | #define SYS_getdents 61 45 | #define SYS_dup 23 46 | #define SYS_readlinkat 78 47 | #define SYS_rt_sigprocmask 135 48 | #define SYS_ioctl 29 49 | #define SYS_getrlimit 163 50 | #define SYS_setrlimit 164 51 | #define SYS_getrusage 165 52 | #define SYS_clock_gettime 113 53 | #define SYS_set_tid_address 96 54 | #define SYS_set_robust_list 99 55 | 56 | #define OLD_SYSCALL_THRESHOLD 1024 57 | #define SYS_open 1024 58 | #define SYS_link 1025 59 | #define SYS_unlink 1026 60 | #define SYS_mkdir 1030 61 | #define SYS_access 1033 62 | #define SYS_stat 1038 63 | #define SYS_lstat 1039 64 | #define SYS_time 1062 65 | 66 | #define IS_ERR_VALUE(x) ((unsigned long)(x) >= (unsigned long)-4096) 67 | #define ERR_PTR(x) ((void*)(long)(x)) 68 | #define PTR_ERR(x) ((long)(x)) 69 | 70 | #define AT_FDCWD -100 71 | 72 | long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, unsigned long n); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /riscv64gc-unknown-linux-gnuhf.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "cdecl", 4 | "stdcall", 5 | "fastcall", 6 | "vectorcall", 7 | "thiscall", 8 | "aapcs", 9 | "win64", 10 | "sysv64", 11 | "ptx-kernel", 12 | "msp430-interrupt", 13 | "x86-interrupt", 14 | "amdgpu-kernel" 15 | ], 16 | "arch": "riscv64", 17 | "code-model": "medium", 18 | "cpu": "generic-rv64", 19 | "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n64-S128", 20 | "eliminate-frame-pointer": false, 21 | "emit-debug-gdb-scripts": false, 22 | "env": "gnu", 23 | "executables": true, 24 | "features": "+m,+a,+f,+d,+c", 25 | "linker": "riscv64-unknown-linux-gnu-gcc", 26 | "linker-flavor": "gcc", 27 | "llvm-target": "riscv64", 28 | "max-atomic-width": 64, 29 | "os": "linux", 30 | "target-family": "unix", 31 | "panic-strategy": "abort", 32 | "target-c-int-width": "32", 33 | "target-endian": "little", 34 | "target-pointer-width": "64", 35 | "vendor": "unknown", 36 | "pre-link-args": { 37 | "gcc": [ 38 | "-mabi=lp64d", 39 | "-Wl,--as-needed" 40 | ] 41 | }, 42 | "has-rpath": true, 43 | "llvm-abiname": "lp64d", 44 | "dynamic-linking": true 45 | } 46 | -------------------------------------------------------------------------------- /riscv64gc-unknown-none-elfhf.json: -------------------------------------------------------------------------------- 1 | { 2 | "abi-blacklist": [ 3 | "cdecl", 4 | "stdcall", 5 | "fastcall", 6 | "vectorcall", 7 | "thiscall", 8 | "aapcs", 9 | "win64", 10 | "sysv64", 11 | "ptx-kernel", 12 | "msp430-interrupt", 13 | "x86-interrupt", 14 | "amdgpu-kernel" 15 | ], 16 | "arch": "riscv64", 17 | "code-model": "medium", 18 | "cpu": "generic-rv64", 19 | "data-layout": "e-m:e-p:64:64-i64:64-i128:128-n64-S128", 20 | "eliminate-frame-pointer": false, 21 | "emit-debug-gdb-scripts": false, 22 | "env": "", 23 | "executables": true, 24 | "features": "+m,+a,+f,+d,+c", 25 | "linker": "rust-lld", 26 | "linker-flavor": "ld.lld", 27 | "llvm-target": "riscv64", 28 | "max-atomic-width": 64, 29 | "os": "none", 30 | "panic-strategy": "abort", 31 | "relocation-model": "static", 32 | "target-c-int-width": "32", 33 | "target-endian": "little", 34 | "target-pointer-width": "64", 35 | "vendor": "unknown", 36 | "llvm-abiname": "lp64d" 37 | } 38 | -------------------------------------------------------------------------------- /scripts/mk-install-dirs.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Public domain 6 | 7 | # $Id: mkinstalldirs,v 1.1 2003/09/09 22:24:03 mhampton Exp $ 8 | 9 | errstatus=0 10 | 11 | for file 12 | do 13 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 14 | shift 15 | 16 | pathcomp= 17 | for d 18 | do 19 | pathcomp="$pathcomp$d" 20 | case "$pathcomp" in 21 | -* ) pathcomp=./$pathcomp ;; 22 | esac 23 | 24 | if test ! -d "$pathcomp"; then 25 | echo "mkdir $pathcomp" 1>&2 26 | 27 | mkdir "$pathcomp" || lasterr=$? 28 | 29 | if test ! -d "$pathcomp"; then 30 | errstatus=$lasterr 31 | fi 32 | fi 33 | 34 | pathcomp="$pathcomp/" 35 | done 36 | done 37 | 38 | exit $errstatus 39 | 40 | # mkinstalldirs ends here 41 | -------------------------------------------------------------------------------- /scripts/qemu-riscv64: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | qemu-riscv64 -L $(riscv64-unknown-linux-gnu-gcc -print-sysroot) $@ 4 | -------------------------------------------------------------------------------- /sm/cpu.c: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #include "cpu.h" 6 | 7 | static struct cpu_state cpus[MAX_HARTS]; 8 | 9 | int cpu_is_enclave_context() 10 | { 11 | return cpus[read_csr(mhartid)].is_enclave != 0; 12 | } 13 | 14 | int cpu_get_enclave_id() 15 | { 16 | return cpus[read_csr(mhartid)].eid; 17 | } 18 | 19 | void cpu_enter_enclave_context(enclave_id eid) 20 | { 21 | cpus[read_csr(mhartid)].is_enclave = 1; 22 | cpus[read_csr(mhartid)].eid = eid; 23 | } 24 | 25 | void cpu_exit_enclave_context() 26 | { 27 | cpus[read_csr(mhartid)].is_enclave = 0; 28 | } 29 | -------------------------------------------------------------------------------- /sm/cpu.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef __CPU_H__ 6 | #define __CPU_H__ 7 | 8 | #include "sm.h" 9 | #include "enclave.h" 10 | 11 | /* hart state for regulating SBI */ 12 | struct cpu_state 13 | { 14 | int is_enclave; 15 | enclave_id eid; 16 | }; 17 | 18 | /* external functions */ 19 | int cpu_is_enclave_context(); 20 | int cpu_get_enclave_id(); 21 | void cpu_enter_enclave_context(enclave_id eid); 22 | void cpu_exit_enclave_context(); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sm/crypto.c: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #include "crypto.h" 6 | #include "page.h" 7 | 8 | void hash_init(hash_ctx* hash_ctx) 9 | { 10 | sha3_init(hash_ctx, MDSIZE); 11 | } 12 | 13 | void hash_extend(hash_ctx* hash_ctx, const void* ptr, size_t len) 14 | { 15 | sha3_update(hash_ctx, ptr, len); 16 | } 17 | 18 | void hash_extend_page(hash_ctx* hash_ctx, const void* ptr) 19 | { 20 | sha3_update(hash_ctx, ptr, RISCV_PGSIZE); 21 | } 22 | 23 | void hash_finalize(void* md, hash_ctx* hash_ctx) 24 | { 25 | sha3_final(md, hash_ctx); 26 | } 27 | 28 | void sign(void* sign, const void* data, size_t len, const unsigned char* public_key, const unsigned char* private_key) 29 | { 30 | ed25519_sign(sign, data, len, public_key, private_key); 31 | } 32 | 33 | int kdf(const unsigned char* salt, size_t salt_len, 34 | const unsigned char* ikm, size_t ikm_len, 35 | const unsigned char* info, size_t info_len, 36 | unsigned char* okm, size_t okm_len) 37 | { 38 | return hkdf_sha3_512(salt, salt_len, ikm, ikm_len, info, info_len, okm, okm_len); 39 | } 40 | -------------------------------------------------------------------------------- /sm/crypto.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef __CRYPTO_H__ 6 | #define __CRYPTO_H__ 7 | 8 | #include 9 | #include "sha3/sha3.h" 10 | #include "ed25519/ed25519.h" 11 | #include "hkdf_sha3_512/hkdf_sha3_512.h" 12 | 13 | typedef sha3_ctx_t hash_ctx; 14 | #define MDSIZE 64 15 | 16 | #define SIGNATURE_SIZE 64 17 | #define PRIVATE_KEY_SIZE 64 // includes public key 18 | #define PUBLIC_KEY_SIZE 32 19 | 20 | typedef unsigned char byte; 21 | 22 | extern byte sm_hash[MDSIZE]; 23 | extern byte sm_signature[SIGNATURE_SIZE]; 24 | extern byte sm_public_key[PUBLIC_KEY_SIZE]; 25 | extern byte sm_private_key[PRIVATE_KEY_SIZE]; 26 | 27 | void hash_init(hash_ctx* hash_ctx); 28 | void hash_extend(hash_ctx* hash_ctx, const void* ptr, size_t len); 29 | void hash_extend_page(hash_ctx* hash_ctx, const void* ptr); 30 | void hash_finalize(void* md, hash_ctx* hash_ctx); 31 | 32 | void sign(void* sign, const void* data, size_t len, const byte* public_key, const byte* private_key); 33 | int kdf(const unsigned char* salt, size_t salt_len, 34 | const unsigned char* ikm, size_t ikm_len, 35 | const unsigned char* info, size_t info_len, 36 | unsigned char* okm, size_t okm_len); 37 | #endif /* crypto.h */ 38 | -------------------------------------------------------------------------------- /sm/ed25519/ed25519.h: -------------------------------------------------------------------------------- 1 | #ifndef ED25519_H 2 | #define ED25519_H 3 | 4 | #include 5 | 6 | #if defined(_WIN32) 7 | #if defined(ED25519_BUILD_DLL) 8 | #define ED25519_DECLSPEC __declspec(dllexport) 9 | #elif defined(ED25519_DLL) 10 | #define ED25519_DECLSPEC __declspec(dllimport) 11 | #else 12 | #define ED25519_DECLSPEC 13 | #endif 14 | #else 15 | #define ED25519_DECLSPEC 16 | #endif 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifndef ED25519_NO_SEED 24 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); 25 | #endif 26 | 27 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); 28 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); 29 | //int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); 30 | //void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); 31 | //void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /sm/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "fixedint.h" 5 | 6 | 7 | /* 8 | fe means field element. 9 | Here the field is \Z/(2^255-19). 10 | An element t, entries t[0]...t[9], represents the integer 11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 12 | Bounds on each t[i] vary depending on context. 13 | */ 14 | 15 | 16 | typedef int32_t fe[10]; 17 | 18 | 19 | void fe_0(fe h); 20 | void fe_1(fe h); 21 | 22 | void fe_frombytes(fe h, const unsigned char *s); 23 | void fe_tobytes(unsigned char *s, const fe h); 24 | 25 | void fe_copy(fe h, const fe f); 26 | int fe_isnegative(const fe f); 27 | int fe_isnonzero(const fe f); 28 | void fe_cmov(fe f, const fe g, unsigned int b); 29 | void fe_cswap(fe f, fe g, unsigned int b); 30 | 31 | void fe_neg(fe h, const fe f); 32 | void fe_add(fe h, const fe f, const fe g); 33 | void fe_invert(fe out, const fe z); 34 | void fe_sq(fe h, const fe f); 35 | void fe_sq2(fe h, const fe f); 36 | void fe_mul(fe h, const fe f, const fe g); 37 | void fe_mul121666(fe h, fe f); 38 | void fe_pow22523(fe out, const fe z); 39 | void fe_sub(fe h, const fe f, const fe g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /sm/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | #include "fe.h" 5 | 6 | 7 | /* 8 | ge means group element. 9 | 10 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 11 | satisfying -x^2 + y^2 = 1 + d x^2y^2 12 | where d = -121665/121666. 13 | 14 | Representations: 15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 18 | ge_precomp (Duif): (y+x,y-x,2dxy) 19 | */ 20 | 21 | typedef struct { 22 | fe X; 23 | fe Y; 24 | fe Z; 25 | } ge_p2; 26 | 27 | typedef struct { 28 | fe X; 29 | fe Y; 30 | fe Z; 31 | fe T; 32 | } ge_p3; 33 | 34 | typedef struct { 35 | fe X; 36 | fe Y; 37 | fe Z; 38 | fe T; 39 | } ge_p1p1; 40 | 41 | typedef struct { 42 | fe yplusx; 43 | fe yminusx; 44 | fe xy2d; 45 | } ge_precomp; 46 | 47 | typedef struct { 48 | fe YplusX; 49 | fe YminusX; 50 | fe Z; 51 | fe T2d; 52 | } ge_cached; 53 | 54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); 55 | void ge_tobytes(unsigned char *s, const ge_p2 *h); 56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); 57 | 58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); 61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); 64 | 65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 67 | void ge_p2_0(ge_p2 *h); 68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 69 | void ge_p3_0(ge_p3 *h); 70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /sm/ed25519/keypair.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha3/sha3.h" 3 | #include "ge.h" 4 | 5 | 6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { 7 | ge_p3 A; 8 | 9 | sha3(seed, 32, private_key, 64); 10 | private_key[0] &= 248; 11 | private_key[31] &= 63; 12 | private_key[31] |= 64; 13 | 14 | ge_scalarmult_base(&A, private_key); 15 | ge_p3_tobytes(public_key, &A); 16 | } 17 | -------------------------------------------------------------------------------- /sm/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | void sc_reduce(unsigned char *s); 10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /sm/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha3/sha3.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | 7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { 8 | sha3_ctx_t hash; 9 | unsigned char hram[64]; 10 | unsigned char r[64]; 11 | ge_p3 R; 12 | 13 | 14 | sha3_init(&hash, 64); 15 | sha3_update(&hash, private_key + 32, 32); 16 | sha3_update(&hash, message, message_len); 17 | sha3_final(r, &hash); 18 | 19 | sc_reduce(r); 20 | ge_scalarmult_base(&R, r); 21 | ge_p3_tobytes(signature, &R); 22 | 23 | sha3_init(&hash, 64); 24 | sha3_update(&hash, signature, 32); 25 | sha3_update(&hash, public_key, 32); 26 | sha3_update(&hash, message, message_len); 27 | sha3_final(hram, &hash); 28 | 29 | sc_reduce(hram); 30 | sc_muladd(signature + 32, hram, private_key, r); 31 | } 32 | -------------------------------------------------------------------------------- /sm/hkdf_sha3_512/hkdf_sha3_512.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Fraunhofer AISEC 3 | * Authors: Benedikt Kopf 4 | * Lukas Auer 5 | * Mathias Morbitzer 6 | * 7 | * hkdf_sha3_512.h 8 | * 9 | * All Rights Reserved. See LICENSE for license details. 10 | */ 11 | 12 | #ifndef HDKF_SHA3_512_H 13 | #define HDKF_SHA3_512_H 14 | 15 | int hkdf_sha3_512(const unsigned char *salt, int salt_len, 16 | const unsigned char *in_key, int in_key_len, 17 | const unsigned char *info, int info_len, 18 | unsigned char *out_key, int out_key_length); 19 | void hkdf_extract(const unsigned char *salt, int salt_len, 20 | const unsigned char *in_key, int in_key_len, 21 | unsigned char *prk); 22 | int hkdf_expand(const unsigned char *prk, int prk_len, 23 | const unsigned char *info, int info_len, 24 | unsigned char *out_key, int out_key_len); 25 | 26 | #endif /* HDKF_SHA3_512_H */ 27 | -------------------------------------------------------------------------------- /sm/hmac_sha3/hmac_sha3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Fraunhofer AISEC 3 | * Authors: Benedikt Kopf 4 | * Lukas Auer 5 | * Mathias Morbitzer 6 | * 7 | * hmac_sha3.h 8 | * 9 | * All Rights Reserved. See LICENSE for license details. 10 | */ 11 | 12 | #ifndef HMAC_SHA3_H 13 | #define HMAC_SHA3_H 14 | 15 | #include "sha3/sha3.h" 16 | 17 | // Internal block length of sha3_512 in bytes 18 | #define SHA3_512_BLOCK_LEN 72 19 | // Output hash length of sha3_512 in bytes 20 | #define SHA3_512_HASH_LEN 64 21 | 22 | typedef struct { 23 | sha3_ctx_t sha3_ctx; 24 | unsigned char key[SHA3_512_BLOCK_LEN]; 25 | } hmac_sha3_ctx_t; 26 | 27 | void hmac_sha3(const unsigned char *key, int key_len, 28 | const unsigned char *text, int text_len, unsigned char *hash); 29 | void hmac_sha3_init(hmac_sha3_ctx_t *ctx, 30 | const unsigned char *key, int key_len); 31 | void hmac_sha3_update(hmac_sha3_ctx_t *ctx, 32 | const unsigned char *text, int text_len); 33 | void hmac_sha3_final(hmac_sha3_ctx_t *ctx, unsigned char *hash); 34 | 35 | #endif /* HMAC_SHA3_H */ 36 | -------------------------------------------------------------------------------- /sm/page.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef _SM_PAGE_H_ 6 | #define _SM_PAGE_H_ 7 | 8 | #include "bits.h" 9 | #include "encoding.h" 10 | #include "vm.h" 11 | #include "mtrap.h" 12 | 13 | #if __riscv_xlen == 64 14 | # define RISCV_PGLEVEL_MASK 0x1ff 15 | # define RISCV_PGTABLE_HIGHEST_BIT 0x100 16 | #else 17 | # define RISCV_PGLEVEL_MASK 0x3ff 18 | # define RISCV_PGTABLE_HIGHEST_BIT 0x300 19 | #endif 20 | 21 | #define RISCV_PGLEVEL_TOP ((VA_BITS - RISCV_PGSHIFT)/RISCV_PGLEVEL_BITS) 22 | #endif 23 | -------------------------------------------------------------------------------- /sm/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_H_ 2 | #define _PLATFORM_H_ 3 | 4 | /* These functions are defined by platform/soc specific objects, 5 | defined in platform/$PLATFORM/$PLATFORM.c */ 6 | 7 | /* This fires once FOR EACH sm supported enclave during init of 8 | enclave metadata. It may not fail currently. */ 9 | void platform_init_enclave(struct enclave* enclave); 10 | 11 | /* This fires once GLOBALLY before any other platform init */ 12 | enclave_ret_code platform_init_global_once(); 13 | /* Fires once per-hart after global_once */ 14 | enclave_ret_code platform_init_global(); 15 | 16 | /* This fires once each time an enclave is created by the sm */ 17 | enclave_ret_code platform_create_enclave(struct enclave* enclave); 18 | 19 | /* This fires once each time an enclave is destroyed by the sm */ 20 | void platform_destroy_enclave(struct enclave* enclave); 21 | 22 | /* This fires when context switching INTO an enclave from the OS */ 23 | void platform_switch_to_enclave(struct enclave* enclave); 24 | 25 | /* This fires when context switching OUT of an enclave into the OS */ 26 | void platform_switch_from_enclave(struct enclave* enclave); 27 | 28 | /* Future version: This fires when context switching from enclave A to 29 | enclave B */ 30 | // void platform_switch_between_enclaves(platform_enclave_data* enclaveA, 31 | // platform_enclave_data* enclaveB); 32 | 33 | /* This is a required feature, it must return 64bits of random data on 34 | demand and never fail. If it would fail it may power off 35 | instead. */ 36 | uint64_t platform_random(); 37 | 38 | #endif /* _PLATFORM_H_ */ 39 | -------------------------------------------------------------------------------- /sm/platform/default/default.c: -------------------------------------------------------------------------------- 1 | /* Default platform does nothing special here */ 2 | #include "enclave.h" 3 | 4 | enclave_ret_code platform_init_global_once(){ 5 | return ENCLAVE_SUCCESS; 6 | } 7 | 8 | enclave_ret_code platform_init_global(){ 9 | return ENCLAVE_SUCCESS; 10 | } 11 | 12 | void platform_init_enclave(struct enclave* enclave){ 13 | return; 14 | } 15 | 16 | void platform_destroy_enclave(struct enclave* enclave){ 17 | return; 18 | } 19 | 20 | enclave_ret_code platform_create_enclave(struct enclave* enclave){ 21 | return ENCLAVE_SUCCESS; 22 | } 23 | 24 | void platform_switch_to_enclave(struct enclave* enclave){ 25 | return; 26 | } 27 | 28 | void platform_switch_from_enclave(struct enclave* enclave){ 29 | return; 30 | } 31 | 32 | uint64_t platform_random(){ 33 | #pragma message("Platform has no entropy source, this is unsafe. TEST ONLY") 34 | static uint64_t w = 0, s = 0xb5ad4eceda1ce2a9; 35 | 36 | unsigned long cycles; 37 | asm volatile ("rdcycle %0" : "=r" (cycles)); 38 | 39 | // from Middle Square Weyl Sequence algorithm 40 | uint64_t x = cycles; 41 | x *= x; 42 | x += (w += s); 43 | return (x>>32) | (x<<32); 44 | } 45 | -------------------------------------------------------------------------------- /sm/platform/default/default.h: -------------------------------------------------------------------------------- 1 | 2 | // No special data needed for default platform 3 | struct platform_enclave_data{ 4 | 5 | }; 6 | -------------------------------------------------------------------------------- /sm/platform/fu540/fu540.c: -------------------------------------------------------------------------------- 1 | #include "fu540_internal.c" 2 | #include "waymasks.c" 3 | 4 | uint64_t platform_random(){ 5 | #pragma message("Platform has no entropy source, this is unsafe. TEST ONLY") 6 | unsigned long cycles; 7 | asm volatile ("rdcycle %0" : "=r" (cycles)); 8 | return cycles; 9 | } 10 | -------------------------------------------------------------------------------- /sm/platform/fu540/fu540.h: -------------------------------------------------------------------------------- 1 | #ifndef _FU540_H_ 2 | #define _FU540_H_ 3 | 4 | #include "waymasks.h" 5 | 6 | struct platform_enclave_data { 7 | /* 0 means don't do cache partitioning. Otherwise the number of ways 8 | required. */ 9 | size_t num_ways; 10 | /* Used if there is a waymask needed (>0 num_ways)*/ 11 | waymask_t saved_mask; 12 | 13 | /* 0 for doesn't use scratchpad, 1 for does */ 14 | int use_scratch; 15 | }; 16 | 17 | #endif /* _FU540_H_ */ 18 | -------------------------------------------------------------------------------- /sm/plugins/multimem.c: -------------------------------------------------------------------------------- 1 | #include "plugins/multimem.h" 2 | #include "sm.h" 3 | 4 | uintptr_t multimem_get_other_region_size(enclave_id eid) 5 | { 6 | int mem_id = get_enclave_region_index(eid, REGION_OTHER); 7 | return get_enclave_region_size(eid, mem_id); 8 | } 9 | 10 | uintptr_t multimem_get_other_region_addr(enclave_id eid) 11 | { 12 | int mem_id = get_enclave_region_index(eid, REGION_OTHER); 13 | return get_enclave_region_base(eid, mem_id); 14 | } 15 | 16 | uintptr_t do_sbi_multimem(enclave_id eid, uintptr_t call_id) 17 | { 18 | switch(call_id) 19 | { 20 | case MULTIMEM_GET_OTHER_REGION_SIZE: 21 | return multimem_get_other_region_size(eid); 22 | case MULTIMEM_GET_OTHER_REGION_ADDR: 23 | return multimem_get_other_region_addr(eid); 24 | default: 25 | return 0; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /sm/plugins/multimem.h: -------------------------------------------------------------------------------- 1 | #ifndef __SM_MULTIMEM_H__ 2 | #define __SM_MULTIMEM_H__ 3 | 4 | #include "plugins/plugins.h" 5 | #include "enclave.h" 6 | 7 | #define MULTIMEM_GET_OTHER_REGION_SIZE 0x1 8 | #define MULTIMEM_GET_OTHER_REGION_ADDR 0x2 9 | 10 | uintptr_t do_sbi_multimem(enclave_id id, uintptr_t call_id); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /sm/plugins/plugins.c: -------------------------------------------------------------------------------- 1 | #include "plugins/plugins.h" 2 | 3 | #ifdef PLUGIN_ENABLE_MULTIMEM 4 | #include "plugins/multimem.c" 5 | #endif 6 | 7 | uintptr_t 8 | call_plugin( 9 | enclave_id id, 10 | uintptr_t plugin_id, 11 | uintptr_t call_id, 12 | uintptr_t arg0, 13 | uintptr_t arg1) 14 | { 15 | switch(plugin_id) { 16 | #ifdef PLUGIN_ENABLE_MULTIMEM 17 | case PLUGIN_ID_MULTIMEM: 18 | return do_sbi_multimem(id, call_id); 19 | break; 20 | #endif 21 | default: 22 | // TOO fix it 23 | return -ENOSYS; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /sm/plugins/plugins.h: -------------------------------------------------------------------------------- 1 | #ifndef __SM_PLUGINS_H__ 2 | #define __SM_PLUGINS_H__ 3 | 4 | #include "config.h" 5 | #include "sm.h" 6 | #include "enclave.h" 7 | 8 | /* PLUGIN IDs */ 9 | #define PLUGIN_ID_MULTIMEM 0x1 10 | 11 | #ifdef PLUGIN_ENABLE_MULTIMEM 12 | #include "plugins/multimem.h" 13 | #endif 14 | 15 | uintptr_t 16 | call_plugin( 17 | enclave_id id, 18 | uintptr_t plugin_id, 19 | uintptr_t call_id, 20 | uintptr_t arg0, 21 | uintptr_t arg1 22 | ); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sm/safe_math_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _SAFE_MATH_UTIL_H_ 2 | #define _SAFE_MATH_UTIL_H_ 3 | 4 | // TODO: We may want to add checks for GCC/Clang version. We also want 5 | // to add wrappers for other checked math functions. 6 | 7 | #if __riscv_xlen == 32 8 | #define CHECKED_ADD(a, b, out) (__builtin_uadd_overflow(a, b, out)) 9 | #else 10 | #define CHECKED_ADD(a, b, out) (__builtin_uaddl_overflow(a, b, out)) 11 | #endif 12 | 13 | #endif /* _SAFE_MATH_UTIL_H_ */ 14 | -------------------------------------------------------------------------------- /sm/sha3/sha3.h: -------------------------------------------------------------------------------- 1 | // sha3.h 2 | // 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | #ifndef SHA3_H 5 | #define SHA3_H 6 | 7 | #include 8 | #include 9 | 10 | #ifndef KECCAKF_ROUNDS 11 | #define KECCAKF_ROUNDS 24 12 | #endif 13 | 14 | #ifndef ROTL64 15 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) 16 | #endif 17 | 18 | // state context 19 | typedef struct { 20 | union { // state: 21 | uint8_t b[200]; // 8-bit bytes 22 | uint64_t q[25]; // 64-bit words 23 | } st; 24 | int pt, rsiz, mdlen; // these don't overflow 25 | } sha3_ctx_t; 26 | 27 | // Compression function. 28 | void sha3_keccakf(uint64_t st[25]); 29 | 30 | // OpenSSL - like interfece 31 | int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes 32 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len); 33 | int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md 34 | 35 | // compute a sha3 hash (md) of given byte length from "in" 36 | void *sha3(const void *in, size_t inlen, void *md, int mdlen); 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /sm/sm-sbi.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef _KEYSTONE_SBI_H_ 6 | #define _KEYSTONE_SBI_H_ 7 | 8 | #include 9 | #include 10 | 11 | typedef uintptr_t enclave_ret_code; 12 | 13 | uintptr_t mcall_sm_create_enclave(uintptr_t create_args); 14 | 15 | uintptr_t mcall_sm_destroy_enclave(unsigned long eid); 16 | 17 | uintptr_t mcall_sm_run_enclave(uintptr_t* regs, unsigned long eid); 18 | uintptr_t mcall_sm_exit_enclave(uintptr_t* regs, unsigned long retval); 19 | uintptr_t mcall_sm_not_implemented(uintptr_t* regs, unsigned long a0); 20 | uintptr_t mcall_sm_stop_enclave(uintptr_t* regs, unsigned long request); 21 | uintptr_t mcall_sm_resume_enclave(uintptr_t* regs, unsigned long eid); 22 | uintptr_t mcall_sm_attest_enclave(uintptr_t report, uintptr_t data, uintptr_t size); 23 | uintptr_t mcall_sm_get_sealing_key(uintptr_t seal_key, uintptr_t key_ident, 24 | size_t key_ident_size); 25 | uintptr_t mcall_sm_random(); 26 | 27 | uintptr_t mcall_sm_call_plugin(uintptr_t plugin_id, uintptr_t call_id, uintptr_t arg0, uintptr_t arg1); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /sm/sm.ac: -------------------------------------------------------------------------------- 1 | AC_ARG_WITH([target_platform], AS_HELP_STRING([--with-target-platform], [Set a specific platform for the sm to build with]), 2 | [AC_SUBST([TARGET_PLATFORM], $with_target_platform, [Set a specific platform for the sm to build with])], 3 | [AC_SUBST([TARGET_PLATFORM], default, [Set a specific platform for the sm to build with])]) 4 | 5 | AC_ARG_ENABLE([sm_multimem], AS_HELP_STRING([--enable-sm-multimem], [Specify sm plugins to include]), 6 | AC_DEFINE([PLUGIN_ENABLE_MULTIMEM],[],[Enable multimem plugin]),[]) 7 | -------------------------------------------------------------------------------- /sm/sm.mk.in: -------------------------------------------------------------------------------- 1 | sm_hdrs = \ 2 | sm.h \ 3 | sm-sbi.h \ 4 | 5 | sm_c_srcs = \ 6 | sm.c \ 7 | sm-sbi.c \ 8 | cpu.c \ 9 | thread.c \ 10 | pmp.c \ 11 | enclave.c \ 12 | crypto.c \ 13 | attest.c \ 14 | sha3/sha3.c \ 15 | ed25519/keypair.c \ 16 | ed25519/sign.c \ 17 | ed25519/fe.c \ 18 | ed25519/ge.c \ 19 | ed25519/sc.c \ 20 | hkdf_sha3_512/hkdf_sha3_512.c \ 21 | hmac_sha3/hmac_sha3.c \ 22 | platform/@TARGET_PLATFORM@/@TARGET_PLATFORM@.c \ 23 | plugins/plugins.c \ 24 | 25 | sm_asm_srcs = \ 26 | trap.S \ 27 | mprv.S \ 28 | 29 | sm_test_srcs = 30 | 31 | sm_install_prog_srcs = 32 | -------------------------------------------------------------------------------- /sm/tests/cmocka/cmocka_pbc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 Luis Pabon, Jr. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * Programming by Contract is a programming methodology 19 | * which binds the caller and the function called to a 20 | * contract. The contract is represented using Hoare Triple: 21 | * {P} C {Q} 22 | * where {P} is the precondition before executing command C, 23 | * and {Q} is the postcondition. 24 | * 25 | * See also: 26 | * http://en.wikipedia.org/wiki/Design_by_contract 27 | * http://en.wikipedia.org/wiki/Hoare_logic 28 | * http://dlang.org/dbc.html 29 | */ 30 | #ifndef CMOCKA_PBC_H_ 31 | #define CMOCKA_PBC_H_ 32 | 33 | #if defined(UNIT_TESTING) || defined (DEBUG) 34 | 35 | #include 36 | 37 | /* 38 | * Checks caller responsibility against contract 39 | */ 40 | #define REQUIRE(cond) assert(cond) 41 | 42 | /* 43 | * Checks function reponsability against contract. 44 | */ 45 | #define ENSURE(cond) assert(cond) 46 | 47 | /* 48 | * While REQUIRE and ENSURE apply to functions, INVARIANT 49 | * applies to classes/structs. It ensures that intances 50 | * of the class/struct are consistent. In other words, 51 | * that the instance has not been corrupted. 52 | */ 53 | #define INVARIANT(invariant_fnc) do{ (invariant_fnc) } while (0); 54 | 55 | #else 56 | #define REQUIRE(cond) do { } while (0); 57 | #define ENSURE(cond) do { } while (0); 58 | #define INVARIANT(invariant_fnc) do{ } while (0); 59 | 60 | #endif /* defined(UNIT_TESTING) || defined (DEBUG) */ 61 | #endif /* CMOCKA_PBC_H_ */ 62 | 63 | -------------------------------------------------------------------------------- /sm/tests/cmocka/libcmocka-static-32.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/sm/tests/cmocka/libcmocka-static-32.a -------------------------------------------------------------------------------- /sm/tests/cmocka/libcmocka-static.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/sm/tests/cmocka/libcmocka-static.a -------------------------------------------------------------------------------- /sm/tests/mock/machine.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern void mock_assert(const int result, const char* const expression, 4 | const char * const file, const int line); 5 | 6 | void __wrap_printm(const char* s, ...) 7 | { 8 | return; 9 | } 10 | 11 | void __wrap_poweroff(uint16_t code) 12 | { 13 | mock_assert(0, "poweroff", __FILE__, __LINE__); 14 | } 15 | 16 | void __wrap_trap_vector_enclave(){ 17 | return; 18 | } 19 | 20 | void __wrap_trap_vector(){ 21 | return; 22 | } 23 | 24 | uint64_t __wrap_mtime; 25 | long __wrap_disabled_hart_mask; 26 | uint64_t __wrap_hart_mask; 27 | -------------------------------------------------------------------------------- /sm/tests/mock/mprv.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int __wrap_copy1_to_sm(uint8_t *dst, uint8_t *src) 4 | { 5 | *dst = *src; 6 | return 0; 7 | } 8 | 9 | int __wrap_copy_word_to_sm(uint64_t *dst, uint64_t *src) 10 | { 11 | *dst = *src; 12 | return 0; 13 | } 14 | 15 | int __wrap_copy_block_to_sm(uint64_t *dst, uint64_t *src) 16 | { 17 | for (int i = 0; i < 8; i++) 18 | *dst++ = *src++; 19 | return 0; 20 | } 21 | 22 | int __wrap_copy1_from_sm(uint8_t *dst, uint8_t *src) 23 | { 24 | *dst = *src; 25 | return 0; 26 | } 27 | 28 | int __wrap_copy_word_from_sm(uint64_t *dst, uint64_t *src) 29 | { 30 | *dst = *src; 31 | return 0; 32 | } 33 | 34 | int __wrap_copy_block_from_sm(uint64_t *dst, uint64_t *src) 35 | { 36 | for (int i = 0; i < 8; i++) 37 | *dst++ = *src++; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /sm/tests/mock/secure_boot.c: -------------------------------------------------------------------------------- 1 | #include "crypto.h" 2 | 3 | byte __wrap_sanctum_sm_hash[MDSIZE]; 4 | byte __wrap_sanctum_sm_signature[SIGNATURE_SIZE]; 5 | byte __wrap_sanctum_sm_public_key[PRIVATE_KEY_SIZE]; 6 | byte __wrap_sanctum_sm_secret_key[PUBLIC_KEY_SIZE]; 7 | byte __wrap_sanctum_dev_public_key[PUBLIC_KEY_SIZE]; 8 | -------------------------------------------------------------------------------- /sm_rs/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sm-rs" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [lib] 7 | crate-type = ["staticlib"] 8 | path = "lib.rs" 9 | 10 | [profile.dev] 11 | overflow-checks = false 12 | [profile.test] 13 | overflow-checks = false 14 | 15 | [dependencies] 16 | spin = "0.5" 17 | util = { path = "../util" } 18 | libc = { git = "https://github.com/rust-lang/libc" } 19 | 20 | [patch.crates-io] 21 | cc = { git = "https://github.com/alexcrichton/cc-rs" } 22 | 23 | [dependencies.riscv] 24 | git = "https://github.com/keystone-enclave/riscv" 25 | features = ["inline-asm"] 26 | 27 | [build-dependencies] 28 | bindgen = "0.50" 29 | 30 | 31 | [dev-dependencies] 32 | test = { git = "https://github.com/keystone-enclave/utest", branch = "fix-interface" } 33 | utest-macros = { git = "https://github.com/keystone-enclave/utest", branch = "fix-interface" } 34 | mock = { path = "./tests/mock" } 35 | -------------------------------------------------------------------------------- /sm_rs/bindings.h: -------------------------------------------------------------------------------- 1 | #include "sm.h" 2 | #include "mtrap.h" 3 | #include "pmp.h" 4 | #include "crypto.h" 5 | #include "enclave.h" 6 | #include "page.h" 7 | #include "platform.h" 8 | -------------------------------------------------------------------------------- /sm_rs/build.rs: -------------------------------------------------------------------------------- 1 | extern crate bindgen; 2 | 3 | use std::env; 4 | use std::ffi::OsStr; 5 | use std::os::unix::ffi::OsStrExt; 6 | use std::path::{Path, PathBuf}; 7 | use std::process::{Command, Stdio}; 8 | 9 | fn main() { 10 | //let cc = env::var("CC") 11 | // .expect("could not find compiler!"); 12 | let cc = "riscv64-unknown-elf-gcc"; 13 | 14 | let cc_child = Command::new(cc) 15 | .arg("-print-sysroot") 16 | .stdout(Stdio::piped()) 17 | .spawn() 18 | .expect("Failed to start cc process"); 19 | 20 | let output = cc_child.wait_with_output() 21 | .expect("Failed to wait on cc"); 22 | let sysroot_bytes = output.stdout.split(|b| *b == b'\n') 23 | .next() 24 | .expect("Found no output for $(CC) -print-sysroot!"); 25 | 26 | let sysroot = OsStr::from_bytes(sysroot_bytes); 27 | let sysroot_include = Path::new(sysroot) 28 | .join("include") 29 | .canonicalize() 30 | .expect("Failure to canonicalize sysroot include directory!"); 31 | 32 | let cflags = env::var("CFLAGS") 33 | .unwrap_or("".into()); 34 | let cflags_iter = cflags 35 | .split_whitespace(); 36 | 37 | let bindings = bindgen::Builder::default() 38 | .header("bindings.h") 39 | .clang_arg("--target=riscv64") 40 | .clang_arg("-I.") 41 | .clang_arg("-I../machine/") 42 | .clang_arg(format!("-I{}", sysroot_include.to_str().unwrap())) 43 | .clang_args(cflags_iter) 44 | .ctypes_prefix("::util") 45 | .use_core() 46 | .rustfmt_bindings(true) 47 | .generate() 48 | .expect("Unable to generate bindings"); 49 | 50 | let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); 51 | bindings 52 | .write_to_file(out_path.join("bindings.rs")) 53 | .expect("Couldn't write bindings!"); 54 | } 55 | -------------------------------------------------------------------------------- /sm_rs/cpu.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef __CPU_H__ 6 | #define __CPU_H__ 7 | 8 | #include "sm.h" 9 | #include "enclave.h" 10 | 11 | /* external functions */ 12 | int cpu_is_enclave_context(); 13 | int cpu_get_enclave_id(); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /sm_rs/cpu.rs: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | 6 | use riscv::register as csr; 7 | 8 | use crate::bindings::*; 9 | 10 | /* hart state for regulating SBI */ 11 | #[derive(Copy, Clone)] 12 | struct CpuState 13 | { 14 | is_enclave: i32, 15 | eid: enclave_id, 16 | } 17 | 18 | const MAX_HARTS: usize = 8; 19 | static mut CPUS: [CpuState; MAX_HARTS] 20 | = [CpuState { is_enclave: 0, eid: 0 }; MAX_HARTS]; 21 | 22 | #[no_mangle] 23 | pub extern fn cpu_is_enclave_context() -> i32 24 | { 25 | unsafe { 26 | return (CPUS[csr::mhartid::read()].is_enclave != 0) as i32; 27 | } 28 | } 29 | 30 | #[no_mangle] 31 | pub extern fn cpu_get_enclave_id() -> i32 32 | { 33 | unsafe { 34 | return CPUS[csr::mhartid::read()].eid as i32; 35 | } 36 | } 37 | 38 | pub fn cpu_enter_enclave_context(eid: enclave_id) 39 | { 40 | unsafe { 41 | CPUS[csr::mhartid::read()].is_enclave = 1; 42 | CPUS[csr::mhartid::read()].eid = eid; 43 | } 44 | } 45 | 46 | pub fn exit_enclave_context() 47 | { 48 | unsafe { 49 | CPUS[csr::mhartid::read()].is_enclave = 0; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sm_rs/crypto.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef __CRYPTO_H__ 6 | #define __CRYPTO_H__ 7 | 8 | #include 9 | #include "sha3/sha3.h" 10 | #include "ed25519/ed25519.h" 11 | #include "hkdf_sha3_512/hkdf_sha3_512.h" 12 | 13 | typedef sha3_ctx_t hash_ctx; 14 | #define MDSIZE 64 15 | 16 | #define SIGNATURE_SIZE 64 17 | #define PRIVATE_KEY_SIZE 64 // includes public key 18 | #define PUBLIC_KEY_SIZE 32 19 | 20 | typedef unsigned char byte; 21 | 22 | #endif /* crypto.h */ 23 | -------------------------------------------------------------------------------- /sm_rs/ed25519/ed25519.h: -------------------------------------------------------------------------------- 1 | #ifndef ED25519_H 2 | #define ED25519_H 3 | 4 | #include 5 | 6 | #if defined(_WIN32) 7 | #if defined(ED25519_BUILD_DLL) 8 | #define ED25519_DECLSPEC __declspec(dllexport) 9 | #elif defined(ED25519_DLL) 10 | #define ED25519_DECLSPEC __declspec(dllimport) 11 | #else 12 | #define ED25519_DECLSPEC 13 | #endif 14 | #else 15 | #define ED25519_DECLSPEC 16 | #endif 17 | 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifndef ED25519_NO_SEED 24 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); 25 | #endif 26 | 27 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); 28 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); 29 | //int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); 30 | //void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); 31 | //void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); 32 | 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /sm_rs/ed25519/fe.h: -------------------------------------------------------------------------------- 1 | #ifndef FE_H 2 | #define FE_H 3 | 4 | #include "fixedint.h" 5 | 6 | 7 | /* 8 | fe means field element. 9 | Here the field is \Z/(2^255-19). 10 | An element t, entries t[0]...t[9], represents the integer 11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. 12 | Bounds on each t[i] vary depending on context. 13 | */ 14 | 15 | 16 | typedef int32_t fe[10]; 17 | 18 | 19 | void fe_0(fe h); 20 | void fe_1(fe h); 21 | 22 | void fe_frombytes(fe h, const unsigned char *s); 23 | void fe_tobytes(unsigned char *s, const fe h); 24 | 25 | void fe_copy(fe h, const fe f); 26 | int fe_isnegative(const fe f); 27 | int fe_isnonzero(const fe f); 28 | void fe_cmov(fe f, const fe g, unsigned int b); 29 | void fe_cswap(fe f, fe g, unsigned int b); 30 | 31 | void fe_neg(fe h, const fe f); 32 | void fe_add(fe h, const fe f, const fe g); 33 | void fe_invert(fe out, const fe z); 34 | void fe_sq(fe h, const fe f); 35 | void fe_sq2(fe h, const fe f); 36 | void fe_mul(fe h, const fe f, const fe g); 37 | void fe_mul121666(fe h, fe f); 38 | void fe_pow22523(fe out, const fe z); 39 | void fe_sub(fe h, const fe f, const fe g); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /sm_rs/ed25519/ge.h: -------------------------------------------------------------------------------- 1 | #ifndef GE_H 2 | #define GE_H 3 | 4 | #include "fe.h" 5 | 6 | 7 | /* 8 | ge means group element. 9 | 10 | Here the group is the set of pairs (x,y) of field elements (see fe.h) 11 | satisfying -x^2 + y^2 = 1 + d x^2y^2 12 | where d = -121665/121666. 13 | 14 | Representations: 15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z 16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT 17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T 18 | ge_precomp (Duif): (y+x,y-x,2dxy) 19 | */ 20 | 21 | typedef struct { 22 | fe X; 23 | fe Y; 24 | fe Z; 25 | } ge_p2; 26 | 27 | typedef struct { 28 | fe X; 29 | fe Y; 30 | fe Z; 31 | fe T; 32 | } ge_p3; 33 | 34 | typedef struct { 35 | fe X; 36 | fe Y; 37 | fe Z; 38 | fe T; 39 | } ge_p1p1; 40 | 41 | typedef struct { 42 | fe yplusx; 43 | fe yminusx; 44 | fe xy2d; 45 | } ge_precomp; 46 | 47 | typedef struct { 48 | fe YplusX; 49 | fe YminusX; 50 | fe Z; 51 | fe T2d; 52 | } ge_cached; 53 | 54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h); 55 | void ge_tobytes(unsigned char *s, const ge_p2 *h); 56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s); 57 | 58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q); 60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b); 61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q); 63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a); 64 | 65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p); 66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p); 67 | void ge_p2_0(ge_p2 *h); 68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p); 69 | void ge_p3_0(ge_p3 *h); 70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p); 71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p); 72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /sm_rs/ed25519/keypair.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha3/sha3.h" 3 | #include "ge.h" 4 | 5 | 6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) { 7 | ge_p3 A; 8 | 9 | sha3(seed, 32, private_key, 64); 10 | private_key[0] &= 248; 11 | private_key[31] &= 63; 12 | private_key[31] |= 64; 13 | 14 | ge_scalarmult_base(&A, private_key); 15 | ge_p3_tobytes(public_key, &A); 16 | } 17 | -------------------------------------------------------------------------------- /sm_rs/ed25519/sc.h: -------------------------------------------------------------------------------- 1 | #ifndef SC_H 2 | #define SC_H 3 | 4 | /* 5 | The set of scalars is \Z/l 6 | where l = 2^252 + 27742317777372353535851937790883648493. 7 | */ 8 | 9 | void sc_reduce(unsigned char *s); 10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /sm_rs/ed25519/sign.c: -------------------------------------------------------------------------------- 1 | #include "ed25519.h" 2 | #include "sha3/sha3.h" 3 | #include "ge.h" 4 | #include "sc.h" 5 | 6 | 7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) { 8 | sha3_ctx_t hash; 9 | unsigned char hram[64]; 10 | unsigned char r[64]; 11 | ge_p3 R; 12 | 13 | 14 | sha3_init(&hash, 64); 15 | sha3_update(&hash, private_key + 32, 32); 16 | sha3_update(&hash, message, message_len); 17 | sha3_final(r, &hash); 18 | 19 | sc_reduce(r); 20 | ge_scalarmult_base(&R, r); 21 | ge_p3_tobytes(signature, &R); 22 | 23 | sha3_init(&hash, 64); 24 | sha3_update(&hash, signature, 32); 25 | sha3_update(&hash, public_key, 32); 26 | sha3_update(&hash, message, message_len); 27 | sha3_final(hram, &hash); 28 | 29 | sc_reduce(hram); 30 | sc_muladd(signature + 32, hram, private_key, r); 31 | } 32 | -------------------------------------------------------------------------------- /sm_rs/hkdf_sha3_512/hkdf_sha3_512.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Fraunhofer AISEC 3 | * Authors: Benedikt Kopf 4 | * Lukas Auer 5 | * Mathias Morbitzer 6 | * 7 | * hkdf_sha3_512.h 8 | * 9 | * All Rights Reserved. See LICENSE for license details. 10 | */ 11 | 12 | #ifndef HDKF_SHA3_512_H 13 | #define HDKF_SHA3_512_H 14 | 15 | int hkdf_sha3_512(const unsigned char *salt, int salt_len, 16 | const unsigned char *in_key, int in_key_len, 17 | const unsigned char *info, int info_len, 18 | unsigned char *out_key, int out_key_length); 19 | void hkdf_extract(const unsigned char *salt, int salt_len, 20 | const unsigned char *in_key, int in_key_len, 21 | unsigned char *prk); 22 | int hkdf_expand(const unsigned char *prk, int prk_len, 23 | const unsigned char *info, int info_len, 24 | unsigned char *out_key, int out_key_len); 25 | 26 | #endif /* HDKF_SHA3_512_H */ 27 | -------------------------------------------------------------------------------- /sm_rs/hmac_sha3/hmac_sha3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2020 Fraunhofer AISEC 3 | * Authors: Benedikt Kopf 4 | * Lukas Auer 5 | * Mathias Morbitzer 6 | * 7 | * hmac_sha3.h 8 | * 9 | * All Rights Reserved. See LICENSE for license details. 10 | */ 11 | 12 | #ifndef HMAC_SHA3_H 13 | #define HMAC_SHA3_H 14 | 15 | #include "sha3/sha3.h" 16 | 17 | // Internal block length of sha3_512 in bytes 18 | #define SHA3_512_BLOCK_LEN 72 19 | // Output hash length of sha3_512 in bytes 20 | #define SHA3_512_HASH_LEN 64 21 | 22 | typedef struct { 23 | sha3_ctx_t sha3_ctx; 24 | unsigned char key[SHA3_512_BLOCK_LEN]; 25 | } hmac_sha3_ctx_t; 26 | 27 | void hmac_sha3(const unsigned char *key, int key_len, 28 | const unsigned char *text, int text_len, unsigned char *hash); 29 | void hmac_sha3_init(hmac_sha3_ctx_t *ctx, 30 | const unsigned char *key, int key_len); 31 | void hmac_sha3_update(hmac_sha3_ctx_t *ctx, 32 | const unsigned char *text, int text_len); 33 | void hmac_sha3_final(hmac_sha3_ctx_t *ctx, unsigned char *hash); 34 | 35 | #endif /* HMAC_SHA3_H */ 36 | -------------------------------------------------------------------------------- /sm_rs/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![feature(concat_idents)] 3 | #[deny(warnings)] 4 | 5 | #[cfg(test)] 6 | extern crate mock; 7 | 8 | pub mod attest; 9 | pub mod cpu; 10 | pub mod sm; 11 | pub mod enclave; 12 | mod mprv; 13 | mod crypto; 14 | mod pmp; 15 | 16 | #[allow(warnings)] 17 | pub mod bindings { 18 | include!(concat!(env!("OUT_DIR"), "/bindings.rs")); 19 | } 20 | 21 | 22 | #[cfg(test)] 23 | extern crate utest_macros; 24 | 25 | #[cfg(test)] 26 | #[allow(unused_macros)] 27 | macro_rules! panic { 28 | ($($tt:tt)*) => { 29 | utest_macros::upanic!($($tt)*); 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /sm_rs/page.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef _SM_PAGE_H_ 6 | #define _SM_PAGE_H_ 7 | 8 | #include "bits.h" 9 | #include "encoding.h" 10 | #include "vm.h" 11 | #include "mtrap.h" 12 | 13 | #if __riscv_xlen == 64 14 | # define RISCV_PGLEVEL_MASK 0x1ff 15 | # define RISCV_PGTABLE_HIGHEST_BIT 0x100 16 | #else 17 | # define RISCV_PGLEVEL_MASK 0x3ff 18 | # define RISCV_PGTABLE_HIGHEST_BIT 0x300 19 | #endif 20 | 21 | #define RISCV_PGLEVEL_TOP ((VA_BITS - RISCV_PGSHIFT)/RISCV_PGLEVEL_BITS) 22 | #endif 23 | -------------------------------------------------------------------------------- /sm_rs/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef _PLATFORM_H_ 2 | #define _PLATFORM_H_ 3 | 4 | struct enclave; 5 | 6 | /* These functions are defined by platform/soc specific objects, 7 | defined in platform/$PLATFORM/$PLATFORM.c */ 8 | 9 | /* This fires once FOR EACH sm supported enclave during init of 10 | enclave metadata. It may not fail currently. */ 11 | void platform_init_enclave(struct enclave* enclave); 12 | 13 | /* This fires once GLOBALLY before any other platform init */ 14 | enclave_ret_code platform_init_global_once(); 15 | /* Fires once per-hart after global_once */ 16 | enclave_ret_code platform_init_global(); 17 | 18 | /* This fires once each time an enclave is created by the sm */ 19 | enclave_ret_code platform_create_enclave(struct enclave* enclave); 20 | 21 | /* This fires once each time an enclave is destroyed by the sm */ 22 | void platform_destroy_enclave(struct enclave* enclave); 23 | 24 | /* This fires when context switching INTO an enclave from the OS */ 25 | void platform_switch_to_enclave(struct enclave* enclave); 26 | 27 | /* This fires when context switching OUT of an enclave into the OS */ 28 | void platform_switch_from_enclave(struct enclave* enclave); 29 | 30 | /* Future version: This fires when context switching from enclave A to 31 | enclave B */ 32 | // void platform_switch_between_enclaves(platform_enclave_data* enclaveA, 33 | // platform_enclave_data* enclaveB); 34 | 35 | /* This is a required feature, it must return 64bits of random data on 36 | demand and never fail. If it would fail it may power off 37 | instead. */ 38 | uint64_t platform_random(); 39 | 40 | #endif /* _PLATFORM_H_ */ 41 | -------------------------------------------------------------------------------- /sm_rs/platform/default/default.c: -------------------------------------------------------------------------------- 1 | /* Default platform does nothing special here */ 2 | #include "enclave.h" 3 | 4 | enclave_ret_code platform_init_global_once(){ 5 | return ENCLAVE_SUCCESS; 6 | } 7 | 8 | enclave_ret_code platform_init_global(){ 9 | return ENCLAVE_SUCCESS; 10 | } 11 | 12 | void platform_init_enclave(struct enclave* enclave){ 13 | return; 14 | } 15 | 16 | void platform_destroy_enclave(struct enclave* enclave){ 17 | return; 18 | } 19 | 20 | enclave_ret_code platform_create_enclave(struct enclave* enclave){ 21 | return ENCLAVE_SUCCESS; 22 | } 23 | 24 | void platform_switch_to_enclave(struct enclave* enclave){ 25 | return; 26 | } 27 | 28 | void platform_switch_from_enclave(struct enclave* enclave){ 29 | return; 30 | } 31 | 32 | uint64_t platform_random(){ 33 | #pragma message("Platform has no entropy source, this is unsafe. TEST ONLY") 34 | static uint64_t w = 0, s = 0xb5ad4eceda1ce2a9; 35 | 36 | unsigned long cycles; 37 | asm volatile ("rdcycle %0" : "=r" (cycles)); 38 | 39 | // from Middle Square Weyl Sequence algorithm 40 | uint64_t x = cycles; 41 | x *= x; 42 | x += (w += s); 43 | return (x>>32) | (x<<32); 44 | } 45 | -------------------------------------------------------------------------------- /sm_rs/platform/default/default.h: -------------------------------------------------------------------------------- 1 | 2 | // No special data needed for default platform 3 | struct platform_enclave_data{ 4 | 5 | }; 6 | -------------------------------------------------------------------------------- /sm_rs/platform/fu540/fu540.c: -------------------------------------------------------------------------------- 1 | #include "fu540_internal.c" 2 | #include "waymasks.c" 3 | 4 | uint64_t platform_random(){ 5 | #pragma message("Platform has no entropy source, this is unsafe. TEST ONLY") 6 | unsigned long cycles; 7 | asm volatile ("rdcycle %0" : "=r" (cycles)); 8 | return cycles; 9 | } 10 | -------------------------------------------------------------------------------- /sm_rs/platform/fu540/fu540.h: -------------------------------------------------------------------------------- 1 | #ifndef _FU540_H_ 2 | #define _FU540_H_ 3 | 4 | #include "waymasks.h" 5 | 6 | struct platform_enclave_data { 7 | /* 0 means don't do cache partitioning. Otherwise the number of ways 8 | required. */ 9 | size_t num_ways; 10 | /* Used if there is a waymask needed (>0 num_ways)*/ 11 | waymask_t saved_mask; 12 | 13 | /* 0 for doesn't use scratchpad, 1 for does */ 14 | int use_scratch; 15 | }; 16 | 17 | #endif /* _FU540_H_ */ 18 | -------------------------------------------------------------------------------- /sm_rs/plugins/multimem.c: -------------------------------------------------------------------------------- 1 | #include "plugins/multimem.h" 2 | #include "sm.h" 3 | 4 | uintptr_t multimem_get_other_region_size(enclave_id eid) 5 | { 6 | int mem_id = get_enclave_region_index(eid, REGION_OTHER); 7 | return get_enclave_region_size(eid, mem_id); 8 | } 9 | 10 | uintptr_t multimem_get_other_region_addr(enclave_id eid) 11 | { 12 | int mem_id = get_enclave_region_index(eid, REGION_OTHER); 13 | return get_enclave_region_base(eid, mem_id); 14 | } 15 | 16 | uintptr_t do_sbi_multimem(enclave_id eid, uintptr_t call_id) 17 | { 18 | switch(call_id) 19 | { 20 | case MULTIMEM_GET_OTHER_REGION_SIZE: 21 | return multimem_get_other_region_size(eid); 22 | case MULTIMEM_GET_OTHER_REGION_ADDR: 23 | return multimem_get_other_region_addr(eid); 24 | default: 25 | return 0; 26 | } 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /sm_rs/plugins/multimem.h: -------------------------------------------------------------------------------- 1 | #ifndef __SM_MULTIMEM_H__ 2 | #define __SM_MULTIMEM_H__ 3 | 4 | #include "plugins/plugins.h" 5 | #include "enclave.h" 6 | 7 | #define MULTIMEM_GET_OTHER_REGION_SIZE 0x1 8 | #define MULTIMEM_GET_OTHER_REGION_ADDR 0x2 9 | 10 | uintptr_t do_sbi_multimem(enclave_id id, uintptr_t call_id); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /sm_rs/plugins/plugins.c: -------------------------------------------------------------------------------- 1 | #include "plugins/plugins.h" 2 | 3 | #ifdef PLUGIN_ENABLE_MULTIMEM 4 | #include "plugins/multimem.c" 5 | #endif 6 | 7 | uintptr_t 8 | call_plugin( 9 | enclave_id id, 10 | uintptr_t plugin_id, 11 | uintptr_t call_id, 12 | uintptr_t arg0, 13 | uintptr_t arg1) 14 | { 15 | switch(plugin_id) { 16 | #ifdef PLUGIN_ENABLE_MULTIMEM 17 | case PLUGIN_ID_MULTIMEM: 18 | return do_sbi_multimem(id, call_id); 19 | break; 20 | #endif 21 | default: 22 | // TOO fix it 23 | return -ENOSYS; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /sm_rs/plugins/plugins.h: -------------------------------------------------------------------------------- 1 | #ifndef __SM_PLUGINS_H__ 2 | #define __SM_PLUGINS_H__ 3 | 4 | #include "config.h" 5 | #include "sm.h" 6 | #include "enclave.h" 7 | 8 | /* PLUGIN IDs */ 9 | #define PLUGIN_ID_MULTIMEM 0x1 10 | 11 | #ifdef PLUGIN_ENABLE_MULTIMEM 12 | #include "plugins/multimem.h" 13 | #endif 14 | 15 | uintptr_t 16 | call_plugin( 17 | enclave_id id, 18 | uintptr_t plugin_id, 19 | uintptr_t call_id, 20 | uintptr_t arg0, 21 | uintptr_t arg1 22 | ); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /sm_rs/safe_math_util.h: -------------------------------------------------------------------------------- 1 | #ifndef _SAFE_MATH_UTIL_H_ 2 | #define _SAFE_MATH_UTIL_H_ 3 | 4 | // TODO: We may want to add checks for GCC/Clang version. We also want 5 | // to add wrappers for other checked math functions. 6 | 7 | #define __checked_uadd(a, b, out) (__builtin_uadd_overflow(a, b, out)) 8 | #define __checked_uaddl(a, b, out) (__builtin_uaddl_overflow(a, b, out)) 9 | #define __checked_uaddll(a, b, out) (__builtin_uaddll_overflow(a, b, out)) 10 | 11 | 12 | #endif /* _SAFE_MATH_UTIL_H_ */ 13 | -------------------------------------------------------------------------------- /sm_rs/sha3/sha3.h: -------------------------------------------------------------------------------- 1 | // sha3.h 2 | // 19-Nov-11 Markku-Juhani O. Saarinen 3 | 4 | #ifndef SHA3_H 5 | #define SHA3_H 6 | 7 | #include 8 | #include 9 | 10 | #ifndef KECCAKF_ROUNDS 11 | #define KECCAKF_ROUNDS 24 12 | #endif 13 | 14 | #ifndef ROTL64 15 | #define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) 16 | #endif 17 | 18 | // state context 19 | typedef struct { 20 | union { // state: 21 | uint8_t b[200]; // 8-bit bytes 22 | uint64_t q[25]; // 64-bit words 23 | } st; 24 | int pt, rsiz, mdlen; // these don't overflow 25 | } sha3_ctx_t; 26 | 27 | // Compression function. 28 | void sha3_keccakf(uint64_t st[25]); 29 | 30 | // OpenSSL - like interfece 31 | int sha3_init(sha3_ctx_t *c, int mdlen); // mdlen = hash output in bytes 32 | int sha3_update(sha3_ctx_t *c, const void *data, size_t len); 33 | int sha3_final(void *md, sha3_ctx_t *c); // digest goes to md 34 | 35 | // compute a sha3 hash (md) of given byte length from "in" 36 | void *sha3(const void *in, size_t inlen, void *md, int mdlen); 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /sm_rs/sm-sbi.h: -------------------------------------------------------------------------------- 1 | //****************************************************************************** 2 | // Copyright (c) 2018, The Regents of the University of California (Regents). 3 | // All Rights Reserved. See LICENSE for license details. 4 | //------------------------------------------------------------------------------ 5 | #ifndef _KEYSTONE_SBI_H_ 6 | #define _KEYSTONE_SBI_H_ 7 | 8 | #include 9 | #include 10 | 11 | typedef uintptr_t enclave_ret_code; 12 | 13 | uintptr_t mcall_sm_create_enclave(uintptr_t create_args); 14 | 15 | uintptr_t mcall_sm_destroy_enclave(unsigned long eid); 16 | 17 | uintptr_t mcall_sm_run_enclave(uintptr_t* regs, unsigned long eid); 18 | uintptr_t mcall_sm_exit_enclave(uintptr_t* regs, unsigned long retval); 19 | uintptr_t mcall_sm_not_implemented(uintptr_t* regs, unsigned long a0); 20 | uintptr_t mcall_sm_stop_enclave(uintptr_t* regs, unsigned long request); 21 | uintptr_t mcall_sm_resume_enclave(uintptr_t* regs, unsigned long eid); 22 | uintptr_t mcall_sm_attest_enclave(uintptr_t report, uintptr_t data, uintptr_t size); 23 | uintptr_t mcall_sm_get_sealing_key(uintptr_t sealing_key, uintptr_t key_ident, 24 | size_t key_ident_size); 25 | uintptr_t mcall_sm_random(); 26 | 27 | uintptr_t mcall_sm_call_plugin(uintptr_t plugin_id, uintptr_t call_id, uintptr_t arg0, uintptr_t arg1); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /sm_rs/sm_rs.ac: -------------------------------------------------------------------------------- 1 | AC_ARG_WITH([target_platform], AS_HELP_STRING([--with-target-platform], [Set a specific platform for the sm to build with]), 2 | [AC_SUBST([TARGET_PLATFORM], $with_target_platform, [Set a specific platform for the sm to build with])], 3 | [AC_SUBST([TARGET_PLATFORM], default, [Set a specific platform for the sm to build with])]) 4 | 5 | AC_ARG_ENABLE([sm_multimem], AS_HELP_STRING([--enable-sm-multimem], [Specify sm plugins to include]), 6 | AC_DEFINE([PLUGIN_ENABLE_MULTIMEM],[],[Enable multimem plugin]),[]) 7 | 8 | AC_DEFINE([SM_ENABLED],[],[Define SM as enabled]) 9 | -------------------------------------------------------------------------------- /sm_rs/sm_rs.mk.in: -------------------------------------------------------------------------------- 1 | sm_rs_hdrs = \ 2 | sm.h \ 3 | sm-sbi.h \ 4 | 5 | sm_rs_c_srcs = \ 6 | sm-sbi.c \ 7 | thread.c \ 8 | pmp.c \ 9 | sha3/sha3.c \ 10 | hkdf_sha3_512/hkdf_sha3_512.c \ 11 | hmac_sha3/hmac_sha3.c \ 12 | ed25519/keypair.c \ 13 | ed25519/sign.c \ 14 | ed25519/fe.c \ 15 | ed25519/ge.c \ 16 | ed25519/sc.c \ 17 | platform/@TARGET_PLATFORM@/@TARGET_PLATFORM@.c \ 18 | plugins/plugins.c \ 19 | 20 | sm_rs_asm_srcs = \ 21 | trap.S \ 22 | mprv.S \ 23 | 24 | sm_rs_test_srcs = 25 | 26 | sm_rs_install_prog_srcs = 27 | 28 | sm_rs_crates = sm-rs 29 | 30 | sm_rs_provides = sm 31 | -------------------------------------------------------------------------------- /sm_rs/tests/mock/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mock" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [lib] 7 | path = "lib.rs" 8 | 9 | [dependencies] 10 | util = { path="../../../util" } 11 | -------------------------------------------------------------------------------- /sm_rs/tests/mock/machine.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern void mock_assert(const int result, const char* const expression, 4 | const char * const file, const int line); 5 | 6 | void __wrap_printm(const char* s, ...) 7 | { 8 | return; 9 | } 10 | 11 | void __wrap_poweroff(uint16_t code) 12 | { 13 | mock_assert(0, "poweroff", __FILE__, __LINE__); 14 | } 15 | 16 | uint32_t __wrap_mcall_console_putchar(uint8_t ch) 17 | { 18 | return 0; 19 | } 20 | 21 | long __wrap_disabled_hart_mask; 22 | uint64_t __wrap_hart_mask; 23 | -------------------------------------------------------------------------------- /sm_rs/tests/mock/secure_boot.c: -------------------------------------------------------------------------------- 1 | #include "crypto.h" 2 | 3 | byte __wrap_sanctum_sm_hash[MDSIZE]; 4 | byte __wrap_sanctum_sm_signature[SIGNATURE_SIZE]; 5 | byte __wrap_sanctum_sm_public_key[PRIVATE_KEY_SIZE]; 6 | byte __wrap_sanctum_sm_secret_key[PUBLIC_KEY_SIZE]; 7 | byte __wrap_sanctum_dev_public_key[PUBLIC_KEY_SIZE]; 8 | -------------------------------------------------------------------------------- /softfloat/8086/platform.h: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | *** FIX. 5 | 6 | This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 7 | Arithmetic Package, Release 2b. 8 | 9 | Written by John R. Hauser. This work was made possible in part by the 10 | International Computer Science Institute, located at Suite 600, 1947 Center 11 | Street, Berkeley, California 94704. Funding was partially provided by the 12 | National Science Foundation under grant MIP-9311980. The original version 13 | of this code was written as part of a project to build a fixed-point vector 14 | processor in collaboration with the University of California at Berkeley, 15 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information 16 | is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ 17 | arithmetic/SoftFloat.html'. 18 | 19 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 20 | been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 21 | RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 22 | AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, 23 | COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE 24 | EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE 25 | INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR 26 | OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. 27 | 28 | Derivative works are acceptable, even for commercial purposes, so long as 29 | (1) the source code for the derivative work includes prominent notice that 30 | the work is derivative, and (2) the source code includes prominent notice with 31 | these four paragraphs for those parts of this code that are retained. 32 | 33 | =============================================================================*/ 34 | 35 | /*---------------------------------------------------------------------------- 36 | *----------------------------------------------------------------------------*/ 37 | #define LITTLEENDIAN 38 | 39 | -------------------------------------------------------------------------------- /softfloat/8086/s_commonNaNToF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | 6 | /*---------------------------------------------------------------------------- 7 | | Returns the result of converting the canonical NaN `a' to the single- 8 | | precision floating-point format. 9 | *----------------------------------------------------------------------------*/ 10 | 11 | uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) 12 | { 13 | 14 | return (uint_fast32_t) a.sign<<31 | 0x7FC00000 | a.v64>>41; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /softfloat/8086/s_commonNaNToF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | 6 | /*---------------------------------------------------------------------------- 7 | | Returns the result of converting the canonical NaN `a' to the double- 8 | | precision floating-point format. 9 | *----------------------------------------------------------------------------*/ 10 | 11 | uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) 12 | { 13 | 14 | return 15 | (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FF8000000000000 ) 16 | | a.v64>>12; 17 | 18 | } 19 | 20 | -------------------------------------------------------------------------------- /softfloat/8086/s_f32UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | #include "softfloat.h" 6 | 7 | /*---------------------------------------------------------------------------- 8 | | Returns the result of converting the single-precision floating-point NaN 9 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 10 | | exception is raised. 11 | *----------------------------------------------------------------------------*/ 12 | struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) 13 | { 14 | struct commonNaN z; 15 | 16 | if ( softfloat_isSigNaNF32UI( uiA ) ) { 17 | softfloat_raiseFlags( softfloat_flag_invalid ); 18 | } 19 | z.sign = uiA>>31; 20 | z.v64 = (uint_fast64_t) uiA<<41; 21 | z.v0 = 0; 22 | return z; 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/8086/s_f64UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | #include "softfloat.h" 6 | 7 | /*---------------------------------------------------------------------------- 8 | | Returns the result of converting the double-precision floating-point NaN 9 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 10 | | exception is raised. 11 | *----------------------------------------------------------------------------*/ 12 | struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) 13 | { 14 | struct commonNaN z; 15 | 16 | if ( softfloat_isSigNaNF64UI( uiA ) ) { 17 | softfloat_raiseFlags( softfloat_flag_invalid ); 18 | } 19 | z.sign = uiA>>63; 20 | z.v64 = uiA<<12; 21 | z.v0 = 0; 22 | return z; 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/8086/s_isSigNaNF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "specialize.h" 6 | 7 | bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) 8 | { 9 | 10 | return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /softfloat/8086/s_isSigNaNF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "specialize.h" 6 | 7 | bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) 8 | { 9 | 10 | return 11 | ( ( ui>>51 & 0xFFF ) == 0xFFE ) 12 | && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /softfloat/8086/s_propagateNaNF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*** UPDATE COMMENTS. ***/ 3 | 4 | #include 5 | #include 6 | #include "platform.h" 7 | #include "internals.h" 8 | #include "specialize.h" 9 | #include "softfloat.h" 10 | 11 | /*---------------------------------------------------------------------------- 12 | | Takes two single-precision floating-point values `a' and `b', one of which 13 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 14 | | signaling NaN, the invalid exception is raised. 15 | *----------------------------------------------------------------------------*/ 16 | 17 | uint_fast32_t 18 | softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) 19 | { 20 | bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; 21 | uint_fast32_t uiMagA, uiMagB; 22 | 23 | /*------------------------------------------------------------------------ 24 | *------------------------------------------------------------------------*/ 25 | isNaNA = isNaNF32UI( uiA ); 26 | isSigNaNA = softfloat_isSigNaNF32UI( uiA ); 27 | isNaNB = isNaNF32UI( uiB ); 28 | isSigNaNB = softfloat_isSigNaNF32UI( uiB ); 29 | /*------------------------------------------------------------------------ 30 | | Make NaNs non-signaling. 31 | *------------------------------------------------------------------------*/ 32 | uiA |= 0x00400000; 33 | uiB |= 0x00400000; 34 | /*------------------------------------------------------------------------ 35 | *------------------------------------------------------------------------*/ 36 | if ( isSigNaNA | isSigNaNB ) { 37 | softfloat_raiseFlags( softfloat_flag_invalid ); 38 | } 39 | if ( isSigNaNA ) { 40 | if ( isSigNaNB ) goto returnLargerSignificand; 41 | return isNaNB ? uiB : uiA; 42 | } else if ( isNaNA ) { 43 | if ( isSigNaNB || ! isNaNB ) return uiA; 44 | returnLargerSignificand: 45 | uiMagA = uiA<<1; 46 | uiMagB = uiB<<1; 47 | if ( uiMagA < uiMagB ) return uiB; 48 | if ( uiMagB < uiMagA ) return uiA; 49 | return ( uiA < uiB ) ? uiA : uiB; 50 | } else { 51 | return uiB; 52 | } 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /softfloat/8086/s_propagateNaNF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*** UPDATE COMMENTS. ***/ 3 | 4 | #include 5 | #include 6 | #include "platform.h" 7 | #include "internals.h" 8 | #include "specialize.h" 9 | #include "softfloat.h" 10 | 11 | /*---------------------------------------------------------------------------- 12 | | Takes two double-precision floating-point values `a' and `b', one of which 13 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 14 | | signaling NaN, the invalid exception is raised. 15 | *----------------------------------------------------------------------------*/ 16 | 17 | uint_fast64_t 18 | softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) 19 | { 20 | bool isNaNA, isSigNaNA, isNaNB, isSigNaNB; 21 | uint_fast64_t uiMagA, uiMagB; 22 | 23 | /*------------------------------------------------------------------------ 24 | *------------------------------------------------------------------------*/ 25 | isNaNA = isNaNF64UI( uiA ); 26 | isSigNaNA = softfloat_isSigNaNF64UI( uiA ); 27 | isNaNB = isNaNF64UI( uiB ); 28 | isSigNaNB = softfloat_isSigNaNF64UI( uiB ); 29 | /*------------------------------------------------------------------------ 30 | | Make NaNs non-signaling. 31 | *------------------------------------------------------------------------*/ 32 | uiA |= UINT64_C( 0x0008000000000000 ); 33 | uiB |= UINT64_C( 0x0008000000000000 ); 34 | /*------------------------------------------------------------------------ 35 | *------------------------------------------------------------------------*/ 36 | if ( isSigNaNA | isSigNaNB ) { 37 | softfloat_raiseFlags( softfloat_flag_invalid ); 38 | } 39 | if ( isSigNaNA ) { 40 | if ( isSigNaNB ) goto returnLargerSignificand; 41 | return isNaNB ? uiB : uiA; 42 | } else if ( isNaNA ) { 43 | if ( isSigNaNB || ! isNaNB ) return uiA; 44 | returnLargerSignificand: 45 | uiMagA = uiA & UINT64_C( 0x7FFFFFFFFFFFFFFF ); 46 | uiMagB = uiB & UINT64_C( 0x7FFFFFFFFFFFFFFF ); 47 | if ( uiMagA < uiMagB ) return uiB; 48 | if ( uiMagB < uiMagA ) return uiA; 49 | return ( uiA < uiB ) ? uiA : uiB; 50 | } else { 51 | return uiB; 52 | } 53 | 54 | } 55 | 56 | -------------------------------------------------------------------------------- /softfloat/8086/softfloat_types.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef softfloat_types_h 3 | #define softfloat_types_h 4 | 5 | /*** COMMENTS. ***/ 6 | 7 | #include 8 | #include 9 | 10 | typedef struct { uint32_t v; } float32_t; 11 | typedef struct { uint64_t v; } float64_t; 12 | typedef struct { uint64_t v; uint16_t x; } floatx80_t; 13 | typedef struct { uint64_t v[ 2 ]; } float128_t; 14 | 15 | #endif 16 | 17 | -------------------------------------------------------------------------------- /softfloat/f32_add.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float32_t f32_add( float32_t a, float32_t b ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | bool signA; 13 | union ui32_f32 uB; 14 | uint_fast32_t uiB; 15 | bool signB; 16 | float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | signA = signF32UI( uiA ); 21 | uB.f = b; 22 | uiB = uB.ui; 23 | signB = signF32UI( uiB ); 24 | magsRoutine = 25 | ( signA == signB ) ? softfloat_addMagsF32 : softfloat_subMagsF32; 26 | return magsRoutine( uiA, uiB, signA ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f32_classify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast16_t f32_classify( float32_t a ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | 14 | uA.f = a; 15 | uiA = uA.ui; 16 | 17 | uint_fast16_t infOrNaN = expF32UI( uiA ) == 0xFF; 18 | uint_fast16_t subnormalOrZero = expF32UI( uiA ) == 0; 19 | bool sign = signF32UI( uiA ); 20 | 21 | return 22 | ( sign && infOrNaN && fracF32UI( uiA ) == 0 ) << 0 | 23 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | 24 | ( sign && subnormalOrZero && fracF32UI( uiA ) ) << 2 | 25 | ( sign && subnormalOrZero && fracF32UI( uiA ) == 0 ) << 3 | 26 | ( !sign && infOrNaN && fracF32UI( uiA ) == 0 ) << 7 | 27 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | 28 | ( !sign && subnormalOrZero && fracF32UI( uiA ) ) << 5 | 29 | ( !sign && subnormalOrZero && fracF32UI( uiA ) == 0 ) << 4 | 30 | ( isNaNF32UI( uiA ) && softfloat_isSigNaNF32UI( uiA )) << 8 | 31 | ( isNaNF32UI( uiA ) && !softfloat_isSigNaNF32UI( uiA )) << 9; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /softfloat/f32_eq.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f32_eq( float32_t a, float32_t b ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | union ui32_f32 uB; 14 | uint_fast32_t uiB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 22 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 23 | ) { 24 | if ( 25 | softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) 26 | ) { 27 | softfloat_raiseFlags( softfloat_flag_invalid ); 28 | } 29 | return false; 30 | } 31 | return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /softfloat/f32_eq_signaling.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f32_eq_signaling( float32_t a, float32_t b ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | union ui32_f32 uB; 13 | uint_fast32_t uiB; 14 | 15 | uA.f = a; 16 | uiA = uA.ui; 17 | uB.f = b; 18 | uiB = uB.ui; 19 | if ( 20 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 21 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 22 | ) { 23 | softfloat_raiseFlags( softfloat_flag_invalid ); 24 | return false; 25 | } 26 | return ( uiA == uiB ) || ! (uint32_t) ( ( uiA | uiB )<<1 ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f32_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "internals.h" 5 | #include "specialize.h" 6 | #include "softfloat.h" 7 | 8 | bool f32_isSignalingNaN( float32_t a ) 9 | { 10 | union ui32_f32 uA; 11 | 12 | uA.f = a; 13 | return softfloat_isSigNaNF32UI( uA.ui ); 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /softfloat/f32_le.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f32_le( float32_t a, float32_t b ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | union ui32_f32 uB; 13 | uint_fast32_t uiB; 14 | bool signA, signB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 22 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 23 | ) { 24 | softfloat_raiseFlags( softfloat_flag_invalid ); 25 | return false; 26 | } 27 | signA = signF32UI( uiA ); 28 | signB = signF32UI( uiB ); 29 | return 30 | ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) 31 | : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /softfloat/f32_le_quiet.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f32_le_quiet( float32_t a, float32_t b ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | union ui32_f32 uB; 14 | uint_fast32_t uiB; 15 | bool signA, signB; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | uB.f = b; 20 | uiB = uB.ui; 21 | if ( 22 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 23 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 24 | ) { 25 | if ( 26 | softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) 27 | ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | } 30 | return false; 31 | } 32 | signA = signF32UI( uiA ); 33 | signB = signF32UI( uiB ); 34 | return 35 | ( signA != signB ) ? signA || ! (uint32_t) ( ( uiA | uiB )<<1 ) 36 | : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /softfloat/f32_lt.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f32_lt( float32_t a, float32_t b ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | union ui32_f32 uB; 13 | uint_fast32_t uiB; 14 | bool signA, signB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 22 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 23 | ) { 24 | softfloat_raiseFlags( softfloat_flag_invalid ); 25 | return false; 26 | } 27 | signA = signF32UI( uiA ); 28 | signB = signF32UI( uiB ); 29 | return 30 | ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) 31 | : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /softfloat/f32_lt_quiet.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f32_lt_quiet( float32_t a, float32_t b ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | union ui32_f32 uB; 14 | uint_fast32_t uiB; 15 | bool signA, signB; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | uB.f = b; 20 | uiB = uB.ui; 21 | if ( 22 | ( ( expF32UI( uiA ) == 0xFF ) && fracF32UI( uiA ) ) 23 | || ( ( expF32UI( uiB ) == 0xFF ) && fracF32UI( uiB ) ) 24 | ) { 25 | if ( 26 | softfloat_isSigNaNF32UI( uiA ) || softfloat_isSigNaNF32UI( uiB ) 27 | ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | } 30 | return false; 31 | } 32 | signA = signF32UI( uiA ); 33 | signB = signF32UI( uiB ); 34 | return 35 | ( signA != signB ) ? signA && ( (uint32_t) ( ( uiA | uiB )<<1 ) != 0 ) 36 | : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); 37 | 38 | } 39 | 40 | -------------------------------------------------------------------------------- /softfloat/f32_mulAdd.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "internals.h" 5 | #include "softfloat.h" 6 | 7 | float32_t f32_mulAdd( float32_t a, float32_t b, float32_t c ) 8 | { 9 | union ui32_f32 uA; 10 | uint_fast32_t uiA; 11 | union ui32_f32 uB; 12 | uint_fast32_t uiB; 13 | union ui32_f32 uC; 14 | uint_fast32_t uiC; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | uC.f = c; 21 | uiC = uC.ui; 22 | return softfloat_mulAddF32( 0, uiA, uiB, uiC ); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/f32_sqrt.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "specialize.h" 8 | #include "softfloat.h" 9 | 10 | float32_t f32_sqrt( float32_t a ) 11 | { 12 | union ui32_f32 uA; 13 | uint_fast32_t uiA; 14 | bool signA; 15 | int_fast16_t expA; 16 | uint_fast32_t sigA, uiZ; 17 | struct exp16_sig32 normExpSig; 18 | int_fast16_t expZ; 19 | uint_fast32_t sigZ; 20 | uint_fast64_t term, rem; 21 | union ui32_f32 uZ; 22 | 23 | uA.f = a; 24 | uiA = uA.ui; 25 | signA = signF32UI( uiA ); 26 | expA = expF32UI( uiA ); 27 | sigA = fracF32UI( uiA ); 28 | if ( expA == 0xFF ) { 29 | if ( sigA ) { 30 | uiZ = softfloat_propagateNaNF32UI( uiA, 0 ); 31 | goto uiZ; 32 | } 33 | if ( ! signA ) return a; 34 | goto invalid; 35 | } 36 | if ( signA ) { 37 | if ( ! ( expA | sigA ) ) return a; 38 | goto invalid; 39 | } 40 | if ( ! expA ) { 41 | if ( ! sigA ) return a; 42 | normExpSig = softfloat_normSubnormalF32Sig( sigA ); 43 | expA = normExpSig.exp; 44 | sigA = normExpSig.sig; 45 | } 46 | expZ = ( ( expA - 0x7F )>>1 ) + 0x7E; 47 | sigA = ( sigA | 0x00800000 )<<8; 48 | sigZ = softfloat_estimateSqrt32( expA, sigA ) + 2; 49 | if ( ( sigZ & 0x7F ) <= 5 ) { 50 | if ( sigZ < 2 ) { 51 | sigZ = 0x7FFFFFFF; 52 | goto roundPack; 53 | } 54 | sigA >>= expA & 1; 55 | term = (uint_fast64_t) sigZ * sigZ; 56 | rem = ( (uint_fast64_t) sigA<<32 ) - term; 57 | while ( UINT64_C( 0x8000000000000000 ) <= rem ) { 58 | --sigZ; 59 | rem += ( (uint_fast64_t) sigZ<<1 ) | 1; 60 | } 61 | sigZ |= ( rem != 0 ); 62 | } 63 | sigZ = softfloat_shortShift32Right1Jam( sigZ ); 64 | roundPack: 65 | return softfloat_roundPackToF32( 0, expZ, sigZ ); 66 | invalid: 67 | softfloat_raiseFlags( softfloat_flag_invalid ); 68 | uiZ = defaultNaNF32UI; 69 | uiZ: 70 | uZ.ui = uiZ; 71 | return uZ.f; 72 | 73 | } 74 | 75 | -------------------------------------------------------------------------------- /softfloat/f32_sub.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float32_t f32_sub( float32_t a, float32_t b ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | bool signA; 13 | union ui32_f32 uB; 14 | uint_fast32_t uiB; 15 | bool signB; 16 | float32_t ( *magsRoutine )( uint_fast32_t, uint_fast32_t, bool ); 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | signA = signF32UI( uiA ); 21 | uB.f = b; 22 | uiB = uB.ui; 23 | signB = signF32UI( uiB ); 24 | magsRoutine = 25 | ( signA == signB ) ? softfloat_subMagsF32 : softfloat_addMagsF32; 26 | return magsRoutine( uiA, uiB ^ 0x80000000, signA ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f32_to_f64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | float64_t f32_to_f64( float32_t a ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast32_t sig; 16 | uint_fast64_t uiZ; 17 | struct exp16_sig32 normExpSig; 18 | union ui64_f64 uZ; 19 | 20 | uA.f = a; 21 | uiA = uA.ui; 22 | sign = signF32UI( uiA ); 23 | exp = expF32UI( uiA ); 24 | sig = fracF32UI( uiA ); 25 | if ( exp == 0xFF ) { 26 | uiZ = 27 | sig ? softfloat_commonNaNToF64UI( 28 | softfloat_f32UIToCommonNaN( uiA ) ) 29 | : packToF64UI( sign, 0x7FF, 0 ); 30 | goto uiZ; 31 | } 32 | if ( ! exp ) { 33 | if ( ! sig ) { 34 | uiZ = packToF64UI( sign, 0, 0 ); 35 | goto uiZ; 36 | } 37 | normExpSig = softfloat_normSubnormalF32Sig( sig ); 38 | exp = normExpSig.exp - 1; 39 | sig = normExpSig.sig; 40 | } 41 | uiZ = packToF64UI( sign, exp + 0x380, (uint_fast64_t) sig<<29 ); 42 | uiZ: 43 | uZ.ui = uiZ; 44 | return uZ.f; 45 | 46 | } 47 | 48 | -------------------------------------------------------------------------------- /softfloat/f32_to_i32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | int_fast32_t f32_to_i32( float32_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast32_t sig; 16 | uint_fast64_t sig64; 17 | int_fast16_t shiftCount; 18 | 19 | uA.f = a; 20 | uiA = uA.ui; 21 | sign = signF32UI( uiA ); 22 | exp = expF32UI( uiA ); 23 | sig = fracF32UI( uiA ); 24 | if ( exp ) sig |= 0x00800000; 25 | sig64 = (uint_fast64_t) sig<<32; 26 | shiftCount = 0xAF - exp; 27 | if ( 0 < shiftCount ) { 28 | sig64 = softfloat_shift64RightJam( sig64, shiftCount ); 29 | } 30 | return softfloat_roundPackToI32( sign, sig64, roundingMode, exact ); 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /softfloat/f32_to_i32_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast32_t f32_to_i32_r_minMag( float32_t a, bool exact ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | int_fast16_t exp; 13 | uint_fast32_t sig; 14 | bool sign; 15 | int_fast16_t shiftCount; 16 | int_fast32_t absZ; 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | exp = expF32UI( uiA ); 21 | sig = fracF32UI( uiA ); 22 | if ( exp < 0x7F ) { 23 | if ( exact && ( exp | sig ) ) { 24 | softfloat_raiseFlags( softfloat_flag_inexact ); 25 | } 26 | return 0; 27 | } 28 | sign = signF32UI( uiA ); 29 | shiftCount = 0x9E - exp; 30 | if ( shiftCount <= 0 ) { 31 | if ( uiA != packToF32UI( 1, 0x9E, 0 ) ) { 32 | softfloat_raiseFlags( softfloat_flag_invalid ); 33 | if ( ! sign || ( ( exp == 0xFF ) && sig ) ) return 0x7FFFFFFF; 34 | } 35 | return -0x7FFFFFFF - 1; 36 | } 37 | sig = ( sig | 0x00800000 )<<8; 38 | absZ = sig>>shiftCount; 39 | if ( exact && (uint32_t) ( sig<<( ( - shiftCount ) & 31 ) ) ) { 40 | softfloat_raiseFlags( softfloat_flag_inexact ); 41 | } 42 | return sign ? - absZ : absZ; 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /softfloat/f32_to_i64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | int_fast64_t f32_to_i64( float32_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast32_t sig; 16 | int_fast16_t shiftCount; 17 | uint_fast64_t sig64, extra; 18 | struct uint64_extra sig64Extra; 19 | 20 | uA.f = a; 21 | uiA = uA.ui; 22 | sign = signF32UI( uiA ); 23 | exp = expF32UI( uiA ); 24 | sig = fracF32UI( uiA ); 25 | shiftCount = 0xBE - exp; 26 | if ( shiftCount < 0 ) { 27 | softfloat_raiseFlags( softfloat_flag_invalid ); 28 | if ( ! sign ) { 29 | return INT64_C( 0x7FFFFFFFFFFFFFFF ); 30 | } 31 | return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; 32 | } 33 | if ( exp ) sig |= 0x00800000; 34 | sig64 = (uint_fast64_t) sig<<40; 35 | extra = 0; 36 | if ( shiftCount ) { 37 | sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); 38 | sig64 = sig64Extra.v; 39 | extra = sig64Extra.extra; 40 | } 41 | return softfloat_roundPackToI64( sign, sig64, extra, roundingMode, exact ); 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /softfloat/f32_to_i64_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast64_t f32_to_i64_r_minMag( float32_t a, bool exact ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | int_fast16_t exp; 13 | uint_fast32_t sig; 14 | bool sign; 15 | int_fast16_t shiftCount; 16 | uint_fast64_t sig64; 17 | int_fast64_t absZ; 18 | 19 | uA.f = a; 20 | uiA = uA.ui; 21 | exp = expF32UI( uiA ); 22 | sig = fracF32UI( uiA ); 23 | if ( exp < 0x7F ) { 24 | if ( exact && ( exp | sig ) ) { 25 | softfloat_raiseFlags( softfloat_flag_inexact ); 26 | } 27 | return 0; 28 | } 29 | sign = signF32UI( uiA ); 30 | shiftCount = 0xBE - exp; 31 | if ( shiftCount <= 0 ) { 32 | if ( uiA != packToF32UI( 1, 0xBE, 0 ) ) { 33 | softfloat_raiseFlags( softfloat_flag_invalid ); 34 | if ( ! sign || ( ( exp == 0xFF ) && sig ) ) { 35 | return INT64_C( 0x7FFFFFFFFFFFFFFF ); 36 | } 37 | } 38 | return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; 39 | } 40 | sig |= 0x00800000; 41 | sig64 = (uint_fast64_t) sig<<40; 42 | absZ = sig64>>shiftCount; 43 | shiftCount = 40 - shiftCount; 44 | if ( 45 | exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) 46 | ) { 47 | softfloat_raiseFlags( softfloat_flag_inexact ); 48 | } 49 | return sign ? - absZ : absZ; 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /softfloat/f32_to_ui32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast32_t f32_to_ui32( float32_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast32_t sig; 16 | uint_fast64_t sig64; 17 | int_fast16_t shiftCount; 18 | 19 | uA.f = a; 20 | uiA = uA.ui; 21 | sign = signF32UI( uiA ); 22 | exp = expF32UI( uiA ); 23 | sig = fracF32UI( uiA ); 24 | if ( exp ) sig |= 0x00800000; 25 | sig64 = (uint_fast64_t) sig<<32; 26 | shiftCount = 0xAF - exp; 27 | if ( 0 < shiftCount ) { 28 | sig64 = softfloat_shift64RightJam( sig64, shiftCount ); 29 | } 30 | return softfloat_roundPackToUI32( sign, sig64, roundingMode, exact ); 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /softfloat/f32_to_ui32_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast32_t f32_to_ui32_r_minMag( float32_t a, bool exact ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | int_fast16_t exp; 13 | uint_fast32_t sig; 14 | int_fast16_t shiftCount; 15 | uint_fast32_t z; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | exp = expF32UI( uiA ); 20 | sig = fracF32UI( uiA ); 21 | if ( exp < 0x7F ) { 22 | if ( exact && ( exp | sig ) ) { 23 | softfloat_raiseFlags( softfloat_flag_inexact ); 24 | } 25 | return 0; 26 | } 27 | if ( signF32UI( uiA ) ) goto invalid; 28 | shiftCount = 0x9E - exp; 29 | if ( shiftCount < 0 ) goto invalid; 30 | sig = ( sig | 0x00800000 )<<8; 31 | z = sig>>shiftCount; 32 | if ( exact && ( sig & ( ( (uint_fast32_t) 1< 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast64_t f32_to_ui64( float32_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui32_f32 uA; 12 | uint_fast32_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast32_t sig; 16 | int_fast16_t shiftCount; 17 | uint_fast64_t sig64, extra; 18 | struct uint64_extra sig64Extra; 19 | 20 | uA.f = a; 21 | uiA = uA.ui; 22 | sign = signF32UI( uiA ); 23 | exp = expF32UI( uiA ); 24 | sig = fracF32UI( uiA ); 25 | shiftCount = 0xBE - exp; 26 | if ( shiftCount < 0 ) { 27 | softfloat_raiseFlags( softfloat_flag_invalid ); 28 | return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 29 | } 30 | if ( exp ) sig |= 0x00800000; 31 | sig64 = (uint_fast64_t) sig<<40; 32 | extra = 0; 33 | if ( shiftCount ) { 34 | sig64Extra = softfloat_shift64ExtraRightJam( sig64, 0, shiftCount ); 35 | sig64 = sig64Extra.v; 36 | extra = sig64Extra.extra; 37 | } 38 | return 39 | softfloat_roundPackToUI64( sign, sig64, extra, roundingMode, exact ); 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /softfloat/f32_to_ui64_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast64_t f32_to_ui64_r_minMag( float32_t a, bool exact ) 9 | { 10 | union ui32_f32 uA; 11 | uint_fast32_t uiA; 12 | int_fast16_t exp; 13 | uint_fast32_t sig; 14 | int_fast16_t shiftCount; 15 | uint_fast64_t sig64, z; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | exp = expF32UI( uiA ); 20 | sig = fracF32UI( uiA ); 21 | if ( exp < 0x7F ) { 22 | if ( exact && ( exp | sig ) ) { 23 | softfloat_raiseFlags( softfloat_flag_inexact ); 24 | } 25 | return 0; 26 | } 27 | if ( signF32UI( uiA ) ) goto invalid; 28 | shiftCount = 0xBE - exp; 29 | if ( shiftCount < 0 ) goto invalid; 30 | sig |= 0x00800000; 31 | sig64 = (uint_fast64_t) sig<<40; 32 | z = sig64>>shiftCount; 33 | shiftCount = 40 - shiftCount; 34 | if ( 35 | exact && ( shiftCount < 0 ) && (uint32_t) ( sig<<( shiftCount & 31 ) ) 36 | ) { 37 | softfloat_raiseFlags( softfloat_flag_inexact ); 38 | } 39 | return z; 40 | invalid: 41 | softfloat_raiseFlags( softfloat_flag_invalid ); 42 | return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /softfloat/f64_add.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float64_t f64_add( float64_t a, float64_t b ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | bool signA; 13 | union ui64_f64 uB; 14 | uint_fast64_t uiB; 15 | bool signB; 16 | float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | signA = signF64UI( uiA ); 21 | uB.f = b; 22 | uiB = uB.ui; 23 | signB = signF64UI( uiB ); 24 | magsRoutine = 25 | ( signA == signB ) ? softfloat_addMagsF64 : softfloat_subMagsF64; 26 | return magsRoutine( uiA, uiB, signA ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f64_classify.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast16_t f64_classify( float64_t a ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | 14 | uA.f = a; 15 | uiA = uA.ui; 16 | 17 | uint_fast16_t infOrNaN = expF64UI( uiA ) == 0x7FF; 18 | uint_fast16_t subnormalOrZero = expF64UI( uiA ) == 0; 19 | bool sign = signF64UI( uiA ); 20 | 21 | return 22 | ( sign && infOrNaN && fracF64UI( uiA ) == 0 ) << 0 | 23 | ( sign && !infOrNaN && !subnormalOrZero ) << 1 | 24 | ( sign && subnormalOrZero && fracF64UI( uiA ) ) << 2 | 25 | ( sign && subnormalOrZero && fracF64UI( uiA ) == 0 ) << 3 | 26 | ( !sign && infOrNaN && fracF64UI( uiA ) == 0 ) << 7 | 27 | ( !sign && !infOrNaN && !subnormalOrZero ) << 6 | 28 | ( !sign && subnormalOrZero && fracF64UI( uiA ) ) << 5 | 29 | ( !sign && subnormalOrZero && fracF64UI( uiA ) == 0 ) << 4 | 30 | ( isNaNF64UI( uiA ) && softfloat_isSigNaNF64UI( uiA )) << 8 | 31 | ( isNaNF64UI( uiA ) && !softfloat_isSigNaNF64UI( uiA )) << 9; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /softfloat/f64_eq.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f64_eq( float64_t a, float64_t b ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | union ui64_f64 uB; 14 | uint_fast64_t uiB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 22 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 23 | ) { 24 | if ( 25 | softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) 26 | ) { 27 | softfloat_raiseFlags( softfloat_flag_invalid ); 28 | } 29 | return false; 30 | } 31 | return 32 | ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /softfloat/f64_eq_signaling.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f64_eq_signaling( float64_t a, float64_t b ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | union ui64_f64 uB; 13 | uint_fast64_t uiB; 14 | 15 | uA.f = a; 16 | uiA = uA.ui; 17 | uB.f = b; 18 | uiB = uB.ui; 19 | if ( 20 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 21 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 22 | ) { 23 | softfloat_raiseFlags( softfloat_flag_invalid ); 24 | return false; 25 | } 26 | return 27 | ( uiA == uiB ) || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ); 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /softfloat/f64_isSignalingNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "internals.h" 5 | #include "specialize.h" 6 | #include "softfloat.h" 7 | 8 | bool f64_isSignalingNaN( float64_t a ) 9 | { 10 | union ui64_f64 uA; 11 | 12 | uA.f = a; 13 | return softfloat_isSigNaNF64UI( uA.ui ); 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /softfloat/f64_le.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f64_le( float64_t a, float64_t b ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | union ui64_f64 uB; 13 | uint_fast64_t uiB; 14 | bool signA, signB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 22 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 23 | ) { 24 | softfloat_raiseFlags( softfloat_flag_invalid ); 25 | return false; 26 | } 27 | signA = signF64UI( uiA ); 28 | signB = signF64UI( uiB ); 29 | return 30 | ( signA != signB ) 31 | ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 32 | : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /softfloat/f64_le_quiet.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f64_le_quiet( float64_t a, float64_t b ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | union ui64_f64 uB; 14 | uint_fast64_t uiB; 15 | bool signA, signB; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | uB.f = b; 20 | uiB = uB.ui; 21 | if ( 22 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 23 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 24 | ) { 25 | if ( 26 | softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) 27 | ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | } 30 | return false; 31 | } 32 | signA = signF64UI( uiA ); 33 | signB = signF64UI( uiB ); 34 | return 35 | ( signA != signB ) 36 | ? signA || ! ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 37 | : ( uiA == uiB ) || ( signA ^ ( uiA < uiB ) ); 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /softfloat/f64_lt.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | bool f64_lt( float64_t a, float64_t b ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | union ui64_f64 uB; 13 | uint_fast64_t uiB; 14 | bool signA, signB; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | if ( 21 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 22 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 23 | ) { 24 | softfloat_raiseFlags( softfloat_flag_invalid ); 25 | return false; 26 | } 27 | signA = signF64UI( uiA ); 28 | signB = signF64UI( uiB ); 29 | return 30 | ( signA != signB ) 31 | ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 32 | : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /softfloat/f64_lt_quiet.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "specialize.h" 7 | #include "softfloat.h" 8 | 9 | bool f64_lt_quiet( float64_t a, float64_t b ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | union ui64_f64 uB; 14 | uint_fast64_t uiB; 15 | bool signA, signB; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | uB.f = b; 20 | uiB = uB.ui; 21 | if ( 22 | ( ( expF64UI( uiA ) == 0x7FF ) && fracF64UI( uiA ) ) 23 | || ( ( expF64UI( uiB ) == 0x7FF ) && fracF64UI( uiB ) ) 24 | ) { 25 | if ( 26 | softfloat_isSigNaNF64UI( uiA ) || softfloat_isSigNaNF64UI( uiB ) 27 | ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | } 30 | return false; 31 | } 32 | signA = signF64UI( uiA ); 33 | signB = signF64UI( uiB ); 34 | return 35 | ( signA != signB ) 36 | ? signA && ( ( uiA | uiB ) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 37 | : ( uiA != uiB ) && ( signA ^ ( uiA < uiB ) ); 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /softfloat/f64_mulAdd.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "internals.h" 5 | #include "softfloat.h" 6 | 7 | float64_t f64_mulAdd( float64_t a, float64_t b, float64_t c ) 8 | { 9 | union ui64_f64 uA; 10 | uint_fast64_t uiA; 11 | union ui64_f64 uB; 12 | uint_fast64_t uiB; 13 | union ui64_f64 uC; 14 | uint_fast64_t uiC; 15 | 16 | uA.f = a; 17 | uiA = uA.ui; 18 | uB.f = b; 19 | uiB = uB.ui; 20 | uC.f = c; 21 | uiC = uC.ui; 22 | return softfloat_mulAddF64( 0, uiA, uiB, uiC ); 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/f64_sub.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float64_t f64_sub( float64_t a, float64_t b ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | bool signA; 13 | union ui64_f64 uB; 14 | uint_fast64_t uiB; 15 | bool signB; 16 | float64_t ( *magsRoutine )( uint_fast64_t, uint_fast64_t, bool ); 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | signA = signF64UI( uiA ); 21 | uB.f = b; 22 | uiB = uB.ui; 23 | signB = signF64UI( uiB ); 24 | magsRoutine = 25 | ( signA == signB ) ? softfloat_subMagsF64 : softfloat_addMagsF64; 26 | return magsRoutine( uiA, uiB, signA ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f64_to_f32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "specialize.h" 8 | #include "softfloat.h" 9 | 10 | float32_t f64_to_f32( float64_t a ) 11 | { 12 | union ui64_f64 uA; 13 | uint_fast64_t uiA; 14 | bool sign; 15 | int_fast16_t exp; 16 | uint_fast64_t sig; 17 | uint_fast32_t uiZ, sig32; 18 | union ui32_f32 uZ; 19 | 20 | uA.f = a; 21 | uiA = uA.ui; 22 | sign = signF64UI( uiA ); 23 | exp = expF64UI( uiA ); 24 | sig = fracF64UI( uiA ); 25 | if ( exp == 0x7FF ) { 26 | uiZ = 27 | sig ? softfloat_commonNaNToF32UI( 28 | softfloat_f64UIToCommonNaN( uiA ) ) 29 | : packToF32UI( sign, 0xFF, 0 ); 30 | goto uiZ; 31 | } 32 | sig32 = softfloat_shortShift64RightJam( sig, 22 ); 33 | if ( ! ( exp | sig32 ) ) { 34 | uiZ = packToF32UI( sign, 0, 0 ); 35 | goto uiZ; 36 | } 37 | return softfloat_roundPackToF32( sign, exp - 0x381, sig32 | 0x40000000 ); 38 | uiZ: 39 | uZ.ui = uiZ; 40 | return uZ.f; 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /softfloat/f64_to_i32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | int_fast32_t f64_to_i32( float64_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast64_t sig; 16 | int_fast16_t shiftCount; 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | sign = signF64UI( uiA ); 21 | exp = expF64UI( uiA ); 22 | sig = fracF64UI( uiA ); 23 | if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); 24 | shiftCount = 0x42C - exp; 25 | if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); 26 | return softfloat_roundPackToI32( sign, sig, roundingMode, exact ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f64_to_i32_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast32_t f64_to_i32_r_minMag( float64_t a, bool exact ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | int_fast16_t exp; 13 | uint_fast64_t sig; 14 | bool sign; 15 | int_fast16_t shiftCount; 16 | uint_fast32_t absZ; 17 | union { uint32_t ui; int32_t i; } uZ; 18 | int_fast32_t z; 19 | 20 | uA.f = a; 21 | uiA = uA.ui; 22 | exp = expF64UI( uiA ); 23 | sig = fracF64UI( uiA ); 24 | if ( exp < 0x3FF ) { 25 | if ( exact && ( exp | sig ) ) { 26 | softfloat_raiseFlags( softfloat_flag_inexact ); 27 | } 28 | return 0; 29 | } 30 | sign = signF64UI( uiA ); 31 | if ( 0x41E < exp ) { 32 | if ( ( exp == 0x7FF ) && sig ) sign = 0; 33 | goto invalid; 34 | } 35 | sig |= UINT64_C( 0x0010000000000000 ); 36 | shiftCount = 0x433 - exp; 37 | absZ = sig>>shiftCount; 38 | uZ.ui = sign ? - absZ : absZ; 39 | z = uZ.i; 40 | if ( ( z < 0 ) != sign ) goto invalid; 41 | if ( exact && ( (uint_fast64_t) absZ< 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | int_fast64_t f64_to_i64( float64_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast64_t sig; 16 | int_fast16_t shiftCount; 17 | struct uint64_extra sigExtra; 18 | 19 | uA.f = a; 20 | uiA = uA.ui; 21 | sign = signF64UI( uiA ); 22 | exp = expF64UI( uiA ); 23 | sig = fracF64UI( uiA ); 24 | if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); 25 | shiftCount = 0x433 - exp; 26 | if ( shiftCount <= 0 ) { 27 | if ( 0x43E < exp ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | return 30 | ! sign 31 | ? INT64_C( 0x7FFFFFFFFFFFFFFF ) 32 | : - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; 33 | } 34 | sigExtra.v = sig<<( - shiftCount ); 35 | sigExtra.extra = 0; 36 | } else { 37 | sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); 38 | } 39 | return 40 | softfloat_roundPackToI64( 41 | sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /softfloat/f64_to_i64_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast64_t f64_to_i64_r_minMag( float64_t a, bool exact ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | bool sign; 13 | int_fast16_t exp; 14 | uint_fast64_t sig; 15 | int_fast16_t shiftCount; 16 | int_fast64_t absZ; 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | sign = signF64UI( uiA ); 21 | exp = expF64UI( uiA ); 22 | sig = fracF64UI( uiA ); 23 | shiftCount = exp - 0x433; 24 | if ( 0 <= shiftCount ) { 25 | if ( 0x43E <= exp ) { 26 | if ( uiA != packToF64UI( 1, 0x43E, 0 ) ) { 27 | softfloat_raiseFlags( softfloat_flag_invalid ); 28 | if ( ! sign || ( ( exp == 0x7FF ) && sig ) ) { 29 | return INT64_C( 0x7FFFFFFFFFFFFFFF ); 30 | } 31 | } 32 | return - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1; 33 | } 34 | sig |= UINT64_C( 0x0010000000000000 ); 35 | absZ = sig<>( - shiftCount ); 45 | if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { 46 | softfloat_raiseFlags( softfloat_flag_inexact ); 47 | } 48 | } 49 | return sign ? - absZ : absZ; 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /softfloat/f64_to_ui32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast32_t f64_to_ui32( float64_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast64_t sig; 16 | int_fast16_t shiftCount; 17 | 18 | uA.f = a; 19 | uiA = uA.ui; 20 | sign = signF64UI( uiA ); 21 | exp = expF64UI( uiA ); 22 | sig = fracF64UI( uiA ); 23 | if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); 24 | shiftCount = 0x42C - exp; 25 | if ( 0 < shiftCount ) sig = softfloat_shift64RightJam( sig, shiftCount ); 26 | return softfloat_roundPackToUI32( sign, sig, roundingMode, exact ); 27 | 28 | } 29 | 30 | -------------------------------------------------------------------------------- /softfloat/f64_to_ui32_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast32_t f64_to_ui32_r_minMag( float64_t a, bool exact ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | int_fast16_t exp; 13 | uint_fast64_t sig; 14 | int_fast16_t shiftCount; 15 | uint_fast32_t z; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | exp = expF64UI( uiA ); 20 | sig = fracF64UI( uiA ); 21 | if ( exp < 0x3FF ) { 22 | if ( exact && ( exp | sig ) ) { 23 | softfloat_raiseFlags( softfloat_flag_inexact ); 24 | } 25 | return 0; 26 | } 27 | if ( signF64UI( uiA ) || ( 0x41E < exp ) ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | return 0xFFFFFFFF; 30 | } 31 | sig |= UINT64_C( 0x0010000000000000 ); 32 | shiftCount = 0x433 - exp; 33 | z = sig>>shiftCount; 34 | if ( exact && ( (uint_fast64_t) z< 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | uint_fast64_t f64_to_ui64( float64_t a, int_fast8_t roundingMode, bool exact ) 10 | { 11 | union ui64_f64 uA; 12 | uint_fast64_t uiA; 13 | bool sign; 14 | int_fast16_t exp; 15 | uint_fast64_t sig; 16 | int_fast16_t shiftCount; 17 | struct uint64_extra sigExtra; 18 | 19 | uA.f = a; 20 | uiA = uA.ui; 21 | sign = signF64UI( uiA ); 22 | exp = expF64UI( uiA ); 23 | sig = fracF64UI( uiA ); 24 | if ( exp ) sig |= UINT64_C( 0x0010000000000000 ); 25 | shiftCount = 0x433 - exp; 26 | if ( shiftCount <= 0 ) { 27 | if ( 0x43E < exp ) { 28 | softfloat_raiseFlags( softfloat_flag_invalid ); 29 | return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 30 | } 31 | sigExtra.v = sig<<( - shiftCount ); 32 | sigExtra.extra = 0; 33 | } else { 34 | sigExtra = softfloat_shift64ExtraRightJam( sig, 0, shiftCount ); 35 | } 36 | return 37 | softfloat_roundPackToUI64( 38 | sign, sigExtra.v, sigExtra.extra, roundingMode, exact ); 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /softfloat/f64_to_ui64_r_minMag.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast64_t f64_to_ui64_r_minMag( float64_t a, bool exact ) 9 | { 10 | union ui64_f64 uA; 11 | uint_fast64_t uiA; 12 | int_fast16_t exp; 13 | uint_fast64_t sig; 14 | int_fast16_t shiftCount; 15 | uint_fast64_t z; 16 | 17 | uA.f = a; 18 | uiA = uA.ui; 19 | exp = expF64UI( uiA ); 20 | sig = fracF64UI( uiA ); 21 | if ( exp < 0x3FF ) { 22 | if ( exact && ( exp | sig ) ) { 23 | softfloat_raiseFlags( softfloat_flag_inexact ); 24 | } 25 | return 0; 26 | } 27 | if ( signF64UI( uiA ) ) goto invalid; 28 | shiftCount = exp - 0x433; 29 | if ( 0 <= shiftCount ) { 30 | if ( 0x43E < exp ) goto invalid; 31 | z = ( sig | UINT64_C( 0x0010000000000000 ) )<>( - shiftCount ); 35 | if ( exact && (uint64_t) ( sig<<( shiftCount & 63 ) ) ) { 36 | softfloat_raiseFlags( softfloat_flag_inexact ); 37 | } 38 | } 39 | return z; 40 | invalid: 41 | softfloat_raiseFlags( softfloat_flag_invalid ); 42 | return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /softfloat/i32_to_f32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float32_t i32_to_f32( int_fast32_t a ) 9 | { 10 | bool sign; 11 | union ui32_f32 uZ; 12 | 13 | sign = ( a < 0 ); 14 | if ( ! ( a & 0x7FFFFFFF ) ) { 15 | uZ.ui = sign ? packToF32UI( 1, 0x9E, 0 ) : 0; 16 | return uZ.f; 17 | } 18 | return softfloat_normRoundPackToF32( sign, 0x9C, sign ? - a : a ); 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /softfloat/i32_to_f64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | float64_t i32_to_f64( int_fast32_t a ) 10 | { 11 | uint_fast64_t uiZ; 12 | bool sign; 13 | uint_fast32_t absA; 14 | int shiftCount; 15 | union ui64_f64 uZ; 16 | 17 | if ( ! a ) { 18 | uiZ = 0; 19 | } else { 20 | sign = ( a < 0 ); 21 | absA = sign ? - a : a; 22 | shiftCount = softfloat_countLeadingZeros32( absA ) + 21; 23 | uiZ = 24 | packToF64UI( 25 | sign, 0x432 - shiftCount, (uint_fast64_t) absA< 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | float32_t i64_to_f32( int_fast64_t a ) 10 | { 11 | bool sign; 12 | uint_fast64_t absA; 13 | int shiftCount; 14 | union ui32_f32 u; 15 | uint_fast32_t sig; 16 | 17 | sign = ( a < 0 ); 18 | absA = sign ? - (uint_fast64_t) a : a; 19 | shiftCount = softfloat_countLeadingZeros64( absA ) - 40; 20 | if ( 0 <= shiftCount ) { 21 | u.ui = 22 | a ? packToF32UI( 23 | sign, 0x95 - shiftCount, (uint_fast32_t) absA< 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float64_t i64_to_f64( int_fast64_t a ) 9 | { 10 | bool sign; 11 | union ui64_f64 uZ; 12 | 13 | sign = ( a < 0 ); 14 | if ( ! ( a & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) ) { 15 | uZ.ui = sign ? packToF64UI( 1, 0x43E, 0 ) : 0; 16 | return uZ.f; 17 | } 18 | return softfloat_normRoundPackToF64( sign, 0x43C, sign ? - a : a ); 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /softfloat/platform.h: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | *** FIX. 5 | 6 | This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 7 | Arithmetic Package, Release 2b. 8 | 9 | Written by John R. Hauser. This work was made possible in part by the 10 | International Computer Science Institute, located at Suite 600, 1947 Center 11 | Street, Berkeley, California 94704. Funding was partially provided by the 12 | National Science Foundation under grant MIP-9311980. The original version 13 | of this code was written as part of a project to build a fixed-point vector 14 | processor in collaboration with the University of California at Berkeley, 15 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information 16 | is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ 17 | arithmetic/SoftFloat.html'. 18 | 19 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 20 | been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 21 | RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 22 | AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, 23 | COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE 24 | EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE 25 | INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR 26 | OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. 27 | 28 | Derivative works are acceptable, even for commercial purposes, so long as 29 | (1) the source code for the derivative work includes prominent notice that 30 | the work is derivative, and (2) the source code includes prominent notice with 31 | these four paragraphs for those parts of this code that are retained. 32 | 33 | =============================================================================*/ 34 | 35 | /*---------------------------------------------------------------------------- 36 | *----------------------------------------------------------------------------*/ 37 | #define LITTLEENDIAN 38 | 39 | #ifndef UINT64_C 40 | # define UINT64_C(x) (x ## ULL) 41 | # define INT64_C(x) (x ## LL) 42 | #endif 43 | -------------------------------------------------------------------------------- /softfloat/s_add128.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 7 | softfloat_add128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | struct uint128 z; 10 | 11 | z.v0 = a0 + b0; 12 | z.v64 = a64 + b64; 13 | z.v64 += ( z.v0 < a0 ); 14 | return z; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /softfloat/s_add192.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint192 7 | softfloat_add192( 8 | uint64_t a128, 9 | uint64_t a64, 10 | uint64_t a0, 11 | uint64_t b128, 12 | uint64_t b64, 13 | uint64_t b0 14 | ) 15 | { 16 | struct uint192 z; 17 | unsigned int carry64, carry128; 18 | 19 | z.v0 = a0 + b0; 20 | carry64 = ( z.v0 < a0 ); 21 | z.v64 = a64 + b64; 22 | carry128 = ( z.v64 < a64 ); 23 | z.v128 = a128 + b128; 24 | z.v64 += carry64; 25 | carry128 += ( z.v64 < carry64 ); 26 | z.v128 += carry128; 27 | return z; 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /softfloat/s_addMagsF32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "specialize.h" 8 | 9 | float32_t 10 | softfloat_addMagsF32( uint_fast32_t uiA, uint_fast32_t uiB, bool signZ ) 11 | { 12 | int_fast16_t expA; 13 | uint_fast32_t sigA; 14 | int_fast16_t expB; 15 | uint_fast32_t sigB; 16 | int_fast16_t expDiff; 17 | uint_fast32_t uiZ; 18 | int_fast16_t expZ; 19 | uint_fast32_t sigZ; 20 | union ui32_f32 uZ; 21 | 22 | expA = expF32UI( uiA ); 23 | sigA = fracF32UI( uiA ); 24 | expB = expF32UI( uiB ); 25 | sigB = fracF32UI( uiB ); 26 | expDiff = expA - expB; 27 | sigA <<= 6; 28 | sigB <<= 6; 29 | if ( ! expDiff ) { 30 | if ( expA == 0xFF ) { 31 | if ( sigA | sigB ) goto propagateNaN; 32 | uiZ = uiA; 33 | goto uiZ; 34 | } 35 | if ( ! expA ) { 36 | uiZ = packToF32UI( signZ, 0, ( uiA + uiB ) & 0x7FFFFFFF ); 37 | goto uiZ; 38 | } 39 | expZ = expA; 40 | sigZ = 0x40000000 + sigA + sigB; 41 | } else { 42 | if ( expDiff < 0 ) { 43 | if ( expB == 0xFF ) { 44 | if ( sigB ) goto propagateNaN; 45 | uiZ = packToF32UI( signZ, 0xFF, 0 ); 46 | goto uiZ; 47 | } 48 | expZ = expB; 49 | sigA += expA ? 0x20000000 : sigA; 50 | sigA = softfloat_shift32RightJam( sigA, - expDiff ); 51 | } else { 52 | if ( expA == 0xFF ) { 53 | if ( sigA ) goto propagateNaN; 54 | uiZ = uiA; 55 | goto uiZ; 56 | } 57 | expZ = expA; 58 | sigB += expB ? 0x20000000 : sigB; 59 | sigB = softfloat_shift32RightJam( sigB, expDiff ); 60 | } 61 | sigZ = 0x20000000 + sigA + sigB; 62 | if ( sigZ < 0x40000000 ) { 63 | --expZ; 64 | sigZ <<= 1; 65 | } 66 | } 67 | return softfloat_roundPackToF32( signZ, expZ, sigZ ); 68 | propagateNaN: 69 | uiZ = softfloat_propagateNaNF32UI( uiA, uiB ); 70 | uiZ: 71 | uZ.ui = uiZ; 72 | return uZ.f; 73 | 74 | } 75 | 76 | -------------------------------------------------------------------------------- /softfloat/s_commonNaNToF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | 6 | /*---------------------------------------------------------------------------- 7 | | Returns the result of converting the canonical NaN `a' to the single- 8 | | precision floating-point format. 9 | *----------------------------------------------------------------------------*/ 10 | 11 | uint_fast32_t softfloat_commonNaNToF32UI( struct commonNaN a ) 12 | { 13 | 14 | return (uint_fast32_t) a.sign<<31 | 0x7FFFFFFF; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /softfloat/s_commonNaNToF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | 6 | /*---------------------------------------------------------------------------- 7 | | Returns the result of converting the canonical NaN `a' to the double- 8 | | precision floating-point format. 9 | *----------------------------------------------------------------------------*/ 10 | 11 | uint_fast64_t softfloat_commonNaNToF64UI( struct commonNaN a ) 12 | { 13 | 14 | return 15 | (uint_fast64_t) a.sign<<63 | UINT64_C( 0x7FFFFFFFFFFFFFFF ); 16 | 17 | } 18 | 19 | -------------------------------------------------------------------------------- /softfloat/s_countLeadingZeros32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "primitives.h" 4 | 5 | int softfloat_countLeadingZeros32( uint32_t a ) 6 | { 7 | int count; 8 | 9 | count = 0; 10 | if ( a < 0x10000 ) { 11 | count = 16; 12 | a <<= 16; 13 | } 14 | if ( a < 0x1000000 ) { 15 | count += 8; 16 | a <<= 8; 17 | } 18 | count += softfloat_countLeadingZeros8[ a>>24 ]; 19 | return count; 20 | 21 | } 22 | 23 | -------------------------------------------------------------------------------- /softfloat/s_countLeadingZeros64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "primitives.h" 4 | #include "platform.h" 5 | 6 | int softfloat_countLeadingZeros64( uint64_t a ) 7 | { 8 | int count; 9 | uint32_t a32; 10 | 11 | count = 32; 12 | a32 = a; 13 | if ( UINT64_C( 0x100000000 ) <= a ) { 14 | count = 0; 15 | a32 = a>>32; 16 | } 17 | /*------------------------------------------------------------------------ 18 | | From here, result is current count + count leading zeros of `a32'. 19 | *------------------------------------------------------------------------*/ 20 | if ( a32 < 0x10000 ) { 21 | count += 16; 22 | a32 <<= 16; 23 | } 24 | if ( a32 < 0x1000000 ) { 25 | count += 8; 26 | a32 <<= 8; 27 | } 28 | count += softfloat_countLeadingZeros8[ a32>>24 ]; 29 | return count; 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /softfloat/s_countLeadingZeros8.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | const uint8_t softfloat_countLeadingZeros8[ 256 ] = { 7 | 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 8 | 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 9 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10 | 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 11 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14 | 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 21 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /softfloat/s_eq128.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | 7 | bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | 10 | return ( a64 == b64 ) && ( a0 == b0 ); 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /softfloat/s_estimateDiv128To64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint64_t softfloat_estimateDiv128To64( uint64_t a64, uint64_t a0, uint64_t b ) 7 | { 8 | uint32_t b32; 9 | uint64_t z; 10 | struct uint128 term, rem; 11 | uint64_t rem32; 12 | 13 | if ( b <= a64 ) return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 14 | b32 = b>>32; 15 | z = ( (uint64_t) b32<<32 <= a64 ) ? UINT64_C( 0xFFFFFFFF00000000 ) 16 | : ( a64 / b32 )<<32; 17 | term = softfloat_mul64To128( b, z ); 18 | rem = softfloat_sub128( a64, a0, term.v64, term.v0 ); 19 | while ( UINT64_C( 0x8000000000000000 ) <= rem.v64 ) { 20 | z -= UINT64_C( 0x100000000 ); 21 | rem = softfloat_add128( rem.v64, rem.v0, b32, (uint64_t) ( b<<32 ) ); 22 | } 23 | rem32 = ( rem.v64<<32 ) | ( rem.v0>>32 ); 24 | z |= ( (uint64_t) b32<<32 <= rem32 ) ? 0xFFFFFFFF : rem32 / b32; 25 | return z; 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /softfloat/s_estimateSqrt32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint32_t softfloat_estimateSqrt32( unsigned int expA, uint32_t a ) 7 | { 8 | static const uint16_t sqrtOddAdjustments[] = { 9 | 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, 10 | 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 11 | }; 12 | static const uint16_t sqrtEvenAdjustments[] = { 13 | 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, 14 | 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 15 | }; 16 | int index; 17 | uint32_t z; 18 | union { uint32_t ui; int32_t i; } u32; 19 | 20 | index = ( a>>27 ) & 15; 21 | if ( expA & 1 ) { 22 | z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; 23 | z = ( ( a / z )<<14 ) + ( z<<15 ); 24 | a >>= 1; 25 | } else { 26 | z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; 27 | z = a / z + z; 28 | z = ( 0x20000 <= z ) ? 0xFFFF8000 : z<<15; 29 | if ( z <= a ) { 30 | u32.ui = a; 31 | return u32.i>>1; 32 | } 33 | } 34 | return (uint32_t) ( ( (uint64_t) a<<31 ) / z ) + ( z>>1 ); 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /softfloat/s_f32UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | #include "softfloat.h" 6 | 7 | /*---------------------------------------------------------------------------- 8 | | Returns the result of converting the single-precision floating-point NaN 9 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 10 | | exception is raised. 11 | *----------------------------------------------------------------------------*/ 12 | struct commonNaN softfloat_f32UIToCommonNaN( uint_fast32_t uiA ) 13 | { 14 | struct commonNaN z; 15 | 16 | if ( softfloat_isSigNaNF32UI( uiA ) ) { 17 | softfloat_raiseFlags( softfloat_flag_invalid ); 18 | } 19 | z.sign = uiA>>31; 20 | z.v64 = (uint_fast64_t) 0x7FFFF <<41; 21 | z.v0 = 0; 22 | return z; 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/s_f64UIToCommonNaN.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "specialize.h" 5 | #include "softfloat.h" 6 | 7 | /*---------------------------------------------------------------------------- 8 | | Returns the result of converting the double-precision floating-point NaN 9 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 10 | | exception is raised. 11 | *----------------------------------------------------------------------------*/ 12 | struct commonNaN softfloat_f64UIToCommonNaN( uint_fast64_t uiA ) 13 | { 14 | struct commonNaN z; 15 | 16 | if ( softfloat_isSigNaNF64UI( uiA ) ) { 17 | softfloat_raiseFlags( softfloat_flag_invalid ); 18 | } 19 | z.sign = uiA>>63; 20 | z.v64 = (uint_fast64_t) 0xFFFFFFFFFFFFF <<12; 21 | z.v0 = 0; 22 | return z; 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/s_isSigNaNF32UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "specialize.h" 6 | 7 | bool softfloat_isSigNaNF32UI( uint_fast32_t ui ) 8 | { 9 | 10 | return ( ( ui>>22 & 0x1FF ) == 0x1FE ) && ( ui & 0x003FFFFF ); 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /softfloat/s_isSigNaNF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "specialize.h" 6 | 7 | bool softfloat_isSigNaNF64UI( uint_fast64_t ui ) 8 | { 9 | 10 | return 11 | ( ( ui>>51 & 0xFFF ) == 0xFFE ) 12 | && ( ui & UINT64_C( 0x0007FFFFFFFFFFFF ) ); 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /softfloat/s_le128.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | 7 | bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | 10 | return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 <= b0 ) ); 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /softfloat/s_lt128.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | 7 | bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | 10 | return ( a64 < b64 ) || ( ( a64 == b64 ) && ( a0 < b0 ) ); 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /softfloat/s_mul128By64To192.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint192 7 | softfloat_mul128By64To192( uint64_t a64, uint64_t a0, uint64_t b ) 8 | { 9 | struct uint128 p0, p64; 10 | struct uint192 z; 11 | 12 | p0 = softfloat_mul64To128( a0, b ); 13 | z.v0 = p0.v0; 14 | p64 = softfloat_mul64To128( a64, b ); 15 | z.v64 = p64.v0 + p0.v64; 16 | z.v128 = p64.v64 + ( z.v64 < p64.v0 ); 17 | return z; 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /softfloat/s_mul128To256.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint256 7 | softfloat_mul128To256( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | struct uint128 p0, p64, p128; 10 | struct uint256 z; 11 | 12 | p0 = softfloat_mul64To128( a0, b0 ); 13 | z.v0 = p0.v0; 14 | p64 = softfloat_mul64To128( a64, b0 ); 15 | z.v64 = p64.v0 + p0.v64; 16 | z.v128 = p64.v64 + ( z.v64 < p64.v0 ); 17 | p128 = softfloat_mul64To128( a64, b64 ); 18 | z.v128 += p128.v0; 19 | z.v192 = p128.v64 + ( z.v128 < p128.v0 ); 20 | p64 = softfloat_mul64To128( a0, b64 ); 21 | z.v64 += p64.v0; 22 | p64.v64 += ( z.v64 < p64.v0 ); 23 | z.v128 += p64.v64; 24 | z.v192 += ( z.v128 < p64.v64 ); 25 | return z; 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /softfloat/s_mul64To128.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 softfloat_mul64To128( uint64_t a, uint64_t b ) 7 | { 8 | uint32_t a32, a0, b32, b0; 9 | struct uint128 z; 10 | uint64_t mid1, mid2, mid; 11 | 12 | a32 = a>>32; 13 | a0 = a; 14 | b32 = b>>32; 15 | b0 = b; 16 | z.v0 = (uint64_t) a0 * b0; 17 | mid1 = (uint64_t) a32 * b0; 18 | mid2 = (uint64_t) a0 * b32; 19 | z.v64 = (uint64_t) a32 * b32; 20 | mid = mid1 + mid2; 21 | z.v64 += ( (uint64_t) ( mid < mid1 ) )<<32 | mid>>32; 22 | mid <<= 32; 23 | z.v0 += mid; 24 | z.v64 += ( z.v0 < mid ); 25 | return z; 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /softfloat/s_normRoundPackToF32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | 8 | float32_t 9 | softfloat_normRoundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) 10 | { 11 | int shiftCount; 12 | union ui32_f32 uZ; 13 | 14 | shiftCount = softfloat_countLeadingZeros32( sig ) - 1; 15 | exp -= shiftCount; 16 | if ( ( 7 <= shiftCount ) && ( (uint16_t) exp < 0xFD ) ) { 17 | uZ.ui = packToF32UI( sign, sig ? exp : 0, sig<<( shiftCount - 7 ) ); 18 | return uZ.f; 19 | } else { 20 | return softfloat_roundPackToF32( sign, exp, sig< 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | 8 | float64_t 9 | softfloat_normRoundPackToF64( bool sign, int_fast16_t exp, uint_fast64_t sig ) 10 | { 11 | int shiftCount; 12 | union ui64_f64 uZ; 13 | 14 | shiftCount = softfloat_countLeadingZeros64( sig ) - 1; 15 | exp -= shiftCount; 16 | if ( ( 10 <= shiftCount ) && ( (uint16_t) exp < 0x7FD ) ) { 17 | uZ.ui = packToF64UI( sign, sig ? exp : 0, sig<<( shiftCount - 10 ) ); 18 | return uZ.f; 19 | } else { 20 | return softfloat_roundPackToF64( sign, exp, sig< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | 7 | struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t sig ) 8 | { 9 | int shiftCount; 10 | struct exp16_sig32 z; 11 | 12 | shiftCount = softfloat_countLeadingZeros32( sig ) - 8; 13 | z.exp = 1 - shiftCount; 14 | z.sig = sig< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | 7 | struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t sig ) 8 | { 9 | int shiftCount; 10 | struct exp16_sig64 z; 11 | 12 | shiftCount = softfloat_countLeadingZeros64( sig ) - 11; 13 | z.exp = 1 - shiftCount; 14 | z.sig = sig< 5 | #include 6 | #include "platform.h" 7 | #include "internals.h" 8 | #include "specialize.h" 9 | #include "softfloat.h" 10 | 11 | /*---------------------------------------------------------------------------- 12 | | Takes two single-precision floating-point values `a' and `b', one of which 13 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 14 | | signaling NaN, the invalid exception is raised. 15 | *----------------------------------------------------------------------------*/ 16 | 17 | uint_fast32_t 18 | softfloat_propagateNaNF32UI( uint_fast32_t uiA, uint_fast32_t uiB ) 19 | { 20 | if ( softfloat_isSigNaNF32UI( uiA ) | softfloat_isSigNaNF32UI( uiB ) ) { 21 | softfloat_raiseFlags( softfloat_flag_invalid ); 22 | } 23 | return defaultNaNF32UI; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/s_propagateNaNF64UI.c: -------------------------------------------------------------------------------- 1 | 2 | /*** UPDATE COMMENTS. ***/ 3 | 4 | #include 5 | #include 6 | #include "platform.h" 7 | #include "internals.h" 8 | #include "specialize.h" 9 | #include "softfloat.h" 10 | 11 | /*---------------------------------------------------------------------------- 12 | | Takes two double-precision floating-point values `a' and `b', one of which 13 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 14 | | signaling NaN, the invalid exception is raised. 15 | *----------------------------------------------------------------------------*/ 16 | 17 | uint_fast64_t 18 | softfloat_propagateNaNF64UI( uint_fast64_t uiA, uint_fast64_t uiB ) 19 | { 20 | if ( softfloat_isSigNaNF64UI( uiA ) | softfloat_isSigNaNF64UI( uiB ) ) { 21 | softfloat_raiseFlags( softfloat_flag_invalid ); 22 | } 23 | return defaultNaNF64UI; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/s_roundPackToF32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "primitives.h" 6 | #include "internals.h" 7 | #include "softfloat.h" 8 | 9 | float32_t 10 | softfloat_roundPackToF32( bool sign, int_fast16_t exp, uint_fast32_t sig ) 11 | { 12 | int roundingMode; 13 | bool roundNearestEven; 14 | int roundIncrement, roundBits; 15 | bool isTiny; 16 | uint_fast32_t uiZ; 17 | union ui32_f32 uZ; 18 | 19 | roundingMode = softfloat_roundingMode; 20 | roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); 21 | roundIncrement = 0x40; 22 | if ( 23 | ! roundNearestEven 24 | && ( roundingMode != softfloat_round_nearest_maxMag ) 25 | ) { 26 | roundIncrement = 27 | ( roundingMode == softfloat_round_minMag ) 28 | || ( roundingMode 29 | == ( sign ? softfloat_round_max : softfloat_round_min ) ) 30 | ? 0 31 | : 0x7F; 32 | } 33 | roundBits = sig & 0x7F; 34 | if ( 0xFD <= (uint16_t) exp ) { 35 | if ( exp < 0 ) { 36 | isTiny = 37 | ( softfloat_detectTininess 38 | == softfloat_tininess_beforeRounding ) 39 | || ( exp < -1 ) 40 | || ( sig + roundIncrement < 0x80000000 ); 41 | sig = softfloat_shift32RightJam( sig, - exp ); 42 | exp = 0; 43 | roundBits = sig & 0x7F; 44 | if ( isTiny && roundBits ) { 45 | softfloat_raiseFlags( softfloat_flag_underflow ); 46 | } 47 | } else if ( 48 | ( 0xFD < exp ) || ( 0x80000000 <= sig + roundIncrement ) 49 | ) { 50 | softfloat_raiseFlags( 51 | softfloat_flag_overflow | softfloat_flag_inexact ); 52 | uiZ = packToF32UI( sign, 0xFF, 0 ) - ! roundIncrement; 53 | goto uiZ; 54 | } 55 | } 56 | if ( roundBits ) softfloat_raiseFlags( softfloat_flag_inexact ); 57 | sig = ( sig + roundIncrement )>>7; 58 | sig &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); 59 | uiZ = packToF32UI( sign, sig ? exp : 0, sig ); 60 | uiZ: 61 | uZ.ui = uiZ; 62 | return uZ.f; 63 | 64 | } 65 | 66 | -------------------------------------------------------------------------------- /softfloat/s_roundPackToI32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast32_t 9 | softfloat_roundPackToI32( 10 | bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) 11 | { 12 | bool roundNearestEven; 13 | int roundIncrement, roundBits; 14 | uint_fast32_t sig32; 15 | union { uint32_t ui; int32_t i; } uZ; 16 | int_fast32_t z; 17 | 18 | roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); 19 | roundIncrement = 0x40; 20 | if ( 21 | ! roundNearestEven 22 | && ( roundingMode != softfloat_round_nearest_maxMag ) 23 | ) { 24 | roundIncrement = 25 | ( roundingMode == softfloat_round_minMag ) 26 | || ( roundingMode 27 | == ( sign ? softfloat_round_max : softfloat_round_min ) ) 28 | ? 0 29 | : 0x7F; 30 | } 31 | roundBits = sig & 0x7F; 32 | sig += roundIncrement; 33 | if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; 34 | sig32 = sig>>7; 35 | sig32 &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); 36 | uZ.ui = sign ? - sig32 : sig32; 37 | z = uZ.i; 38 | if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; 39 | if ( exact && roundBits ) { 40 | softfloat_raiseFlags( softfloat_flag_inexact ); 41 | } 42 | return z; 43 | invalid: 44 | softfloat_raiseFlags( softfloat_flag_invalid ); 45 | return sign ? -0x7FFFFFFF - 1 : 0x7FFFFFFF; 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /softfloat/s_roundPackToI64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | int_fast64_t 9 | softfloat_roundPackToI64( 10 | bool sign, 11 | uint_fast64_t sig64, 12 | uint_fast64_t sig0, 13 | int_fast8_t roundingMode, 14 | bool exact 15 | ) 16 | { 17 | bool roundNearestEven, increment; 18 | union { uint64_t ui; int64_t i; } uZ; 19 | int_fast64_t z; 20 | 21 | roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); 22 | increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); 23 | if ( 24 | ! roundNearestEven 25 | && ( roundingMode != softfloat_round_nearest_maxMag ) 26 | ) { 27 | increment = 28 | ( roundingMode != softfloat_round_minMag ) 29 | && ( roundingMode 30 | == ( sign ? softfloat_round_min : softfloat_round_max ) ) 31 | && sig0; 32 | } 33 | if ( increment ) { 34 | ++sig64; 35 | if ( ! sig64 ) goto invalid; 36 | sig64 &= 37 | ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 38 | & roundNearestEven ); 39 | } 40 | uZ.ui = sign ? - sig64 : sig64; 41 | z = uZ.i; 42 | if ( z && ( ( z < 0 ) ^ sign ) ) goto invalid; 43 | if ( exact && sig0 ) softfloat_raiseFlags( softfloat_flag_inexact ); 44 | return z; 45 | invalid: 46 | softfloat_raiseFlags( softfloat_flag_invalid ); 47 | return 48 | sign ? - INT64_C( 0x7FFFFFFFFFFFFFFF ) - 1 49 | : INT64_C( 0x7FFFFFFFFFFFFFFF ); 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /softfloat/s_roundPackToUI32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast32_t 9 | softfloat_roundPackToUI32( 10 | bool sign, uint_fast64_t sig, int_fast8_t roundingMode, bool exact ) 11 | { 12 | bool roundNearestEven; 13 | int roundIncrement, roundBits; 14 | uint_fast32_t z; 15 | 16 | roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); 17 | roundIncrement = 0x40; 18 | if ( 19 | ! roundNearestEven 20 | && ( roundingMode != softfloat_round_nearest_maxMag ) 21 | ) { 22 | roundIncrement = 23 | ( roundingMode == softfloat_round_minMag ) 24 | || ( roundingMode 25 | == ( sign ? softfloat_round_max : softfloat_round_min ) ) 26 | ? 0 27 | : 0x7F; 28 | } 29 | roundBits = sig & 0x7F; 30 | sig += roundIncrement; 31 | if ( sig & UINT64_C( 0xFFFFFF8000000000 ) ) goto invalid; 32 | z = sig>>7; 33 | z &= ~ ( ! ( roundBits ^ 0x40 ) & roundNearestEven ); 34 | if ( sign && z ) goto invalid; 35 | if ( exact && roundBits ) { 36 | softfloat_raiseFlags( softfloat_flag_inexact ); 37 | } 38 | return z; 39 | invalid: 40 | softfloat_raiseFlags( softfloat_flag_invalid ); 41 | return 0xFFFFFFFF; 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /softfloat/s_roundPackToUI64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "platform.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | uint_fast64_t 9 | softfloat_roundPackToUI64( 10 | bool sign, 11 | uint_fast64_t sig64, 12 | uint_fast64_t sig0, 13 | int_fast8_t roundingMode, 14 | bool exact 15 | ) 16 | { 17 | bool roundNearestEven, increment; 18 | 19 | roundNearestEven = ( roundingMode == softfloat_round_nearest_even ); 20 | increment = ( UINT64_C( 0x8000000000000000 ) <= sig0 ); 21 | if ( 22 | ! roundNearestEven 23 | && ( roundingMode != softfloat_round_nearest_maxMag ) 24 | ) { 25 | increment = 26 | ( roundingMode != softfloat_round_minMag ) 27 | && ( roundingMode 28 | == ( sign ? softfloat_round_min : softfloat_round_max ) ) 29 | && sig0; 30 | } 31 | if ( increment ) { 32 | ++sig64; 33 | if ( ! sig64 ) goto invalid; 34 | sig64 &= 35 | ~ ( ! ( sig0 & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) 36 | & roundNearestEven ); 37 | } 38 | if ( sign && sig64 ) goto invalid; 39 | if ( exact && sig0 ) softfloat_raiseFlags( softfloat_flag_inexact ); 40 | return sig64; 41 | invalid: 42 | softfloat_raiseFlags( softfloat_flag_invalid ); 43 | return UINT64_C( 0xFFFFFFFFFFFFFFFF ); 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /softfloat/s_shift128ExtraRightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128_extra 7 | softfloat_shift128ExtraRightJam( 8 | uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) 9 | { 10 | unsigned int negCount; 11 | struct uint128_extra z; 12 | 13 | negCount = - count; 14 | if ( count < 64 ) { 15 | z.v64 = a64>>count; 16 | z.v0 = a64<<( negCount & 63 ) | a0>>count; 17 | z.extra = a0<<( negCount & 63 ); 18 | } else { 19 | z.v64 = 0; 20 | if ( count == 64 ) { 21 | z.v0 = a64; 22 | z.extra = a0; 23 | } else { 24 | extra |= a0; 25 | if ( count < 128 ) { 26 | z.v0 = a64>>( count & 63 ); 27 | z.extra = a64<<( negCount & 63 ); 28 | } else { 29 | z.v0 = 0; 30 | z.extra = ( count == 128 ) ? a64 : ( a64 != 0 ); 31 | } 32 | } 33 | } 34 | z.extra |= ( extra != 0 ); 35 | return z; 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /softfloat/s_shift128RightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 7 | softfloat_shift128RightJam( uint64_t a64, uint64_t a0, unsigned int count ) 8 | { 9 | unsigned int negCount; 10 | struct uint128 z; 11 | 12 | if ( count < 64 ) { 13 | negCount = - count; 14 | z.v64 = a64>>( count & 63 ); 15 | z.v0 = 16 | a64<<( negCount & 63 ) | a0>>count 17 | | ( (uint64_t) ( a0<<( negCount & 63 ) ) != 0 ); 18 | } else { 19 | z.v64 = 0; 20 | z.v0 = 21 | ( count < 128 ) 22 | ? a64>>( count & 63 ) 23 | | ( ( ( a64 & ( ( (uint64_t) 1<<( count & 63 ) ) - 1 ) ) 24 | | a0 ) 25 | != 0 ) 26 | : ( ( a64 | a0 ) != 0 ); 27 | } 28 | return z; 29 | 30 | } 31 | 32 | -------------------------------------------------------------------------------- /softfloat/s_shift32RightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint32_t softfloat_shift32RightJam( uint32_t a, unsigned int count ) 7 | { 8 | 9 | return 10 | ( count < 32 ) 11 | ? a>>count | ( (uint32_t) ( a<<( ( - count ) & 31 ) ) != 0 ) 12 | : ( a != 0 ); 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /softfloat/s_shift64ExtraRightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint64_extra 7 | softfloat_shift64ExtraRightJam( 8 | uint64_t a, uint64_t extra, unsigned int count ) 9 | { 10 | struct uint64_extra z; 11 | 12 | if ( count < 64 ) { 13 | z.v = a>>count; 14 | z.extra = a<<( ( - count ) & 63 ); 15 | } else { 16 | z.v = 0; 17 | z.extra = ( count == 64 ) ? a : ( a != 0 ); 18 | } 19 | z.extra |= ( extra != 0 ); 20 | return z; 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /softfloat/s_shift64RightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint64_t softfloat_shift64RightJam( uint64_t a, unsigned int count ) 7 | { 8 | 9 | return 10 | ( count < 64 ) 11 | ? a>>count | ( (uint64_t) ( a<<( ( - count ) & 63 ) ) != 0 ) 12 | : ( a != 0 ); 13 | 14 | } 15 | 16 | -------------------------------------------------------------------------------- /softfloat/s_shortShift128ExtraRightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128_extra 7 | softfloat_shortShift128ExtraRightJam( 8 | uint64_t a64, uint64_t a0, uint64_t extra, unsigned int count ) 9 | { 10 | unsigned int negCount; 11 | struct uint128_extra z; 12 | 13 | negCount = - count; 14 | z.v64 = a64>>count; 15 | z.v0 = a64<<( negCount & 63 ) | a0>>count; 16 | z.extra = a0<<( negCount & 63 ) | ( extra != 0 ); 17 | return z; 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /softfloat/s_shortShift128Left.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 7 | softfloat_shortShift128Left( uint64_t a64, uint64_t a0, unsigned int count ) 8 | { 9 | struct uint128 z; 10 | 11 | z.v64 = a64<>( ( - count ) & 63 ); 12 | z.v0 = a0< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 7 | softfloat_shortShift128Right( uint64_t a64, uint64_t a0, unsigned int count ) 8 | { 9 | struct uint128 z; 10 | 11 | z.v64 = a64>>count; 12 | z.v0 = a64<<( ( - count ) & 63 ) | a0>>count; 13 | return z; 14 | 15 | } 16 | 17 | -------------------------------------------------------------------------------- /softfloat/s_shortShift192Left.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint192 7 | softfloat_shortShift192Left( 8 | uint64_t a128, uint64_t a64, uint64_t a0, unsigned int count ) 9 | { 10 | unsigned int negCount; 11 | struct uint192 z; 12 | 13 | negCount = - count; 14 | z.v128 = a128<>( negCount & 63 ); 15 | z.v64 = a64<>( negCount & 63 ); 16 | z.v0 = a0< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint32_t softfloat_shortShift32Right1Jam( uint32_t a ) 7 | { 8 | 9 | return a>>1 | ( a & 1 ); 10 | 11 | } 12 | 13 | -------------------------------------------------------------------------------- /softfloat/s_shortShift64ExtraRightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint64_extra 7 | softfloat_shortShift64ExtraRightJam( 8 | uint64_t a, uint64_t extra, unsigned int count ) 9 | { 10 | struct uint64_extra z; 11 | 12 | z.v = a>>count; 13 | z.extra = a<<( ( - count ) & 63 ) | ( extra != 0 ); 14 | return z; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /softfloat/s_shortShift64RightJam.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | uint64_t softfloat_shortShift64RightJam( uint64_t a, unsigned int count ) 7 | { 8 | 9 | return a>>count | ( ( a & ( ( (uint64_t) 1< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint128 7 | softfloat_sub128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) 8 | { 9 | struct uint128 z; 10 | 11 | z.v0 = a0 - b0; 12 | z.v64 = a64 - b64; 13 | z.v64 -= ( a0 < b0 ); 14 | return z; 15 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /softfloat/s_sub192.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | 6 | struct uint192 7 | softfloat_sub192( 8 | uint64_t a128, 9 | uint64_t a64, 10 | uint64_t a0, 11 | uint64_t b128, 12 | uint64_t b64, 13 | uint64_t b0 14 | ) 15 | { 16 | struct uint192 z; 17 | unsigned int borrow64, borrow128; 18 | 19 | z.v0 = a0 - b0; 20 | borrow64 = ( a0 < b0 ); 21 | z.v64 = a64 - b64; 22 | borrow128 = ( a64 < b64 ); 23 | z.v128 = a128 - b128; 24 | borrow128 += ( z.v64 < borrow64 ); 25 | z.v64 -= borrow64; 26 | z.v128 -= borrow128; 27 | return z; 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /softfloat/softfloat.ac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/softfloat/softfloat.ac -------------------------------------------------------------------------------- /softfloat/softfloat_types.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef softfloat_types_h 3 | #define softfloat_types_h 4 | 5 | /*** COMMENTS. ***/ 6 | 7 | #include 8 | #include 9 | 10 | typedef uint32_t float32_t; 11 | typedef uint64_t float64_t; 12 | typedef struct { uint64_t v; uint16_t x; } floatx80_t; 13 | typedef struct { uint64_t v[ 2 ]; } float128_t; 14 | 15 | #define INLINE inline 16 | #define INLINE_LEVEL 1 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /softfloat/ui32_to_f32.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float32_t ui32_to_f32( uint_fast32_t a ) 9 | { 10 | union ui32_f32 uZ; 11 | 12 | if ( ! a ) { 13 | uZ.ui = 0; 14 | return uZ.f; 15 | } 16 | if ( a & 0x80000000 ) { 17 | return 18 | softfloat_roundPackToF32( 19 | 0, 0x9D, softfloat_shortShift32Right1Jam( a ) ); 20 | } else { 21 | return softfloat_normRoundPackToF32( 0, 0x9C, a ); 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /softfloat/ui32_to_f64.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float64_t ui32_to_f64( uint_fast32_t a ) 9 | { 10 | uint_fast64_t uiZ; 11 | int shiftCount; 12 | union ui64_f64 uZ; 13 | 14 | if ( ! a ) { 15 | uiZ = 0; 16 | } else { 17 | shiftCount = softfloat_countLeadingZeros32( a ) + 21; 18 | uiZ = 19 | packToF64UI( 20 | 0, 0x432 - shiftCount, (uint_fast64_t) a< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float32_t ui64_to_f32( uint_fast64_t a ) 9 | { 10 | int shiftCount; 11 | union ui32_f32 u; 12 | uint_fast32_t sig; 13 | 14 | shiftCount = softfloat_countLeadingZeros64( a ) - 40; 15 | if ( 0 <= shiftCount ) { 16 | u.ui = 17 | a ? packToF32UI( 18 | 0, 0x95 - shiftCount, (uint_fast32_t) a< 3 | #include "platform.h" 4 | #include "primitives.h" 5 | #include "internals.h" 6 | #include "softfloat.h" 7 | 8 | float64_t ui64_to_f64( uint_fast64_t a ) 9 | { 10 | union ui64_f64 uZ; 11 | 12 | if ( ! a ) { 13 | uZ.ui = 0; 14 | return uZ.f; 15 | } 16 | if ( a & UINT64_C( 0x8000000000000000 ) ) { 17 | return 18 | softfloat_roundPackToF64( 19 | 0, 0x43D, softfloat_shortShift64RightJam( a, 1 ) ); 20 | } else { 21 | return softfloat_normRoundPackToF64( 0, 0x43C, a ); 22 | } 23 | 24 | } 25 | 26 | -------------------------------------------------------------------------------- /test-sm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | mkdir -p test-build 5 | cd test-build 6 | 7 | if [ ! -f Makefile ]; then 8 | ../configure --host=riscv64-unknown-linux-gnu --enable-sm_rs 9 | fi 10 | make -j12 RUST_TARGET=../riscv64gc-unknown-none-elfhf.json 11 | 12 | export RUSTFLAGS="-Z pre-link-arg=-L$(pwd) -Z pre-link-arg=-lsm_rs_Clib -C link-arg=-Wl,--start-group -C link-arg=-lmachine -C link-arg=-lutil -C link-arg=-lsm_rs_Clib -C link-arg=-Wl,--end-group" 13 | export CFLAGS='-DTARGET_PLATFORM_HEADER="platform/default/default.h"' 14 | cargo +nightly xtest --target-dir sm_rs/ --target ../riscv64gc-unknown-linux-gnuhf.json --manifest-path=../sm_rs/Cargo.toml 15 | 16 | -------------------------------------------------------------------------------- /util/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "util" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | [lib] 7 | path = "lib.rs" 8 | 9 | -------------------------------------------------------------------------------- /util/bitfield.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! insert_field { 3 | ($val:expr, $which:expr, $fieldval:expr) => ( 4 | (($val & !$which) | ($fieldval * ($which & !($which-1)))) 5 | ) 6 | } 7 | -------------------------------------------------------------------------------- /util/string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void* __attribute__((weak)) memcpy(void* dest, const void* src, size_t len) 6 | { 7 | const char* s = src; 8 | char *d = dest; 9 | 10 | if ((((uintptr_t)dest | (uintptr_t)src) & (sizeof(uintptr_t)-1)) == 0) { 11 | while ((void*)d < (dest + len - (sizeof(uintptr_t)-1))) { 12 | *(uintptr_t*)d = *(const uintptr_t*)s; 13 | d += sizeof(uintptr_t); 14 | s += sizeof(uintptr_t); 15 | } 16 | } 17 | 18 | while (d < (char*)(dest + len)) 19 | *d++ = *s++; 20 | 21 | return dest; 22 | } 23 | 24 | void* __attribute__((weak)) memset(void* dest, int byte, size_t len) 25 | { 26 | if ((((uintptr_t)dest | len) & (sizeof(uintptr_t)-1)) == 0) { 27 | uintptr_t word = byte & 0xFF; 28 | word |= word << 8; 29 | word |= word << 16; 30 | word |= word << 16 << 16; 31 | 32 | uintptr_t *d = dest; 33 | while (d < (uintptr_t*)(dest + len)) 34 | *d++ = word; 35 | } else { 36 | char *d = dest; 37 | while (d < (char*)(dest + len)) 38 | *d++ = byte; 39 | } 40 | return dest; 41 | } 42 | 43 | size_t strlen(const char *s) 44 | { 45 | const char *p = s; 46 | while (*p) 47 | p++; 48 | return p - s; 49 | } 50 | 51 | int strcmp(const char* s1, const char* s2) 52 | { 53 | unsigned char c1, c2; 54 | 55 | do { 56 | c1 = *s1++; 57 | c2 = *s2++; 58 | } while (c1 != 0 && c1 == c2); 59 | 60 | return c1 - c2; 61 | } 62 | 63 | char* strcpy(char* dest, const char* src) 64 | { 65 | char* d = dest; 66 | while ((*d++ = *src++)) 67 | ; 68 | return dest; 69 | } 70 | 71 | long atol(const char* str) 72 | { 73 | long res = 0; 74 | int sign = 0; 75 | 76 | while (*str == ' ') 77 | str++; 78 | 79 | if (*str == '-' || *str == '+') { 80 | sign = *str == '-'; 81 | str++; 82 | } 83 | 84 | while (*str) { 85 | res *= 10; 86 | res += *str++ - '0'; 87 | } 88 | 89 | return sign ? -res : res; 90 | } 91 | -------------------------------------------------------------------------------- /util/util.ac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keystone-enclave/riscv-pk/f855a56f919142a0fa9987be79a3c1ad09384e66/util/util.ac -------------------------------------------------------------------------------- /util/util.mk.in: -------------------------------------------------------------------------------- 1 | util_subproject_deps = \ 2 | 3 | util_hdrs = \ 4 | 5 | util_c_srcs = \ 6 | snprintf.c \ 7 | string.c \ 8 | 9 | util_asm_srcs = \ 10 | --------------------------------------------------------------------------------