[1950] | 1 | #ifndef BITBLOCK128_HPP_ |
---|
| 2 | #define BITBLOCK128_HPP_ |
---|
| 3 | /*============================================================================= |
---|
[1550] | 4 | bitblock128 - Specific 128 bit IDISA implementations. |
---|
[1503] | 5 | |
---|
| 6 | Idealized SIMD Operations with SSE versions |
---|
| 7 | Copyright (C) 2011, Robert D. Cameron, Kenneth S. Herdy, Hua Huang and Nigel Medforth. |
---|
| 8 | Licensed to the public under the Open Software License 3.0. |
---|
| 9 | Licensed to International Characters Inc. |
---|
| 10 | under the Academic Free License version 3.0. |
---|
| 11 | |
---|
[1950] | 12 | =============================================================================*/ |
---|
[1503] | 13 | |
---|
[1550] | 14 | #include "idisa128.hpp" |
---|
[1555] | 15 | #include "builtins.hpp" |
---|
[1550] | 16 | |
---|
[1815] | 17 | union ubitblock { |
---|
[1550] | 18 | bitblock128_t _128; |
---|
| 19 | uint64_t _64[sizeof(bitblock128_t)/sizeof(uint64_t)]; |
---|
| 20 | uint32_t _32[sizeof(bitblock128_t)/sizeof(uint32_t)]; |
---|
| 21 | uint16_t _16[sizeof(bitblock128_t)/sizeof(uint16_t)]; |
---|
| 22 | uint8_t _8[sizeof(bitblock128_t)/sizeof(uint8_t)]; |
---|
| 23 | }; |
---|
| 24 | |
---|
[1975] | 25 | /* The type used to store a carry bit. */ |
---|
| 26 | typedef bitblock128_t carry_t; |
---|
| 27 | |
---|
| 28 | static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry); |
---|
| 29 | static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry); |
---|
| 30 | |
---|
| 31 | static IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum); |
---|
| 32 | static IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference); |
---|
| 33 | static IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt); |
---|
| 34 | |
---|
[1542] | 35 | static IDISA_ALWAYS_INLINE bitblock128_t convert (uint64_t s); |
---|
| 36 | static IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v); |
---|
[1527] | 37 | |
---|
[1975] | 38 | static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry) { return carry;} |
---|
| 39 | static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry) { return carry;} |
---|
| 40 | |
---|
| 41 | IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum) |
---|
[1542] | 42 | { |
---|
| 43 | bitblock128_t gen = simd_and(x, y); |
---|
| 44 | bitblock128_t prop = simd_or(x, y); |
---|
[1975] | 45 | bitblock128_t partial = simd128<64>::add(simd128<64>::add(x, y), carry2bitblock(carry)); |
---|
[1550] | 46 | bitblock128_t c1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_andc(prop, partial)))); |
---|
| 47 | sum = simd128<64>::add(c1, partial); |
---|
[1975] | 48 | carry = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_andc(prop, sum)))); |
---|
[1542] | 49 | } |
---|
| 50 | |
---|
[1975] | 51 | IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference) |
---|
[1542] | 52 | { |
---|
| 53 | bitblock128_t gen = simd_andc(y, x); |
---|
| 54 | bitblock128_t prop = simd_not(simd_xor(x, y)); |
---|
[1975] | 55 | bitblock128_t partial = simd128<64>::sub(simd128<64>::sub(x, y), carry2bitblock(borrow)); |
---|
[1550] | 56 | bitblock128_t b1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_and(prop, partial)))); |
---|
| 57 | difference = simd128<64>::sub(partial, b1); |
---|
[1975] | 58 | borrow = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_and(prop, difference)))); |
---|
[1542] | 59 | } |
---|
| 60 | |
---|
[1975] | 61 | IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt) |
---|
[1542] | 62 | { |
---|
[1550] | 63 | bitblock128_t shift_out = simd128<64>::srli<63>(cursor); |
---|
[1975] | 64 | bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry2bitblock(carry)); |
---|
| 65 | carry = bitblock2carry(simd128<128>::srli<64>(shift_out)); |
---|
[1550] | 66 | rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits); |
---|
[1542] | 67 | } |
---|
| 68 | |
---|
| 69 | IDISA_ALWAYS_INLINE bitblock128_t convert(uint64_t s) |
---|
| 70 | { |
---|
[1815] | 71 | ubitblock b = {b._128 = simd128<128>::constant<0>()}; // = {0}; |
---|
[1542] | 72 | b._64[0] = s; |
---|
| 73 | return b._128; |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v) |
---|
| 77 | { |
---|
[1550] | 78 | return (uint64_t) mvmd128<64>::extract<0>(v); |
---|
[1542] | 79 | } |
---|
| 80 | |
---|
[1950] | 81 | #endif // BITBLOCK128_HPP_ |
---|