source: trunk/lib_ir/bitblock128.hpp @ 4044

Last change on this file since 4044 was 3909, checked in by linmengl, 5 years ago

initial commit of lib_ir

File size: 6.6 KB
Line 
1#ifndef BITBLOCK128_HPP_
2#define BITBLOCK128_HPP_
3/*=============================================================================
4    bitblock128 - Specific 128 bit IDISA implementations.
5
6    Copyright (C) 2011, Robert D. Cameron, Kenneth S. Herdy, Hua Huang and Nigel Medforth.
7    Licensed to the public under the Open Software License 3.0.
8    Licensed to International Characters Inc.
9       under the Academic Free License version 3.0.
10
11=============================================================================*/
12
13#include "idisa128.hpp"
14#include "builtins.hpp"
15
16union ubitblock {
17    bitblock128_t _bitblock;
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
25static IDISA_ALWAYS_INLINE void add_ci_co(bitblock128_t x, bitblock128_t y, bitblock128_t carry_in, bitblock128_t & carry_out, bitblock128_t & sum);
26static IDISA_ALWAYS_INLINE void sub_bi_bo(bitblock128_t x, bitblock128_t y, bitblock128_t borrow_in, bitblock128_t & borrow_out, bitblock128_t & difference);
27static IDISA_ALWAYS_INLINE void adv_ci_co(bitblock128_t cursor, bitblock128_t carry_in, bitblock128_t & carry_out, bitblock128_t & rslt);
28
29/* The type used to store a carry bit. */
30typedef bitblock128_t carry_t;
31
32
33
34
35
36static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry);
37static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry);
38
39static IDISA_ALWAYS_INLINE carry_t carryout2carry(bitblock128_t carryout);
40
41static IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum);
42static IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference);
43static IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt);
44
45static IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t carry_in, carry_t & carry_out, bitblock128_t & sum);
46static IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t borrow_in, carry_t & borrow_out, bitblock128_t & difference);
47static IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t carry_in, carry_t & carry_out, bitblock128_t & rslt);
48
49static IDISA_ALWAYS_INLINE bitblock128_t convert (uint64_t s);
50static IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v);
51
52static IDISA_ALWAYS_INLINE bitblock128_t carry2bitblock(carry_t carry) {  return carry;} 
53static IDISA_ALWAYS_INLINE carry_t bitblock2carry(bitblock128_t carry) {  return carry;}
54
55static IDISA_ALWAYS_INLINE carry_t carryout2carry(bitblock128_t carryout) {
56 return bitblock::srli<BLOCK_SIZE-1>(carryout);
57}
58
59
60
61static IDISA_ALWAYS_INLINE void add_ci_co(bitblock128_t x, bitblock128_t y, bitblock128_t carry_in, bitblock128_t & carry_out, bitblock128_t & sum) {
62        bitblock128_t gen = simd_and(x, y);
63        bitblock128_t prop = simd_or(x, y);
64        bitblock128_t partial = simd128<64>::add(simd128<64>::add(x, y), carry_in);
65        bitblock128_t c1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_andc(prop, partial))));
66        sum = simd128<64>::add(c1, partial);
67        carry_out = simd_or(gen, simd_andc(prop, sum));
68}
69static IDISA_ALWAYS_INLINE void sub_bi_bo(bitblock128_t x, bitblock128_t y, bitblock128_t borrow_in, bitblock128_t & borrow_out, bitblock128_t & difference){
70        bitblock128_t gen = simd_andc(y, x);
71        bitblock128_t prop = simd_not(simd_xor(x, y));
72        bitblock128_t partial = simd128<64>::sub(simd128<64>::sub(x, y), borrow_in);
73        bitblock128_t b1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_and(prop, partial))));
74        difference = simd128<64>::sub(partial, b1);
75        borrow_out = simd_or(gen, simd_and(prop, difference));
76}
77static IDISA_ALWAYS_INLINE void adv_ci_co(bitblock128_t cursor, bitblock128_t carry_in, bitblock128_t & carry_out, bitblock128_t & rslt){
78        bitblock128_t shift_out = simd128<64>::srli<63>(cursor);
79        bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry_in);
80        carry_out = cursor;
81        rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits);
82}
83
84IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t & carry, bitblock128_t & sum)
85{
86        bitblock128_t gen = simd_and(x, y);
87        bitblock128_t prop = simd_or(x, y);
88        bitblock128_t partial = simd128<64>::add(simd128<64>::add(x, y), carry2bitblock(carry));
89        bitblock128_t c1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_andc(prop, partial))));
90        sum = simd128<64>::add(c1, partial);
91        carry = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_andc(prop, sum))));
92}
93
94IDISA_ALWAYS_INLINE void adc(bitblock128_t x, bitblock128_t y, carry_t carry_in, carry_t & carry_out, bitblock128_t & sum)
95{
96        bitblock128_t co;
97        add_ci_co(x, y, carry2bitblock(carry_in), co, sum);
98        carry_out = bitblock2carry(simd128<128>::srli<127>(co));
99}
100
101IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t & borrow, bitblock128_t & difference)
102{
103        bitblock128_t gen = simd_andc(y, x);
104        bitblock128_t prop = simd_not(simd_xor(x, y));
105        bitblock128_t partial = simd128<64>::sub(simd128<64>::sub(x, y), carry2bitblock(borrow));
106        bitblock128_t b1 = simd128<128>::slli<64>(simd128<64>::srli<63>(simd_or(gen, simd_and(prop, partial))));
107        difference = simd128<64>::sub(partial, b1);
108        borrow = bitblock2carry(simd128<128>::srli<127>(simd_or(gen, simd_and(prop, difference))));
109}
110
111IDISA_ALWAYS_INLINE void sbb(bitblock128_t x, bitblock128_t y, carry_t borrow_in, carry_t & borrow_out, bitblock128_t & difference)
112{
113        bitblock128_t bo;
114        sub_bi_bo(x, y, carry2bitblock(borrow_in), bo, difference);
115        borrow_out = bitblock2carry(simd128<128>::srli<127>(bo));
116}
117
118IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t & carry, bitblock128_t & rslt)
119{
120bitblock128_t shift_out = simd128<64>::srli<63>(cursor);
121bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry2bitblock(carry));
122carry = bitblock2carry(simd128<128>::srli<64>(shift_out));
123rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits);
124}
125
126IDISA_ALWAYS_INLINE void advance_with_carry(bitblock128_t cursor, carry_t carry_in, carry_t & carry_out, bitblock128_t & rslt)
127{
128bitblock128_t shift_out = simd128<64>::srli<63>(cursor);
129bitblock128_t low_bits = esimd128<64>::mergel(shift_out, carry2bitblock(carry_in));
130carry_out = bitblock2carry(simd128<128>::srli<64>(shift_out));
131rslt = simd_or(simd128<64>::add(cursor, cursor), low_bits);
132}
133
134IDISA_ALWAYS_INLINE bitblock128_t convert(uint64_t s)
135{
136        ubitblock b;
137        b._128 = simd128<128>::constant<0>();
138        b._64[0] = s;
139        return b._128;
140}
141
142IDISA_ALWAYS_INLINE uint64_t convert (bitblock128_t v)
143{
144        return (uint64_t) mvmd128<64>::extract<0>(v);
145}
146
147#endif // BITBLOCK128_HPP_
Note: See TracBrowser for help on using the repository browser.