diff --git a/hardy.nim b/hardy.nim index 7bdfe4f..92d5105 100644 --- a/hardy.nim +++ b/hardy.nim @@ -1,6 +1,6 @@ -# hardy +# Hardy # Copyright (c) 2018 Status Research & Development GmbH # Licensed and distributed under either of # * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). -# at your option. This file may not be copied, modified, or distributed except according to those terms. \ No newline at end of file +# at your option. This file may not be copied, modified, or distributed except according to those terms. diff --git a/hardy/bool_primitives.nim b/hardy/bool_primitives.nim new file mode 100644 index 0000000..168fc4e --- /dev/null +++ b/hardy/bool_primitives.nim @@ -0,0 +1,45 @@ +# Hardy +# Copyright (c) 2018 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +import ./datatypes + +# ################################ +# +# Constant-time boolean primitives +# +# ################################ + +# The main challenge is to prevent conditional branch/jump +# in the generated assembly. +# +# Note: +# let x = if true: 1 else: 2 +# +# does not guarantee a constant-time conditional move +# The compiler might introduce branching. + +# These primitives are internal to Hardy. +# We don't want to pollute unsuspecting users +# with `not` and `-` on unsigned ints + +func high*(T: typedesc[HardBase]): T {.inline.}= + result = not T(0) + +func `not`*[T: HardBase](ctl: HardBool[T]): HardBool[T] {.inline.}= + ## Negate a constant-time boolean + result = ctl xor 1.T + +func `-`*(x: HardBase): HardBase {.inline.}= + ## Unary minus returns the two-complement representation + ## of an unsigned integer + const max = high(type x) + result = (max xor x) + 1 + +func mux*[T: HardBase](ctl: HardBool[T], x, y: T): T {.inline.}= + ## Returns x if ctl == 1 + ## else returns y + result = y xor (-ctl.HardBase and (x xor y)) diff --git a/hardy/datatypes.nim b/hardy/datatypes.nim new file mode 100644 index 0000000..7115afb --- /dev/null +++ b/hardy/datatypes.nim @@ -0,0 +1,23 @@ +# Hardy +# Copyright (c) 2018 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +type + HardBase* = SomeUnsignedInt or byte + + HardBool*[T: HardBase] = range[T(0)..T(1)] + ## To avoid the compiler replacing bitwise boolean operations + ## by conditional branches, we don't use booleans. + ## We use an int to prevent compiler "optimization" and introduction of branches + + Hard*[T: HardBase] = distinct openarray[T] + ## Hardy primitives are memory-backend agnostic. + ## Hardy integers can be stored in an opaque stack array + ## or a seq or even a string. + ## + ## Allocations is left to the client library. + ## Note that constant-time allocation is very involved for + ## heap-allocated types (i.e. requires a memory pool)