1 /* This file is part of the dynarmic project.
2  * Copyright (c) 2018 MerryMage
3  * SPDX-License-Identifier: 0BSD
4  */
5 
6 #include "common/common_types.h"
7 #include "common/u128.h"
8 
9 namespace Dynarmic {
10 
Multiply64To128(u64 a,u64 b)11 u128 Multiply64To128(u64 a, u64 b) {
12     const u32 a0 = static_cast<u32>(a);
13     const u32 b0 = static_cast<u32>(b);
14     const u32 a1 = static_cast<u32>(a >> 32);
15     const u32 b1 = static_cast<u32>(b >> 32);
16 
17     // result = (c2 << 64) + (c1 << 32) + c0
18     // c2 = a1 * b1
19     // c1 = a1 * b0 + a0 * b1
20     // c0 = a0 * b0
21     // noting that these operations may overflow
22 
23     const u64 c0 = static_cast<u64>(a0) * b0;
24     const u64 c1_0 = static_cast<u64>(a1) * b0;
25     const u64 c1_1 = static_cast<u64>(a0) * b1;
26     const u64 c2 = static_cast<u64>(a1) * b1;
27 
28     const u64 c1 = c1_0 + c1_1;
29     const u64 c1_overflow = c1 < c1_0;
30 
31     const u64 lower = c0 + (c1 << 32);
32     const u64 lower_overflow = lower < c0;
33 
34     const u64 upper = lower_overflow + (c1 >> 32) + (c1_overflow << 32) + c2;
35 
36     u128 result;
37     result.lower = lower;
38     result.upper = upper;
39     return result;
40 }
41 
operator <<(u128 operand,int amount)42 u128 operator<<(u128 operand, int amount) {
43     if (amount < 0) {
44         return operand >> -amount;
45     }
46 
47     if (amount == 0) {
48         return operand;
49     }
50 
51     if (amount < 64) {
52         u128 result;
53         result.lower = (operand.lower << amount);
54         result.upper = (operand.upper << amount) | (operand.lower >> (64 - amount));
55         return result;
56     }
57 
58     if (amount < 128) {
59         u128 result;
60         result.upper = operand.lower << (amount - 64);
61         return result;
62     }
63 
64     return {};
65 }
66 
operator >>(u128 operand,int amount)67 u128 operator>>(u128 operand, int amount) {
68     if (amount < 0) {
69         return operand << -amount;
70     }
71 
72     if (amount == 0) {
73         return operand;
74     }
75 
76     if (amount < 64) {
77         u128 result;
78         result.lower = (operand.lower >> amount) | (operand.upper << (64 - amount));
79         result.upper = (operand.upper >> amount);
80         return result;
81     }
82 
83     if (amount < 128) {
84         u128 result;
85         result.lower = operand.upper >> (amount - 64);
86         return result;
87     }
88 
89     return {};
90 }
91 
StickyLogicalShiftRight(u128 operand,int amount)92 u128 StickyLogicalShiftRight(u128 operand, int amount) {
93     if (amount < 0) {
94         return operand << -amount;
95     }
96 
97     if (amount == 0) {
98         return operand;
99     }
100 
101     if (amount < 64) {
102         u128 result;
103         result.lower = (operand.lower >> amount) | (operand.upper << (64 - amount));
104         result.upper = (operand.upper >> amount);
105         // Sticky bit
106         if ((operand.lower << (64 - amount)) != 0) {
107             result.lower |= 1;
108         }
109         return result;
110     }
111 
112     if (amount == 64) {
113         u128 result;
114         result.lower = operand.upper;
115         // Sticky bit
116         if (operand.lower != 0) {
117             result.lower |= 1;
118         }
119         return result;
120     }
121 
122     if (amount < 128) {
123         u128 result;
124         result.lower = operand.upper >> (amount - 64);
125         // Sticky bit
126         if (operand.lower != 0) {
127             result.lower |= 1;
128         }
129         if ((operand.upper << (128 - amount)) != 0) {
130             result.lower |= 1;
131         }
132         return result;
133     }
134 
135     if (operand.lower != 0 || operand.upper != 0) {
136         return u128(1);
137     }
138     return {};
139 }
140 
141 } // namespace Dynarmic
142