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>
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "host-utils.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project//#define DEBUG_MULDIV
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Long integer helpers */
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(__x86_64__)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void add128 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *plow += a;
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* carry test */
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*plow < a)
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        (*phigh)++;
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phigh += b;
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void neg128 (uint64_t *plow, uint64_t *phigh)
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *plow = ~*plow;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phigh = ~*phigh;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    add128(plow, phigh, 1, 0);
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void mul64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t a0, a1, b0, b1;
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint64_t v;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a0 = a;
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    a1 = a >> 32;
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    b0 = b;
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    b1 = b >> 32;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v = (uint64_t)a0 * (uint64_t)b0;
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *plow = v;
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phigh = 0;
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v = (uint64_t)a0 * (uint64_t)b1;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    add128(plow, phigh, v << 32, v >> 32);
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v = (uint64_t)a1 * (uint64_t)b0;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    add128(plow, phigh, v << 32, v >> 32);
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    v = (uint64_t)a1 * (uint64_t)b1;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *phigh += v;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Unsigned 64x64 -> 128 multiplication */
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid mulu64 (uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mul64(plow, phigh, a, b);
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_MULDIV)
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("mulu64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           a, b, *phigh, *plow);
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Signed 64x64 -> 128 multiplication */
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid muls64 (uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int sa, sb;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sa = (a < 0);
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sa)
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        a = -a;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sb = (b < 0);
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sb)
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        b = -b;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    mul64(plow, phigh, a, b);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sa ^ sb) {
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        neg128(plow, phigh);
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(DEBUG_MULDIV)
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    printf("muls64: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           a, b, *phigh, *plow);
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !defined(__x86_64__) */
106