source: trunk/lib/bitblock128.hpp @ 2039

Last change on this file since 2039 was 1996, checked in by cameron, 7 years ago

Functions with separate parameters for carry-in and carry-out.

File size: 5.2 KB
RevLine 
[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]17union 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. */
26typedef bitblock128_t carry_t;
27
28static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry);
29static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry);
30
31static IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum);
32static IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference);
33static IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt);
34
[1996]35static IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t carry_in, carry_t & carry_out, bitblock128_t & sum);
36static IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t borrow_in, carry_t & borrow_out, bitblock128_t & difference);
37static IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t carry_in, carry_t & carry_out, bitblock128_t & rslt);
38
[1542]39static IDISA_ALWAYS_INLINE bitblock128_t convert (uint64_t s);
40static IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v);
[1527]41
[1975]42static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry) {  return carry;} 
43static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry) {  return carry;}
44
45IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum)
[1542]46{
47        bitblock128_t gen = simd_and(x, y);
48        bitblock128_t prop = simd_or(x, y);
[1975]49        bitblock128_t partial = simd128<64>::add(simd128<64>::add(x, y), carry2bitblock(carry));
[1550]50        bitblock128_t c1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_andc(prop, partial))));
51        sum = simd128<64>::add(c1, partial);
[1975]52        carry = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_andc(prop, sum))));
[1542]53}
54
[1996]55IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t carry_in, carry_t & carry_out, bitblock128_t & sum)
56{
57        bitblock128_t gen = simd_and(x, y);
58        bitblock128_t prop = simd_or(x, y);
59        bitblock128_t partial = simd128<64>::add(simd128<64>::add(x, y), carry2bitblock(carry_in));
60        bitblock128_t c1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_andc(prop, partial))));
61        sum = simd128<64>::add(c1, partial);
62        carry_out = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_andc(prop, sum))));
63}
64
[1975]65IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference)
[1542]66{
67        bitblock128_t gen = simd_andc(y, x);
68        bitblock128_t prop = simd_not(simd_xor(x, y));
[1975]69        bitblock128_t partial = simd128<64>::sub(simd128<64>::sub(x, y), carry2bitblock(borrow));
[1550]70        bitblock128_t b1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_and(prop, partial))));
71        difference = simd128<64>::sub(partial, b1);
[1975]72        borrow = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_and(prop, difference))));
[1542]73}
74
[1996]75IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t borrow_in, carry_t & borrow_out, bitblock128_t & difference)
76{
77        bitblock128_t gen = simd_andc(y, x);
78        bitblock128_t prop = simd_not(simd_xor(x, y));
79        bitblock128_t partial = simd128<64>::sub(simd128<64>::sub(x, y), carry2bitblock(borrow_in));
80        bitblock128_t b1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_and(prop, partial))));
81        difference = simd128<64>::sub(partial, b1);
82        borrow_out = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_and(prop, difference))));
83}
84
[1975]85IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt)
[1542]86{
[1550]87bitblock128_t shift_out = simd128<64>::srli<63>(cursor);
[1975]88bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry2bitblock(carry));
89carry = bitblock2carry(simd128<128>::srli<64>(shift_out));
[1550]90rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits);
[1542]91}
92
[1996]93IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t carry_in, carry_t & carry_out, bitblock128_t & rslt)
94{
95bitblock128_t shift_out = simd128<64>::srli<63>(cursor);
96bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry2bitblock(carry_in));
97carry_out = bitblock2carry(simd128<128>::srli<64>(shift_out));
98rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits);
99}
100
[1542]101IDISA_ALWAYS_INLINE bitblock128_t convert(uint64_t s)
102{
[1815]103        ubitblock b = {b._128 = simd128<128>::constant<0>()}; // = {0};
[1542]104        b._64[0] = s;
105        return b._128;
106}
107
108IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v)
109{
[1550]110        return (uint64_t) mvmd128<64>::extract<0>(v);
[1542]111}
112
[1950]113#endif // BITBLOCK128_HPP_
Note: See TracBrowser for help on using the repository browser.