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)11u128 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)42u128 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)67u128 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)92u128 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