uint2048& operator+=(uint2048& operand_a, uint64_t operand_b){ uint64_t a; uint64_t* b; uint8_t carry_flag = 0u; a = operand_a.parts_[0u]; b = &(operand_a.parts_[0u]); // intrinsic function // adcx instruction // *c = a + b + carry // carry_flag is set to 1 if there is a carry bit carry_flag = _addcarry_u64(carry_flag, a, operand_b, b); if (carry_flag){ for (auto i = 1u; i < 32u; ++i){ a = operand_a.parts_[i]; b = &(operand_a.parts_[i]); // intrinsic function // adcx instruction // *c = a + b + carry carry_flag = _addcarry_u64(carry_flag, a, 0, b); if (!carry_flag) break; } } return operand_a; }
static void adx_test (void) { volatile unsigned char c; unsigned long long x; volatile unsigned long long y, sum_ref; c = 0; x = y = 0xFFFFFFFFFFFFFFFFLL; sum_ref = 0xFFFFFFFFFFFFFFFELL; /* X = 0xFFFFFFFFFFFFFFFF, Y = 0xFFFFFFFFFFFFFFFF, C = 0. */ c = _addcarryx_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ c = _addcarryx_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ if (x != sum_ref) abort (); c = 0; x = y = 0xFFFFFFFFFFFFFFFFLL; sum_ref = 0xFFFFFFFFFFFFFFFELL; /* X = 0xFFFFFFFFFFFFFFFF, Y = 0xFFFFFFFFFFFFFFFF, C = 0. */ c = _addcarry_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ c = _addcarry_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFE, Y = 0xFFFFFFFFFFFFFFFF, C = 1. */ if (x != sum_ref) abort (); c = 0; x = 1LL; y = 0LL; sum_ref = 0x0LL; /* X = 0x0000000000000001, Y = 0x0000000000000000, C = 0. */ c = _subborrow_u64 (c, x, y, &x); /* X = 0xFFFFFFFFFFFFFFFF, Y = 0x0000000000000000, C = 1. */ c = _subborrow_u64 (c, x, y, &x); /* X = 0x0000000000000000, Y = 0x0000000000000000, C = 1. */ if (x != sum_ref) abort (); }
uint2048& operator+=(uint2048& operand_a, const uint2048& operand_b){ uint64_t a, b; uint64_t* c; uint8_t carry_flag = 0u; for (auto i = 0u; i < 32u; ++i){ a = operand_a.parts_[i]; b = operand_b.parts_[i]; c = &(operand_a.parts_[i]); // intrinsic function // adcx instruction // *c = a + b + carry // carry_flag is set to 1 if there is a carry bit carry_flag = _addcarry_u64(carry_flag, a, b, c); } return operand_a; }