11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include <stdint.h> 61cb0ef41Sopenharmony_ci#include <limits> 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/build_config.h" 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#if !defined(UNDEFINED_SANITIZER) || !defined(V8_TARGET_ARCH_32_BIT) 111cb0ef41Sopenharmony_ci#error "This file is only needed for 32-bit UBSan builds." 121cb0ef41Sopenharmony_ci#endif 131cb0ef41Sopenharmony_ci 141cb0ef41Sopenharmony_ci// Compiling with -fsanitize=undefined on 32-bit platforms requires __mulodi4 151cb0ef41Sopenharmony_ci// to be available. Usually it comes from libcompiler_rt, which our build 161cb0ef41Sopenharmony_ci// doesn't provide, so here is a custom implementation (inspired by digit_mul 171cb0ef41Sopenharmony_ci// in src/objects/bigint.cc). 181cb0ef41Sopenharmony_ciextern "C" int64_t __mulodi4(int64_t a, int64_t b, int* overflow) { 191cb0ef41Sopenharmony_ci // Multiply in 32-bit chunks. 201cb0ef41Sopenharmony_ci // For inputs [AH AL]*[BH BL], the result is: 211cb0ef41Sopenharmony_ci // 221cb0ef41Sopenharmony_ci // [AL*BL] // r_low 231cb0ef41Sopenharmony_ci // + [AL*BH] // r_mid1 241cb0ef41Sopenharmony_ci // + [AH*BL] // r_mid2 251cb0ef41Sopenharmony_ci // + [AH*BH] // r_high 261cb0ef41Sopenharmony_ci // = [R4 R3 R2 R1] // high = [R4 R3], low = [R2 R1] 271cb0ef41Sopenharmony_ci // 281cb0ef41Sopenharmony_ci // Where of course we must be careful with carries between the columns. 291cb0ef41Sopenharmony_ci uint64_t a_low = a & 0xFFFFFFFFu; 301cb0ef41Sopenharmony_ci uint64_t a_high = static_cast<uint64_t>(a) >> 32; 311cb0ef41Sopenharmony_ci uint64_t b_low = b & 0xFFFFFFFFu; 321cb0ef41Sopenharmony_ci uint64_t b_high = static_cast<uint64_t>(b) >> 32; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci uint64_t r_low = a_low * b_low; 351cb0ef41Sopenharmony_ci uint64_t r_mid1 = a_low * b_high; 361cb0ef41Sopenharmony_ci uint64_t r_mid2 = a_high * b_low; 371cb0ef41Sopenharmony_ci uint64_t r_high = a_high * b_high; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ci uint64_t result1 = r_low + (r_mid1 << 32); 401cb0ef41Sopenharmony_ci if (result1 < r_low) r_high++; 411cb0ef41Sopenharmony_ci uint64_t result2 = result1 + (r_mid2 << 32); 421cb0ef41Sopenharmony_ci if (result2 < result1) r_high++; 431cb0ef41Sopenharmony_ci r_high += (r_mid1 >> 32) + (r_mid2 >> 32); 441cb0ef41Sopenharmony_ci int64_t result = static_cast<int64_t>(result2); 451cb0ef41Sopenharmony_ci uint64_t result_sign = (result >> 63); 461cb0ef41Sopenharmony_ci uint64_t expected_result_sign = (a >> 63) ^ (b >> 63); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci *overflow = (r_high > 0 || result_sign != expected_result_sign) ? 1 : 0; 491cb0ef41Sopenharmony_ci return result; 501cb0ef41Sopenharmony_ci} 51