18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Utility compute operations used by translated code.
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2003 Fabrice Bellard
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 2007 Aurelien Jarno
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the Software without restriction, including without limitation the rights
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * furnished to do so, subject to the following conditions:
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice shall be included in
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * all copies or substantial portions of the Software.
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE.
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include <stdlib.h>
272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include <stdint.h>
28e90d665cd63a0bc5c3306e1ee3e98ad362546b16David 'Digit' Turner#include "qemu/host-utils.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Long integer helpers */
316731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner#ifndef CONFIG_INT128
326731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turnerstatic inline void mul64(uint64_t *plow, uint64_t *phigh,
336731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner                         uint64_t a, uint64_t b)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
356731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    typedef union {
366731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner        uint64_t ll;
376731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner        struct {
386731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner#ifdef HOST_WORDS_BIGENDIAN
396731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner            uint32_t high, low;
406731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner#else
416731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner            uint32_t low, high;
426731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner#endif
436731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner        } l;
446731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    } LL;
456731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    LL rl, rm, rn, rh, a0, b0;
466731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    uint64_t c;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
486731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    a0.ll = a;
496731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    b0.ll = b;
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
516731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rl.ll = (uint64_t)a0.l.low * b0.l.low;
526731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rm.ll = (uint64_t)a0.l.low * b0.l.high;
536731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rn.ll = (uint64_t)a0.l.high * b0.l.low;
546731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rh.ll = (uint64_t)a0.l.high * b0.l.high;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
566731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    c = (uint64_t)rl.l.high + rm.l.low + rn.l.low;
576731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rl.l.high = c;
586731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    c >>= 32;
596731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    c = c + rm.l.high + rn.l.high + rh.l.low;
606731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rh.l.low = c;
616731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    rh.l.high += (uint32_t)(c >> 32);
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
636731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    *plow = rl.ll;
646731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    *phigh = rh.ll;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned 64x64 -> 128 multiplication */
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mul64(plow, phigh, a, b);
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed 64x64 -> 128 multiplication */
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
766731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    uint64_t rh;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
786731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    mul64(plow, &rh, a, b);
796731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner
806731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    /* Adjust for signs.  */
816731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    if (b < 0) {
826731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner        rh -= a;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
846731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    if (a < 0) {
856731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner        rh -= b;
866731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    }
876731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner    *phigh = rh;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
896731cf52901064b55e19bae60ade2ccb5f69829cDavid 'Digit' Turner#endif /* !CONFIG_INT128 */
90