110037SARM gem5 Developers/*
213118SEdmund.Grimley-Evans@arm.com* Copyright (c) 2012-2013, 2017-2018 ARM Limited
310037SARM gem5 Developers* All rights reserved
410037SARM gem5 Developers*
510037SARM gem5 Developers* The license below extends only to copyright in the software and shall
610037SARM gem5 Developers* not be construed as granting a license to any other intellectual
710037SARM gem5 Developers* property including but not limited to intellectual property relating
810037SARM gem5 Developers* to a hardware implementation of the functionality of the software
910037SARM gem5 Developers* licensed hereunder.  You may use the software subject to the license
1010037SARM gem5 Developers* terms below provided that you ensure that this notice is replicated
1110037SARM gem5 Developers* unmodified and in its entirety in all distributions of the software,
1210037SARM gem5 Developers* modified or unmodified, in source code or in binary form.
1310037SARM gem5 Developers*
1410037SARM gem5 Developers* Redistribution and use in source and binary forms, with or without
1510037SARM gem5 Developers* modification, are permitted provided that the following conditions are
1610037SARM gem5 Developers* met: redistributions of source code must retain the above copyright
1710037SARM gem5 Developers* notice, this list of conditions and the following disclaimer;
1810037SARM gem5 Developers* redistributions in binary form must reproduce the above copyright
1910037SARM gem5 Developers* notice, this list of conditions and the following disclaimer in the
2010037SARM gem5 Developers* documentation and/or other materials provided with the distribution;
2110037SARM gem5 Developers* neither the name of the copyright holders nor the names of its
2210037SARM gem5 Developers* contributors may be used to endorse or promote products derived from
2310037SARM gem5 Developers* this software without specific prior written permission.
2410037SARM gem5 Developers*
2510037SARM gem5 Developers* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2610037SARM gem5 Developers* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2710037SARM gem5 Developers* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2810037SARM gem5 Developers* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2910037SARM gem5 Developers* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3010037SARM gem5 Developers* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3110037SARM gem5 Developers* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3210037SARM gem5 Developers* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3310037SARM gem5 Developers* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3410037SARM gem5 Developers* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3510037SARM gem5 Developers* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3610037SARM gem5 Developers*
3710037SARM gem5 Developers* Authors: Edmund Grimley Evans
3810037SARM gem5 Developers*          Thomas Grocutt
3910037SARM gem5 Developers*/
4010037SARM gem5 Developers
4110037SARM gem5 Developers#include <stdint.h>
4210037SARM gem5 Developers
4310037SARM gem5 Developers#include <cassert>
4410037SARM gem5 Developers
4513449Sgabeblack@google.com#include "base/logging.hh"
4610037SARM gem5 Developers#include "fplib.hh"
4710037SARM gem5 Developers
4810037SARM gem5 Developersnamespace ArmISA
4910037SARM gem5 Developers{
5010037SARM gem5 Developers
5110037SARM gem5 Developers#define FPLIB_RN 0
5210037SARM gem5 Developers#define FPLIB_RP 1
5310037SARM gem5 Developers#define FPLIB_RM 2
5410037SARM gem5 Developers#define FPLIB_RZ 3
5510037SARM gem5 Developers#define FPLIB_FZ 4
5610037SARM gem5 Developers#define FPLIB_DN 8
5710037SARM gem5 Developers#define FPLIB_AHP 16
5813118SEdmund.Grimley-Evans@arm.com#define FPLIB_FZ16 32
5910037SARM gem5 Developers
6010037SARM gem5 Developers#define FPLIB_IDC 128 // Input Denormal
6110037SARM gem5 Developers#define FPLIB_IXC 16  // Inexact
6210037SARM gem5 Developers#define FPLIB_UFC 8   // Underflow
6310037SARM gem5 Developers#define FPLIB_OFC 4   // Overflow
6410037SARM gem5 Developers#define FPLIB_DZC 2   // Division by Zero
6510037SARM gem5 Developers#define FPLIB_IOC 1   // Invalid Operation
6610037SARM gem5 Developers
6713118SEdmund.Grimley-Evans@arm.com#define FP16_BITS 16
6813118SEdmund.Grimley-Evans@arm.com#define FP32_BITS 32
6913118SEdmund.Grimley-Evans@arm.com#define FP64_BITS 64
7013118SEdmund.Grimley-Evans@arm.com
7113118SEdmund.Grimley-Evans@arm.com#define FP16_EXP_BITS 5
7213118SEdmund.Grimley-Evans@arm.com#define FP32_EXP_BITS 8
7313118SEdmund.Grimley-Evans@arm.com#define FP64_EXP_BITS 11
7413118SEdmund.Grimley-Evans@arm.com
7513118SEdmund.Grimley-Evans@arm.com#define FP16_EXP_BIAS 15
7613118SEdmund.Grimley-Evans@arm.com#define FP32_EXP_BIAS 127
7713118SEdmund.Grimley-Evans@arm.com#define FP64_EXP_BIAS 1023
7813118SEdmund.Grimley-Evans@arm.com
7913118SEdmund.Grimley-Evans@arm.com#define FP16_EXP_INF ((1ULL << FP16_EXP_BITS) - 1)
8013118SEdmund.Grimley-Evans@arm.com#define FP32_EXP_INF ((1ULL << FP32_EXP_BITS) - 1)
8113118SEdmund.Grimley-Evans@arm.com#define FP64_EXP_INF ((1ULL << FP64_EXP_BITS) - 1)
8213118SEdmund.Grimley-Evans@arm.com
8313118SEdmund.Grimley-Evans@arm.com#define FP16_MANT_BITS (FP16_BITS - FP16_EXP_BITS - 1)
8413118SEdmund.Grimley-Evans@arm.com#define FP32_MANT_BITS (FP32_BITS - FP32_EXP_BITS - 1)
8513118SEdmund.Grimley-Evans@arm.com#define FP64_MANT_BITS (FP64_BITS - FP64_EXP_BITS - 1)
8613118SEdmund.Grimley-Evans@arm.com
8713118SEdmund.Grimley-Evans@arm.com#define FP16_EXP(x) ((x) >> FP16_MANT_BITS & ((1ULL << FP16_EXP_BITS) - 1))
8813118SEdmund.Grimley-Evans@arm.com#define FP32_EXP(x) ((x) >> FP32_MANT_BITS & ((1ULL << FP32_EXP_BITS) - 1))
8913118SEdmund.Grimley-Evans@arm.com#define FP64_EXP(x) ((x) >> FP64_MANT_BITS & ((1ULL << FP64_EXP_BITS) - 1))
9013118SEdmund.Grimley-Evans@arm.com
9113118SEdmund.Grimley-Evans@arm.com#define FP16_MANT(x) ((x) & ((1ULL << FP16_MANT_BITS) - 1))
9213118SEdmund.Grimley-Evans@arm.com#define FP32_MANT(x) ((x) & ((1ULL << FP32_MANT_BITS) - 1))
9313118SEdmund.Grimley-Evans@arm.com#define FP64_MANT(x) ((x) & ((1ULL << FP64_MANT_BITS) - 1))
9413118SEdmund.Grimley-Evans@arm.com
9510037SARM gem5 Developersstatic inline uint16_t
9610037SARM gem5 Developerslsl16(uint16_t x, uint32_t shift)
9710037SARM gem5 Developers{
9810037SARM gem5 Developers    return shift < 16 ? x << shift : 0;
9910037SARM gem5 Developers}
10010037SARM gem5 Developers
10110037SARM gem5 Developersstatic inline uint16_t
10210037SARM gem5 Developerslsr16(uint16_t x, uint32_t shift)
10310037SARM gem5 Developers{
10410037SARM gem5 Developers    return shift < 16 ? x >> shift : 0;
10510037SARM gem5 Developers}
10610037SARM gem5 Developers
10710037SARM gem5 Developersstatic inline uint32_t
10810037SARM gem5 Developerslsl32(uint32_t x, uint32_t shift)
10910037SARM gem5 Developers{
11010037SARM gem5 Developers    return shift < 32 ? x << shift : 0;
11110037SARM gem5 Developers}
11210037SARM gem5 Developers
11310037SARM gem5 Developersstatic inline uint32_t
11410037SARM gem5 Developerslsr32(uint32_t x, uint32_t shift)
11510037SARM gem5 Developers{
11610037SARM gem5 Developers    return shift < 32 ? x >> shift : 0;
11710037SARM gem5 Developers}
11810037SARM gem5 Developers
11910037SARM gem5 Developersstatic inline uint64_t
12010037SARM gem5 Developerslsl64(uint64_t x, uint32_t shift)
12110037SARM gem5 Developers{
12210037SARM gem5 Developers    return shift < 64 ? x << shift : 0;
12310037SARM gem5 Developers}
12410037SARM gem5 Developers
12510037SARM gem5 Developersstatic inline uint64_t
12610037SARM gem5 Developerslsr64(uint64_t x, uint32_t shift)
12710037SARM gem5 Developers{
12810037SARM gem5 Developers    return shift < 64 ? x >> shift : 0;
12910037SARM gem5 Developers}
13010037SARM gem5 Developers
13110037SARM gem5 Developersstatic inline void
13210037SARM gem5 Developerslsl128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
13310037SARM gem5 Developers{
13411224Snathananel.premillieu@arm.com    if (shift == 0) {
13511224Snathananel.premillieu@arm.com        *r1 = x1;
13611224Snathananel.premillieu@arm.com        *r0 = x0;
13711224Snathananel.premillieu@arm.com    } else if (shift < 64) {
13810037SARM gem5 Developers        *r1 = x1 << shift | x0 >> (64 - shift);
13910037SARM gem5 Developers        *r0 = x0 << shift;
14010037SARM gem5 Developers    } else if (shift < 128) {
14110037SARM gem5 Developers        *r1 = x0 << (shift - 64);
14210037SARM gem5 Developers        *r0 = 0;
14310037SARM gem5 Developers    } else {
14410037SARM gem5 Developers        *r1 = 0;
14510037SARM gem5 Developers        *r0 = 0;
14610037SARM gem5 Developers    }
14710037SARM gem5 Developers}
14810037SARM gem5 Developers
14910037SARM gem5 Developersstatic inline void
15010037SARM gem5 Developerslsr128(uint64_t *r0, uint64_t *r1, uint64_t x0, uint64_t x1, uint32_t shift)
15110037SARM gem5 Developers{
15211224Snathananel.premillieu@arm.com    if (shift == 0) {
15311224Snathananel.premillieu@arm.com        *r1 = x1;
15411224Snathananel.premillieu@arm.com        *r0 = x0;
15511224Snathananel.premillieu@arm.com    } else if (shift < 64) {
15610037SARM gem5 Developers        *r0 = x0 >> shift | x1 << (64 - shift);
15710037SARM gem5 Developers        *r1 = x1 >> shift;
15810037SARM gem5 Developers    } else if (shift < 128) {
15910037SARM gem5 Developers        *r0 = x1 >> (shift - 64);
16010037SARM gem5 Developers        *r1 = 0;
16110037SARM gem5 Developers    } else {
16210037SARM gem5 Developers        *r0 = 0;
16310037SARM gem5 Developers        *r1 = 0;
16410037SARM gem5 Developers    }
16510037SARM gem5 Developers}
16610037SARM gem5 Developers
16710037SARM gem5 Developersstatic inline void
16810037SARM gem5 Developersmul62x62(uint64_t *x0, uint64_t *x1, uint64_t a, uint64_t b)
16910037SARM gem5 Developers{
17010037SARM gem5 Developers    uint32_t mask = ((uint32_t)1 << 31) - 1;
17110037SARM gem5 Developers    uint64_t a0 = a & mask;
17210037SARM gem5 Developers    uint64_t a1 = a >> 31 & mask;
17310037SARM gem5 Developers    uint64_t b0 = b & mask;
17410037SARM gem5 Developers    uint64_t b1 = b >> 31 & mask;
17510037SARM gem5 Developers    uint64_t p0 = a0 * b0;
17610037SARM gem5 Developers    uint64_t p2 = a1 * b1;
17710037SARM gem5 Developers    uint64_t p1 = (a0 + a1) * (b0 + b1) - p0 - p2;
17810037SARM gem5 Developers    uint64_t s0 = p0;
17910037SARM gem5 Developers    uint64_t s1 = (s0 >> 31) + p1;
18010037SARM gem5 Developers    uint64_t s2 = (s1 >> 31) + p2;
18110037SARM gem5 Developers    *x0 = (s0 & mask) | (s1 & mask) << 31 | s2 << 62;
18210037SARM gem5 Developers    *x1 = s2 >> 2;
18310037SARM gem5 Developers}
18410037SARM gem5 Developers
18510037SARM gem5 Developersstatic inline
18610037SARM gem5 Developersvoid mul64x32(uint64_t *x0, uint64_t *x1, uint64_t a, uint32_t b)
18710037SARM gem5 Developers{
18810037SARM gem5 Developers    uint64_t t0 = (uint64_t)(uint32_t)a * b;
18910037SARM gem5 Developers    uint64_t t1 = (t0 >> 32) + (a >> 32) * b;
19010037SARM gem5 Developers    *x0 = t1 << 32 | (uint32_t)t0;
19110037SARM gem5 Developers    *x1 = t1 >> 32;
19210037SARM gem5 Developers}
19310037SARM gem5 Developers
19410037SARM gem5 Developersstatic inline void
19510037SARM gem5 Developersadd128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
19610037SARM gem5 Developers       uint64_t b1)
19710037SARM gem5 Developers{
19810037SARM gem5 Developers    *x0 = a0 + b0;
19910037SARM gem5 Developers    *x1 = a1 + b1 + (*x0 < a0);
20010037SARM gem5 Developers}
20110037SARM gem5 Developers
20210037SARM gem5 Developersstatic inline void
20310037SARM gem5 Developerssub128(uint64_t *x0, uint64_t *x1, uint64_t a0, uint64_t a1, uint64_t b0,
20410037SARM gem5 Developers       uint64_t b1)
20510037SARM gem5 Developers{
20610037SARM gem5 Developers    *x0 = a0 - b0;
20710037SARM gem5 Developers    *x1 = a1 - b1 - (*x0 > a0);
20810037SARM gem5 Developers}
20910037SARM gem5 Developers
21010037SARM gem5 Developersstatic inline int
21110037SARM gem5 Developerscmp128(uint64_t a0, uint64_t a1, uint64_t b0, uint64_t b1)
21210037SARM gem5 Developers{
21310037SARM gem5 Developers    return (a1 < b1 ? -1 : a1 > b1 ? 1 : a0 < b0 ? -1 : a0 > b0 ? 1 : 0);
21410037SARM gem5 Developers}
21510037SARM gem5 Developers
21610037SARM gem5 Developersstatic inline uint16_t
21710037SARM gem5 Developersfp16_normalise(uint16_t mnt, int *exp)
21810037SARM gem5 Developers{
21910037SARM gem5 Developers    int shift;
22010037SARM gem5 Developers
22110037SARM gem5 Developers    if (!mnt) {
22210037SARM gem5 Developers        return 0;
22310037SARM gem5 Developers    }
22410037SARM gem5 Developers
22510037SARM gem5 Developers    for (shift = 8; shift; shift >>= 1) {
22610037SARM gem5 Developers        if (!(mnt >> (16 - shift))) {
22710037SARM gem5 Developers            mnt <<= shift;
22810037SARM gem5 Developers            *exp -= shift;
22910037SARM gem5 Developers        }
23010037SARM gem5 Developers    }
23110037SARM gem5 Developers    return mnt;
23210037SARM gem5 Developers}
23310037SARM gem5 Developers
23410037SARM gem5 Developersstatic inline uint32_t
23510037SARM gem5 Developersfp32_normalise(uint32_t mnt, int *exp)
23610037SARM gem5 Developers{
23710037SARM gem5 Developers    int shift;
23810037SARM gem5 Developers
23910037SARM gem5 Developers    if (!mnt) {
24010037SARM gem5 Developers        return 0;
24110037SARM gem5 Developers    }
24210037SARM gem5 Developers
24310037SARM gem5 Developers    for (shift = 16; shift; shift >>= 1) {
24410037SARM gem5 Developers        if (!(mnt >> (32 - shift))) {
24510037SARM gem5 Developers            mnt <<= shift;
24610037SARM gem5 Developers            *exp -= shift;
24710037SARM gem5 Developers        }
24810037SARM gem5 Developers    }
24910037SARM gem5 Developers    return mnt;
25010037SARM gem5 Developers}
25110037SARM gem5 Developers
25210037SARM gem5 Developersstatic inline uint64_t
25310037SARM gem5 Developersfp64_normalise(uint64_t mnt, int *exp)
25410037SARM gem5 Developers{
25510037SARM gem5 Developers    int shift;
25610037SARM gem5 Developers
25710037SARM gem5 Developers    if (!mnt) {
25810037SARM gem5 Developers        return 0;
25910037SARM gem5 Developers    }
26010037SARM gem5 Developers
26110037SARM gem5 Developers    for (shift = 32; shift; shift >>= 1) {
26210037SARM gem5 Developers        if (!(mnt >> (64 - shift))) {
26310037SARM gem5 Developers            mnt <<= shift;
26410037SARM gem5 Developers            *exp -= shift;
26510037SARM gem5 Developers        }
26610037SARM gem5 Developers    }
26710037SARM gem5 Developers    return mnt;
26810037SARM gem5 Developers}
26910037SARM gem5 Developers
27010037SARM gem5 Developersstatic inline void
27110037SARM gem5 Developersfp128_normalise(uint64_t *mnt0, uint64_t *mnt1, int *exp)
27210037SARM gem5 Developers{
27310037SARM gem5 Developers    uint64_t x0 = *mnt0;
27410037SARM gem5 Developers    uint64_t x1 = *mnt1;
27510037SARM gem5 Developers    int shift;
27610037SARM gem5 Developers
27710037SARM gem5 Developers    if (!x0 && !x1) {
27810037SARM gem5 Developers        return;
27910037SARM gem5 Developers    }
28010037SARM gem5 Developers
28110037SARM gem5 Developers    if (!x1) {
28210037SARM gem5 Developers        x1 = x0;
28310037SARM gem5 Developers        x0 = 0;
28410037SARM gem5 Developers        *exp -= 64;
28510037SARM gem5 Developers    }
28610037SARM gem5 Developers
28710037SARM gem5 Developers    for (shift = 32; shift; shift >>= 1) {
28810037SARM gem5 Developers        if (!(x1 >> (64 - shift))) {
28910037SARM gem5 Developers            x1 = x1 << shift | x0 >> (64 - shift);
29010037SARM gem5 Developers            x0 <<= shift;
29110037SARM gem5 Developers            *exp -= shift;
29210037SARM gem5 Developers        }
29310037SARM gem5 Developers    }
29410037SARM gem5 Developers
29510037SARM gem5 Developers    *mnt0 = x0;
29610037SARM gem5 Developers    *mnt1 = x1;
29710037SARM gem5 Developers}
29810037SARM gem5 Developers
29910037SARM gem5 Developersstatic inline uint16_t
30010037SARM gem5 Developersfp16_pack(uint16_t sgn, uint16_t exp, uint16_t mnt)
30110037SARM gem5 Developers{
30213118SEdmund.Grimley-Evans@arm.com    return sgn << (FP16_BITS - 1) | exp << FP16_MANT_BITS | FP16_MANT(mnt);
30310037SARM gem5 Developers}
30410037SARM gem5 Developers
30510037SARM gem5 Developersstatic inline uint32_t
30610037SARM gem5 Developersfp32_pack(uint32_t sgn, uint32_t exp, uint32_t mnt)
30710037SARM gem5 Developers{
30813118SEdmund.Grimley-Evans@arm.com    return sgn << (FP32_BITS - 1) | exp << FP32_MANT_BITS | FP32_MANT(mnt);
30910037SARM gem5 Developers}
31010037SARM gem5 Developers
31110037SARM gem5 Developersstatic inline uint64_t
31210037SARM gem5 Developersfp64_pack(uint64_t sgn, uint64_t exp, uint64_t mnt)
31310037SARM gem5 Developers{
31413118SEdmund.Grimley-Evans@arm.com    return sgn << (FP64_BITS - 1) | exp << FP64_MANT_BITS | FP64_MANT(mnt);
31510037SARM gem5 Developers}
31610037SARM gem5 Developers
31710037SARM gem5 Developersstatic inline uint16_t
31810037SARM gem5 Developersfp16_zero(int sgn)
31910037SARM gem5 Developers{
32010037SARM gem5 Developers    return fp16_pack(sgn, 0, 0);
32110037SARM gem5 Developers}
32210037SARM gem5 Developers
32310037SARM gem5 Developersstatic inline uint32_t
32410037SARM gem5 Developersfp32_zero(int sgn)
32510037SARM gem5 Developers{
32610037SARM gem5 Developers    return fp32_pack(sgn, 0, 0);
32710037SARM gem5 Developers}
32810037SARM gem5 Developers
32910037SARM gem5 Developersstatic inline uint64_t
33010037SARM gem5 Developersfp64_zero(int sgn)
33110037SARM gem5 Developers{
33210037SARM gem5 Developers    return fp64_pack(sgn, 0, 0);
33310037SARM gem5 Developers}
33410037SARM gem5 Developers
33510037SARM gem5 Developersstatic inline uint16_t
33610037SARM gem5 Developersfp16_max_normal(int sgn)
33710037SARM gem5 Developers{
33813118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, FP16_EXP_INF - 1, -1);
33910037SARM gem5 Developers}
34010037SARM gem5 Developers
34110037SARM gem5 Developersstatic inline uint32_t
34210037SARM gem5 Developersfp32_max_normal(int sgn)
34310037SARM gem5 Developers{
34413118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, FP32_EXP_INF - 1, -1);
34510037SARM gem5 Developers}
34610037SARM gem5 Developers
34710037SARM gem5 Developersstatic inline uint64_t
34810037SARM gem5 Developersfp64_max_normal(int sgn)
34910037SARM gem5 Developers{
35013118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, FP64_EXP_INF - 1, -1);
35110037SARM gem5 Developers}
35210037SARM gem5 Developers
35310037SARM gem5 Developersstatic inline uint16_t
35410037SARM gem5 Developersfp16_infinity(int sgn)
35510037SARM gem5 Developers{
35613118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, FP16_EXP_INF, 0);
35710037SARM gem5 Developers}
35810037SARM gem5 Developers
35910037SARM gem5 Developersstatic inline uint32_t
36010037SARM gem5 Developersfp32_infinity(int sgn)
36110037SARM gem5 Developers{
36213118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, FP32_EXP_INF, 0);
36310037SARM gem5 Developers}
36410037SARM gem5 Developers
36510037SARM gem5 Developersstatic inline uint64_t
36610037SARM gem5 Developersfp64_infinity(int sgn)
36710037SARM gem5 Developers{
36813118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, FP64_EXP_INF, 0);
36910037SARM gem5 Developers}
37010037SARM gem5 Developers
37110037SARM gem5 Developersstatic inline uint16_t
37210037SARM gem5 Developersfp16_defaultNaN()
37310037SARM gem5 Developers{
37413118SEdmund.Grimley-Evans@arm.com    return fp16_pack(0, FP16_EXP_INF, 1ULL << (FP16_MANT_BITS - 1));
37510037SARM gem5 Developers}
37610037SARM gem5 Developers
37710037SARM gem5 Developersstatic inline uint32_t
37810037SARM gem5 Developersfp32_defaultNaN()
37910037SARM gem5 Developers{
38013118SEdmund.Grimley-Evans@arm.com    return fp32_pack(0, FP32_EXP_INF, 1ULL << (FP32_MANT_BITS - 1));
38110037SARM gem5 Developers}
38210037SARM gem5 Developers
38310037SARM gem5 Developersstatic inline uint64_t
38410037SARM gem5 Developersfp64_defaultNaN()
38510037SARM gem5 Developers{
38613118SEdmund.Grimley-Evans@arm.com    return fp64_pack(0, FP64_EXP_INF, 1ULL << (FP64_MANT_BITS - 1));
38710037SARM gem5 Developers}
38810037SARM gem5 Developers
38910037SARM gem5 Developersstatic inline void
39010037SARM gem5 Developersfp16_unpack(int *sgn, int *exp, uint16_t *mnt, uint16_t x, int mode,
39110037SARM gem5 Developers            int *flags)
39210037SARM gem5 Developers{
39313118SEdmund.Grimley-Evans@arm.com    *sgn = x >> (FP16_BITS - 1);
39413118SEdmund.Grimley-Evans@arm.com    *exp = FP16_EXP(x);
39513118SEdmund.Grimley-Evans@arm.com    *mnt = FP16_MANT(x);
39610037SARM gem5 Developers
39710037SARM gem5 Developers    // Handle subnormals:
39810037SARM gem5 Developers    if (*exp) {
39913118SEdmund.Grimley-Evans@arm.com        *mnt |= 1ULL << FP16_MANT_BITS;
40010037SARM gem5 Developers    } else {
40110037SARM gem5 Developers        ++*exp;
40213118SEdmund.Grimley-Evans@arm.com        // IDC (Input Denormal) is not set in this case.
40313118SEdmund.Grimley-Evans@arm.com        if (mode & FPLIB_FZ16)
40413118SEdmund.Grimley-Evans@arm.com            *mnt = 0;
40510037SARM gem5 Developers    }
40610037SARM gem5 Developers}
40710037SARM gem5 Developers
40810037SARM gem5 Developersstatic inline void
40910037SARM gem5 Developersfp32_unpack(int *sgn, int *exp, uint32_t *mnt, uint32_t x, int mode,
41010037SARM gem5 Developers            int *flags)
41110037SARM gem5 Developers{
41213118SEdmund.Grimley-Evans@arm.com    *sgn = x >> (FP32_BITS - 1);
41313118SEdmund.Grimley-Evans@arm.com    *exp = FP32_EXP(x);
41413118SEdmund.Grimley-Evans@arm.com    *mnt = FP32_MANT(x);
41510037SARM gem5 Developers
41610037SARM gem5 Developers    // Handle subnormals:
41710037SARM gem5 Developers    if (*exp) {
41813118SEdmund.Grimley-Evans@arm.com        *mnt |= 1ULL << FP32_MANT_BITS;
41910037SARM gem5 Developers    } else {
42010037SARM gem5 Developers        ++*exp;
42110037SARM gem5 Developers        if ((mode & FPLIB_FZ) && *mnt) {
42210037SARM gem5 Developers            *flags |= FPLIB_IDC;
42310037SARM gem5 Developers            *mnt = 0;
42410037SARM gem5 Developers        }
42510037SARM gem5 Developers    }
42610037SARM gem5 Developers}
42710037SARM gem5 Developers
42810037SARM gem5 Developersstatic inline void
42910037SARM gem5 Developersfp64_unpack(int *sgn, int *exp, uint64_t *mnt, uint64_t x, int mode,
43010037SARM gem5 Developers            int *flags)
43110037SARM gem5 Developers{
43213118SEdmund.Grimley-Evans@arm.com    *sgn = x >> (FP64_BITS - 1);
43313118SEdmund.Grimley-Evans@arm.com    *exp = FP64_EXP(x);
43413118SEdmund.Grimley-Evans@arm.com    *mnt = FP64_MANT(x);
43510037SARM gem5 Developers
43610037SARM gem5 Developers    // Handle subnormals:
43710037SARM gem5 Developers    if (*exp) {
43813118SEdmund.Grimley-Evans@arm.com        *mnt |= 1ULL << FP64_MANT_BITS;
43910037SARM gem5 Developers    } else {
44010037SARM gem5 Developers        ++*exp;
44110037SARM gem5 Developers        if ((mode & FPLIB_FZ) && *mnt) {
44210037SARM gem5 Developers            *flags |= FPLIB_IDC;
44310037SARM gem5 Developers            *mnt = 0;
44410037SARM gem5 Developers        }
44510037SARM gem5 Developers    }
44610037SARM gem5 Developers}
44710037SARM gem5 Developers
44813118SEdmund.Grimley-Evans@arm.comstatic inline int
44913118SEdmund.Grimley-Evans@arm.comfp16_is_NaN(int exp, uint16_t mnt)
45013118SEdmund.Grimley-Evans@arm.com{
45113118SEdmund.Grimley-Evans@arm.com    return exp == FP16_EXP_INF && FP16_MANT(mnt);
45213118SEdmund.Grimley-Evans@arm.com}
45313118SEdmund.Grimley-Evans@arm.com
45413118SEdmund.Grimley-Evans@arm.comstatic inline int
45513118SEdmund.Grimley-Evans@arm.comfp32_is_NaN(int exp, uint32_t mnt)
45613118SEdmund.Grimley-Evans@arm.com{
45713118SEdmund.Grimley-Evans@arm.com    return exp == FP32_EXP_INF && FP32_MANT(mnt);
45813118SEdmund.Grimley-Evans@arm.com}
45913118SEdmund.Grimley-Evans@arm.com
46013118SEdmund.Grimley-Evans@arm.comstatic inline int
46113118SEdmund.Grimley-Evans@arm.comfp64_is_NaN(int exp, uint64_t mnt)
46213118SEdmund.Grimley-Evans@arm.com{
46313118SEdmund.Grimley-Evans@arm.com    return exp == FP64_EXP_INF && FP64_MANT(mnt);
46413118SEdmund.Grimley-Evans@arm.com}
46513118SEdmund.Grimley-Evans@arm.com
46613118SEdmund.Grimley-Evans@arm.comstatic inline int
46713118SEdmund.Grimley-Evans@arm.comfp16_is_signalling_NaN(int exp, uint16_t mnt)
46813118SEdmund.Grimley-Evans@arm.com{
46913118SEdmund.Grimley-Evans@arm.com    return fp16_is_NaN(exp, mnt) && !(mnt >> (FP16_MANT_BITS - 1) & 1);
47013118SEdmund.Grimley-Evans@arm.com}
47113118SEdmund.Grimley-Evans@arm.com
47213118SEdmund.Grimley-Evans@arm.comstatic inline int
47313118SEdmund.Grimley-Evans@arm.comfp32_is_signalling_NaN(int exp, uint32_t mnt)
47413118SEdmund.Grimley-Evans@arm.com{
47513118SEdmund.Grimley-Evans@arm.com    return fp32_is_NaN(exp, mnt) && !(mnt >> (FP32_MANT_BITS - 1) & 1);
47613118SEdmund.Grimley-Evans@arm.com}
47713118SEdmund.Grimley-Evans@arm.com
47813118SEdmund.Grimley-Evans@arm.comstatic inline int
47913118SEdmund.Grimley-Evans@arm.comfp64_is_signalling_NaN(int exp, uint64_t mnt)
48013118SEdmund.Grimley-Evans@arm.com{
48113118SEdmund.Grimley-Evans@arm.com    return fp64_is_NaN(exp, mnt) && !(mnt >> (FP64_MANT_BITS - 1) & 1);
48213118SEdmund.Grimley-Evans@arm.com}
48313118SEdmund.Grimley-Evans@arm.com
48413118SEdmund.Grimley-Evans@arm.comstatic inline int
48513118SEdmund.Grimley-Evans@arm.comfp16_is_quiet_NaN(int exp, uint16_t mnt)
48613118SEdmund.Grimley-Evans@arm.com{
48713118SEdmund.Grimley-Evans@arm.com    return exp == FP16_EXP_INF && (mnt >> (FP16_MANT_BITS - 1) & 1);
48813118SEdmund.Grimley-Evans@arm.com}
48913118SEdmund.Grimley-Evans@arm.com
49013118SEdmund.Grimley-Evans@arm.comstatic inline int
49113118SEdmund.Grimley-Evans@arm.comfp32_is_quiet_NaN(int exp, uint32_t mnt)
49213118SEdmund.Grimley-Evans@arm.com{
49313118SEdmund.Grimley-Evans@arm.com    return exp == FP32_EXP_INF && (mnt >> (FP32_MANT_BITS - 1) & 1);
49413118SEdmund.Grimley-Evans@arm.com}
49513118SEdmund.Grimley-Evans@arm.com
49613118SEdmund.Grimley-Evans@arm.comstatic inline int
49713118SEdmund.Grimley-Evans@arm.comfp64_is_quiet_NaN(int exp, uint64_t mnt)
49813118SEdmund.Grimley-Evans@arm.com{
49913118SEdmund.Grimley-Evans@arm.com    return exp == FP64_EXP_INF && (mnt >> (FP64_MANT_BITS - 1) & 1);
50013118SEdmund.Grimley-Evans@arm.com}
50113118SEdmund.Grimley-Evans@arm.com
50213118SEdmund.Grimley-Evans@arm.comstatic inline int
50313118SEdmund.Grimley-Evans@arm.comfp16_is_infinity(int exp, uint16_t mnt)
50413118SEdmund.Grimley-Evans@arm.com{
50513118SEdmund.Grimley-Evans@arm.com    return exp == FP16_EXP_INF && !FP16_MANT(mnt);
50613118SEdmund.Grimley-Evans@arm.com}
50713118SEdmund.Grimley-Evans@arm.com
50813118SEdmund.Grimley-Evans@arm.comstatic inline int
50913118SEdmund.Grimley-Evans@arm.comfp32_is_infinity(int exp, uint32_t mnt)
51013118SEdmund.Grimley-Evans@arm.com{
51113118SEdmund.Grimley-Evans@arm.com    return exp == FP32_EXP_INF && !FP32_MANT(mnt);
51213118SEdmund.Grimley-Evans@arm.com}
51313118SEdmund.Grimley-Evans@arm.com
51413118SEdmund.Grimley-Evans@arm.comstatic inline int
51513118SEdmund.Grimley-Evans@arm.comfp64_is_infinity(int exp, uint64_t mnt)
51613118SEdmund.Grimley-Evans@arm.com{
51713118SEdmund.Grimley-Evans@arm.com    return exp == FP64_EXP_INF && !FP64_MANT(mnt);
51813118SEdmund.Grimley-Evans@arm.com}
51913118SEdmund.Grimley-Evans@arm.com
52013118SEdmund.Grimley-Evans@arm.comstatic inline uint16_t
52113118SEdmund.Grimley-Evans@arm.comfp16_process_NaN(uint16_t a, int mode, int *flags)
52213118SEdmund.Grimley-Evans@arm.com{
52313118SEdmund.Grimley-Evans@arm.com    if (!(a >> (FP16_MANT_BITS - 1) & 1)) {
52413118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
52513118SEdmund.Grimley-Evans@arm.com        a |= 1ULL << (FP16_MANT_BITS - 1);
52613118SEdmund.Grimley-Evans@arm.com    }
52713118SEdmund.Grimley-Evans@arm.com    return mode & FPLIB_DN ? fp16_defaultNaN() : a;
52813118SEdmund.Grimley-Evans@arm.com}
52913118SEdmund.Grimley-Evans@arm.com
53010037SARM gem5 Developersstatic inline uint32_t
53110037SARM gem5 Developersfp32_process_NaN(uint32_t a, int mode, int *flags)
53210037SARM gem5 Developers{
53313118SEdmund.Grimley-Evans@arm.com    if (!(a >> (FP32_MANT_BITS - 1) & 1)) {
53410037SARM gem5 Developers        *flags |= FPLIB_IOC;
53513118SEdmund.Grimley-Evans@arm.com        a |= 1ULL << (FP32_MANT_BITS - 1);
53610037SARM gem5 Developers    }
53710037SARM gem5 Developers    return mode & FPLIB_DN ? fp32_defaultNaN() : a;
53810037SARM gem5 Developers}
53910037SARM gem5 Developers
54010037SARM gem5 Developersstatic inline uint64_t
54110037SARM gem5 Developersfp64_process_NaN(uint64_t a, int mode, int *flags)
54210037SARM gem5 Developers{
54313118SEdmund.Grimley-Evans@arm.com    if (!(a >> (FP64_MANT_BITS - 1) & 1)) {
54410037SARM gem5 Developers        *flags |= FPLIB_IOC;
54513118SEdmund.Grimley-Evans@arm.com        a |= 1ULL << (FP64_MANT_BITS - 1);
54610037SARM gem5 Developers    }
54710037SARM gem5 Developers    return mode & FPLIB_DN ? fp64_defaultNaN() : a;
54810037SARM gem5 Developers}
54910037SARM gem5 Developers
55013118SEdmund.Grimley-Evans@arm.comstatic uint16_t
55113118SEdmund.Grimley-Evans@arm.comfp16_process_NaNs(uint16_t a, uint16_t b, int mode, int *flags)
55213118SEdmund.Grimley-Evans@arm.com{
55313118SEdmund.Grimley-Evans@arm.com    int a_exp = FP16_EXP(a);
55413118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt = FP16_MANT(a);
55513118SEdmund.Grimley-Evans@arm.com    int b_exp = FP16_EXP(b);
55613118SEdmund.Grimley-Evans@arm.com    uint16_t b_mnt = FP16_MANT(b);
55713118SEdmund.Grimley-Evans@arm.com
55813118SEdmund.Grimley-Evans@arm.com    // Handle signalling NaNs:
55913118SEdmund.Grimley-Evans@arm.com    if (fp16_is_signalling_NaN(a_exp, a_mnt))
56013118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
56113118SEdmund.Grimley-Evans@arm.com    if (fp16_is_signalling_NaN(b_exp, b_mnt))
56213118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(b, mode, flags);
56313118SEdmund.Grimley-Evans@arm.com
56413118SEdmund.Grimley-Evans@arm.com    // Handle quiet NaNs:
56513118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt))
56613118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
56713118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(b_exp, b_mnt))
56813118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(b, mode, flags);
56913118SEdmund.Grimley-Evans@arm.com
57013118SEdmund.Grimley-Evans@arm.com    return 0;
57113118SEdmund.Grimley-Evans@arm.com}
57213118SEdmund.Grimley-Evans@arm.com
57310037SARM gem5 Developersstatic uint32_t
57410037SARM gem5 Developersfp32_process_NaNs(uint32_t a, uint32_t b, int mode, int *flags)
57510037SARM gem5 Developers{
57613118SEdmund.Grimley-Evans@arm.com    int a_exp = FP32_EXP(a);
57713118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt = FP32_MANT(a);
57813118SEdmund.Grimley-Evans@arm.com    int b_exp = FP32_EXP(b);
57913118SEdmund.Grimley-Evans@arm.com    uint32_t b_mnt = FP32_MANT(b);
58010037SARM gem5 Developers
58110037SARM gem5 Developers    // Handle signalling NaNs:
58213118SEdmund.Grimley-Evans@arm.com    if (fp32_is_signalling_NaN(a_exp, a_mnt))
58310037SARM gem5 Developers        return fp32_process_NaN(a, mode, flags);
58413118SEdmund.Grimley-Evans@arm.com    if (fp32_is_signalling_NaN(b_exp, b_mnt))
58510037SARM gem5 Developers        return fp32_process_NaN(b, mode, flags);
58610037SARM gem5 Developers
58710037SARM gem5 Developers    // Handle quiet NaNs:
58813118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt))
58910037SARM gem5 Developers        return fp32_process_NaN(a, mode, flags);
59013118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(b_exp, b_mnt))
59110037SARM gem5 Developers        return fp32_process_NaN(b, mode, flags);
59210037SARM gem5 Developers
59310037SARM gem5 Developers    return 0;
59410037SARM gem5 Developers}
59510037SARM gem5 Developers
59610037SARM gem5 Developersstatic uint64_t
59710037SARM gem5 Developersfp64_process_NaNs(uint64_t a, uint64_t b, int mode, int *flags)
59810037SARM gem5 Developers{
59913118SEdmund.Grimley-Evans@arm.com    int a_exp = FP64_EXP(a);
60013118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt = FP64_MANT(a);
60113118SEdmund.Grimley-Evans@arm.com    int b_exp = FP64_EXP(b);
60213118SEdmund.Grimley-Evans@arm.com    uint64_t b_mnt = FP64_MANT(b);
60310037SARM gem5 Developers
60410037SARM gem5 Developers    // Handle signalling NaNs:
60513118SEdmund.Grimley-Evans@arm.com    if (fp64_is_signalling_NaN(a_exp, a_mnt))
60610037SARM gem5 Developers        return fp64_process_NaN(a, mode, flags);
60713118SEdmund.Grimley-Evans@arm.com    if (fp64_is_signalling_NaN(b_exp, b_mnt))
60810037SARM gem5 Developers        return fp64_process_NaN(b, mode, flags);
60910037SARM gem5 Developers
61010037SARM gem5 Developers    // Handle quiet NaNs:
61113118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt))
61210037SARM gem5 Developers        return fp64_process_NaN(a, mode, flags);
61313118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(b_exp, b_mnt))
61410037SARM gem5 Developers        return fp64_process_NaN(b, mode, flags);
61510037SARM gem5 Developers
61610037SARM gem5 Developers    return 0;
61710037SARM gem5 Developers}
61810037SARM gem5 Developers
61913118SEdmund.Grimley-Evans@arm.comstatic uint16_t
62013118SEdmund.Grimley-Evans@arm.comfp16_process_NaNs3(uint16_t a, uint16_t b, uint16_t c, int mode, int *flags)
62113118SEdmund.Grimley-Evans@arm.com{
62213118SEdmund.Grimley-Evans@arm.com    int a_exp = FP16_EXP(a);
62313118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt = FP16_MANT(a);
62413118SEdmund.Grimley-Evans@arm.com    int b_exp = FP16_EXP(b);
62513118SEdmund.Grimley-Evans@arm.com    uint16_t b_mnt = FP16_MANT(b);
62613118SEdmund.Grimley-Evans@arm.com    int c_exp = FP16_EXP(c);
62713118SEdmund.Grimley-Evans@arm.com    uint16_t c_mnt = FP16_MANT(c);
62813118SEdmund.Grimley-Evans@arm.com
62913118SEdmund.Grimley-Evans@arm.com    // Handle signalling NaNs:
63013118SEdmund.Grimley-Evans@arm.com    if (fp16_is_signalling_NaN(a_exp, a_mnt))
63113118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
63213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_signalling_NaN(b_exp, b_mnt))
63313118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(b, mode, flags);
63413118SEdmund.Grimley-Evans@arm.com    if (fp16_is_signalling_NaN(c_exp, c_mnt))
63513118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(c, mode, flags);
63613118SEdmund.Grimley-Evans@arm.com
63713118SEdmund.Grimley-Evans@arm.com    // Handle quiet NaNs:
63813118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt))
63913118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
64013118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(b_exp, b_mnt))
64113118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(b, mode, flags);
64213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(c_exp, c_mnt))
64313118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(c, mode, flags);
64413118SEdmund.Grimley-Evans@arm.com
64513118SEdmund.Grimley-Evans@arm.com    return 0;
64613118SEdmund.Grimley-Evans@arm.com}
64713118SEdmund.Grimley-Evans@arm.com
64810037SARM gem5 Developersstatic uint32_t
64910037SARM gem5 Developersfp32_process_NaNs3(uint32_t a, uint32_t b, uint32_t c, int mode, int *flags)
65010037SARM gem5 Developers{
65113118SEdmund.Grimley-Evans@arm.com    int a_exp = FP32_EXP(a);
65213118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt = FP32_MANT(a);
65313118SEdmund.Grimley-Evans@arm.com    int b_exp = FP32_EXP(b);
65413118SEdmund.Grimley-Evans@arm.com    uint32_t b_mnt = FP32_MANT(b);
65513118SEdmund.Grimley-Evans@arm.com    int c_exp = FP32_EXP(c);
65613118SEdmund.Grimley-Evans@arm.com    uint32_t c_mnt = FP32_MANT(c);
65710037SARM gem5 Developers
65810037SARM gem5 Developers    // Handle signalling NaNs:
65913118SEdmund.Grimley-Evans@arm.com    if (fp32_is_signalling_NaN(a_exp, a_mnt))
66010037SARM gem5 Developers        return fp32_process_NaN(a, mode, flags);
66113118SEdmund.Grimley-Evans@arm.com    if (fp32_is_signalling_NaN(b_exp, b_mnt))
66210037SARM gem5 Developers        return fp32_process_NaN(b, mode, flags);
66313118SEdmund.Grimley-Evans@arm.com    if (fp32_is_signalling_NaN(c_exp, c_mnt))
66410037SARM gem5 Developers        return fp32_process_NaN(c, mode, flags);
66510037SARM gem5 Developers
66610037SARM gem5 Developers    // Handle quiet NaNs:
66713118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt))
66810037SARM gem5 Developers        return fp32_process_NaN(a, mode, flags);
66913118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(b_exp, b_mnt))
67010037SARM gem5 Developers        return fp32_process_NaN(b, mode, flags);
67113118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(c_exp, c_mnt))
67210037SARM gem5 Developers        return fp32_process_NaN(c, mode, flags);
67310037SARM gem5 Developers
67410037SARM gem5 Developers    return 0;
67510037SARM gem5 Developers}
67610037SARM gem5 Developers
67710037SARM gem5 Developersstatic uint64_t
67810037SARM gem5 Developersfp64_process_NaNs3(uint64_t a, uint64_t b, uint64_t c, int mode, int *flags)
67910037SARM gem5 Developers{
68013118SEdmund.Grimley-Evans@arm.com    int a_exp = FP64_EXP(a);
68113118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt = FP64_MANT(a);
68213118SEdmund.Grimley-Evans@arm.com    int b_exp = FP64_EXP(b);
68313118SEdmund.Grimley-Evans@arm.com    uint64_t b_mnt = FP64_MANT(b);
68413118SEdmund.Grimley-Evans@arm.com    int c_exp = FP64_EXP(c);
68513118SEdmund.Grimley-Evans@arm.com    uint64_t c_mnt = FP64_MANT(c);
68610037SARM gem5 Developers
68710037SARM gem5 Developers    // Handle signalling NaNs:
68813118SEdmund.Grimley-Evans@arm.com    if (fp64_is_signalling_NaN(a_exp, a_mnt))
68910037SARM gem5 Developers        return fp64_process_NaN(a, mode, flags);
69013118SEdmund.Grimley-Evans@arm.com    if (fp64_is_signalling_NaN(b_exp, b_mnt))
69110037SARM gem5 Developers        return fp64_process_NaN(b, mode, flags);
69213118SEdmund.Grimley-Evans@arm.com    if (fp64_is_signalling_NaN(c_exp, c_mnt))
69310037SARM gem5 Developers        return fp64_process_NaN(c, mode, flags);
69410037SARM gem5 Developers
69510037SARM gem5 Developers    // Handle quiet NaNs:
69613118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt))
69710037SARM gem5 Developers        return fp64_process_NaN(a, mode, flags);
69813118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(b_exp, b_mnt))
69910037SARM gem5 Developers        return fp64_process_NaN(b, mode, flags);
70013118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(c_exp, c_mnt))
70110037SARM gem5 Developers        return fp64_process_NaN(c, mode, flags);
70210037SARM gem5 Developers
70310037SARM gem5 Developers    return 0;
70410037SARM gem5 Developers}
70510037SARM gem5 Developers
70610037SARM gem5 Developersstatic uint16_t
70710037SARM gem5 Developersfp16_round_(int sgn, int exp, uint16_t mnt, int rm, int mode, int *flags)
70810037SARM gem5 Developers{
70910037SARM gem5 Developers    int biased_exp; // non-negative exponent value for result
71013118SEdmund.Grimley-Evans@arm.com    uint16_t int_mant; // mantissa for result, less than (2 << FP16_MANT_BITS)
71110037SARM gem5 Developers    int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
71210037SARM gem5 Developers
71310037SARM gem5 Developers    assert(rm != FPRounding_TIEAWAY);
71410037SARM gem5 Developers
71513118SEdmund.Grimley-Evans@arm.com    // Flush to zero:
71613118SEdmund.Grimley-Evans@arm.com    if ((mode & FPLIB_FZ16) && exp < 1) {
71713118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_UFC;
71813118SEdmund.Grimley-Evans@arm.com        return fp16_zero(sgn);
71913118SEdmund.Grimley-Evans@arm.com    }
72013118SEdmund.Grimley-Evans@arm.com
72113118SEdmund.Grimley-Evans@arm.com    // The bottom FP16_EXP_BITS bits of mnt are orred together:
72213118SEdmund.Grimley-Evans@arm.com    mnt = (4ULL << FP16_MANT_BITS | mnt >> (FP16_EXP_BITS - 1) |
72313118SEdmund.Grimley-Evans@arm.com           ((mnt & ((1ULL << FP16_EXP_BITS) - 1)) != 0));
72410037SARM gem5 Developers
72510037SARM gem5 Developers    if (exp > 0) {
72610037SARM gem5 Developers        biased_exp = exp;
72710037SARM gem5 Developers        int_mant = mnt >> 2;
72810037SARM gem5 Developers        error = mnt & 3;
72910037SARM gem5 Developers    } else {
73010037SARM gem5 Developers        biased_exp = 0;
73110037SARM gem5 Developers        int_mant = lsr16(mnt, 3 - exp);
73210037SARM gem5 Developers        error = (lsr16(mnt, 1 - exp) & 3) | !!(mnt & (lsl16(1, 1 - exp) - 1));
73310037SARM gem5 Developers    }
73410037SARM gem5 Developers
73510037SARM gem5 Developers    if (!biased_exp && error) { // xx should also check fpscr_val<11>
73610037SARM gem5 Developers        *flags |= FPLIB_UFC;
73710037SARM gem5 Developers    }
73810037SARM gem5 Developers
73910037SARM gem5 Developers    // Round up:
74010037SARM gem5 Developers    if ((rm == FPLIB_RN && (error == 3 ||
74110037SARM gem5 Developers                            (error == 2 && (int_mant & 1)))) ||
74210037SARM gem5 Developers        (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
74310037SARM gem5 Developers        ++int_mant;
74413118SEdmund.Grimley-Evans@arm.com        if (int_mant == 1ULL << FP16_MANT_BITS) {
74510037SARM gem5 Developers            // Rounded up from denormalized to normalized
74610037SARM gem5 Developers            biased_exp = 1;
74710037SARM gem5 Developers        }
74813118SEdmund.Grimley-Evans@arm.com        if (int_mant == 2ULL << FP16_MANT_BITS) {
74910037SARM gem5 Developers            // Rounded up to next exponent
75010037SARM gem5 Developers            ++biased_exp;
75110037SARM gem5 Developers            int_mant >>= 1;
75210037SARM gem5 Developers        }
75310037SARM gem5 Developers    }
75410037SARM gem5 Developers
75510037SARM gem5 Developers    // Handle rounding to odd aka Von Neumann rounding:
75610037SARM gem5 Developers    if (error && rm == FPRounding_ODD)
75710037SARM gem5 Developers        int_mant |= 1;
75810037SARM gem5 Developers
75910037SARM gem5 Developers    // Handle overflow:
76010037SARM gem5 Developers    if (!(mode & FPLIB_AHP)) {
76113118SEdmund.Grimley-Evans@arm.com        if (biased_exp >= (int)FP16_EXP_INF) {
76210037SARM gem5 Developers            *flags |= FPLIB_OFC | FPLIB_IXC;
76310037SARM gem5 Developers            if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
76410037SARM gem5 Developers                (rm == FPLIB_RM && sgn)) {
76510037SARM gem5 Developers                return fp16_infinity(sgn);
76610037SARM gem5 Developers            } else {
76710037SARM gem5 Developers                return fp16_max_normal(sgn);
76810037SARM gem5 Developers            }
76910037SARM gem5 Developers        }
77010037SARM gem5 Developers    } else {
77113118SEdmund.Grimley-Evans@arm.com        if (biased_exp >= (int)FP16_EXP_INF + 1) {
77210037SARM gem5 Developers            *flags |= FPLIB_IOC;
77313118SEdmund.Grimley-Evans@arm.com            return fp16_pack(sgn, FP16_EXP_INF, -1);
77410037SARM gem5 Developers        }
77510037SARM gem5 Developers    }
77610037SARM gem5 Developers
77710037SARM gem5 Developers    if (error) {
77810037SARM gem5 Developers        *flags |= FPLIB_IXC;
77910037SARM gem5 Developers    }
78010037SARM gem5 Developers
78110037SARM gem5 Developers    return fp16_pack(sgn, biased_exp, int_mant);
78210037SARM gem5 Developers}
78310037SARM gem5 Developers
78413118SEdmund.Grimley-Evans@arm.comstatic uint16_t
78513118SEdmund.Grimley-Evans@arm.comfp16_round(int sgn, int exp, uint16_t mnt, int mode, int *flags)
78613118SEdmund.Grimley-Evans@arm.com{
78713118SEdmund.Grimley-Evans@arm.com    return fp16_round_(sgn, exp, mnt, mode & 3, mode, flags);
78813118SEdmund.Grimley-Evans@arm.com}
78913118SEdmund.Grimley-Evans@arm.com
79010037SARM gem5 Developersstatic uint32_t
79110037SARM gem5 Developersfp32_round_(int sgn, int exp, uint32_t mnt, int rm, int mode, int *flags)
79210037SARM gem5 Developers{
79310037SARM gem5 Developers    int biased_exp; // non-negative exponent value for result
79413118SEdmund.Grimley-Evans@arm.com    uint32_t int_mant; // mantissa for result, less than (2 << FP32_MANT_BITS)
79510037SARM gem5 Developers    int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
79610037SARM gem5 Developers
79710037SARM gem5 Developers    assert(rm != FPRounding_TIEAWAY);
79810037SARM gem5 Developers
79910037SARM gem5 Developers    // Flush to zero:
80010037SARM gem5 Developers    if ((mode & FPLIB_FZ) && exp < 1) {
80110037SARM gem5 Developers        *flags |= FPLIB_UFC;
80210037SARM gem5 Developers        return fp32_zero(sgn);
80310037SARM gem5 Developers    }
80410037SARM gem5 Developers
80513118SEdmund.Grimley-Evans@arm.com    // The bottom FP32_EXP_BITS bits of mnt are orred together:
80613118SEdmund.Grimley-Evans@arm.com    mnt = (4ULL << FP32_MANT_BITS | mnt >> (FP32_EXP_BITS - 1) |
80713118SEdmund.Grimley-Evans@arm.com           ((mnt & ((1ULL << FP32_EXP_BITS) - 1)) != 0));
80810037SARM gem5 Developers
80910037SARM gem5 Developers    if (exp > 0) {
81010037SARM gem5 Developers        biased_exp = exp;
81110037SARM gem5 Developers        int_mant = mnt >> 2;
81210037SARM gem5 Developers        error = mnt & 3;
81310037SARM gem5 Developers    } else {
81410037SARM gem5 Developers        biased_exp = 0;
81510037SARM gem5 Developers        int_mant = lsr32(mnt, 3 - exp);
81610037SARM gem5 Developers        error = (lsr32(mnt, 1 - exp) & 3) | !!(mnt & (lsl32(1, 1 - exp) - 1));
81710037SARM gem5 Developers    }
81810037SARM gem5 Developers
81910037SARM gem5 Developers    if (!biased_exp && error) { // xx should also check fpscr_val<11>
82010037SARM gem5 Developers        *flags |= FPLIB_UFC;
82110037SARM gem5 Developers    }
82210037SARM gem5 Developers
82310037SARM gem5 Developers    // Round up:
82410037SARM gem5 Developers    if ((rm == FPLIB_RN && (error == 3 ||
82510037SARM gem5 Developers                            (error == 2 && (int_mant & 1)))) ||
82610037SARM gem5 Developers        (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
82710037SARM gem5 Developers        ++int_mant;
82813118SEdmund.Grimley-Evans@arm.com        if (int_mant == 1ULL << FP32_MANT_BITS) {
82910037SARM gem5 Developers            // Rounded up from denormalized to normalized
83010037SARM gem5 Developers            biased_exp = 1;
83110037SARM gem5 Developers        }
83213118SEdmund.Grimley-Evans@arm.com        if (int_mant == 2ULL << FP32_MANT_BITS) {
83310037SARM gem5 Developers            // Rounded up to next exponent
83410037SARM gem5 Developers            ++biased_exp;
83510037SARM gem5 Developers            int_mant >>= 1;
83610037SARM gem5 Developers        }
83710037SARM gem5 Developers    }
83810037SARM gem5 Developers
83910037SARM gem5 Developers    // Handle rounding to odd aka Von Neumann rounding:
84010037SARM gem5 Developers    if (error && rm == FPRounding_ODD)
84110037SARM gem5 Developers        int_mant |= 1;
84210037SARM gem5 Developers
84310037SARM gem5 Developers    // Handle overflow:
84413118SEdmund.Grimley-Evans@arm.com    if (biased_exp >= (int)FP32_EXP_INF) {
84510037SARM gem5 Developers        *flags |= FPLIB_OFC | FPLIB_IXC;
84610037SARM gem5 Developers        if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
84710037SARM gem5 Developers            (rm == FPLIB_RM && sgn)) {
84810037SARM gem5 Developers            return fp32_infinity(sgn);
84910037SARM gem5 Developers        } else {
85010037SARM gem5 Developers            return fp32_max_normal(sgn);
85110037SARM gem5 Developers        }
85210037SARM gem5 Developers    }
85310037SARM gem5 Developers
85410037SARM gem5 Developers    if (error) {
85510037SARM gem5 Developers        *flags |= FPLIB_IXC;
85610037SARM gem5 Developers    }
85710037SARM gem5 Developers
85810037SARM gem5 Developers    return fp32_pack(sgn, biased_exp, int_mant);
85910037SARM gem5 Developers}
86010037SARM gem5 Developers
86110037SARM gem5 Developersstatic uint32_t
86210037SARM gem5 Developersfp32_round(int sgn, int exp, uint32_t mnt, int mode, int *flags)
86310037SARM gem5 Developers{
86410037SARM gem5 Developers    return fp32_round_(sgn, exp, mnt, mode & 3, mode, flags);
86510037SARM gem5 Developers}
86610037SARM gem5 Developers
86710037SARM gem5 Developersstatic uint64_t
86810037SARM gem5 Developersfp64_round_(int sgn, int exp, uint64_t mnt, int rm, int mode, int *flags)
86910037SARM gem5 Developers{
87010037SARM gem5 Developers    int biased_exp; // non-negative exponent value for result
87113118SEdmund.Grimley-Evans@arm.com    uint64_t int_mant; // mantissa for result, less than (2 << FP64_MANT_BITS)
87210037SARM gem5 Developers    int error; // 0, 1, 2 or 3, where 2 means int_mant is wrong by exactly 0.5
87310037SARM gem5 Developers
87410037SARM gem5 Developers    assert(rm != FPRounding_TIEAWAY);
87510037SARM gem5 Developers
87610037SARM gem5 Developers    // Flush to zero:
87710037SARM gem5 Developers    if ((mode & FPLIB_FZ) && exp < 1) {
87810037SARM gem5 Developers        *flags |= FPLIB_UFC;
87910037SARM gem5 Developers        return fp64_zero(sgn);
88010037SARM gem5 Developers    }
88110037SARM gem5 Developers
88213118SEdmund.Grimley-Evans@arm.com    // The bottom FP64_EXP_BITS bits of mnt are orred together:
88313118SEdmund.Grimley-Evans@arm.com    mnt = (4ULL << FP64_MANT_BITS | mnt >> (FP64_EXP_BITS - 1) |
88413118SEdmund.Grimley-Evans@arm.com           ((mnt & ((1ULL << FP64_EXP_BITS) - 1)) != 0));
88510037SARM gem5 Developers
88610037SARM gem5 Developers    if (exp > 0) {
88710037SARM gem5 Developers        biased_exp = exp;
88810037SARM gem5 Developers        int_mant = mnt >> 2;
88910037SARM gem5 Developers        error = mnt & 3;
89010037SARM gem5 Developers    } else {
89110037SARM gem5 Developers        biased_exp = 0;
89210037SARM gem5 Developers        int_mant = lsr64(mnt, 3 - exp);
89310037SARM gem5 Developers        error = (lsr64(mnt, 1 - exp) & 3) | !!(mnt & (lsl64(1, 1 - exp) - 1));
89410037SARM gem5 Developers    }
89510037SARM gem5 Developers
89610037SARM gem5 Developers    if (!biased_exp && error) { // xx should also check fpscr_val<11>
89710037SARM gem5 Developers        *flags |= FPLIB_UFC;
89810037SARM gem5 Developers    }
89910037SARM gem5 Developers
90010037SARM gem5 Developers    // Round up:
90110037SARM gem5 Developers    if ((rm == FPLIB_RN && (error == 3 ||
90210037SARM gem5 Developers                            (error == 2 && (int_mant & 1)))) ||
90310037SARM gem5 Developers        (((rm == FPLIB_RP && !sgn) || (rm == FPLIB_RM && sgn)) && error)) {
90410037SARM gem5 Developers        ++int_mant;
90513118SEdmund.Grimley-Evans@arm.com        if (int_mant == 1ULL << FP64_MANT_BITS) {
90610037SARM gem5 Developers            // Rounded up from denormalized to normalized
90710037SARM gem5 Developers            biased_exp = 1;
90810037SARM gem5 Developers        }
90913118SEdmund.Grimley-Evans@arm.com        if (int_mant == 2ULL << FP64_MANT_BITS) {
91010037SARM gem5 Developers            // Rounded up to next exponent
91110037SARM gem5 Developers            ++biased_exp;
91210037SARM gem5 Developers            int_mant >>= 1;
91310037SARM gem5 Developers        }
91410037SARM gem5 Developers    }
91510037SARM gem5 Developers
91610037SARM gem5 Developers    // Handle rounding to odd aka Von Neumann rounding:
91710037SARM gem5 Developers    if (error && rm == FPRounding_ODD)
91810037SARM gem5 Developers        int_mant |= 1;
91910037SARM gem5 Developers
92010037SARM gem5 Developers    // Handle overflow:
92113118SEdmund.Grimley-Evans@arm.com    if (biased_exp >= (int)FP64_EXP_INF) {
92210037SARM gem5 Developers        *flags |= FPLIB_OFC | FPLIB_IXC;
92310037SARM gem5 Developers        if (rm == FPLIB_RN || (rm == FPLIB_RP && !sgn) ||
92410037SARM gem5 Developers            (rm == FPLIB_RM && sgn)) {
92510037SARM gem5 Developers            return fp64_infinity(sgn);
92610037SARM gem5 Developers        } else {
92710037SARM gem5 Developers            return fp64_max_normal(sgn);
92810037SARM gem5 Developers        }
92910037SARM gem5 Developers    }
93010037SARM gem5 Developers
93110037SARM gem5 Developers    if (error) {
93210037SARM gem5 Developers        *flags |= FPLIB_IXC;
93310037SARM gem5 Developers    }
93410037SARM gem5 Developers
93510037SARM gem5 Developers    return fp64_pack(sgn, biased_exp, int_mant);
93610037SARM gem5 Developers}
93710037SARM gem5 Developers
93810037SARM gem5 Developersstatic uint64_t
93910037SARM gem5 Developersfp64_round(int sgn, int exp, uint64_t mnt, int mode, int *flags)
94010037SARM gem5 Developers{
94110037SARM gem5 Developers    return fp64_round_(sgn, exp, mnt, mode & 3, mode, flags);
94210037SARM gem5 Developers}
94310037SARM gem5 Developers
94410037SARM gem5 Developersstatic int
94513118SEdmund.Grimley-Evans@arm.comfp16_compare_eq(uint16_t a, uint16_t b, int mode, int *flags)
94610037SARM gem5 Developers{
94710037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
94813118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt;
94913118SEdmund.Grimley-Evans@arm.com
95013118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
95113118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
95213118SEdmund.Grimley-Evans@arm.com
95313118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt) ||
95413118SEdmund.Grimley-Evans@arm.com        fp16_is_NaN(b_exp, b_mnt)) {
95513118SEdmund.Grimley-Evans@arm.com        if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
95613118SEdmund.Grimley-Evans@arm.com            fp16_is_signalling_NaN(b_exp, b_mnt))
95710037SARM gem5 Developers            *flags |= FPLIB_IOC;
95810037SARM gem5 Developers        return 0;
95910037SARM gem5 Developers    }
96010037SARM gem5 Developers    return a == b || (!a_mnt && !b_mnt);
96110037SARM gem5 Developers}
96210037SARM gem5 Developers
96310037SARM gem5 Developersstatic int
96413118SEdmund.Grimley-Evans@arm.comfp16_compare_ge(uint16_t a, uint16_t b, int mode, int *flags)
96510037SARM gem5 Developers{
96610037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
96713118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt;
96813118SEdmund.Grimley-Evans@arm.com
96913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
97013118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
97113118SEdmund.Grimley-Evans@arm.com
97213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt) ||
97313118SEdmund.Grimley-Evans@arm.com        fp16_is_NaN(b_exp, b_mnt)) {
97410037SARM gem5 Developers        *flags |= FPLIB_IOC;
97510037SARM gem5 Developers        return 0;
97610037SARM gem5 Developers    }
97710037SARM gem5 Developers    if (!a_mnt && !b_mnt)
97810037SARM gem5 Developers        return 1;
97910037SARM gem5 Developers    if (a_sgn != b_sgn)
98010037SARM gem5 Developers        return b_sgn;
98110037SARM gem5 Developers    if (a_exp != b_exp)
98210037SARM gem5 Developers        return a_sgn ^ (a_exp > b_exp);
98310037SARM gem5 Developers    if (a_mnt != b_mnt)
98410037SARM gem5 Developers        return a_sgn ^ (a_mnt > b_mnt);
98510037SARM gem5 Developers    return 1;
98610037SARM gem5 Developers}
98710037SARM gem5 Developers
98810037SARM gem5 Developersstatic int
98913118SEdmund.Grimley-Evans@arm.comfp16_compare_gt(uint16_t a, uint16_t b, int mode, int *flags)
99010037SARM gem5 Developers{
99110037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
99213118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt;
99313118SEdmund.Grimley-Evans@arm.com
99413118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
99513118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
99613118SEdmund.Grimley-Evans@arm.com
99713118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt) ||
99813118SEdmund.Grimley-Evans@arm.com        fp16_is_NaN(b_exp, b_mnt)) {
99910037SARM gem5 Developers        *flags |= FPLIB_IOC;
100010037SARM gem5 Developers        return 0;
100110037SARM gem5 Developers    }
100210037SARM gem5 Developers    if (!a_mnt && !b_mnt)
100310037SARM gem5 Developers        return 0;
100410037SARM gem5 Developers    if (a_sgn != b_sgn)
100510037SARM gem5 Developers        return b_sgn;
100610037SARM gem5 Developers    if (a_exp != b_exp)
100710037SARM gem5 Developers        return a_sgn ^ (a_exp > b_exp);
100810037SARM gem5 Developers    if (a_mnt != b_mnt)
100910037SARM gem5 Developers        return a_sgn ^ (a_mnt > b_mnt);
101010037SARM gem5 Developers    return 0;
101110037SARM gem5 Developers}
101210037SARM gem5 Developers
101310037SARM gem5 Developersstatic int
101413118SEdmund.Grimley-Evans@arm.comfp16_compare_un(uint16_t a, uint16_t b, int mode, int *flags)
101510037SARM gem5 Developers{
101610037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
101713118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt;
101813118SEdmund.Grimley-Evans@arm.com
101913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
102013118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
102113118SEdmund.Grimley-Evans@arm.com
102213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt) ||
102313118SEdmund.Grimley-Evans@arm.com        fp16_is_NaN(b_exp, b_mnt)) {
102413118SEdmund.Grimley-Evans@arm.com        if (fp16_is_signalling_NaN(a_exp, a_mnt) ||
102513118SEdmund.Grimley-Evans@arm.com            fp16_is_signalling_NaN(b_exp, b_mnt))
102613118SEdmund.Grimley-Evans@arm.com            *flags |= FPLIB_IOC;
102713118SEdmund.Grimley-Evans@arm.com        return 1;
102813118SEdmund.Grimley-Evans@arm.com    }
102913118SEdmund.Grimley-Evans@arm.com    return 0;
103013118SEdmund.Grimley-Evans@arm.com}
103113118SEdmund.Grimley-Evans@arm.com
103213118SEdmund.Grimley-Evans@arm.comstatic int
103313118SEdmund.Grimley-Evans@arm.comfp32_compare_eq(uint32_t a, uint32_t b, int mode, int *flags)
103413118SEdmund.Grimley-Evans@arm.com{
103513118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
103613118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt, b_mnt;
103713118SEdmund.Grimley-Evans@arm.com
103813118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
103913118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
104013118SEdmund.Grimley-Evans@arm.com
104113118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt) ||
104213118SEdmund.Grimley-Evans@arm.com        fp32_is_NaN(b_exp, b_mnt)) {
104313118SEdmund.Grimley-Evans@arm.com        if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
104413118SEdmund.Grimley-Evans@arm.com            fp32_is_signalling_NaN(b_exp, b_mnt))
104510037SARM gem5 Developers            *flags |= FPLIB_IOC;
104610037SARM gem5 Developers        return 0;
104710037SARM gem5 Developers    }
104810037SARM gem5 Developers    return a == b || (!a_mnt && !b_mnt);
104910037SARM gem5 Developers}
105010037SARM gem5 Developers
105110037SARM gem5 Developersstatic int
105213118SEdmund.Grimley-Evans@arm.comfp32_compare_ge(uint32_t a, uint32_t b, int mode, int *flags)
105310037SARM gem5 Developers{
105410037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
105513118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt, b_mnt;
105613118SEdmund.Grimley-Evans@arm.com
105713118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
105813118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
105913118SEdmund.Grimley-Evans@arm.com
106013118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt) ||
106113118SEdmund.Grimley-Evans@arm.com        fp32_is_NaN(b_exp, b_mnt)) {
106210037SARM gem5 Developers        *flags |= FPLIB_IOC;
106310037SARM gem5 Developers        return 0;
106410037SARM gem5 Developers    }
106510037SARM gem5 Developers    if (!a_mnt && !b_mnt)
106610037SARM gem5 Developers        return 1;
106710037SARM gem5 Developers    if (a_sgn != b_sgn)
106810037SARM gem5 Developers        return b_sgn;
106910037SARM gem5 Developers    if (a_exp != b_exp)
107010037SARM gem5 Developers        return a_sgn ^ (a_exp > b_exp);
107110037SARM gem5 Developers    if (a_mnt != b_mnt)
107210037SARM gem5 Developers        return a_sgn ^ (a_mnt > b_mnt);
107310037SARM gem5 Developers    return 1;
107410037SARM gem5 Developers}
107510037SARM gem5 Developers
107610037SARM gem5 Developersstatic int
107713118SEdmund.Grimley-Evans@arm.comfp32_compare_gt(uint32_t a, uint32_t b, int mode, int *flags)
107810037SARM gem5 Developers{
107910037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp;
108013118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt, b_mnt;
108113118SEdmund.Grimley-Evans@arm.com
108213118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
108313118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
108413118SEdmund.Grimley-Evans@arm.com
108513118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt) ||
108613118SEdmund.Grimley-Evans@arm.com        fp32_is_NaN(b_exp, b_mnt)) {
108710037SARM gem5 Developers        *flags |= FPLIB_IOC;
108810037SARM gem5 Developers        return 0;
108910037SARM gem5 Developers    }
109010037SARM gem5 Developers    if (!a_mnt && !b_mnt)
109110037SARM gem5 Developers        return 0;
109210037SARM gem5 Developers    if (a_sgn != b_sgn)
109310037SARM gem5 Developers        return b_sgn;
109410037SARM gem5 Developers    if (a_exp != b_exp)
109510037SARM gem5 Developers        return a_sgn ^ (a_exp > b_exp);
109610037SARM gem5 Developers    if (a_mnt != b_mnt)
109710037SARM gem5 Developers        return a_sgn ^ (a_mnt > b_mnt);
109810037SARM gem5 Developers    return 0;
109910037SARM gem5 Developers}
110010037SARM gem5 Developers
110113118SEdmund.Grimley-Evans@arm.comstatic int
110213118SEdmund.Grimley-Evans@arm.comfp32_compare_un(uint32_t a, uint32_t b, int mode, int *flags)
110313118SEdmund.Grimley-Evans@arm.com{
110413118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
110513118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt, b_mnt;
110613118SEdmund.Grimley-Evans@arm.com
110713118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
110813118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
110913118SEdmund.Grimley-Evans@arm.com
111013118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt) ||
111113118SEdmund.Grimley-Evans@arm.com        fp32_is_NaN(b_exp, b_mnt)) {
111213118SEdmund.Grimley-Evans@arm.com        if (fp32_is_signalling_NaN(a_exp, a_mnt) ||
111313118SEdmund.Grimley-Evans@arm.com            fp32_is_signalling_NaN(b_exp, b_mnt))
111413118SEdmund.Grimley-Evans@arm.com            *flags |= FPLIB_IOC;
111513118SEdmund.Grimley-Evans@arm.com        return 1;
111613118SEdmund.Grimley-Evans@arm.com    }
111713118SEdmund.Grimley-Evans@arm.com    return 0;
111813118SEdmund.Grimley-Evans@arm.com}
111913118SEdmund.Grimley-Evans@arm.com
112013118SEdmund.Grimley-Evans@arm.comstatic int
112113118SEdmund.Grimley-Evans@arm.comfp64_compare_eq(uint64_t a, uint64_t b, int mode, int *flags)
112213118SEdmund.Grimley-Evans@arm.com{
112313118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
112413118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt, b_mnt;
112513118SEdmund.Grimley-Evans@arm.com
112613118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
112713118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
112813118SEdmund.Grimley-Evans@arm.com
112913118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt) ||
113013118SEdmund.Grimley-Evans@arm.com        fp64_is_NaN(b_exp, b_mnt)) {
113113118SEdmund.Grimley-Evans@arm.com        if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
113213118SEdmund.Grimley-Evans@arm.com            fp64_is_signalling_NaN(b_exp, b_mnt))
113313118SEdmund.Grimley-Evans@arm.com            *flags |= FPLIB_IOC;
113413118SEdmund.Grimley-Evans@arm.com        return 0;
113513118SEdmund.Grimley-Evans@arm.com    }
113613118SEdmund.Grimley-Evans@arm.com    return a == b || (!a_mnt && !b_mnt);
113713118SEdmund.Grimley-Evans@arm.com}
113813118SEdmund.Grimley-Evans@arm.com
113913118SEdmund.Grimley-Evans@arm.comstatic int
114013118SEdmund.Grimley-Evans@arm.comfp64_compare_ge(uint64_t a, uint64_t b, int mode, int *flags)
114113118SEdmund.Grimley-Evans@arm.com{
114213118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
114313118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt, b_mnt;
114413118SEdmund.Grimley-Evans@arm.com
114513118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
114613118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
114713118SEdmund.Grimley-Evans@arm.com
114813118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt) ||
114913118SEdmund.Grimley-Evans@arm.com        fp64_is_NaN(b_exp, b_mnt)) {
115013118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
115113118SEdmund.Grimley-Evans@arm.com        return 0;
115213118SEdmund.Grimley-Evans@arm.com    }
115313118SEdmund.Grimley-Evans@arm.com    if (!a_mnt && !b_mnt)
115413118SEdmund.Grimley-Evans@arm.com        return 1;
115513118SEdmund.Grimley-Evans@arm.com    if (a_sgn != b_sgn)
115613118SEdmund.Grimley-Evans@arm.com        return b_sgn;
115713118SEdmund.Grimley-Evans@arm.com    if (a_exp != b_exp)
115813118SEdmund.Grimley-Evans@arm.com        return a_sgn ^ (a_exp > b_exp);
115913118SEdmund.Grimley-Evans@arm.com    if (a_mnt != b_mnt)
116013118SEdmund.Grimley-Evans@arm.com        return a_sgn ^ (a_mnt > b_mnt);
116113118SEdmund.Grimley-Evans@arm.com    return 1;
116213118SEdmund.Grimley-Evans@arm.com}
116313118SEdmund.Grimley-Evans@arm.com
116413118SEdmund.Grimley-Evans@arm.comstatic int
116513118SEdmund.Grimley-Evans@arm.comfp64_compare_gt(uint64_t a, uint64_t b, int mode, int *flags)
116613118SEdmund.Grimley-Evans@arm.com{
116713118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
116813118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt, b_mnt;
116913118SEdmund.Grimley-Evans@arm.com
117013118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
117113118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
117213118SEdmund.Grimley-Evans@arm.com
117313118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt) ||
117413118SEdmund.Grimley-Evans@arm.com        fp64_is_NaN(b_exp, b_mnt)) {
117513118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
117613118SEdmund.Grimley-Evans@arm.com        return 0;
117713118SEdmund.Grimley-Evans@arm.com    }
117813118SEdmund.Grimley-Evans@arm.com    if (!a_mnt && !b_mnt)
117913118SEdmund.Grimley-Evans@arm.com        return 0;
118013118SEdmund.Grimley-Evans@arm.com    if (a_sgn != b_sgn)
118113118SEdmund.Grimley-Evans@arm.com        return b_sgn;
118213118SEdmund.Grimley-Evans@arm.com    if (a_exp != b_exp)
118313118SEdmund.Grimley-Evans@arm.com        return a_sgn ^ (a_exp > b_exp);
118413118SEdmund.Grimley-Evans@arm.com    if (a_mnt != b_mnt)
118513118SEdmund.Grimley-Evans@arm.com        return a_sgn ^ (a_mnt > b_mnt);
118613118SEdmund.Grimley-Evans@arm.com    return 0;
118713118SEdmund.Grimley-Evans@arm.com}
118813118SEdmund.Grimley-Evans@arm.com
118913118SEdmund.Grimley-Evans@arm.comstatic int
119013118SEdmund.Grimley-Evans@arm.comfp64_compare_un(uint64_t a, uint64_t b, int mode, int *flags)
119113118SEdmund.Grimley-Evans@arm.com{
119213118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp;
119313118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt, b_mnt;
119413118SEdmund.Grimley-Evans@arm.com
119513118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
119613118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
119713118SEdmund.Grimley-Evans@arm.com
119813118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt) ||
119913118SEdmund.Grimley-Evans@arm.com        fp64_is_NaN(b_exp, b_mnt)) {
120013118SEdmund.Grimley-Evans@arm.com        if (fp64_is_signalling_NaN(a_exp, a_mnt) ||
120113118SEdmund.Grimley-Evans@arm.com            fp64_is_signalling_NaN(b_exp, b_mnt))
120213118SEdmund.Grimley-Evans@arm.com            *flags |= FPLIB_IOC;
120313118SEdmund.Grimley-Evans@arm.com        return 1;
120413118SEdmund.Grimley-Evans@arm.com    }
120513118SEdmund.Grimley-Evans@arm.com    return 0;
120613118SEdmund.Grimley-Evans@arm.com}
120713118SEdmund.Grimley-Evans@arm.com
120813118SEdmund.Grimley-Evans@arm.comstatic uint16_t
120913118SEdmund.Grimley-Evans@arm.comfp16_add(uint16_t a, uint16_t b, int neg, int mode, int *flags)
121013118SEdmund.Grimley-Evans@arm.com{
121113118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
121213118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt, x, x_mnt;
121313118SEdmund.Grimley-Evans@arm.com
121413118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
121513118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
121613118SEdmund.Grimley-Evans@arm.com
121713118SEdmund.Grimley-Evans@arm.com    if ((x = fp16_process_NaNs(a, b, mode, flags))) {
121813118SEdmund.Grimley-Evans@arm.com        return x;
121913118SEdmund.Grimley-Evans@arm.com    }
122013118SEdmund.Grimley-Evans@arm.com
122113118SEdmund.Grimley-Evans@arm.com    b_sgn ^= neg;
122213118SEdmund.Grimley-Evans@arm.com
122313118SEdmund.Grimley-Evans@arm.com    // Handle infinities and zeroes:
122413118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF && a_sgn != b_sgn) {
122513118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
122613118SEdmund.Grimley-Evans@arm.com        return fp16_defaultNaN();
122713118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP16_EXP_INF) {
122813118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn);
122913118SEdmund.Grimley-Evans@arm.com    } else if (b_exp == FP16_EXP_INF) {
123013118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(b_sgn);
123113118SEdmund.Grimley-Evans@arm.com    } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
123213118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn);
123313118SEdmund.Grimley-Evans@arm.com    }
123413118SEdmund.Grimley-Evans@arm.com
123513118SEdmund.Grimley-Evans@arm.com    a_mnt <<= 3;
123613118SEdmund.Grimley-Evans@arm.com    b_mnt <<= 3;
123713118SEdmund.Grimley-Evans@arm.com    if (a_exp >= b_exp) {
123813118SEdmund.Grimley-Evans@arm.com        b_mnt = (lsr16(b_mnt, a_exp - b_exp) |
123913118SEdmund.Grimley-Evans@arm.com                 !!(b_mnt & (lsl16(1, a_exp - b_exp) - 1)));
124013118SEdmund.Grimley-Evans@arm.com        b_exp = a_exp;
124113118SEdmund.Grimley-Evans@arm.com    } else {
124213118SEdmund.Grimley-Evans@arm.com        a_mnt = (lsr16(a_mnt, b_exp - a_exp) |
124313118SEdmund.Grimley-Evans@arm.com                 !!(a_mnt & (lsl16(1, b_exp - a_exp) - 1)));
124413118SEdmund.Grimley-Evans@arm.com        a_exp = b_exp;
124513118SEdmund.Grimley-Evans@arm.com    }
124613118SEdmund.Grimley-Evans@arm.com    x_sgn = a_sgn;
124713118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp;
124813118SEdmund.Grimley-Evans@arm.com    if (a_sgn == b_sgn) {
124913118SEdmund.Grimley-Evans@arm.com        x_mnt = a_mnt + b_mnt;
125013118SEdmund.Grimley-Evans@arm.com    } else if (a_mnt >= b_mnt) {
125113118SEdmund.Grimley-Evans@arm.com        x_mnt = a_mnt - b_mnt;
125213118SEdmund.Grimley-Evans@arm.com    } else {
125313118SEdmund.Grimley-Evans@arm.com        x_sgn ^= 1;
125413118SEdmund.Grimley-Evans@arm.com        x_mnt = b_mnt - a_mnt;
125513118SEdmund.Grimley-Evans@arm.com    }
125613118SEdmund.Grimley-Evans@arm.com
125713118SEdmund.Grimley-Evans@arm.com    if (!x_mnt) {
125813118SEdmund.Grimley-Evans@arm.com        // Sign of exact zero result depends on rounding mode
125913118SEdmund.Grimley-Evans@arm.com        return fp16_zero((mode & 3) == 2);
126013118SEdmund.Grimley-Evans@arm.com    }
126113118SEdmund.Grimley-Evans@arm.com
126213118SEdmund.Grimley-Evans@arm.com    x_mnt = fp16_normalise(x_mnt, &x_exp);
126313118SEdmund.Grimley-Evans@arm.com
126413118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp + FP16_EXP_BITS - 3, x_mnt << 1,
126513118SEdmund.Grimley-Evans@arm.com                      mode, flags);
126613118SEdmund.Grimley-Evans@arm.com}
126713118SEdmund.Grimley-Evans@arm.com
126810037SARM gem5 Developersstatic uint32_t
126910037SARM gem5 Developersfp32_add(uint32_t a, uint32_t b, int neg, int mode, int *flags)
127010037SARM gem5 Developers{
127110037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
127210037SARM gem5 Developers    uint32_t a_mnt, b_mnt, x, x_mnt;
127310037SARM gem5 Developers
127410037SARM gem5 Developers    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
127510037SARM gem5 Developers    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
127610037SARM gem5 Developers
127710037SARM gem5 Developers    if ((x = fp32_process_NaNs(a, b, mode, flags))) {
127810037SARM gem5 Developers        return x;
127910037SARM gem5 Developers    }
128010037SARM gem5 Developers
128110037SARM gem5 Developers    b_sgn ^= neg;
128210037SARM gem5 Developers
128310037SARM gem5 Developers    // Handle infinities and zeroes:
128413118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF && a_sgn != b_sgn) {
128510037SARM gem5 Developers        *flags |= FPLIB_IOC;
128610037SARM gem5 Developers        return fp32_defaultNaN();
128713118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP32_EXP_INF) {
128810037SARM gem5 Developers        return fp32_infinity(a_sgn);
128913118SEdmund.Grimley-Evans@arm.com    } else if (b_exp == FP32_EXP_INF) {
129010037SARM gem5 Developers        return fp32_infinity(b_sgn);
129110037SARM gem5 Developers    } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
129210037SARM gem5 Developers        return fp32_zero(a_sgn);
129310037SARM gem5 Developers    }
129410037SARM gem5 Developers
129510037SARM gem5 Developers    a_mnt <<= 3;
129610037SARM gem5 Developers    b_mnt <<= 3;
129710037SARM gem5 Developers    if (a_exp >= b_exp) {
129810037SARM gem5 Developers        b_mnt = (lsr32(b_mnt, a_exp - b_exp) |
129910037SARM gem5 Developers                 !!(b_mnt & (lsl32(1, a_exp - b_exp) - 1)));
130010037SARM gem5 Developers        b_exp = a_exp;
130110037SARM gem5 Developers    } else {
130210037SARM gem5 Developers        a_mnt = (lsr32(a_mnt, b_exp - a_exp) |
130310037SARM gem5 Developers                 !!(a_mnt & (lsl32(1, b_exp - a_exp) - 1)));
130410037SARM gem5 Developers        a_exp = b_exp;
130510037SARM gem5 Developers    }
130610037SARM gem5 Developers    x_sgn = a_sgn;
130710037SARM gem5 Developers    x_exp = a_exp;
130810037SARM gem5 Developers    if (a_sgn == b_sgn) {
130910037SARM gem5 Developers        x_mnt = a_mnt + b_mnt;
131010037SARM gem5 Developers    } else if (a_mnt >= b_mnt) {
131110037SARM gem5 Developers        x_mnt = a_mnt - b_mnt;
131210037SARM gem5 Developers    } else {
131310037SARM gem5 Developers        x_sgn ^= 1;
131410037SARM gem5 Developers        x_mnt = b_mnt - a_mnt;
131510037SARM gem5 Developers    }
131610037SARM gem5 Developers
131710037SARM gem5 Developers    if (!x_mnt) {
131810037SARM gem5 Developers        // Sign of exact zero result depends on rounding mode
131910037SARM gem5 Developers        return fp32_zero((mode & 3) == 2);
132010037SARM gem5 Developers    }
132110037SARM gem5 Developers
132210037SARM gem5 Developers    x_mnt = fp32_normalise(x_mnt, &x_exp);
132310037SARM gem5 Developers
132413118SEdmund.Grimley-Evans@arm.com    return fp32_round(x_sgn, x_exp + FP32_EXP_BITS - 3, x_mnt << 1,
132513118SEdmund.Grimley-Evans@arm.com                      mode, flags);
132610037SARM gem5 Developers}
132710037SARM gem5 Developers
132810037SARM gem5 Developersstatic uint64_t
132910037SARM gem5 Developersfp64_add(uint64_t a, uint64_t b, int neg, int mode, int *flags)
133010037SARM gem5 Developers{
133110037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
133210037SARM gem5 Developers    uint64_t a_mnt, b_mnt, x, x_mnt;
133310037SARM gem5 Developers
133410037SARM gem5 Developers    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
133510037SARM gem5 Developers    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
133610037SARM gem5 Developers
133710037SARM gem5 Developers    if ((x = fp64_process_NaNs(a, b, mode, flags))) {
133810037SARM gem5 Developers        return x;
133910037SARM gem5 Developers    }
134010037SARM gem5 Developers
134110037SARM gem5 Developers    b_sgn ^= neg;
134210037SARM gem5 Developers
134310037SARM gem5 Developers    // Handle infinities and zeroes:
134413118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF && a_sgn != b_sgn) {
134510037SARM gem5 Developers        *flags |= FPLIB_IOC;
134610037SARM gem5 Developers        return fp64_defaultNaN();
134713118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP64_EXP_INF) {
134810037SARM gem5 Developers        return fp64_infinity(a_sgn);
134913118SEdmund.Grimley-Evans@arm.com    } else if (b_exp == FP64_EXP_INF) {
135010037SARM gem5 Developers        return fp64_infinity(b_sgn);
135110037SARM gem5 Developers    } else if (!a_mnt && !b_mnt && a_sgn == b_sgn) {
135210037SARM gem5 Developers        return fp64_zero(a_sgn);
135310037SARM gem5 Developers    }
135410037SARM gem5 Developers
135510037SARM gem5 Developers    a_mnt <<= 3;
135610037SARM gem5 Developers    b_mnt <<= 3;
135710037SARM gem5 Developers    if (a_exp >= b_exp) {
135810037SARM gem5 Developers        b_mnt = (lsr64(b_mnt, a_exp - b_exp) |
135910037SARM gem5 Developers                 !!(b_mnt & (lsl64(1, a_exp - b_exp) - 1)));
136010037SARM gem5 Developers        b_exp = a_exp;
136110037SARM gem5 Developers    } else {
136210037SARM gem5 Developers        a_mnt = (lsr64(a_mnt, b_exp - a_exp) |
136310037SARM gem5 Developers                 !!(a_mnt & (lsl64(1, b_exp - a_exp) - 1)));
136410037SARM gem5 Developers        a_exp = b_exp;
136510037SARM gem5 Developers    }
136610037SARM gem5 Developers    x_sgn = a_sgn;
136710037SARM gem5 Developers    x_exp = a_exp;
136810037SARM gem5 Developers    if (a_sgn == b_sgn) {
136910037SARM gem5 Developers        x_mnt = a_mnt + b_mnt;
137010037SARM gem5 Developers    } else if (a_mnt >= b_mnt) {
137110037SARM gem5 Developers        x_mnt = a_mnt - b_mnt;
137210037SARM gem5 Developers    } else {
137310037SARM gem5 Developers        x_sgn ^= 1;
137410037SARM gem5 Developers        x_mnt = b_mnt - a_mnt;
137510037SARM gem5 Developers    }
137610037SARM gem5 Developers
137710037SARM gem5 Developers    if (!x_mnt) {
137810037SARM gem5 Developers        // Sign of exact zero result depends on rounding mode
137910037SARM gem5 Developers        return fp64_zero((mode & 3) == 2);
138010037SARM gem5 Developers    }
138110037SARM gem5 Developers
138210037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
138310037SARM gem5 Developers
138413118SEdmund.Grimley-Evans@arm.com    return fp64_round(x_sgn, x_exp + FP64_EXP_BITS - 3, x_mnt << 1,
138513118SEdmund.Grimley-Evans@arm.com                      mode, flags);
138613118SEdmund.Grimley-Evans@arm.com}
138713118SEdmund.Grimley-Evans@arm.com
138813118SEdmund.Grimley-Evans@arm.comstatic uint16_t
138913118SEdmund.Grimley-Evans@arm.comfp16_mul(uint16_t a, uint16_t b, int mode, int *flags)
139013118SEdmund.Grimley-Evans@arm.com{
139113118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
139213118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt, x;
139313118SEdmund.Grimley-Evans@arm.com    uint32_t x_mnt;
139413118SEdmund.Grimley-Evans@arm.com
139513118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
139613118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
139713118SEdmund.Grimley-Evans@arm.com
139813118SEdmund.Grimley-Evans@arm.com    if ((x = fp16_process_NaNs(a, b, mode, flags))) {
139913118SEdmund.Grimley-Evans@arm.com        return x;
140013118SEdmund.Grimley-Evans@arm.com    }
140113118SEdmund.Grimley-Evans@arm.com
140213118SEdmund.Grimley-Evans@arm.com    // Handle infinities and zeroes:
140313118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP16_EXP_INF && !b_mnt) ||
140413118SEdmund.Grimley-Evans@arm.com        (b_exp == FP16_EXP_INF && !a_mnt)) {
140513118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
140613118SEdmund.Grimley-Evans@arm.com        return fp16_defaultNaN();
140713118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP16_EXP_INF || b_exp == FP16_EXP_INF) {
140813118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn ^ b_sgn);
140913118SEdmund.Grimley-Evans@arm.com    } else if (!a_mnt || !b_mnt) {
141013118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn ^ b_sgn);
141113118SEdmund.Grimley-Evans@arm.com    }
141213118SEdmund.Grimley-Evans@arm.com
141313118SEdmund.Grimley-Evans@arm.com    // Multiply and normalise:
141413118SEdmund.Grimley-Evans@arm.com    x_sgn = a_sgn ^ b_sgn;
141513118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + b_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1;
141613118SEdmund.Grimley-Evans@arm.com    x_mnt = (uint32_t)a_mnt * b_mnt;
141713118SEdmund.Grimley-Evans@arm.com    x_mnt = fp32_normalise(x_mnt, &x_exp);
141813118SEdmund.Grimley-Evans@arm.com
141913118SEdmund.Grimley-Evans@arm.com    // Convert to FP16_BITS bits, collapsing error into bottom bit:
142013118SEdmund.Grimley-Evans@arm.com    x_mnt = lsr32(x_mnt, FP16_BITS - 1) | !!lsl32(x_mnt, FP16_BITS + 1);
142113118SEdmund.Grimley-Evans@arm.com
142213118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
142310037SARM gem5 Developers}
142410037SARM gem5 Developers
142510037SARM gem5 Developersstatic uint32_t
142610037SARM gem5 Developersfp32_mul(uint32_t a, uint32_t b, int mode, int *flags)
142710037SARM gem5 Developers{
142810037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
142910037SARM gem5 Developers    uint32_t a_mnt, b_mnt, x;
143010037SARM gem5 Developers    uint64_t x_mnt;
143110037SARM gem5 Developers
143210037SARM gem5 Developers    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
143310037SARM gem5 Developers    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
143410037SARM gem5 Developers
143510037SARM gem5 Developers    if ((x = fp32_process_NaNs(a, b, mode, flags))) {
143610037SARM gem5 Developers        return x;
143710037SARM gem5 Developers    }
143810037SARM gem5 Developers
143910037SARM gem5 Developers    // Handle infinities and zeroes:
144013118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP32_EXP_INF && !b_mnt) ||
144113118SEdmund.Grimley-Evans@arm.com        (b_exp == FP32_EXP_INF && !a_mnt)) {
144210037SARM gem5 Developers        *flags |= FPLIB_IOC;
144310037SARM gem5 Developers        return fp32_defaultNaN();
144413118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP32_EXP_INF || b_exp == FP32_EXP_INF) {
144510037SARM gem5 Developers        return fp32_infinity(a_sgn ^ b_sgn);
144610037SARM gem5 Developers    } else if (!a_mnt || !b_mnt) {
144710037SARM gem5 Developers        return fp32_zero(a_sgn ^ b_sgn);
144810037SARM gem5 Developers    }
144910037SARM gem5 Developers
145010037SARM gem5 Developers    // Multiply and normalise:
145110037SARM gem5 Developers    x_sgn = a_sgn ^ b_sgn;
145213118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + b_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1;
145310037SARM gem5 Developers    x_mnt = (uint64_t)a_mnt * b_mnt;
145410037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
145510037SARM gem5 Developers
145613118SEdmund.Grimley-Evans@arm.com    // Convert to FP32_BITS bits, collapsing error into bottom bit:
145713118SEdmund.Grimley-Evans@arm.com    x_mnt = lsr64(x_mnt, FP32_BITS - 1) | !!lsl64(x_mnt, FP32_BITS + 1);
145810037SARM gem5 Developers
145910037SARM gem5 Developers    return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
146010037SARM gem5 Developers}
146110037SARM gem5 Developers
146210037SARM gem5 Developersstatic uint64_t
146310037SARM gem5 Developersfp64_mul(uint64_t a, uint64_t b, int mode, int *flags)
146410037SARM gem5 Developers{
146510037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
146610037SARM gem5 Developers    uint64_t a_mnt, b_mnt, x;
146710037SARM gem5 Developers    uint64_t x0_mnt, x1_mnt;
146810037SARM gem5 Developers
146910037SARM gem5 Developers    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
147010037SARM gem5 Developers    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
147110037SARM gem5 Developers
147210037SARM gem5 Developers    if ((x = fp64_process_NaNs(a, b, mode, flags))) {
147310037SARM gem5 Developers        return x;
147410037SARM gem5 Developers    }
147510037SARM gem5 Developers
147610037SARM gem5 Developers    // Handle infinities and zeroes:
147713118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP64_EXP_INF && !b_mnt) ||
147813118SEdmund.Grimley-Evans@arm.com        (b_exp == FP64_EXP_INF && !a_mnt)) {
147910037SARM gem5 Developers        *flags |= FPLIB_IOC;
148010037SARM gem5 Developers        return fp64_defaultNaN();
148113118SEdmund.Grimley-Evans@arm.com    } else if (a_exp == FP64_EXP_INF || b_exp == FP64_EXP_INF) {
148210037SARM gem5 Developers        return fp64_infinity(a_sgn ^ b_sgn);
148310037SARM gem5 Developers    } else if (!a_mnt || !b_mnt) {
148410037SARM gem5 Developers        return fp64_zero(a_sgn ^ b_sgn);
148510037SARM gem5 Developers    }
148610037SARM gem5 Developers
148710037SARM gem5 Developers    // Multiply and normalise:
148810037SARM gem5 Developers    x_sgn = a_sgn ^ b_sgn;
148913118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + b_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1;
149010037SARM gem5 Developers    mul62x62(&x0_mnt, &x1_mnt, a_mnt, b_mnt);
149110037SARM gem5 Developers    fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
149210037SARM gem5 Developers
149313118SEdmund.Grimley-Evans@arm.com    // Convert to FP64_BITS bits, collapsing error into bottom bit:
149410037SARM gem5 Developers    x0_mnt = x1_mnt << 1 | !!x0_mnt;
149510037SARM gem5 Developers
149610037SARM gem5 Developers    return fp64_round(x_sgn, x_exp, x0_mnt, mode, flags);
149710037SARM gem5 Developers}
149810037SARM gem5 Developers
149913118SEdmund.Grimley-Evans@arm.comstatic uint16_t
150013118SEdmund.Grimley-Evans@arm.comfp16_muladd(uint16_t a, uint16_t b, uint16_t c, int scale,
150113118SEdmund.Grimley-Evans@arm.com            int mode, int *flags)
150213118SEdmund.Grimley-Evans@arm.com{
150313118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
150413118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt, c_mnt, x;
150513118SEdmund.Grimley-Evans@arm.com    uint32_t x_mnt, y_mnt;
150613118SEdmund.Grimley-Evans@arm.com
150713118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
150813118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
150913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
151013118SEdmund.Grimley-Evans@arm.com
151113118SEdmund.Grimley-Evans@arm.com    x = fp16_process_NaNs3(a, b, c, mode, flags);
151213118SEdmund.Grimley-Evans@arm.com
151313118SEdmund.Grimley-Evans@arm.com    // Quiet NaN added to product of zero and infinity:
151413118SEdmund.Grimley-Evans@arm.com    if (fp16_is_quiet_NaN(a_exp, a_mnt) &&
151513118SEdmund.Grimley-Evans@arm.com        ((!b_mnt && fp16_is_infinity(c_exp, c_mnt)) ||
151613118SEdmund.Grimley-Evans@arm.com         (!c_mnt && fp16_is_infinity(b_exp, b_mnt)))) {
151713118SEdmund.Grimley-Evans@arm.com        x = fp16_defaultNaN();
151813118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
151913118SEdmund.Grimley-Evans@arm.com    }
152013118SEdmund.Grimley-Evans@arm.com
152113118SEdmund.Grimley-Evans@arm.com    if (x) {
152213118SEdmund.Grimley-Evans@arm.com        return x;
152313118SEdmund.Grimley-Evans@arm.com    }
152413118SEdmund.Grimley-Evans@arm.com
152513118SEdmund.Grimley-Evans@arm.com    // Handle infinities and zeroes:
152613118SEdmund.Grimley-Evans@arm.com    if ((b_exp == FP16_EXP_INF && !c_mnt) ||
152713118SEdmund.Grimley-Evans@arm.com        (c_exp == FP16_EXP_INF && !b_mnt) ||
152813118SEdmund.Grimley-Evans@arm.com        (a_exp == FP16_EXP_INF &&
152913118SEdmund.Grimley-Evans@arm.com         (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF) &&
153013118SEdmund.Grimley-Evans@arm.com         (a_sgn != (b_sgn ^ c_sgn)))) {
153113118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
153213118SEdmund.Grimley-Evans@arm.com        return fp16_defaultNaN();
153313118SEdmund.Grimley-Evans@arm.com    }
153413118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP16_EXP_INF)
153513118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn);
153613118SEdmund.Grimley-Evans@arm.com    if (b_exp == FP16_EXP_INF || c_exp == FP16_EXP_INF)
153713118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(b_sgn ^ c_sgn);
153813118SEdmund.Grimley-Evans@arm.com    if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
153913118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn);
154013118SEdmund.Grimley-Evans@arm.com
154113118SEdmund.Grimley-Evans@arm.com    x_sgn = a_sgn;
154213118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + 2 * FP16_EXP_BITS - 3;
154313118SEdmund.Grimley-Evans@arm.com    x_mnt = (uint32_t)a_mnt << (FP16_MANT_BITS + 4);
154413118SEdmund.Grimley-Evans@arm.com
154513118SEdmund.Grimley-Evans@arm.com    // Multiply:
154613118SEdmund.Grimley-Evans@arm.com    y_sgn = b_sgn ^ c_sgn;
154713118SEdmund.Grimley-Evans@arm.com    y_exp = b_exp + c_exp - FP16_EXP_BIAS + 2 * FP16_EXP_BITS + 1 - 3;
154813118SEdmund.Grimley-Evans@arm.com    y_mnt = (uint32_t)b_mnt * c_mnt << 3;
154913118SEdmund.Grimley-Evans@arm.com    if (!y_mnt) {
155013118SEdmund.Grimley-Evans@arm.com        y_exp = x_exp;
155113118SEdmund.Grimley-Evans@arm.com    }
155213118SEdmund.Grimley-Evans@arm.com
155313118SEdmund.Grimley-Evans@arm.com    // Add:
155413118SEdmund.Grimley-Evans@arm.com    if (x_exp >= y_exp) {
155513118SEdmund.Grimley-Evans@arm.com        y_mnt = (lsr32(y_mnt, x_exp - y_exp) |
155613118SEdmund.Grimley-Evans@arm.com                 !!(y_mnt & (lsl32(1, x_exp - y_exp) - 1)));
155713118SEdmund.Grimley-Evans@arm.com        y_exp = x_exp;
155813118SEdmund.Grimley-Evans@arm.com    } else {
155913118SEdmund.Grimley-Evans@arm.com        x_mnt = (lsr32(x_mnt, y_exp - x_exp) |
156013118SEdmund.Grimley-Evans@arm.com                 !!(x_mnt & (lsl32(1, y_exp - x_exp) - 1)));
156113118SEdmund.Grimley-Evans@arm.com        x_exp = y_exp;
156213118SEdmund.Grimley-Evans@arm.com    }
156313118SEdmund.Grimley-Evans@arm.com    if (x_sgn == y_sgn) {
156413118SEdmund.Grimley-Evans@arm.com        x_mnt = x_mnt + y_mnt;
156513118SEdmund.Grimley-Evans@arm.com    } else if (x_mnt >= y_mnt) {
156613118SEdmund.Grimley-Evans@arm.com        x_mnt = x_mnt - y_mnt;
156713118SEdmund.Grimley-Evans@arm.com    } else {
156813118SEdmund.Grimley-Evans@arm.com        x_sgn ^= 1;
156913118SEdmund.Grimley-Evans@arm.com        x_mnt = y_mnt - x_mnt;
157013118SEdmund.Grimley-Evans@arm.com    }
157113118SEdmund.Grimley-Evans@arm.com
157213118SEdmund.Grimley-Evans@arm.com    if (!x_mnt) {
157313118SEdmund.Grimley-Evans@arm.com        // Sign of exact zero result depends on rounding mode
157413118SEdmund.Grimley-Evans@arm.com        return fp16_zero((mode & 3) == 2);
157513118SEdmund.Grimley-Evans@arm.com    }
157613118SEdmund.Grimley-Evans@arm.com
157713118SEdmund.Grimley-Evans@arm.com    // Normalise into FP16_BITS bits, collapsing error into bottom bit:
157813118SEdmund.Grimley-Evans@arm.com    x_mnt = fp32_normalise(x_mnt, &x_exp);
157913118SEdmund.Grimley-Evans@arm.com    x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
158013118SEdmund.Grimley-Evans@arm.com
158113118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
158213118SEdmund.Grimley-Evans@arm.com}
158313118SEdmund.Grimley-Evans@arm.com
158410037SARM gem5 Developersstatic uint32_t
158510037SARM gem5 Developersfp32_muladd(uint32_t a, uint32_t b, uint32_t c, int scale,
158610037SARM gem5 Developers            int mode, int *flags)
158710037SARM gem5 Developers{
158810037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
158910037SARM gem5 Developers    uint32_t a_mnt, b_mnt, c_mnt, x;
159010037SARM gem5 Developers    uint64_t x_mnt, y_mnt;
159110037SARM gem5 Developers
159210037SARM gem5 Developers    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
159310037SARM gem5 Developers    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
159410037SARM gem5 Developers    fp32_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
159510037SARM gem5 Developers
159610037SARM gem5 Developers    x = fp32_process_NaNs3(a, b, c, mode, flags);
159710037SARM gem5 Developers
159810037SARM gem5 Developers    // Quiet NaN added to product of zero and infinity:
159913118SEdmund.Grimley-Evans@arm.com    if (fp32_is_quiet_NaN(a_exp, a_mnt) &&
160013118SEdmund.Grimley-Evans@arm.com        ((!b_mnt && fp32_is_infinity(c_exp, c_mnt)) ||
160113118SEdmund.Grimley-Evans@arm.com         (!c_mnt && fp32_is_infinity(b_exp, b_mnt)))) {
160210037SARM gem5 Developers        x = fp32_defaultNaN();
160310037SARM gem5 Developers        *flags |= FPLIB_IOC;
160410037SARM gem5 Developers    }
160510037SARM gem5 Developers
160610037SARM gem5 Developers    if (x) {
160710037SARM gem5 Developers        return x;
160810037SARM gem5 Developers    }
160910037SARM gem5 Developers
161010037SARM gem5 Developers    // Handle infinities and zeroes:
161113118SEdmund.Grimley-Evans@arm.com    if ((b_exp == FP32_EXP_INF && !c_mnt) ||
161213118SEdmund.Grimley-Evans@arm.com        (c_exp == FP32_EXP_INF && !b_mnt) ||
161313118SEdmund.Grimley-Evans@arm.com        (a_exp == FP32_EXP_INF &&
161413118SEdmund.Grimley-Evans@arm.com         (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF) &&
161510037SARM gem5 Developers         (a_sgn != (b_sgn ^ c_sgn)))) {
161610037SARM gem5 Developers        *flags |= FPLIB_IOC;
161710037SARM gem5 Developers        return fp32_defaultNaN();
161810037SARM gem5 Developers    }
161913118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP32_EXP_INF)
162010037SARM gem5 Developers        return fp32_infinity(a_sgn);
162113118SEdmund.Grimley-Evans@arm.com    if (b_exp == FP32_EXP_INF || c_exp == FP32_EXP_INF)
162210037SARM gem5 Developers        return fp32_infinity(b_sgn ^ c_sgn);
162310037SARM gem5 Developers    if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
162410037SARM gem5 Developers        return fp32_zero(a_sgn);
162510037SARM gem5 Developers
162610037SARM gem5 Developers    x_sgn = a_sgn;
162713118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + 2 * FP32_EXP_BITS - 3;
162813118SEdmund.Grimley-Evans@arm.com    x_mnt = (uint64_t)a_mnt << (FP32_MANT_BITS + 4);
162910037SARM gem5 Developers
163010037SARM gem5 Developers    // Multiply:
163110037SARM gem5 Developers    y_sgn = b_sgn ^ c_sgn;
163213118SEdmund.Grimley-Evans@arm.com    y_exp = b_exp + c_exp - FP32_EXP_BIAS + 2 * FP32_EXP_BITS + 1 - 3;
163310037SARM gem5 Developers    y_mnt = (uint64_t)b_mnt * c_mnt << 3;
163410037SARM gem5 Developers    if (!y_mnt) {
163510037SARM gem5 Developers        y_exp = x_exp;
163610037SARM gem5 Developers    }
163710037SARM gem5 Developers
163810037SARM gem5 Developers    // Add:
163910037SARM gem5 Developers    if (x_exp >= y_exp) {
164010037SARM gem5 Developers        y_mnt = (lsr64(y_mnt, x_exp - y_exp) |
164110037SARM gem5 Developers                 !!(y_mnt & (lsl64(1, x_exp - y_exp) - 1)));
164210037SARM gem5 Developers        y_exp = x_exp;
164310037SARM gem5 Developers    } else {
164410037SARM gem5 Developers        x_mnt = (lsr64(x_mnt, y_exp - x_exp) |
164510037SARM gem5 Developers                 !!(x_mnt & (lsl64(1, y_exp - x_exp) - 1)));
164610037SARM gem5 Developers        x_exp = y_exp;
164710037SARM gem5 Developers    }
164810037SARM gem5 Developers    if (x_sgn == y_sgn) {
164910037SARM gem5 Developers        x_mnt = x_mnt + y_mnt;
165010037SARM gem5 Developers    } else if (x_mnt >= y_mnt) {
165110037SARM gem5 Developers        x_mnt = x_mnt - y_mnt;
165210037SARM gem5 Developers    } else {
165310037SARM gem5 Developers        x_sgn ^= 1;
165410037SARM gem5 Developers        x_mnt = y_mnt - x_mnt;
165510037SARM gem5 Developers    }
165610037SARM gem5 Developers
165710037SARM gem5 Developers    if (!x_mnt) {
165810037SARM gem5 Developers        // Sign of exact zero result depends on rounding mode
165910037SARM gem5 Developers        return fp32_zero((mode & 3) == 2);
166010037SARM gem5 Developers    }
166110037SARM gem5 Developers
166213118SEdmund.Grimley-Evans@arm.com    // Normalise into FP32_BITS bits, collapsing error into bottom bit:
166310037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
166413118SEdmund.Grimley-Evans@arm.com    x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
166510037SARM gem5 Developers
166610037SARM gem5 Developers    return fp32_round(x_sgn, x_exp + scale, x_mnt, mode, flags);
166710037SARM gem5 Developers}
166810037SARM gem5 Developers
166910037SARM gem5 Developersstatic uint64_t
167010037SARM gem5 Developersfp64_muladd(uint64_t a, uint64_t b, uint64_t c, int scale,
167110037SARM gem5 Developers            int mode, int *flags)
167210037SARM gem5 Developers{
167310037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, c_sgn, c_exp, x_sgn, x_exp, y_sgn, y_exp;
167410037SARM gem5 Developers    uint64_t a_mnt, b_mnt, c_mnt, x;
167510037SARM gem5 Developers    uint64_t x0_mnt, x1_mnt, y0_mnt, y1_mnt;
167610037SARM gem5 Developers
167710037SARM gem5 Developers    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
167810037SARM gem5 Developers    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
167910037SARM gem5 Developers    fp64_unpack(&c_sgn, &c_exp, &c_mnt, c, mode, flags);
168010037SARM gem5 Developers
168110037SARM gem5 Developers    x = fp64_process_NaNs3(a, b, c, mode, flags);
168210037SARM gem5 Developers
168310037SARM gem5 Developers    // Quiet NaN added to product of zero and infinity:
168413118SEdmund.Grimley-Evans@arm.com    if (fp64_is_quiet_NaN(a_exp, a_mnt) &&
168513118SEdmund.Grimley-Evans@arm.com        ((!b_mnt && fp64_is_infinity(c_exp, c_mnt)) ||
168613118SEdmund.Grimley-Evans@arm.com         (!c_mnt && fp64_is_infinity(b_exp, b_mnt)))) {
168710037SARM gem5 Developers        x = fp64_defaultNaN();
168810037SARM gem5 Developers        *flags |= FPLIB_IOC;
168910037SARM gem5 Developers    }
169010037SARM gem5 Developers
169110037SARM gem5 Developers    if (x) {
169210037SARM gem5 Developers        return x;
169310037SARM gem5 Developers    }
169410037SARM gem5 Developers
169510037SARM gem5 Developers    // Handle infinities and zeroes:
169613118SEdmund.Grimley-Evans@arm.com    if ((b_exp == FP64_EXP_INF && !c_mnt) ||
169713118SEdmund.Grimley-Evans@arm.com        (c_exp == FP64_EXP_INF && !b_mnt) ||
169813118SEdmund.Grimley-Evans@arm.com        (a_exp == FP64_EXP_INF &&
169913118SEdmund.Grimley-Evans@arm.com         (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF) &&
170010037SARM gem5 Developers         (a_sgn != (b_sgn ^ c_sgn)))) {
170110037SARM gem5 Developers        *flags |= FPLIB_IOC;
170210037SARM gem5 Developers        return fp64_defaultNaN();
170310037SARM gem5 Developers    }
170413118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP64_EXP_INF)
170510037SARM gem5 Developers        return fp64_infinity(a_sgn);
170613118SEdmund.Grimley-Evans@arm.com    if (b_exp == FP64_EXP_INF || c_exp == FP64_EXP_INF)
170710037SARM gem5 Developers        return fp64_infinity(b_sgn ^ c_sgn);
170810037SARM gem5 Developers    if (!a_mnt && (!b_mnt || !c_mnt) && a_sgn == (b_sgn ^ c_sgn))
170910037SARM gem5 Developers        return fp64_zero(a_sgn);
171010037SARM gem5 Developers
171110037SARM gem5 Developers    x_sgn = a_sgn;
171213118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp + FP64_EXP_BITS;
171310037SARM gem5 Developers    x0_mnt = 0;
171410037SARM gem5 Developers    x1_mnt = a_mnt;
171510037SARM gem5 Developers
171610037SARM gem5 Developers    // Multiply:
171710037SARM gem5 Developers    y_sgn = b_sgn ^ c_sgn;
171813118SEdmund.Grimley-Evans@arm.com    y_exp = b_exp + c_exp - FP64_EXP_BIAS + 2 * FP64_EXP_BITS + 1 - 3;
171910037SARM gem5 Developers    mul62x62(&y0_mnt, &y1_mnt, b_mnt, c_mnt << 3);
172010037SARM gem5 Developers    if (!y0_mnt && !y1_mnt) {
172110037SARM gem5 Developers        y_exp = x_exp;
172210037SARM gem5 Developers    }
172310037SARM gem5 Developers
172410037SARM gem5 Developers    // Add:
172510037SARM gem5 Developers    if (x_exp >= y_exp) {
172610037SARM gem5 Developers        uint64_t t0, t1;
172710037SARM gem5 Developers        lsl128(&t0, &t1, y0_mnt, y1_mnt,
172810037SARM gem5 Developers               x_exp - y_exp < 128 ? 128 - (x_exp - y_exp) : 0);
172910037SARM gem5 Developers        lsr128(&y0_mnt, &y1_mnt, y0_mnt, y1_mnt, x_exp - y_exp);
173010037SARM gem5 Developers        y0_mnt |= !!(t0 | t1);
173110037SARM gem5 Developers        y_exp = x_exp;
173210037SARM gem5 Developers    } else {
173310037SARM gem5 Developers        uint64_t t0, t1;
173410037SARM gem5 Developers        lsl128(&t0, &t1, x0_mnt, x1_mnt,
173510037SARM gem5 Developers               y_exp - x_exp < 128 ? 128 - (y_exp - x_exp) : 0);
173610037SARM gem5 Developers        lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y_exp - x_exp);
173710037SARM gem5 Developers        x0_mnt |= !!(t0 | t1);
173810037SARM gem5 Developers        x_exp = y_exp;
173910037SARM gem5 Developers    }
174010037SARM gem5 Developers    if (x_sgn == y_sgn) {
174110037SARM gem5 Developers        add128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
174210037SARM gem5 Developers    } else if (cmp128(x0_mnt, x1_mnt, y0_mnt, y1_mnt) >= 0) {
174310037SARM gem5 Developers        sub128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, y0_mnt, y1_mnt);
174410037SARM gem5 Developers    } else {
174510037SARM gem5 Developers        x_sgn ^= 1;
174610037SARM gem5 Developers        sub128(&x0_mnt, &x1_mnt, y0_mnt, y1_mnt, x0_mnt, x1_mnt);
174710037SARM gem5 Developers    }
174810037SARM gem5 Developers
174910037SARM gem5 Developers    if (!x0_mnt && !x1_mnt) {
175010037SARM gem5 Developers        // Sign of exact zero result depends on rounding mode
175110037SARM gem5 Developers        return fp64_zero((mode & 3) == 2);
175210037SARM gem5 Developers    }
175310037SARM gem5 Developers
175413118SEdmund.Grimley-Evans@arm.com    // Normalise into FP64_BITS bits, collapsing error into bottom bit:
175510037SARM gem5 Developers    fp128_normalise(&x0_mnt, &x1_mnt, &x_exp);
175610037SARM gem5 Developers    x0_mnt = x1_mnt << 1 | !!x0_mnt;
175710037SARM gem5 Developers
175810037SARM gem5 Developers    return fp64_round(x_sgn, x_exp + scale, x0_mnt, mode, flags);
175910037SARM gem5 Developers}
176010037SARM gem5 Developers
176113118SEdmund.Grimley-Evans@arm.comstatic uint16_t
176213118SEdmund.Grimley-Evans@arm.comfp16_div(uint16_t a, uint16_t b, int mode, int *flags)
176313118SEdmund.Grimley-Evans@arm.com{
176413118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
176513118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, b_mnt, x;
176613118SEdmund.Grimley-Evans@arm.com    uint32_t x_mnt;
176713118SEdmund.Grimley-Evans@arm.com
176813118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
176913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
177013118SEdmund.Grimley-Evans@arm.com
177113118SEdmund.Grimley-Evans@arm.com    if ((x = fp16_process_NaNs(a, b, mode, flags)))
177213118SEdmund.Grimley-Evans@arm.com        return x;
177313118SEdmund.Grimley-Evans@arm.com
177413118SEdmund.Grimley-Evans@arm.com    // Handle infinities and zeroes:
177513118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP16_EXP_INF && b_exp == FP16_EXP_INF) ||
177613118SEdmund.Grimley-Evans@arm.com        (!a_mnt && !b_mnt)) {
177713118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
177813118SEdmund.Grimley-Evans@arm.com        return fp16_defaultNaN();
177913118SEdmund.Grimley-Evans@arm.com    }
178013118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP16_EXP_INF || !b_mnt) {
178113118SEdmund.Grimley-Evans@arm.com        if (a_exp != FP16_EXP_INF)
178213118SEdmund.Grimley-Evans@arm.com            *flags |= FPLIB_DZC;
178313118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn ^ b_sgn);
178413118SEdmund.Grimley-Evans@arm.com    }
178513118SEdmund.Grimley-Evans@arm.com    if (!a_mnt || b_exp == FP16_EXP_INF)
178613118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn ^ b_sgn);
178713118SEdmund.Grimley-Evans@arm.com
178813118SEdmund.Grimley-Evans@arm.com    // Divide, setting bottom bit if inexact:
178913118SEdmund.Grimley-Evans@arm.com    a_mnt = fp16_normalise(a_mnt, &a_exp);
179013118SEdmund.Grimley-Evans@arm.com    x_sgn = a_sgn ^ b_sgn;
179113118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp - b_exp + (FP16_EXP_BIAS + FP16_BITS + 2 * FP16_EXP_BITS - 3);
179213118SEdmund.Grimley-Evans@arm.com    x_mnt = ((uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3)) / b_mnt;
179313118SEdmund.Grimley-Evans@arm.com    x_mnt |= (x_mnt * b_mnt !=
179413118SEdmund.Grimley-Evans@arm.com              (uint32_t)a_mnt << (FP16_MANT_BITS - FP16_EXP_BITS + 3));
179513118SEdmund.Grimley-Evans@arm.com
179613118SEdmund.Grimley-Evans@arm.com    // Normalise into FP16_BITS bits, collapsing error into bottom bit:
179713118SEdmund.Grimley-Evans@arm.com    x_mnt = fp32_normalise(x_mnt, &x_exp);
179813118SEdmund.Grimley-Evans@arm.com    x_mnt = x_mnt >> (FP16_BITS - 1) | !!(uint16_t)(x_mnt << 1);
179913118SEdmund.Grimley-Evans@arm.com
180013118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
180113118SEdmund.Grimley-Evans@arm.com}
180213118SEdmund.Grimley-Evans@arm.com
180310037SARM gem5 Developersstatic uint32_t
180410037SARM gem5 Developersfp32_div(uint32_t a, uint32_t b, int mode, int *flags)
180510037SARM gem5 Developers{
180610037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp;
180710037SARM gem5 Developers    uint32_t a_mnt, b_mnt, x;
180810037SARM gem5 Developers    uint64_t x_mnt;
180910037SARM gem5 Developers
181010037SARM gem5 Developers    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
181110037SARM gem5 Developers    fp32_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
181210037SARM gem5 Developers
181310037SARM gem5 Developers    if ((x = fp32_process_NaNs(a, b, mode, flags)))
181410037SARM gem5 Developers        return x;
181510037SARM gem5 Developers
181610037SARM gem5 Developers    // Handle infinities and zeroes:
181713118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP32_EXP_INF && b_exp == FP32_EXP_INF) ||
181813118SEdmund.Grimley-Evans@arm.com        (!a_mnt && !b_mnt)) {
181910037SARM gem5 Developers        *flags |= FPLIB_IOC;
182010037SARM gem5 Developers        return fp32_defaultNaN();
182110037SARM gem5 Developers    }
182213118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP32_EXP_INF || !b_mnt) {
182313118SEdmund.Grimley-Evans@arm.com        if (a_exp != FP32_EXP_INF)
182410037SARM gem5 Developers            *flags |= FPLIB_DZC;
182510037SARM gem5 Developers        return fp32_infinity(a_sgn ^ b_sgn);
182610037SARM gem5 Developers    }
182713118SEdmund.Grimley-Evans@arm.com    if (!a_mnt || b_exp == FP32_EXP_INF)
182810037SARM gem5 Developers        return fp32_zero(a_sgn ^ b_sgn);
182910037SARM gem5 Developers
183010037SARM gem5 Developers    // Divide, setting bottom bit if inexact:
183110037SARM gem5 Developers    a_mnt = fp32_normalise(a_mnt, &a_exp);
183210037SARM gem5 Developers    x_sgn = a_sgn ^ b_sgn;
183313118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp - b_exp + (FP32_EXP_BIAS + FP32_BITS + 2 * FP32_EXP_BITS - 3);
183413118SEdmund.Grimley-Evans@arm.com    x_mnt = ((uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3)) / b_mnt;
183513118SEdmund.Grimley-Evans@arm.com    x_mnt |= (x_mnt * b_mnt !=
183613118SEdmund.Grimley-Evans@arm.com              (uint64_t)a_mnt << (FP32_MANT_BITS - FP32_EXP_BITS + 3));
183713118SEdmund.Grimley-Evans@arm.com
183813118SEdmund.Grimley-Evans@arm.com    // Normalise into FP32_BITS bits, collapsing error into bottom bit:
183910037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
184013118SEdmund.Grimley-Evans@arm.com    x_mnt = x_mnt >> (FP32_BITS - 1) | !!(uint32_t)(x_mnt << 1);
184110037SARM gem5 Developers
184210037SARM gem5 Developers    return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
184310037SARM gem5 Developers}
184410037SARM gem5 Developers
184510037SARM gem5 Developersstatic uint64_t
184610037SARM gem5 Developersfp64_div(uint64_t a, uint64_t b, int mode, int *flags)
184710037SARM gem5 Developers{
184810037SARM gem5 Developers    int a_sgn, a_exp, b_sgn, b_exp, x_sgn, x_exp, c;
184910037SARM gem5 Developers    uint64_t a_mnt, b_mnt, x, x_mnt, x0_mnt, x1_mnt;
185010037SARM gem5 Developers
185110037SARM gem5 Developers    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
185210037SARM gem5 Developers    fp64_unpack(&b_sgn, &b_exp, &b_mnt, b, mode, flags);
185310037SARM gem5 Developers
185410037SARM gem5 Developers    if ((x = fp64_process_NaNs(a, b, mode, flags)))
185510037SARM gem5 Developers        return x;
185610037SARM gem5 Developers
185710037SARM gem5 Developers    // Handle infinities and zeroes:
185813118SEdmund.Grimley-Evans@arm.com    if ((a_exp == FP64_EXP_INF && b_exp == FP64_EXP_INF) ||
185913118SEdmund.Grimley-Evans@arm.com        (!a_mnt && !b_mnt)) {
186010037SARM gem5 Developers        *flags |= FPLIB_IOC;
186110037SARM gem5 Developers        return fp64_defaultNaN();
186210037SARM gem5 Developers    }
186313118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP64_EXP_INF || !b_mnt) {
186413118SEdmund.Grimley-Evans@arm.com        if (a_exp != FP64_EXP_INF)
186510037SARM gem5 Developers            *flags |= FPLIB_DZC;
186610037SARM gem5 Developers        return fp64_infinity(a_sgn ^ b_sgn);
186710037SARM gem5 Developers    }
186813118SEdmund.Grimley-Evans@arm.com    if (!a_mnt || b_exp == FP64_EXP_INF)
186910037SARM gem5 Developers        return fp64_zero(a_sgn ^ b_sgn);
187010037SARM gem5 Developers
187110037SARM gem5 Developers    // Find reciprocal of divisor with Newton-Raphson:
187210037SARM gem5 Developers    a_mnt = fp64_normalise(a_mnt, &a_exp);
187310037SARM gem5 Developers    b_mnt = fp64_normalise(b_mnt, &b_exp);
187410037SARM gem5 Developers    x_mnt = ~(uint64_t)0 / (b_mnt >> 31);
187510037SARM gem5 Developers    mul64x32(&x0_mnt, &x1_mnt, b_mnt, x_mnt);
187610037SARM gem5 Developers    sub128(&x0_mnt, &x1_mnt, 0, (uint64_t)1 << 32, x0_mnt, x1_mnt);
187710037SARM gem5 Developers    lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 32);
187810037SARM gem5 Developers    mul64x32(&x0_mnt, &x1_mnt, x0_mnt, x_mnt);
187910037SARM gem5 Developers    lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 33);
188010037SARM gem5 Developers
188110037SARM gem5 Developers    // Multiply by dividend:
188210037SARM gem5 Developers    x_sgn = a_sgn ^ b_sgn;
188313118SEdmund.Grimley-Evans@arm.com    x_exp = a_exp - b_exp + FP64_EXP_BIAS + 8;
188413118SEdmund.Grimley-Evans@arm.com    mul62x62(&x0_mnt, &x1_mnt, x0_mnt, a_mnt >> 2);
188510037SARM gem5 Developers    lsr128(&x0_mnt, &x1_mnt, x0_mnt, x1_mnt, 4);
188610037SARM gem5 Developers    x_mnt = x1_mnt;
188710037SARM gem5 Developers
188810037SARM gem5 Developers    // This is an underestimate, so try adding one:
188913118SEdmund.Grimley-Evans@arm.com    mul62x62(&x0_mnt, &x1_mnt, b_mnt >> 2, x_mnt + 1);
189010037SARM gem5 Developers    c = cmp128(x0_mnt, x1_mnt, 0, a_mnt >> 11);
189110037SARM gem5 Developers    if (c <= 0) {
189210037SARM gem5 Developers        ++x_mnt;
189310037SARM gem5 Developers    }
189410037SARM gem5 Developers
189510037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
189610037SARM gem5 Developers
189710037SARM gem5 Developers    return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
189810037SARM gem5 Developers}
189910037SARM gem5 Developers
190010037SARM gem5 Developersstatic void
190110037SARM gem5 Developersset_fpscr0(FPSCR &fpscr, int flags)
190210037SARM gem5 Developers{
190310037SARM gem5 Developers    if (flags & FPLIB_IDC) {
190410037SARM gem5 Developers        fpscr.idc = 1;
190510037SARM gem5 Developers    }
190610037SARM gem5 Developers    if (flags & FPLIB_IOC) {
190710037SARM gem5 Developers        fpscr.ioc = 1;
190810037SARM gem5 Developers    }
190910037SARM gem5 Developers    if (flags & FPLIB_DZC) {
191010037SARM gem5 Developers        fpscr.dzc = 1;
191110037SARM gem5 Developers    }
191210037SARM gem5 Developers    if (flags & FPLIB_OFC) {
191310037SARM gem5 Developers        fpscr.ofc = 1;
191410037SARM gem5 Developers    }
191510037SARM gem5 Developers    if (flags & FPLIB_UFC) {
191610037SARM gem5 Developers        fpscr.ufc = 1;
191710037SARM gem5 Developers    }
191810037SARM gem5 Developers    if (flags & FPLIB_IXC) {
191910037SARM gem5 Developers        fpscr.ixc = 1;
192010037SARM gem5 Developers    }
192110037SARM gem5 Developers}
192210037SARM gem5 Developers
192313118SEdmund.Grimley-Evans@arm.comstatic uint16_t
192413118SEdmund.Grimley-Evans@arm.comfp16_scale(uint16_t a, int16_t b, int mode, int *flags)
192513118SEdmund.Grimley-Evans@arm.com{
192613118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp;
192713118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt;
192813118SEdmund.Grimley-Evans@arm.com
192913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
193013118SEdmund.Grimley-Evans@arm.com
193113118SEdmund.Grimley-Evans@arm.com    // Handle NaNs:
193213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt)) {
193313118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
193413118SEdmund.Grimley-Evans@arm.com    }
193513118SEdmund.Grimley-Evans@arm.com
193613118SEdmund.Grimley-Evans@arm.com    // Handle zeroes:
193713118SEdmund.Grimley-Evans@arm.com    if (!a_mnt) {
193813118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn);
193913118SEdmund.Grimley-Evans@arm.com    }
194013118SEdmund.Grimley-Evans@arm.com
194113118SEdmund.Grimley-Evans@arm.com    // Handle infinities:
194213118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP16_EXP_INF) {
194313118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn);
194413118SEdmund.Grimley-Evans@arm.com    }
194513118SEdmund.Grimley-Evans@arm.com
194613118SEdmund.Grimley-Evans@arm.com    b = b < -300 ? -300 : b;
194713118SEdmund.Grimley-Evans@arm.com    b = b >  300 ?  300 : b;
194813118SEdmund.Grimley-Evans@arm.com    a_exp += b;
194913118SEdmund.Grimley-Evans@arm.com    a_mnt <<= 3;
195013118SEdmund.Grimley-Evans@arm.com
195113118SEdmund.Grimley-Evans@arm.com    a_mnt = fp16_normalise(a_mnt, &a_exp);
195213118SEdmund.Grimley-Evans@arm.com
195313118SEdmund.Grimley-Evans@arm.com    return fp16_round(a_sgn, a_exp + FP16_EXP_BITS - 3, a_mnt << 1,
195413118SEdmund.Grimley-Evans@arm.com                      mode, flags);
195513118SEdmund.Grimley-Evans@arm.com}
195613118SEdmund.Grimley-Evans@arm.com
195713118SEdmund.Grimley-Evans@arm.comstatic uint32_t
195813118SEdmund.Grimley-Evans@arm.comfp32_scale(uint32_t a, int32_t b, int mode, int *flags)
195913118SEdmund.Grimley-Evans@arm.com{
196013118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp;
196113118SEdmund.Grimley-Evans@arm.com    uint32_t a_mnt;
196213118SEdmund.Grimley-Evans@arm.com
196313118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
196413118SEdmund.Grimley-Evans@arm.com
196513118SEdmund.Grimley-Evans@arm.com    // Handle NaNs:
196613118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt)) {
196713118SEdmund.Grimley-Evans@arm.com        return fp32_process_NaN(a, mode, flags);
196813118SEdmund.Grimley-Evans@arm.com    }
196913118SEdmund.Grimley-Evans@arm.com
197013118SEdmund.Grimley-Evans@arm.com    // Handle zeroes:
197113118SEdmund.Grimley-Evans@arm.com    if (!a_mnt) {
197213118SEdmund.Grimley-Evans@arm.com        return fp32_zero(a_sgn);
197313118SEdmund.Grimley-Evans@arm.com    }
197413118SEdmund.Grimley-Evans@arm.com
197513118SEdmund.Grimley-Evans@arm.com    // Handle infinities:
197613118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP32_EXP_INF) {
197713118SEdmund.Grimley-Evans@arm.com        return fp32_infinity(a_sgn);
197813118SEdmund.Grimley-Evans@arm.com    }
197913118SEdmund.Grimley-Evans@arm.com
198013118SEdmund.Grimley-Evans@arm.com    b = b < -300 ? -300 : b;
198113118SEdmund.Grimley-Evans@arm.com    b = b >  300 ?  300 : b;
198213118SEdmund.Grimley-Evans@arm.com    a_exp += b;
198313118SEdmund.Grimley-Evans@arm.com    a_mnt <<= 3;
198413118SEdmund.Grimley-Evans@arm.com
198513118SEdmund.Grimley-Evans@arm.com    a_mnt = fp32_normalise(a_mnt, &a_exp);
198613118SEdmund.Grimley-Evans@arm.com
198713118SEdmund.Grimley-Evans@arm.com    return fp32_round(a_sgn, a_exp + FP32_EXP_BITS - 3, a_mnt << 1,
198813118SEdmund.Grimley-Evans@arm.com                      mode, flags);
198913118SEdmund.Grimley-Evans@arm.com}
199013118SEdmund.Grimley-Evans@arm.com
199113118SEdmund.Grimley-Evans@arm.comstatic uint64_t
199213118SEdmund.Grimley-Evans@arm.comfp64_scale(uint64_t a, int64_t b, int mode, int *flags)
199313118SEdmund.Grimley-Evans@arm.com{
199413118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp;
199513118SEdmund.Grimley-Evans@arm.com    uint64_t a_mnt;
199613118SEdmund.Grimley-Evans@arm.com
199713118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
199813118SEdmund.Grimley-Evans@arm.com
199913118SEdmund.Grimley-Evans@arm.com    // Handle NaNs:
200013118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt)) {
200113118SEdmund.Grimley-Evans@arm.com        return fp64_process_NaN(a, mode, flags);
200213118SEdmund.Grimley-Evans@arm.com    }
200313118SEdmund.Grimley-Evans@arm.com
200413118SEdmund.Grimley-Evans@arm.com    // Handle zeroes:
200513118SEdmund.Grimley-Evans@arm.com    if (!a_mnt) {
200613118SEdmund.Grimley-Evans@arm.com        return fp64_zero(a_sgn);
200713118SEdmund.Grimley-Evans@arm.com    }
200813118SEdmund.Grimley-Evans@arm.com
200913118SEdmund.Grimley-Evans@arm.com    // Handle infinities:
201013118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP64_EXP_INF) {
201113118SEdmund.Grimley-Evans@arm.com        return fp64_infinity(a_sgn);
201213118SEdmund.Grimley-Evans@arm.com    }
201313118SEdmund.Grimley-Evans@arm.com
201413118SEdmund.Grimley-Evans@arm.com    b = b < -3000 ? -3000 : b;
201513118SEdmund.Grimley-Evans@arm.com    b = b >  3000 ?  3000 : b;
201613118SEdmund.Grimley-Evans@arm.com    a_exp += b;
201713118SEdmund.Grimley-Evans@arm.com    a_mnt <<= 3;
201813118SEdmund.Grimley-Evans@arm.com
201913118SEdmund.Grimley-Evans@arm.com    a_mnt = fp64_normalise(a_mnt, &a_exp);
202013118SEdmund.Grimley-Evans@arm.com
202113118SEdmund.Grimley-Evans@arm.com    return fp64_round(a_sgn, a_exp + FP64_EXP_BITS - 3, a_mnt << 1,
202213118SEdmund.Grimley-Evans@arm.com                      mode, flags);
202313118SEdmund.Grimley-Evans@arm.com}
202413118SEdmund.Grimley-Evans@arm.com
202513118SEdmund.Grimley-Evans@arm.comstatic uint16_t
202613118SEdmund.Grimley-Evans@arm.comfp16_sqrt(uint16_t a, int mode, int *flags)
202713118SEdmund.Grimley-Evans@arm.com{
202813118SEdmund.Grimley-Evans@arm.com    int a_sgn, a_exp, x_sgn, x_exp;
202913118SEdmund.Grimley-Evans@arm.com    uint16_t a_mnt, x_mnt;
203013118SEdmund.Grimley-Evans@arm.com    uint32_t x, t0, t1;
203113118SEdmund.Grimley-Evans@arm.com
203213118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
203313118SEdmund.Grimley-Evans@arm.com
203413118SEdmund.Grimley-Evans@arm.com    // Handle NaNs:
203513118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(a_exp, a_mnt))
203613118SEdmund.Grimley-Evans@arm.com        return fp16_process_NaN(a, mode, flags);
203713118SEdmund.Grimley-Evans@arm.com
203813118SEdmund.Grimley-Evans@arm.com    // Handle infinities and zeroes:
203913118SEdmund.Grimley-Evans@arm.com    if (!a_mnt)
204013118SEdmund.Grimley-Evans@arm.com        return fp16_zero(a_sgn);
204113118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP16_EXP_INF && !a_sgn)
204213118SEdmund.Grimley-Evans@arm.com        return fp16_infinity(a_sgn);
204313118SEdmund.Grimley-Evans@arm.com    if (a_sgn) {
204413118SEdmund.Grimley-Evans@arm.com        *flags |= FPLIB_IOC;
204513118SEdmund.Grimley-Evans@arm.com        return fp16_defaultNaN();
204613118SEdmund.Grimley-Evans@arm.com    }
204713118SEdmund.Grimley-Evans@arm.com
204813118SEdmund.Grimley-Evans@arm.com    a_mnt = fp16_normalise(a_mnt, &a_exp);
204913118SEdmund.Grimley-Evans@arm.com    if (a_exp & 1) {
205013118SEdmund.Grimley-Evans@arm.com        ++a_exp;
205113118SEdmund.Grimley-Evans@arm.com        a_mnt >>= 1;
205213118SEdmund.Grimley-Evans@arm.com    }
205313118SEdmund.Grimley-Evans@arm.com
205413118SEdmund.Grimley-Evans@arm.com    // x = (a * 3 + 5) / 8
205513118SEdmund.Grimley-Evans@arm.com    x = ((uint32_t)a_mnt << 14) + ((uint32_t)a_mnt << 13) + ((uint32_t)5 << 28);
205613118SEdmund.Grimley-Evans@arm.com
205713118SEdmund.Grimley-Evans@arm.com    // x = (a / x + x) / 2; // 8-bit accuracy
205813118SEdmund.Grimley-Evans@arm.com    x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
205913118SEdmund.Grimley-Evans@arm.com
206013118SEdmund.Grimley-Evans@arm.com    // x = (a / x + x) / 2; // 16-bit accuracy
206113118SEdmund.Grimley-Evans@arm.com    x = (((uint32_t)a_mnt << 16) / (x >> 15) + (x >> 16)) << 15;
206213118SEdmund.Grimley-Evans@arm.com
206313118SEdmund.Grimley-Evans@arm.com    x_sgn = 0;
206413118SEdmund.Grimley-Evans@arm.com    x_exp = (a_exp + 27) >> 1;
206513118SEdmund.Grimley-Evans@arm.com    x_mnt = ((x - (1 << 18)) >> 19) + 1;
206613118SEdmund.Grimley-Evans@arm.com    t1 = (uint32_t)x_mnt * x_mnt;
206713118SEdmund.Grimley-Evans@arm.com    t0 = (uint32_t)a_mnt << 9;
206813118SEdmund.Grimley-Evans@arm.com    if (t1 > t0) {
206913118SEdmund.Grimley-Evans@arm.com        --x_mnt;
207013118SEdmund.Grimley-Evans@arm.com    }
207113118SEdmund.Grimley-Evans@arm.com
207213118SEdmund.Grimley-Evans@arm.com    x_mnt = fp16_normalise(x_mnt, &x_exp);
207313118SEdmund.Grimley-Evans@arm.com
207413118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
207513118SEdmund.Grimley-Evans@arm.com}
207613118SEdmund.Grimley-Evans@arm.com
207710037SARM gem5 Developersstatic uint32_t
207810037SARM gem5 Developersfp32_sqrt(uint32_t a, int mode, int *flags)
207910037SARM gem5 Developers{
208010037SARM gem5 Developers    int a_sgn, a_exp, x_sgn, x_exp;
208110037SARM gem5 Developers    uint32_t a_mnt, x, x_mnt;
208210037SARM gem5 Developers    uint64_t t0, t1;
208310037SARM gem5 Developers
208410037SARM gem5 Developers    fp32_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
208510037SARM gem5 Developers
208610037SARM gem5 Developers    // Handle NaNs:
208713118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(a_exp, a_mnt))
208810037SARM gem5 Developers        return fp32_process_NaN(a, mode, flags);
208910037SARM gem5 Developers
209010037SARM gem5 Developers    // Handle infinities and zeroes:
209113118SEdmund.Grimley-Evans@arm.com    if (!a_mnt)
209210037SARM gem5 Developers        return fp32_zero(a_sgn);
209313118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP32_EXP_INF && !a_sgn)
209410037SARM gem5 Developers        return fp32_infinity(a_sgn);
209510037SARM gem5 Developers    if (a_sgn) {
209610037SARM gem5 Developers        *flags |= FPLIB_IOC;
209710037SARM gem5 Developers        return fp32_defaultNaN();
209810037SARM gem5 Developers    }
209910037SARM gem5 Developers
210010037SARM gem5 Developers    a_mnt = fp32_normalise(a_mnt, &a_exp);
210110037SARM gem5 Developers    if (!(a_exp & 1)) {
210210037SARM gem5 Developers        ++a_exp;
210310037SARM gem5 Developers        a_mnt >>= 1;
210410037SARM gem5 Developers    }
210510037SARM gem5 Developers
210610037SARM gem5 Developers    // x = (a * 3 + 5) / 8
210713118SEdmund.Grimley-Evans@arm.com    x = (a_mnt >> 2) + (a_mnt >> 3) + ((uint32_t)5 << 28);
210813118SEdmund.Grimley-Evans@arm.com
210913118SEdmund.Grimley-Evans@arm.com    // x = (a / x + x) / 2; // 8-bit accuracy
211010037SARM gem5 Developers    x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
211110037SARM gem5 Developers
211210037SARM gem5 Developers    // x = (a / x + x) / 2; // 16-bit accuracy
211310037SARM gem5 Developers    x = (a_mnt / (x >> 15) + (x >> 16)) << 15;
211410037SARM gem5 Developers
211510037SARM gem5 Developers    // x = (a / x + x) / 2; // 32-bit accuracy
211610037SARM gem5 Developers    x = ((((uint64_t)a_mnt << 32) / x) >> 2) + (x >> 1);
211710037SARM gem5 Developers
211810037SARM gem5 Developers    x_sgn = 0;
211910037SARM gem5 Developers    x_exp = (a_exp + 147) >> 1;
212010037SARM gem5 Developers    x_mnt = ((x - (1 << 5)) >> 6) + 1;
212110037SARM gem5 Developers    t1 = (uint64_t)x_mnt * x_mnt;
212210037SARM gem5 Developers    t0 = (uint64_t)a_mnt << 19;
212310037SARM gem5 Developers    if (t1 > t0) {
212410037SARM gem5 Developers        --x_mnt;
212510037SARM gem5 Developers    }
212610037SARM gem5 Developers
212710037SARM gem5 Developers    x_mnt = fp32_normalise(x_mnt, &x_exp);
212810037SARM gem5 Developers
212910037SARM gem5 Developers    return fp32_round(x_sgn, x_exp, x_mnt << 1 | (t1 != t0), mode, flags);
213010037SARM gem5 Developers}
213110037SARM gem5 Developers
213210037SARM gem5 Developersstatic uint64_t
213310037SARM gem5 Developersfp64_sqrt(uint64_t a, int mode, int *flags)
213410037SARM gem5 Developers{
213510037SARM gem5 Developers    int a_sgn, a_exp, x_sgn, x_exp, c;
213610037SARM gem5 Developers    uint64_t a_mnt, x_mnt, r, x0, x1;
213710037SARM gem5 Developers    uint32_t x;
213810037SARM gem5 Developers
213910037SARM gem5 Developers    fp64_unpack(&a_sgn, &a_exp, &a_mnt, a, mode, flags);
214010037SARM gem5 Developers
214110037SARM gem5 Developers    // Handle NaNs:
214213118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(a_exp, a_mnt))
214310037SARM gem5 Developers        return fp64_process_NaN(a, mode, flags);
214410037SARM gem5 Developers
214510037SARM gem5 Developers    // Handle infinities and zeroes:
214610037SARM gem5 Developers    if (!a_mnt)
214710037SARM gem5 Developers        return fp64_zero(a_sgn);
214813118SEdmund.Grimley-Evans@arm.com    if (a_exp == FP64_EXP_INF && !a_sgn)
214910037SARM gem5 Developers        return fp64_infinity(a_sgn);
215010037SARM gem5 Developers    if (a_sgn) {
215110037SARM gem5 Developers        *flags |= FPLIB_IOC;
215210037SARM gem5 Developers        return fp64_defaultNaN();
215310037SARM gem5 Developers    }
215410037SARM gem5 Developers
215510037SARM gem5 Developers    a_mnt = fp64_normalise(a_mnt, &a_exp);
215610037SARM gem5 Developers    if (a_exp & 1) {
215710037SARM gem5 Developers        ++a_exp;
215810037SARM gem5 Developers        a_mnt >>= 1;
215910037SARM gem5 Developers    }
216010037SARM gem5 Developers
216110037SARM gem5 Developers    // x = (a * 3 + 5) / 8
216213118SEdmund.Grimley-Evans@arm.com    x = (a_mnt >> 34) + (a_mnt >> 35) + ((uint32_t)5 << 28);
216313118SEdmund.Grimley-Evans@arm.com
216413118SEdmund.Grimley-Evans@arm.com    // x = (a / x + x) / 2; // 8-bit accuracy
216510037SARM gem5 Developers    x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
216610037SARM gem5 Developers
216710037SARM gem5 Developers    // x = (a / x + x) / 2; // 16-bit accuracy
216810037SARM gem5 Developers    x = ((a_mnt >> 32) / (x >> 15) + (x >> 16)) << 15;
216910037SARM gem5 Developers
217010037SARM gem5 Developers    // x = (a / x + x) / 2; // 32-bit accuracy
217110037SARM gem5 Developers    x = ((a_mnt / x) >> 2) + (x >> 1);
217210037SARM gem5 Developers
217310037SARM gem5 Developers    // r = 1 / x; // 32-bit accuracy
217410037SARM gem5 Developers    r = ((uint64_t)1 << 62) / x;
217510037SARM gem5 Developers
217610037SARM gem5 Developers    // r = r * (2 - x * r); // 64-bit accuracy
217710037SARM gem5 Developers    mul64x32(&x0, &x1, -(uint64_t)x * r << 1, r);
217810037SARM gem5 Developers    lsr128(&x0, &x1, x0, x1, 31);
217910037SARM gem5 Developers
218010037SARM gem5 Developers    // x = (x + a * r) / 2; // 64-bit accuracy
218110037SARM gem5 Developers    mul62x62(&x0, &x1, a_mnt >> 10, x0 >> 2);
218210037SARM gem5 Developers    lsl128(&x0, &x1, x0, x1, 5);
218310037SARM gem5 Developers    lsr128(&x0, &x1, x0, x1, 56);
218410037SARM gem5 Developers
218510037SARM gem5 Developers    x0 = ((uint64_t)x << 31) + (x0 >> 1);
218610037SARM gem5 Developers
218710037SARM gem5 Developers    x_sgn = 0;
218810037SARM gem5 Developers    x_exp = (a_exp + 1053) >> 1;
218910037SARM gem5 Developers    x_mnt = x0;
219010037SARM gem5 Developers    x_mnt = ((x_mnt - (1 << 8)) >> 9) + 1;
219110037SARM gem5 Developers    mul62x62(&x0, &x1, x_mnt, x_mnt);
219210037SARM gem5 Developers    lsl128(&x0, &x1, x0, x1, 19);
219310037SARM gem5 Developers    c = cmp128(x0, x1, 0, a_mnt);
219410037SARM gem5 Developers    if (c > 0)
219510037SARM gem5 Developers        --x_mnt;
219610037SARM gem5 Developers
219710037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
219810037SARM gem5 Developers
219910037SARM gem5 Developers    return fp64_round(x_sgn, x_exp, x_mnt << 1 | !!c, mode, flags);
220010037SARM gem5 Developers}
220110037SARM gem5 Developers
220210037SARM gem5 Developersstatic int
220310037SARM gem5 DevelopersmodeConv(FPSCR fpscr)
220410037SARM gem5 Developers{
220513118SEdmund.Grimley-Evans@arm.com    uint32_t x = (uint32_t)fpscr;
220613118SEdmund.Grimley-Evans@arm.com    return (x >> 22 & 0xf) | (x >> 19 & 1 ? FPLIB_FZ16 : 0);
220713118SEdmund.Grimley-Evans@arm.com    // AHP bit is ignored. Only fplibConvert uses AHP.
220810037SARM gem5 Developers}
220910037SARM gem5 Developers
221010037SARM gem5 Developersstatic void
221110037SARM gem5 Developersset_fpscr(FPSCR &fpscr, int flags)
221210037SARM gem5 Developers{
221310037SARM gem5 Developers    // translate back to FPSCR
221410037SARM gem5 Developers    bool underflow = false;
221510037SARM gem5 Developers    if (flags & FPLIB_IDC) {
221610037SARM gem5 Developers        fpscr.idc = 1;
221710037SARM gem5 Developers    }
221810037SARM gem5 Developers    if (flags & FPLIB_IOC) {
221910037SARM gem5 Developers        fpscr.ioc = 1;
222010037SARM gem5 Developers    }
222110037SARM gem5 Developers    if (flags & FPLIB_DZC) {
222210037SARM gem5 Developers        fpscr.dzc = 1;
222310037SARM gem5 Developers    }
222410037SARM gem5 Developers    if (flags & FPLIB_OFC) {
222510037SARM gem5 Developers        fpscr.ofc = 1;
222610037SARM gem5 Developers    }
222710037SARM gem5 Developers    if (flags & FPLIB_UFC) {
222810037SARM gem5 Developers        underflow = true; //xx Why is this required?
222910037SARM gem5 Developers        fpscr.ufc = 1;
223010037SARM gem5 Developers    }
223110037SARM gem5 Developers    if ((flags & FPLIB_IXC) && !(underflow && fpscr.fz)) {
223210037SARM gem5 Developers        fpscr.ixc = 1;
223310037SARM gem5 Developers    }
223410037SARM gem5 Developers}
223510037SARM gem5 Developers
223610037SARM gem5 Developerstemplate <>
223710037SARM gem5 Developersbool
223813118SEdmund.Grimley-Evans@arm.comfplibCompareEQ(uint16_t a, uint16_t b, FPSCR &fpscr)
223913118SEdmund.Grimley-Evans@arm.com{
224013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
224113118SEdmund.Grimley-Evans@arm.com    int x = fp16_compare_eq(a, b, modeConv(fpscr), &flags);
224213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
224313118SEdmund.Grimley-Evans@arm.com    return x;
224413118SEdmund.Grimley-Evans@arm.com}
224513118SEdmund.Grimley-Evans@arm.com
224613118SEdmund.Grimley-Evans@arm.comtemplate <>
224713118SEdmund.Grimley-Evans@arm.combool
224813118SEdmund.Grimley-Evans@arm.comfplibCompareGE(uint16_t a, uint16_t b, FPSCR &fpscr)
224913118SEdmund.Grimley-Evans@arm.com{
225013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
225113118SEdmund.Grimley-Evans@arm.com    int x = fp16_compare_ge(a, b, modeConv(fpscr), &flags);
225213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
225313118SEdmund.Grimley-Evans@arm.com    return x;
225413118SEdmund.Grimley-Evans@arm.com}
225513118SEdmund.Grimley-Evans@arm.com
225613118SEdmund.Grimley-Evans@arm.comtemplate <>
225713118SEdmund.Grimley-Evans@arm.combool
225813118SEdmund.Grimley-Evans@arm.comfplibCompareGT(uint16_t a, uint16_t b, FPSCR &fpscr)
225913118SEdmund.Grimley-Evans@arm.com{
226013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
226113118SEdmund.Grimley-Evans@arm.com    int x = fp16_compare_gt(a, b, modeConv(fpscr), &flags);
226213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
226313118SEdmund.Grimley-Evans@arm.com    return x;
226413118SEdmund.Grimley-Evans@arm.com}
226513118SEdmund.Grimley-Evans@arm.com
226613118SEdmund.Grimley-Evans@arm.comtemplate <>
226713118SEdmund.Grimley-Evans@arm.combool
226813118SEdmund.Grimley-Evans@arm.comfplibCompareUN(uint16_t a, uint16_t b, FPSCR &fpscr)
226913118SEdmund.Grimley-Evans@arm.com{
227013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
227113118SEdmund.Grimley-Evans@arm.com    int x = fp16_compare_un(a, b, modeConv(fpscr), &flags);
227213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
227313118SEdmund.Grimley-Evans@arm.com    return x;
227413118SEdmund.Grimley-Evans@arm.com}
227513118SEdmund.Grimley-Evans@arm.com
227613118SEdmund.Grimley-Evans@arm.comtemplate <>
227713118SEdmund.Grimley-Evans@arm.combool
227810037SARM gem5 DevelopersfplibCompareEQ(uint32_t a, uint32_t b, FPSCR &fpscr)
227910037SARM gem5 Developers{
228010037SARM gem5 Developers    int flags = 0;
228110037SARM gem5 Developers    int x = fp32_compare_eq(a, b, modeConv(fpscr), &flags);
228210037SARM gem5 Developers    set_fpscr(fpscr, flags);
228310037SARM gem5 Developers    return x;
228410037SARM gem5 Developers}
228510037SARM gem5 Developers
228610037SARM gem5 Developerstemplate <>
228710037SARM gem5 Developersbool
228810037SARM gem5 DevelopersfplibCompareGE(uint32_t a, uint32_t b, FPSCR &fpscr)
228910037SARM gem5 Developers{
229010037SARM gem5 Developers    int flags = 0;
229110037SARM gem5 Developers    int x = fp32_compare_ge(a, b, modeConv(fpscr), &flags);
229210037SARM gem5 Developers    set_fpscr(fpscr, flags);
229310037SARM gem5 Developers    return x;
229410037SARM gem5 Developers}
229510037SARM gem5 Developers
229610037SARM gem5 Developerstemplate <>
229710037SARM gem5 Developersbool
229810037SARM gem5 DevelopersfplibCompareGT(uint32_t a, uint32_t b, FPSCR &fpscr)
229910037SARM gem5 Developers{
230010037SARM gem5 Developers    int flags = 0;
230110037SARM gem5 Developers    int x = fp32_compare_gt(a, b, modeConv(fpscr), &flags);
230210037SARM gem5 Developers    set_fpscr(fpscr, flags);
230310037SARM gem5 Developers    return x;
230410037SARM gem5 Developers}
230510037SARM gem5 Developers
230610037SARM gem5 Developerstemplate <>
230710037SARM gem5 Developersbool
230813118SEdmund.Grimley-Evans@arm.comfplibCompareUN(uint32_t a, uint32_t b, FPSCR &fpscr)
230913118SEdmund.Grimley-Evans@arm.com{
231013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
231113118SEdmund.Grimley-Evans@arm.com    int x = fp32_compare_un(a, b, modeConv(fpscr), &flags);
231213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
231313118SEdmund.Grimley-Evans@arm.com    return x;
231413118SEdmund.Grimley-Evans@arm.com}
231513118SEdmund.Grimley-Evans@arm.com
231613118SEdmund.Grimley-Evans@arm.comtemplate <>
231713118SEdmund.Grimley-Evans@arm.combool
231810037SARM gem5 DevelopersfplibCompareEQ(uint64_t a, uint64_t b, FPSCR &fpscr)
231910037SARM gem5 Developers{
232010037SARM gem5 Developers    int flags = 0;
232110037SARM gem5 Developers    int x = fp64_compare_eq(a, b, modeConv(fpscr), &flags);
232210037SARM gem5 Developers    set_fpscr(fpscr, flags);
232310037SARM gem5 Developers    return x;
232410037SARM gem5 Developers}
232510037SARM gem5 Developers
232610037SARM gem5 Developerstemplate <>
232710037SARM gem5 Developersbool
232810037SARM gem5 DevelopersfplibCompareGE(uint64_t a, uint64_t b, FPSCR &fpscr)
232910037SARM gem5 Developers{
233010037SARM gem5 Developers    int flags = 0;
233110037SARM gem5 Developers    int x = fp64_compare_ge(a, b, modeConv(fpscr), &flags);
233210037SARM gem5 Developers    set_fpscr(fpscr, flags);
233310037SARM gem5 Developers    return x;
233410037SARM gem5 Developers}
233510037SARM gem5 Developers
233610037SARM gem5 Developerstemplate <>
233710037SARM gem5 Developersbool
233810037SARM gem5 DevelopersfplibCompareGT(uint64_t a, uint64_t b, FPSCR &fpscr)
233910037SARM gem5 Developers{
234010037SARM gem5 Developers    int flags = 0;
234110037SARM gem5 Developers    int x = fp64_compare_gt(a, b, modeConv(fpscr), &flags);
234210037SARM gem5 Developers    set_fpscr(fpscr, flags);
234310037SARM gem5 Developers    return x;
234410037SARM gem5 Developers}
234510037SARM gem5 Developers
234610037SARM gem5 Developerstemplate <>
234713118SEdmund.Grimley-Evans@arm.combool
234813118SEdmund.Grimley-Evans@arm.comfplibCompareUN(uint64_t a, uint64_t b, FPSCR &fpscr)
234913118SEdmund.Grimley-Evans@arm.com{
235013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
235113118SEdmund.Grimley-Evans@arm.com    int x = fp64_compare_un(a, b, modeConv(fpscr), &flags);
235213118SEdmund.Grimley-Evans@arm.com    set_fpscr(fpscr, flags);
235313118SEdmund.Grimley-Evans@arm.com    return x;
235413118SEdmund.Grimley-Evans@arm.com}
235513118SEdmund.Grimley-Evans@arm.com
235613118SEdmund.Grimley-Evans@arm.comtemplate <>
235713118SEdmund.Grimley-Evans@arm.comuint16_t
235813118SEdmund.Grimley-Evans@arm.comfplibAbs(uint16_t op)
235913118SEdmund.Grimley-Evans@arm.com{
236013118SEdmund.Grimley-Evans@arm.com    return op & ~(1ULL << (FP16_BITS - 1));
236113118SEdmund.Grimley-Evans@arm.com}
236213118SEdmund.Grimley-Evans@arm.com
236313118SEdmund.Grimley-Evans@arm.comtemplate <>
236410037SARM gem5 Developersuint32_t
236510037SARM gem5 DevelopersfplibAbs(uint32_t op)
236610037SARM gem5 Developers{
236713118SEdmund.Grimley-Evans@arm.com    return op & ~(1ULL << (FP32_BITS - 1));
236810037SARM gem5 Developers}
236910037SARM gem5 Developers
237010037SARM gem5 Developerstemplate <>
237110037SARM gem5 Developersuint64_t
237210037SARM gem5 DevelopersfplibAbs(uint64_t op)
237310037SARM gem5 Developers{
237413118SEdmund.Grimley-Evans@arm.com    return op & ~(1ULL << (FP64_BITS - 1));
237513118SEdmund.Grimley-Evans@arm.com}
237613118SEdmund.Grimley-Evans@arm.com
237713118SEdmund.Grimley-Evans@arm.comtemplate <>
237813118SEdmund.Grimley-Evans@arm.comuint16_t
237913118SEdmund.Grimley-Evans@arm.comfplibAdd(uint16_t op1, uint16_t op2, FPSCR &fpscr)
238013118SEdmund.Grimley-Evans@arm.com{
238113118SEdmund.Grimley-Evans@arm.com    int flags = 0;
238213118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_add(op1, op2, 0, modeConv(fpscr), &flags);
238313118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
238413118SEdmund.Grimley-Evans@arm.com    return result;
238510037SARM gem5 Developers}
238610037SARM gem5 Developers
238710037SARM gem5 Developerstemplate <>
238810037SARM gem5 Developersuint32_t
238910037SARM gem5 DevelopersfplibAdd(uint32_t op1, uint32_t op2, FPSCR &fpscr)
239010037SARM gem5 Developers{
239110037SARM gem5 Developers    int flags = 0;
239210037SARM gem5 Developers    uint32_t result = fp32_add(op1, op2, 0, modeConv(fpscr), &flags);
239310037SARM gem5 Developers    set_fpscr0(fpscr, flags);
239410037SARM gem5 Developers    return result;
239510037SARM gem5 Developers}
239610037SARM gem5 Developers
239710037SARM gem5 Developerstemplate <>
239810037SARM gem5 Developersuint64_t
239910037SARM gem5 DevelopersfplibAdd(uint64_t op1, uint64_t op2, FPSCR &fpscr)
240010037SARM gem5 Developers{
240110037SARM gem5 Developers    int flags = 0;
240210037SARM gem5 Developers    uint64_t result = fp64_add(op1, op2, 0, modeConv(fpscr), &flags);
240310037SARM gem5 Developers    set_fpscr0(fpscr, flags);
240410037SARM gem5 Developers    return result;
240510037SARM gem5 Developers}
240610037SARM gem5 Developers
240710037SARM gem5 Developerstemplate <>
240810037SARM gem5 Developersint
240913118SEdmund.Grimley-Evans@arm.comfplibCompare(uint16_t op1, uint16_t op2, bool signal_nans, FPSCR &fpscr)
241010037SARM gem5 Developers{
241110037SARM gem5 Developers    int mode = modeConv(fpscr);
241210037SARM gem5 Developers    int flags = 0;
241310037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2, result;
241413118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2;
241513118SEdmund.Grimley-Evans@arm.com
241613118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
241713118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
241813118SEdmund.Grimley-Evans@arm.com
241913118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp1, mnt1) || fp16_is_NaN(exp2, mnt2)) {
242010037SARM gem5 Developers        result = 3;
242113118SEdmund.Grimley-Evans@arm.com        if (fp16_is_signalling_NaN(exp1, mnt1) ||
242213118SEdmund.Grimley-Evans@arm.com            fp16_is_signalling_NaN(exp2, mnt2) || signal_nans)
242310037SARM gem5 Developers            flags |= FPLIB_IOC;
242410037SARM gem5 Developers    } else {
242510037SARM gem5 Developers        if (op1 == op2 || (!mnt1 && !mnt2)) {
242610037SARM gem5 Developers            result = 6;
242710037SARM gem5 Developers        } else if (sgn1 != sgn2) {
242810037SARM gem5 Developers            result = sgn1 ? 8 : 2;
242910037SARM gem5 Developers        } else if (exp1 != exp2) {
243010037SARM gem5 Developers            result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
243110037SARM gem5 Developers        } else {
243210037SARM gem5 Developers            result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
243310037SARM gem5 Developers        }
243410037SARM gem5 Developers    }
243510037SARM gem5 Developers
243610037SARM gem5 Developers    set_fpscr0(fpscr, flags);
243710037SARM gem5 Developers
243810037SARM gem5 Developers    return result;
243910037SARM gem5 Developers}
244010037SARM gem5 Developers
244110037SARM gem5 Developerstemplate <>
244210037SARM gem5 Developersint
244313118SEdmund.Grimley-Evans@arm.comfplibCompare(uint32_t op1, uint32_t op2, bool signal_nans, FPSCR &fpscr)
244410037SARM gem5 Developers{
244510037SARM gem5 Developers    int mode = modeConv(fpscr);
244610037SARM gem5 Developers    int flags = 0;
244710037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2, result;
244813118SEdmund.Grimley-Evans@arm.com    uint32_t mnt1, mnt2;
244913118SEdmund.Grimley-Evans@arm.com
245013118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
245113118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
245213118SEdmund.Grimley-Evans@arm.com
245313118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp1, mnt1) || fp32_is_NaN(exp2, mnt2)) {
245410037SARM gem5 Developers        result = 3;
245513118SEdmund.Grimley-Evans@arm.com        if (fp32_is_signalling_NaN(exp1, mnt1) ||
245613118SEdmund.Grimley-Evans@arm.com            fp32_is_signalling_NaN(exp2, mnt2) || signal_nans)
245710037SARM gem5 Developers            flags |= FPLIB_IOC;
245810037SARM gem5 Developers    } else {
245910037SARM gem5 Developers        if (op1 == op2 || (!mnt1 && !mnt2)) {
246010037SARM gem5 Developers            result = 6;
246110037SARM gem5 Developers        } else if (sgn1 != sgn2) {
246210037SARM gem5 Developers            result = sgn1 ? 8 : 2;
246310037SARM gem5 Developers        } else if (exp1 != exp2) {
246410037SARM gem5 Developers            result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
246510037SARM gem5 Developers        } else {
246610037SARM gem5 Developers            result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
246710037SARM gem5 Developers        }
246810037SARM gem5 Developers    }
246910037SARM gem5 Developers
247010037SARM gem5 Developers    set_fpscr0(fpscr, flags);
247110037SARM gem5 Developers
247210037SARM gem5 Developers    return result;
247310037SARM gem5 Developers}
247410037SARM gem5 Developers
247513118SEdmund.Grimley-Evans@arm.comtemplate <>
247613118SEdmund.Grimley-Evans@arm.comint
247713118SEdmund.Grimley-Evans@arm.comfplibCompare(uint64_t op1, uint64_t op2, bool signal_nans, FPSCR &fpscr)
247813118SEdmund.Grimley-Evans@arm.com{
247913118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
248013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
248113118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2, result;
248213118SEdmund.Grimley-Evans@arm.com    uint64_t mnt1, mnt2;
248313118SEdmund.Grimley-Evans@arm.com
248413118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
248513118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
248613118SEdmund.Grimley-Evans@arm.com
248713118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp1, mnt1) || fp64_is_NaN(exp2, mnt2)) {
248813118SEdmund.Grimley-Evans@arm.com        result = 3;
248913118SEdmund.Grimley-Evans@arm.com        if (fp64_is_signalling_NaN(exp1, mnt1) ||
249013118SEdmund.Grimley-Evans@arm.com            fp64_is_signalling_NaN(exp2, mnt2) || signal_nans)
249113118SEdmund.Grimley-Evans@arm.com            flags |= FPLIB_IOC;
249213118SEdmund.Grimley-Evans@arm.com    } else {
249313118SEdmund.Grimley-Evans@arm.com        if (op1 == op2 || (!mnt1 && !mnt2)) {
249413118SEdmund.Grimley-Evans@arm.com            result = 6;
249513118SEdmund.Grimley-Evans@arm.com        } else if (sgn1 != sgn2) {
249613118SEdmund.Grimley-Evans@arm.com            result = sgn1 ? 8 : 2;
249713118SEdmund.Grimley-Evans@arm.com        } else if (exp1 != exp2) {
249813118SEdmund.Grimley-Evans@arm.com            result = sgn1 ^ (exp1 < exp2) ? 8 : 2;
249913118SEdmund.Grimley-Evans@arm.com        } else {
250013118SEdmund.Grimley-Evans@arm.com            result = sgn1 ^ (mnt1 < mnt2) ? 8 : 2;
250113118SEdmund.Grimley-Evans@arm.com        }
250213118SEdmund.Grimley-Evans@arm.com    }
250313118SEdmund.Grimley-Evans@arm.com
250413118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
250513118SEdmund.Grimley-Evans@arm.com
250613118SEdmund.Grimley-Evans@arm.com    return result;
250713118SEdmund.Grimley-Evans@arm.com}
250813118SEdmund.Grimley-Evans@arm.com
250910037SARM gem5 Developersstatic uint16_t
251010037SARM gem5 Developersfp16_FPConvertNaN_32(uint32_t op)
251110037SARM gem5 Developers{
251213118SEdmund.Grimley-Evans@arm.com    return fp16_pack(op >> (FP32_BITS - 1), FP16_EXP_INF,
251313118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP16_MANT_BITS - 1) |
251413118SEdmund.Grimley-Evans@arm.com                     op >> (FP32_MANT_BITS - FP16_MANT_BITS));
251510037SARM gem5 Developers}
251610037SARM gem5 Developers
251710037SARM gem5 Developersstatic uint16_t
251810037SARM gem5 Developersfp16_FPConvertNaN_64(uint64_t op)
251910037SARM gem5 Developers{
252013118SEdmund.Grimley-Evans@arm.com    return fp16_pack(op >> (FP64_BITS - 1), FP16_EXP_INF,
252113118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP16_MANT_BITS - 1) |
252213118SEdmund.Grimley-Evans@arm.com                     op >> (FP64_MANT_BITS - FP16_MANT_BITS));
252310037SARM gem5 Developers}
252410037SARM gem5 Developers
252510037SARM gem5 Developersstatic uint32_t
252610037SARM gem5 Developersfp32_FPConvertNaN_16(uint16_t op)
252710037SARM gem5 Developers{
252813118SEdmund.Grimley-Evans@arm.com    return fp32_pack(op >> (FP16_BITS - 1), FP32_EXP_INF,
252913118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP32_MANT_BITS - 1) |
253013118SEdmund.Grimley-Evans@arm.com                     (uint32_t)op << (FP32_MANT_BITS - FP16_MANT_BITS));
253110037SARM gem5 Developers}
253210037SARM gem5 Developers
253310037SARM gem5 Developersstatic uint32_t
253410037SARM gem5 Developersfp32_FPConvertNaN_64(uint64_t op)
253510037SARM gem5 Developers{
253613118SEdmund.Grimley-Evans@arm.com    return fp32_pack(op >> (FP64_BITS - 1), FP32_EXP_INF,
253713118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP32_MANT_BITS - 1) |
253813118SEdmund.Grimley-Evans@arm.com                     op >> (FP64_MANT_BITS - FP32_MANT_BITS));
253910037SARM gem5 Developers}
254010037SARM gem5 Developers
254110037SARM gem5 Developersstatic uint64_t
254210037SARM gem5 Developersfp64_FPConvertNaN_16(uint16_t op)
254310037SARM gem5 Developers{
254413118SEdmund.Grimley-Evans@arm.com    return fp64_pack(op >> (FP16_BITS - 1), FP64_EXP_INF,
254513118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP64_MANT_BITS - 1) |
254613118SEdmund.Grimley-Evans@arm.com                     (uint64_t)op << (FP64_MANT_BITS - FP16_MANT_BITS));
254710037SARM gem5 Developers}
254810037SARM gem5 Developers
254910037SARM gem5 Developersstatic uint64_t
255010037SARM gem5 Developersfp64_FPConvertNaN_32(uint32_t op)
255110037SARM gem5 Developers{
255213118SEdmund.Grimley-Evans@arm.com    return fp64_pack(op >> (FP32_BITS - 1), FP64_EXP_INF,
255313118SEdmund.Grimley-Evans@arm.com                     1ULL << (FP64_MANT_BITS - 1) |
255413118SEdmund.Grimley-Evans@arm.com                     (uint64_t)op << (FP64_MANT_BITS - FP32_MANT_BITS));
255513118SEdmund.Grimley-Evans@arm.com}
255613118SEdmund.Grimley-Evans@arm.com
255713118SEdmund.Grimley-Evans@arm.comstatic uint16_t
255813118SEdmund.Grimley-Evans@arm.comfp16_FPOnePointFive(int sgn)
255913118SEdmund.Grimley-Evans@arm.com{
256013118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, FP16_EXP_BIAS, 1ULL << (FP16_MANT_BITS - 1));
256110037SARM gem5 Developers}
256210037SARM gem5 Developers
256310037SARM gem5 Developersstatic uint32_t
256410037SARM gem5 Developersfp32_FPOnePointFive(int sgn)
256510037SARM gem5 Developers{
256613118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, FP32_EXP_BIAS, 1ULL << (FP32_MANT_BITS - 1));
256710037SARM gem5 Developers}
256810037SARM gem5 Developers
256910037SARM gem5 Developersstatic uint64_t
257010037SARM gem5 Developersfp64_FPOnePointFive(int sgn)
257110037SARM gem5 Developers{
257213118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, FP64_EXP_BIAS, 1ULL << (FP64_MANT_BITS - 1));
257313118SEdmund.Grimley-Evans@arm.com}
257413118SEdmund.Grimley-Evans@arm.com
257513118SEdmund.Grimley-Evans@arm.comstatic uint16_t
257613118SEdmund.Grimley-Evans@arm.comfp16_FPThree(int sgn)
257713118SEdmund.Grimley-Evans@arm.com{
257813118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, FP16_EXP_BIAS + 1, 1ULL << (FP16_MANT_BITS - 1));
257910037SARM gem5 Developers}
258010037SARM gem5 Developers
258110037SARM gem5 Developersstatic uint32_t
258210037SARM gem5 Developersfp32_FPThree(int sgn)
258310037SARM gem5 Developers{
258413118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, FP32_EXP_BIAS + 1, 1ULL << (FP32_MANT_BITS - 1));
258510037SARM gem5 Developers}
258610037SARM gem5 Developers
258710037SARM gem5 Developersstatic uint64_t
258810037SARM gem5 Developersfp64_FPThree(int sgn)
258910037SARM gem5 Developers{
259013118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, FP64_EXP_BIAS + 1, 1ULL << (FP64_MANT_BITS - 1));
259113118SEdmund.Grimley-Evans@arm.com}
259213118SEdmund.Grimley-Evans@arm.com
259313118SEdmund.Grimley-Evans@arm.comstatic uint16_t
259413118SEdmund.Grimley-Evans@arm.comfp16_FPTwo(int sgn)
259513118SEdmund.Grimley-Evans@arm.com{
259613118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, FP16_EXP_BIAS + 1, 0);
259710037SARM gem5 Developers}
259810037SARM gem5 Developers
259910037SARM gem5 Developersstatic uint32_t
260010037SARM gem5 Developersfp32_FPTwo(int sgn)
260110037SARM gem5 Developers{
260213118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, FP32_EXP_BIAS + 1, 0);
260310037SARM gem5 Developers}
260410037SARM gem5 Developers
260510037SARM gem5 Developersstatic uint64_t
260610037SARM gem5 Developersfp64_FPTwo(int sgn)
260710037SARM gem5 Developers{
260813118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, FP64_EXP_BIAS + 1, 0);
260910037SARM gem5 Developers}
261010037SARM gem5 Developers
261110037SARM gem5 Developerstemplate <>
261210037SARM gem5 Developersuint16_t
261310037SARM gem5 DevelopersfplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr)
261410037SARM gem5 Developers{
261510037SARM gem5 Developers    int mode = modeConv(fpscr);
261610037SARM gem5 Developers    int flags = 0;
261710037SARM gem5 Developers    int sgn, exp;
261810037SARM gem5 Developers    uint32_t mnt;
261910037SARM gem5 Developers    uint16_t result;
262010037SARM gem5 Developers
262110037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
262210037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
262310037SARM gem5 Developers
262410037SARM gem5 Developers    bool alt_hp = fpscr.ahp;
262510037SARM gem5 Developers
262613118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
262710037SARM gem5 Developers        if (alt_hp) {
262810037SARM gem5 Developers            result = fp16_zero(sgn);
262910037SARM gem5 Developers        } else if (fpscr.dn) {
263010037SARM gem5 Developers            result = fp16_defaultNaN();
263110037SARM gem5 Developers        } else {
263210037SARM gem5 Developers            result = fp16_FPConvertNaN_32(op);
263310037SARM gem5 Developers        }
263413118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP32_MANT_BITS - 1) & 1) || alt_hp) {
263510037SARM gem5 Developers            flags |= FPLIB_IOC;
263610037SARM gem5 Developers        }
263713118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP32_EXP_INF) {
263810037SARM gem5 Developers        if (alt_hp) {
263913118SEdmund.Grimley-Evans@arm.com            result = ((uint16_t)sgn << (FP16_BITS - 1) |
264013118SEdmund.Grimley-Evans@arm.com                      ((1ULL << (FP16_BITS - 1)) - 1));
264110037SARM gem5 Developers            flags |= FPLIB_IOC;
264210037SARM gem5 Developers        } else {
264310037SARM gem5 Developers            result = fp16_infinity(sgn);
264410037SARM gem5 Developers        }
264510037SARM gem5 Developers    } else if (!mnt) {
264610037SARM gem5 Developers        result = fp16_zero(sgn);
264710037SARM gem5 Developers    } else {
264813118SEdmund.Grimley-Evans@arm.com        result =
264913118SEdmund.Grimley-Evans@arm.com            fp16_round_(sgn, exp - FP32_EXP_BIAS + FP16_EXP_BIAS,
265013118SEdmund.Grimley-Evans@arm.com                        mnt >> (FP32_MANT_BITS - FP16_BITS) |
265113118SEdmund.Grimley-Evans@arm.com                        !!(mnt & ((1ULL << (FP32_MANT_BITS - FP16_BITS)) - 1)),
265213118SEdmund.Grimley-Evans@arm.com                        rounding, (mode & 0xf) | alt_hp << 4, &flags);
265310037SARM gem5 Developers    }
265410037SARM gem5 Developers
265510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
265610037SARM gem5 Developers
265710037SARM gem5 Developers    return result;
265810037SARM gem5 Developers}
265910037SARM gem5 Developers
266010037SARM gem5 Developerstemplate <>
266110037SARM gem5 Developersuint16_t
266210037SARM gem5 DevelopersfplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr)
266310037SARM gem5 Developers{
266410037SARM gem5 Developers    int mode = modeConv(fpscr);
266510037SARM gem5 Developers    int flags = 0;
266610037SARM gem5 Developers    int sgn, exp;
266710037SARM gem5 Developers    uint64_t mnt;
266810037SARM gem5 Developers    uint16_t result;
266910037SARM gem5 Developers
267010037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
267110037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
267210037SARM gem5 Developers
267310037SARM gem5 Developers    bool alt_hp = fpscr.ahp;
267410037SARM gem5 Developers
267513118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
267610037SARM gem5 Developers        if (alt_hp) {
267710037SARM gem5 Developers            result = fp16_zero(sgn);
267810037SARM gem5 Developers        } else if (fpscr.dn) {
267910037SARM gem5 Developers            result = fp16_defaultNaN();
268010037SARM gem5 Developers        } else {
268110037SARM gem5 Developers            result = fp16_FPConvertNaN_64(op);
268210037SARM gem5 Developers        }
268313118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP64_MANT_BITS - 1) & 1) || alt_hp) {
268410037SARM gem5 Developers            flags |= FPLIB_IOC;
268510037SARM gem5 Developers        }
268613118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP64_EXP_INF) {
268710037SARM gem5 Developers        if (alt_hp) {
268813118SEdmund.Grimley-Evans@arm.com            result = ((uint16_t)sgn << (FP16_BITS - 1) |
268913118SEdmund.Grimley-Evans@arm.com                      ((1ULL << (FP16_BITS - 1)) - 1));
269010037SARM gem5 Developers            flags |= FPLIB_IOC;
269110037SARM gem5 Developers        } else {
269210037SARM gem5 Developers            result = fp16_infinity(sgn);
269310037SARM gem5 Developers        }
269410037SARM gem5 Developers    } else if (!mnt) {
269510037SARM gem5 Developers        result = fp16_zero(sgn);
269610037SARM gem5 Developers    } else {
269713118SEdmund.Grimley-Evans@arm.com        result =
269813118SEdmund.Grimley-Evans@arm.com            fp16_round_(sgn, exp - FP64_EXP_BIAS + FP16_EXP_BIAS,
269913118SEdmund.Grimley-Evans@arm.com                        mnt >> (FP64_MANT_BITS - FP16_BITS) |
270013118SEdmund.Grimley-Evans@arm.com                        !!(mnt & ((1ULL << (FP64_MANT_BITS - FP16_BITS)) - 1)),
270113118SEdmund.Grimley-Evans@arm.com                        rounding, (mode & 0xf) | alt_hp << 4, &flags);
270210037SARM gem5 Developers    }
270310037SARM gem5 Developers
270410037SARM gem5 Developers    set_fpscr0(fpscr, flags);
270510037SARM gem5 Developers
270610037SARM gem5 Developers    return result;
270710037SARM gem5 Developers}
270810037SARM gem5 Developers
270910037SARM gem5 Developerstemplate <>
271010037SARM gem5 Developersuint32_t
271110037SARM gem5 DevelopersfplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr)
271210037SARM gem5 Developers{
271310037SARM gem5 Developers    int mode = modeConv(fpscr);
271410037SARM gem5 Developers    int flags = 0;
271510037SARM gem5 Developers    int sgn, exp;
271610037SARM gem5 Developers    uint16_t mnt;
271710037SARM gem5 Developers    uint32_t result;
271810037SARM gem5 Developers
271910037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
272013118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xf, &flags);
272113118SEdmund.Grimley-Evans@arm.com
272213118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
272310037SARM gem5 Developers        if (fpscr.dn) {
272410037SARM gem5 Developers            result = fp32_defaultNaN();
272510037SARM gem5 Developers        } else {
272610037SARM gem5 Developers            result = fp32_FPConvertNaN_16(op);
272710037SARM gem5 Developers        }
272813118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
272910037SARM gem5 Developers            flags |= FPLIB_IOC;
273010037SARM gem5 Developers        }
273113118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
273210037SARM gem5 Developers        result = fp32_infinity(sgn);
273310037SARM gem5 Developers    } else if (!mnt) {
273410037SARM gem5 Developers        result = fp32_zero(sgn);
273510037SARM gem5 Developers    } else {
273610037SARM gem5 Developers        mnt = fp16_normalise(mnt, &exp);
273713118SEdmund.Grimley-Evans@arm.com        result = fp32_pack(sgn, (exp - FP16_EXP_BIAS +
273813118SEdmund.Grimley-Evans@arm.com                                 FP32_EXP_BIAS + FP16_EXP_BITS),
273913118SEdmund.Grimley-Evans@arm.com                           (uint32_t)mnt << (FP32_MANT_BITS - FP16_BITS + 1));
274010037SARM gem5 Developers    }
274110037SARM gem5 Developers
274210037SARM gem5 Developers    set_fpscr0(fpscr, flags);
274310037SARM gem5 Developers
274410037SARM gem5 Developers    return result;
274510037SARM gem5 Developers}
274610037SARM gem5 Developers
274710037SARM gem5 Developerstemplate <>
274810037SARM gem5 Developersuint32_t
274910037SARM gem5 DevelopersfplibConvert(uint64_t op, FPRounding rounding, FPSCR &fpscr)
275010037SARM gem5 Developers{
275110037SARM gem5 Developers    int mode = modeConv(fpscr);
275210037SARM gem5 Developers    int flags = 0;
275310037SARM gem5 Developers    int sgn, exp;
275410037SARM gem5 Developers    uint64_t mnt;
275510037SARM gem5 Developers    uint32_t result;
275610037SARM gem5 Developers
275710037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
275810037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
275910037SARM gem5 Developers
276013118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
276110037SARM gem5 Developers        if (fpscr.dn) {
276210037SARM gem5 Developers            result = fp32_defaultNaN();
276310037SARM gem5 Developers        } else {
276410037SARM gem5 Developers            result = fp32_FPConvertNaN_64(op);
276510037SARM gem5 Developers        }
276613118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP64_MANT_BITS - 1) & 1)) {
276710037SARM gem5 Developers            flags |= FPLIB_IOC;
276810037SARM gem5 Developers        }
276913118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP64_EXP_INF) {
277010037SARM gem5 Developers        result = fp32_infinity(sgn);
277110037SARM gem5 Developers    } else if (!mnt) {
277210037SARM gem5 Developers        result = fp32_zero(sgn);
277310037SARM gem5 Developers    } else {
277413118SEdmund.Grimley-Evans@arm.com        result =
277513118SEdmund.Grimley-Evans@arm.com            fp32_round_(sgn, exp - FP64_EXP_BIAS + FP32_EXP_BIAS,
277613118SEdmund.Grimley-Evans@arm.com                        mnt >> (FP64_MANT_BITS - FP32_BITS) |
277713118SEdmund.Grimley-Evans@arm.com                        !!(mnt & ((1ULL << (FP64_MANT_BITS - FP32_BITS)) - 1)),
277813118SEdmund.Grimley-Evans@arm.com                        rounding, mode, &flags);
277910037SARM gem5 Developers    }
278010037SARM gem5 Developers
278110037SARM gem5 Developers    set_fpscr0(fpscr, flags);
278210037SARM gem5 Developers
278310037SARM gem5 Developers    return result;
278410037SARM gem5 Developers}
278510037SARM gem5 Developers
278610037SARM gem5 Developerstemplate <>
278710037SARM gem5 Developersuint64_t
278810037SARM gem5 DevelopersfplibConvert(uint16_t op, FPRounding rounding, FPSCR &fpscr)
278910037SARM gem5 Developers{
279010037SARM gem5 Developers    int mode = modeConv(fpscr);
279110037SARM gem5 Developers    int flags = 0;
279210037SARM gem5 Developers    int sgn, exp;
279310037SARM gem5 Developers    uint16_t mnt;
279410037SARM gem5 Developers    uint64_t result;
279510037SARM gem5 Developers
279610037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
279713118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode & 0xf, &flags);
279813118SEdmund.Grimley-Evans@arm.com
279913118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt) && !fpscr.ahp) {
280010037SARM gem5 Developers        if (fpscr.dn) {
280110037SARM gem5 Developers            result = fp64_defaultNaN();
280210037SARM gem5 Developers        } else {
280310037SARM gem5 Developers            result = fp64_FPConvertNaN_16(op);
280410037SARM gem5 Developers        }
280513118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP16_MANT_BITS - 1) & 1)) {
280610037SARM gem5 Developers            flags |= FPLIB_IOC;
280710037SARM gem5 Developers        }
280813118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP16_EXP_INF && !fpscr.ahp) {
280910037SARM gem5 Developers        result = fp64_infinity(sgn);
281010037SARM gem5 Developers    } else if (!mnt) {
281110037SARM gem5 Developers        result = fp64_zero(sgn);
281210037SARM gem5 Developers    } else {
281310037SARM gem5 Developers        mnt = fp16_normalise(mnt, &exp);
281413118SEdmund.Grimley-Evans@arm.com        result = fp64_pack(sgn, (exp - FP16_EXP_BIAS +
281513118SEdmund.Grimley-Evans@arm.com                                 FP64_EXP_BIAS + FP16_EXP_BITS),
281613118SEdmund.Grimley-Evans@arm.com                           (uint64_t)mnt << (FP64_MANT_BITS - FP16_BITS + 1));
281710037SARM gem5 Developers    }
281810037SARM gem5 Developers
281910037SARM gem5 Developers    set_fpscr0(fpscr, flags);
282010037SARM gem5 Developers
282110037SARM gem5 Developers    return result;
282210037SARM gem5 Developers}
282310037SARM gem5 Developers
282410037SARM gem5 Developerstemplate <>
282510037SARM gem5 Developersuint64_t
282610037SARM gem5 DevelopersfplibConvert(uint32_t op, FPRounding rounding, FPSCR &fpscr)
282710037SARM gem5 Developers{
282810037SARM gem5 Developers    int mode = modeConv(fpscr);
282910037SARM gem5 Developers    int flags = 0;
283010037SARM gem5 Developers    int sgn, exp;
283110037SARM gem5 Developers    uint32_t mnt;
283210037SARM gem5 Developers    uint64_t result;
283310037SARM gem5 Developers
283410037SARM gem5 Developers    // Unpack floating-point operand optionally with flush-to-zero:
283510037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
283610037SARM gem5 Developers
283713118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
283810037SARM gem5 Developers        if (fpscr.dn) {
283910037SARM gem5 Developers            result = fp64_defaultNaN();
284010037SARM gem5 Developers        } else {
284110037SARM gem5 Developers            result = fp64_FPConvertNaN_32(op);
284210037SARM gem5 Developers        }
284313118SEdmund.Grimley-Evans@arm.com        if (!(mnt >> (FP32_MANT_BITS - 1) & 1)) {
284410037SARM gem5 Developers            flags |= FPLIB_IOC;
284510037SARM gem5 Developers        }
284613118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP32_EXP_INF) {
284710037SARM gem5 Developers        result = fp64_infinity(sgn);
284810037SARM gem5 Developers    } else if (!mnt) {
284910037SARM gem5 Developers        result = fp64_zero(sgn);
285010037SARM gem5 Developers    } else {
285110037SARM gem5 Developers        mnt = fp32_normalise(mnt, &exp);
285213118SEdmund.Grimley-Evans@arm.com        result = fp64_pack(sgn, (exp - FP32_EXP_BIAS +
285313118SEdmund.Grimley-Evans@arm.com                                 FP64_EXP_BIAS + FP32_EXP_BITS),
285413118SEdmund.Grimley-Evans@arm.com                           (uint64_t)mnt << (FP64_MANT_BITS - FP32_BITS + 1));
285510037SARM gem5 Developers    }
285610037SARM gem5 Developers
285710037SARM gem5 Developers    set_fpscr0(fpscr, flags);
285810037SARM gem5 Developers
285910037SARM gem5 Developers    return result;
286010037SARM gem5 Developers}
286110037SARM gem5 Developers
286210037SARM gem5 Developerstemplate <>
286313118SEdmund.Grimley-Evans@arm.comuint16_t
286413118SEdmund.Grimley-Evans@arm.comfplibMulAdd(uint16_t addend, uint16_t op1, uint16_t op2, FPSCR &fpscr)
286513118SEdmund.Grimley-Evans@arm.com{
286613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
286713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
286813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
286913118SEdmund.Grimley-Evans@arm.com    return result;
287013118SEdmund.Grimley-Evans@arm.com}
287113118SEdmund.Grimley-Evans@arm.com
287213118SEdmund.Grimley-Evans@arm.comtemplate <>
287310037SARM gem5 Developersuint32_t
287410037SARM gem5 DevelopersfplibMulAdd(uint32_t addend, uint32_t op1, uint32_t op2, FPSCR &fpscr)
287510037SARM gem5 Developers{
287610037SARM gem5 Developers    int flags = 0;
287710037SARM gem5 Developers    uint32_t result = fp32_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
287810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
287910037SARM gem5 Developers    return result;
288010037SARM gem5 Developers}
288110037SARM gem5 Developers
288210037SARM gem5 Developerstemplate <>
288310037SARM gem5 Developersuint64_t
288410037SARM gem5 DevelopersfplibMulAdd(uint64_t addend, uint64_t op1, uint64_t op2, FPSCR &fpscr)
288510037SARM gem5 Developers{
288610037SARM gem5 Developers    int flags = 0;
288710037SARM gem5 Developers    uint64_t result = fp64_muladd(addend, op1, op2, 0, modeConv(fpscr), &flags);
288810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
288910037SARM gem5 Developers    return result;
289010037SARM gem5 Developers}
289110037SARM gem5 Developers
289210037SARM gem5 Developerstemplate <>
289313118SEdmund.Grimley-Evans@arm.comuint16_t
289413118SEdmund.Grimley-Evans@arm.comfplibDiv(uint16_t op1, uint16_t op2, FPSCR &fpscr)
289513118SEdmund.Grimley-Evans@arm.com{
289613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
289713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_div(op1, op2, modeConv(fpscr), &flags);
289813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
289913118SEdmund.Grimley-Evans@arm.com    return result;
290013118SEdmund.Grimley-Evans@arm.com}
290113118SEdmund.Grimley-Evans@arm.com
290213118SEdmund.Grimley-Evans@arm.comtemplate <>
290310037SARM gem5 Developersuint32_t
290410037SARM gem5 DevelopersfplibDiv(uint32_t op1, uint32_t op2, FPSCR &fpscr)
290510037SARM gem5 Developers{
290610037SARM gem5 Developers    int flags = 0;
290710037SARM gem5 Developers    uint32_t result = fp32_div(op1, op2, modeConv(fpscr), &flags);
290810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
290910037SARM gem5 Developers    return result;
291010037SARM gem5 Developers}
291110037SARM gem5 Developers
291210037SARM gem5 Developerstemplate <>
291310037SARM gem5 Developersuint64_t
291410037SARM gem5 DevelopersfplibDiv(uint64_t op1, uint64_t op2, FPSCR &fpscr)
291510037SARM gem5 Developers{
291610037SARM gem5 Developers    int flags = 0;
291710037SARM gem5 Developers    uint64_t result = fp64_div(op1, op2, modeConv(fpscr), &flags);
291810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
291910037SARM gem5 Developers    return result;
292010037SARM gem5 Developers}
292110037SARM gem5 Developers
292213118SEdmund.Grimley-Evans@arm.comtemplate <>
292313118SEdmund.Grimley-Evans@arm.comuint16_t
292413118SEdmund.Grimley-Evans@arm.comfplibExpA(uint16_t op)
292513118SEdmund.Grimley-Evans@arm.com{
292613118SEdmund.Grimley-Evans@arm.com    static uint16_t coeff[32] = {
292713118SEdmund.Grimley-Evans@arm.com        0x0000,
292813118SEdmund.Grimley-Evans@arm.com        0x0016,
292913118SEdmund.Grimley-Evans@arm.com        0x002d,
293013118SEdmund.Grimley-Evans@arm.com        0x0045,
293113118SEdmund.Grimley-Evans@arm.com        0x005d,
293213118SEdmund.Grimley-Evans@arm.com        0x0075,
293313118SEdmund.Grimley-Evans@arm.com        0x008e,
293413118SEdmund.Grimley-Evans@arm.com        0x00a8,
293513118SEdmund.Grimley-Evans@arm.com        0x00c2,
293613118SEdmund.Grimley-Evans@arm.com        0x00dc,
293713118SEdmund.Grimley-Evans@arm.com        0x00f8,
293813118SEdmund.Grimley-Evans@arm.com        0x0114,
293913118SEdmund.Grimley-Evans@arm.com        0x0130,
294013118SEdmund.Grimley-Evans@arm.com        0x014d,
294113118SEdmund.Grimley-Evans@arm.com        0x016b,
294213118SEdmund.Grimley-Evans@arm.com        0x0189,
294313118SEdmund.Grimley-Evans@arm.com        0x01a8,
294413118SEdmund.Grimley-Evans@arm.com        0x01c8,
294513118SEdmund.Grimley-Evans@arm.com        0x01e8,
294613118SEdmund.Grimley-Evans@arm.com        0x0209,
294713118SEdmund.Grimley-Evans@arm.com        0x022b,
294813118SEdmund.Grimley-Evans@arm.com        0x024e,
294913118SEdmund.Grimley-Evans@arm.com        0x0271,
295013118SEdmund.Grimley-Evans@arm.com        0x0295,
295113118SEdmund.Grimley-Evans@arm.com        0x02ba,
295213118SEdmund.Grimley-Evans@arm.com        0x02e0,
295313118SEdmund.Grimley-Evans@arm.com        0x0306,
295413118SEdmund.Grimley-Evans@arm.com        0x032e,
295513118SEdmund.Grimley-Evans@arm.com        0x0356,
295613118SEdmund.Grimley-Evans@arm.com        0x037f,
295713118SEdmund.Grimley-Evans@arm.com        0x03a9,
295813118SEdmund.Grimley-Evans@arm.com        0x03d4
295913118SEdmund.Grimley-Evans@arm.com    };
296013118SEdmund.Grimley-Evans@arm.com    return ((((op >> 5) & ((1 << FP16_EXP_BITS) - 1)) << FP16_MANT_BITS) |
296113118SEdmund.Grimley-Evans@arm.com            coeff[op & ((1 << 5) - 1)]);
296213118SEdmund.Grimley-Evans@arm.com}
296313118SEdmund.Grimley-Evans@arm.com
296413118SEdmund.Grimley-Evans@arm.comtemplate <>
296513118SEdmund.Grimley-Evans@arm.comuint32_t
296613118SEdmund.Grimley-Evans@arm.comfplibExpA(uint32_t op)
296713118SEdmund.Grimley-Evans@arm.com{
296813118SEdmund.Grimley-Evans@arm.com    static uint32_t coeff[64] = {
296913118SEdmund.Grimley-Evans@arm.com        0x000000,
297013118SEdmund.Grimley-Evans@arm.com        0x0164d2,
297113118SEdmund.Grimley-Evans@arm.com        0x02cd87,
297213118SEdmund.Grimley-Evans@arm.com        0x043a29,
297313118SEdmund.Grimley-Evans@arm.com        0x05aac3,
297413118SEdmund.Grimley-Evans@arm.com        0x071f62,
297513118SEdmund.Grimley-Evans@arm.com        0x08980f,
297613118SEdmund.Grimley-Evans@arm.com        0x0a14d5,
297713118SEdmund.Grimley-Evans@arm.com        0x0b95c2,
297813118SEdmund.Grimley-Evans@arm.com        0x0d1adf,
297913118SEdmund.Grimley-Evans@arm.com        0x0ea43a,
298013118SEdmund.Grimley-Evans@arm.com        0x1031dc,
298113118SEdmund.Grimley-Evans@arm.com        0x11c3d3,
298213118SEdmund.Grimley-Evans@arm.com        0x135a2b,
298313118SEdmund.Grimley-Evans@arm.com        0x14f4f0,
298413118SEdmund.Grimley-Evans@arm.com        0x16942d,
298513118SEdmund.Grimley-Evans@arm.com        0x1837f0,
298613118SEdmund.Grimley-Evans@arm.com        0x19e046,
298713118SEdmund.Grimley-Evans@arm.com        0x1b8d3a,
298813118SEdmund.Grimley-Evans@arm.com        0x1d3eda,
298913118SEdmund.Grimley-Evans@arm.com        0x1ef532,
299013118SEdmund.Grimley-Evans@arm.com        0x20b051,
299113118SEdmund.Grimley-Evans@arm.com        0x227043,
299213118SEdmund.Grimley-Evans@arm.com        0x243516,
299313118SEdmund.Grimley-Evans@arm.com        0x25fed7,
299413118SEdmund.Grimley-Evans@arm.com        0x27cd94,
299513118SEdmund.Grimley-Evans@arm.com        0x29a15b,
299613118SEdmund.Grimley-Evans@arm.com        0x2b7a3a,
299713118SEdmund.Grimley-Evans@arm.com        0x2d583f,
299813118SEdmund.Grimley-Evans@arm.com        0x2f3b79,
299913118SEdmund.Grimley-Evans@arm.com        0x3123f6,
300013118SEdmund.Grimley-Evans@arm.com        0x3311c4,
300113118SEdmund.Grimley-Evans@arm.com        0x3504f3,
300213118SEdmund.Grimley-Evans@arm.com        0x36fd92,
300313118SEdmund.Grimley-Evans@arm.com        0x38fbaf,
300413118SEdmund.Grimley-Evans@arm.com        0x3aff5b,
300513118SEdmund.Grimley-Evans@arm.com        0x3d08a4,
300613118SEdmund.Grimley-Evans@arm.com        0x3f179a,
300713118SEdmund.Grimley-Evans@arm.com        0x412c4d,
300813118SEdmund.Grimley-Evans@arm.com        0x4346cd,
300913118SEdmund.Grimley-Evans@arm.com        0x45672a,
301013118SEdmund.Grimley-Evans@arm.com        0x478d75,
301113118SEdmund.Grimley-Evans@arm.com        0x49b9be,
301213118SEdmund.Grimley-Evans@arm.com        0x4bec15,
301313118SEdmund.Grimley-Evans@arm.com        0x4e248c,
301413118SEdmund.Grimley-Evans@arm.com        0x506334,
301513118SEdmund.Grimley-Evans@arm.com        0x52a81e,
301613118SEdmund.Grimley-Evans@arm.com        0x54f35b,
301713118SEdmund.Grimley-Evans@arm.com        0x5744fd,
301813118SEdmund.Grimley-Evans@arm.com        0x599d16,
301913118SEdmund.Grimley-Evans@arm.com        0x5bfbb8,
302013118SEdmund.Grimley-Evans@arm.com        0x5e60f5,
302113118SEdmund.Grimley-Evans@arm.com        0x60ccdf,
302213118SEdmund.Grimley-Evans@arm.com        0x633f89,
302313118SEdmund.Grimley-Evans@arm.com        0x65b907,
302413118SEdmund.Grimley-Evans@arm.com        0x68396a,
302513118SEdmund.Grimley-Evans@arm.com        0x6ac0c7,
302613118SEdmund.Grimley-Evans@arm.com        0x6d4f30,
302713118SEdmund.Grimley-Evans@arm.com        0x6fe4ba,
302813118SEdmund.Grimley-Evans@arm.com        0x728177,
302913118SEdmund.Grimley-Evans@arm.com        0x75257d,
303013118SEdmund.Grimley-Evans@arm.com        0x77d0df,
303113118SEdmund.Grimley-Evans@arm.com        0x7a83b3,
303213118SEdmund.Grimley-Evans@arm.com        0x7d3e0c
303313118SEdmund.Grimley-Evans@arm.com    };
303413118SEdmund.Grimley-Evans@arm.com    return ((((op >> 6) & ((1 << FP32_EXP_BITS) - 1)) << FP32_MANT_BITS) |
303513118SEdmund.Grimley-Evans@arm.com            coeff[op & ((1 << 6) - 1)]);
303613118SEdmund.Grimley-Evans@arm.com}
303713118SEdmund.Grimley-Evans@arm.com
303813118SEdmund.Grimley-Evans@arm.comtemplate <>
303913118SEdmund.Grimley-Evans@arm.comuint64_t
304013118SEdmund.Grimley-Evans@arm.comfplibExpA(uint64_t op)
304113118SEdmund.Grimley-Evans@arm.com{
304213118SEdmund.Grimley-Evans@arm.com    static uint64_t coeff[64] = {
304313118SEdmund.Grimley-Evans@arm.com        0x0000000000000ULL,
304413118SEdmund.Grimley-Evans@arm.com        0x02c9a3e778061ULL,
304513118SEdmund.Grimley-Evans@arm.com        0x059b0d3158574ULL,
304613118SEdmund.Grimley-Evans@arm.com        0x0874518759bc8ULL,
304713118SEdmund.Grimley-Evans@arm.com        0x0b5586cf9890fULL,
304813118SEdmund.Grimley-Evans@arm.com        0x0e3ec32d3d1a2ULL,
304913118SEdmund.Grimley-Evans@arm.com        0x11301d0125b51ULL,
305013118SEdmund.Grimley-Evans@arm.com        0x1429aaea92de0ULL,
305113118SEdmund.Grimley-Evans@arm.com        0x172b83c7d517bULL,
305213118SEdmund.Grimley-Evans@arm.com        0x1a35beb6fcb75ULL,
305313118SEdmund.Grimley-Evans@arm.com        0x1d4873168b9aaULL,
305413118SEdmund.Grimley-Evans@arm.com        0x2063b88628cd6ULL,
305513118SEdmund.Grimley-Evans@arm.com        0x2387a6e756238ULL,
305613118SEdmund.Grimley-Evans@arm.com        0x26b4565e27cddULL,
305713118SEdmund.Grimley-Evans@arm.com        0x29e9df51fdee1ULL,
305813118SEdmund.Grimley-Evans@arm.com        0x2d285a6e4030bULL,
305913118SEdmund.Grimley-Evans@arm.com        0x306fe0a31b715ULL,
306013118SEdmund.Grimley-Evans@arm.com        0x33c08b26416ffULL,
306113118SEdmund.Grimley-Evans@arm.com        0x371a7373aa9cbULL,
306213118SEdmund.Grimley-Evans@arm.com        0x3a7db34e59ff7ULL,
306313118SEdmund.Grimley-Evans@arm.com        0x3dea64c123422ULL,
306413118SEdmund.Grimley-Evans@arm.com        0x4160a21f72e2aULL,
306513118SEdmund.Grimley-Evans@arm.com        0x44e086061892dULL,
306613118SEdmund.Grimley-Evans@arm.com        0x486a2b5c13cd0ULL,
306713118SEdmund.Grimley-Evans@arm.com        0x4bfdad5362a27ULL,
306813118SEdmund.Grimley-Evans@arm.com        0x4f9b2769d2ca7ULL,
306913118SEdmund.Grimley-Evans@arm.com        0x5342b569d4f82ULL,
307013118SEdmund.Grimley-Evans@arm.com        0x56f4736b527daULL,
307113118SEdmund.Grimley-Evans@arm.com        0x5ab07dd485429ULL,
307213118SEdmund.Grimley-Evans@arm.com        0x5e76f15ad2148ULL,
307313118SEdmund.Grimley-Evans@arm.com        0x6247eb03a5585ULL,
307413118SEdmund.Grimley-Evans@arm.com        0x6623882552225ULL,
307513118SEdmund.Grimley-Evans@arm.com        0x6a09e667f3bcdULL,
307613118SEdmund.Grimley-Evans@arm.com        0x6dfb23c651a2fULL,
307713118SEdmund.Grimley-Evans@arm.com        0x71f75e8ec5f74ULL,
307813118SEdmund.Grimley-Evans@arm.com        0x75feb564267c9ULL,
307913118SEdmund.Grimley-Evans@arm.com        0x7a11473eb0187ULL,
308013118SEdmund.Grimley-Evans@arm.com        0x7e2f336cf4e62ULL,
308113118SEdmund.Grimley-Evans@arm.com        0x82589994cce13ULL,
308213118SEdmund.Grimley-Evans@arm.com        0x868d99b4492edULL,
308313118SEdmund.Grimley-Evans@arm.com        0x8ace5422aa0dbULL,
308413118SEdmund.Grimley-Evans@arm.com        0x8f1ae99157736ULL,
308513118SEdmund.Grimley-Evans@arm.com        0x93737b0cdc5e5ULL,
308613118SEdmund.Grimley-Evans@arm.com        0x97d829fde4e50ULL,
308713118SEdmund.Grimley-Evans@arm.com        0x9c49182a3f090ULL,
308813118SEdmund.Grimley-Evans@arm.com        0xa0c667b5de565ULL,
308913118SEdmund.Grimley-Evans@arm.com        0xa5503b23e255dULL,
309013118SEdmund.Grimley-Evans@arm.com        0xa9e6b5579fdbfULL,
309113118SEdmund.Grimley-Evans@arm.com        0xae89f995ad3adULL,
309213118SEdmund.Grimley-Evans@arm.com        0xb33a2b84f15fbULL,
309313118SEdmund.Grimley-Evans@arm.com        0xb7f76f2fb5e47ULL,
309413118SEdmund.Grimley-Evans@arm.com        0xbcc1e904bc1d2ULL,
309513118SEdmund.Grimley-Evans@arm.com        0xc199bdd85529cULL,
309613118SEdmund.Grimley-Evans@arm.com        0xc67f12e57d14bULL,
309713118SEdmund.Grimley-Evans@arm.com        0xcb720dcef9069ULL,
309813118SEdmund.Grimley-Evans@arm.com        0xd072d4a07897cULL,
309913118SEdmund.Grimley-Evans@arm.com        0xd5818dcfba487ULL,
310013118SEdmund.Grimley-Evans@arm.com        0xda9e603db3285ULL,
310113118SEdmund.Grimley-Evans@arm.com        0xdfc97337b9b5fULL,
310213118SEdmund.Grimley-Evans@arm.com        0xe502ee78b3ff6ULL,
310313118SEdmund.Grimley-Evans@arm.com        0xea4afa2a490daULL,
310413118SEdmund.Grimley-Evans@arm.com        0xefa1bee615a27ULL,
310513118SEdmund.Grimley-Evans@arm.com        0xf50765b6e4540ULL,
310613118SEdmund.Grimley-Evans@arm.com        0xfa7c1819e90d8ULL
310713118SEdmund.Grimley-Evans@arm.com    };
310813118SEdmund.Grimley-Evans@arm.com    return ((((op >> 6) & ((1 << FP64_EXP_BITS) - 1)) << FP64_MANT_BITS) |
310913118SEdmund.Grimley-Evans@arm.com            coeff[op & ((1 << 6) - 1)]);
311013118SEdmund.Grimley-Evans@arm.com}
311113118SEdmund.Grimley-Evans@arm.com
311213118SEdmund.Grimley-Evans@arm.comstatic uint16_t
311313118SEdmund.Grimley-Evans@arm.comfp16_repack(int sgn, int exp, uint16_t mnt)
311413118SEdmund.Grimley-Evans@arm.com{
311513118SEdmund.Grimley-Evans@arm.com    return fp16_pack(sgn, mnt >> FP16_MANT_BITS ? exp : 0, mnt);
311613118SEdmund.Grimley-Evans@arm.com}
311713118SEdmund.Grimley-Evans@arm.com
311810037SARM gem5 Developersstatic uint32_t
311910037SARM gem5 Developersfp32_repack(int sgn, int exp, uint32_t mnt)
312010037SARM gem5 Developers{
312113118SEdmund.Grimley-Evans@arm.com    return fp32_pack(sgn, mnt >> FP32_MANT_BITS ? exp : 0, mnt);
312210037SARM gem5 Developers}
312310037SARM gem5 Developers
312410037SARM gem5 Developersstatic uint64_t
312510037SARM gem5 Developersfp64_repack(int sgn, int exp, uint64_t mnt)
312610037SARM gem5 Developers{
312713118SEdmund.Grimley-Evans@arm.com    return fp64_pack(sgn, mnt >> FP64_MANT_BITS ? exp : 0, mnt);
312813118SEdmund.Grimley-Evans@arm.com}
312913118SEdmund.Grimley-Evans@arm.com
313013118SEdmund.Grimley-Evans@arm.comstatic void
313113118SEdmund.Grimley-Evans@arm.comfp16_minmaxnum(uint16_t *op1, uint16_t *op2, int sgn)
313213118SEdmund.Grimley-Evans@arm.com{
313313118SEdmund.Grimley-Evans@arm.com    // Treat a single quiet-NaN as +Infinity/-Infinity
313413118SEdmund.Grimley-Evans@arm.com    if (!((uint16_t)~(*op1 << 1) >> FP16_MANT_BITS) &&
313513118SEdmund.Grimley-Evans@arm.com        (uint16_t)~(*op2 << 1) >> FP16_MANT_BITS)
313613118SEdmund.Grimley-Evans@arm.com        *op1 = fp16_infinity(sgn);
313713118SEdmund.Grimley-Evans@arm.com    if (!((uint16_t)~(*op2 << 1) >> FP16_MANT_BITS) &&
313813118SEdmund.Grimley-Evans@arm.com        (uint16_t)~(*op1 << 1) >> FP16_MANT_BITS)
313913118SEdmund.Grimley-Evans@arm.com        *op2 = fp16_infinity(sgn);
314010037SARM gem5 Developers}
314110037SARM gem5 Developers
314210037SARM gem5 Developersstatic void
314310037SARM gem5 Developersfp32_minmaxnum(uint32_t *op1, uint32_t *op2, int sgn)
314410037SARM gem5 Developers{
314510037SARM gem5 Developers    // Treat a single quiet-NaN as +Infinity/-Infinity
314613118SEdmund.Grimley-Evans@arm.com    if (!((uint32_t)~(*op1 << 1) >> FP32_MANT_BITS) &&
314713118SEdmund.Grimley-Evans@arm.com        (uint32_t)~(*op2 << 1) >> FP32_MANT_BITS)
314810037SARM gem5 Developers        *op1 = fp32_infinity(sgn);
314913118SEdmund.Grimley-Evans@arm.com    if (!((uint32_t)~(*op2 << 1) >> FP32_MANT_BITS) &&
315013118SEdmund.Grimley-Evans@arm.com        (uint32_t)~(*op1 << 1) >> FP32_MANT_BITS)
315110037SARM gem5 Developers        *op2 = fp32_infinity(sgn);
315210037SARM gem5 Developers}
315310037SARM gem5 Developers
315410037SARM gem5 Developersstatic void
315510037SARM gem5 Developersfp64_minmaxnum(uint64_t *op1, uint64_t *op2, int sgn)
315610037SARM gem5 Developers{
315710037SARM gem5 Developers    // Treat a single quiet-NaN as +Infinity/-Infinity
315813118SEdmund.Grimley-Evans@arm.com    if (!((uint64_t)~(*op1 << 1) >> FP64_MANT_BITS) &&
315913118SEdmund.Grimley-Evans@arm.com        (uint64_t)~(*op2 << 1) >> FP64_MANT_BITS)
316010037SARM gem5 Developers        *op1 = fp64_infinity(sgn);
316113118SEdmund.Grimley-Evans@arm.com    if (!((uint64_t)~(*op2 << 1) >> FP64_MANT_BITS) &&
316213118SEdmund.Grimley-Evans@arm.com        (uint64_t)~(*op1 << 1) >> FP64_MANT_BITS)
316310037SARM gem5 Developers        *op2 = fp64_infinity(sgn);
316410037SARM gem5 Developers}
316510037SARM gem5 Developers
316610037SARM gem5 Developerstemplate <>
316713118SEdmund.Grimley-Evans@arm.comuint16_t
316813118SEdmund.Grimley-Evans@arm.comfplibMax(uint16_t op1, uint16_t op2, FPSCR &fpscr)
316913118SEdmund.Grimley-Evans@arm.com{
317013118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
317113118SEdmund.Grimley-Evans@arm.com    int flags = 0;
317213118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
317313118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2, x, result;
317413118SEdmund.Grimley-Evans@arm.com
317513118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
317613118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
317713118SEdmund.Grimley-Evans@arm.com
317813118SEdmund.Grimley-Evans@arm.com    if ((x = fp16_process_NaNs(op1, op2, mode, &flags))) {
317913118SEdmund.Grimley-Evans@arm.com        result = x;
318013118SEdmund.Grimley-Evans@arm.com    } else {
318113118SEdmund.Grimley-Evans@arm.com        result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
318213118SEdmund.Grimley-Evans@arm.com                  fp16_repack(sgn1, exp1, mnt1) :
318313118SEdmund.Grimley-Evans@arm.com                  fp16_repack(sgn2, exp2, mnt2));
318413118SEdmund.Grimley-Evans@arm.com    }
318513118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
318613118SEdmund.Grimley-Evans@arm.com    return result;
318713118SEdmund.Grimley-Evans@arm.com}
318813118SEdmund.Grimley-Evans@arm.com
318913118SEdmund.Grimley-Evans@arm.comtemplate <>
319010037SARM gem5 Developersuint32_t
319110037SARM gem5 DevelopersfplibMax(uint32_t op1, uint32_t op2, FPSCR &fpscr)
319210037SARM gem5 Developers{
319310037SARM gem5 Developers    int mode = modeConv(fpscr);
319410037SARM gem5 Developers    int flags = 0;
319510037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
319610037SARM gem5 Developers    uint32_t mnt1, mnt2, x, result;
319710037SARM gem5 Developers
319810037SARM gem5 Developers    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
319910037SARM gem5 Developers    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
320010037SARM gem5 Developers
320110037SARM gem5 Developers    if ((x = fp32_process_NaNs(op1, op2, mode, &flags))) {
320210037SARM gem5 Developers        result = x;
320310037SARM gem5 Developers    } else {
320410037SARM gem5 Developers        result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
320510037SARM gem5 Developers                  fp32_repack(sgn1, exp1, mnt1) :
320610037SARM gem5 Developers                  fp32_repack(sgn2, exp2, mnt2));
320710037SARM gem5 Developers    }
320810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
320910037SARM gem5 Developers    return result;
321010037SARM gem5 Developers}
321110037SARM gem5 Developers
321210037SARM gem5 Developerstemplate <>
321310037SARM gem5 Developersuint64_t
321410037SARM gem5 DevelopersfplibMax(uint64_t op1, uint64_t op2, FPSCR &fpscr)
321510037SARM gem5 Developers{
321610037SARM gem5 Developers    int mode = modeConv(fpscr);
321710037SARM gem5 Developers    int flags = 0;
321810037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
321910037SARM gem5 Developers    uint64_t mnt1, mnt2, x, result;
322010037SARM gem5 Developers
322110037SARM gem5 Developers    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
322210037SARM gem5 Developers    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
322310037SARM gem5 Developers
322410037SARM gem5 Developers    if ((x = fp64_process_NaNs(op1, op2, mode, &flags))) {
322510037SARM gem5 Developers        result = x;
322610037SARM gem5 Developers    } else {
322710037SARM gem5 Developers        result = ((sgn1 != sgn2 ? sgn2 : sgn1 ^ (op1 > op2)) ?
322810037SARM gem5 Developers                  fp64_repack(sgn1, exp1, mnt1) :
322910037SARM gem5 Developers                  fp64_repack(sgn2, exp2, mnt2));
323010037SARM gem5 Developers    }
323110037SARM gem5 Developers    set_fpscr0(fpscr, flags);
323210037SARM gem5 Developers    return result;
323310037SARM gem5 Developers}
323410037SARM gem5 Developers
323510037SARM gem5 Developerstemplate <>
323613118SEdmund.Grimley-Evans@arm.comuint16_t
323713118SEdmund.Grimley-Evans@arm.comfplibMaxNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
323813118SEdmund.Grimley-Evans@arm.com{
323913118SEdmund.Grimley-Evans@arm.com    fp16_minmaxnum(&op1, &op2, 1);
324013118SEdmund.Grimley-Evans@arm.com    return fplibMax<uint16_t>(op1, op2, fpscr);
324113118SEdmund.Grimley-Evans@arm.com}
324213118SEdmund.Grimley-Evans@arm.com
324313118SEdmund.Grimley-Evans@arm.comtemplate <>
324410037SARM gem5 Developersuint32_t
324510037SARM gem5 DevelopersfplibMaxNum(uint32_t op1, uint32_t op2, FPSCR &fpscr)
324610037SARM gem5 Developers{
324710037SARM gem5 Developers    fp32_minmaxnum(&op1, &op2, 1);
324810037SARM gem5 Developers    return fplibMax<uint32_t>(op1, op2, fpscr);
324910037SARM gem5 Developers}
325010037SARM gem5 Developers
325110037SARM gem5 Developerstemplate <>
325210037SARM gem5 Developersuint64_t
325310037SARM gem5 DevelopersfplibMaxNum(uint64_t op1, uint64_t op2, FPSCR &fpscr)
325410037SARM gem5 Developers{
325510037SARM gem5 Developers    fp64_minmaxnum(&op1, &op2, 1);
325610037SARM gem5 Developers    return fplibMax<uint64_t>(op1, op2, fpscr);
325710037SARM gem5 Developers}
325810037SARM gem5 Developers
325910037SARM gem5 Developerstemplate <>
326013118SEdmund.Grimley-Evans@arm.comuint16_t
326113118SEdmund.Grimley-Evans@arm.comfplibMin(uint16_t op1, uint16_t op2, FPSCR &fpscr)
326213118SEdmund.Grimley-Evans@arm.com{
326313118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
326413118SEdmund.Grimley-Evans@arm.com    int flags = 0;
326513118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
326613118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2, x, result;
326713118SEdmund.Grimley-Evans@arm.com
326813118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
326913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
327013118SEdmund.Grimley-Evans@arm.com
327113118SEdmund.Grimley-Evans@arm.com    if ((x = fp16_process_NaNs(op1, op2, mode, &flags))) {
327213118SEdmund.Grimley-Evans@arm.com        result = x;
327313118SEdmund.Grimley-Evans@arm.com    } else {
327413118SEdmund.Grimley-Evans@arm.com        result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
327513118SEdmund.Grimley-Evans@arm.com                  fp16_repack(sgn1, exp1, mnt1) :
327613118SEdmund.Grimley-Evans@arm.com                  fp16_repack(sgn2, exp2, mnt2));
327713118SEdmund.Grimley-Evans@arm.com    }
327813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
327913118SEdmund.Grimley-Evans@arm.com    return result;
328013118SEdmund.Grimley-Evans@arm.com}
328113118SEdmund.Grimley-Evans@arm.com
328213118SEdmund.Grimley-Evans@arm.comtemplate <>
328310037SARM gem5 Developersuint32_t
328410037SARM gem5 DevelopersfplibMin(uint32_t op1, uint32_t op2, FPSCR &fpscr)
328510037SARM gem5 Developers{
328610037SARM gem5 Developers    int mode = modeConv(fpscr);
328710037SARM gem5 Developers    int flags = 0;
328810037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
328910037SARM gem5 Developers    uint32_t mnt1, mnt2, x, result;
329010037SARM gem5 Developers
329110037SARM gem5 Developers    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
329210037SARM gem5 Developers    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
329310037SARM gem5 Developers
329410037SARM gem5 Developers    if ((x = fp32_process_NaNs(op1, op2, mode, &flags))) {
329510037SARM gem5 Developers        result = x;
329610037SARM gem5 Developers    } else {
329710037SARM gem5 Developers        result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
329810037SARM gem5 Developers                  fp32_repack(sgn1, exp1, mnt1) :
329910037SARM gem5 Developers                  fp32_repack(sgn2, exp2, mnt2));
330010037SARM gem5 Developers    }
330110037SARM gem5 Developers    set_fpscr0(fpscr, flags);
330210037SARM gem5 Developers    return result;
330310037SARM gem5 Developers}
330410037SARM gem5 Developers
330510037SARM gem5 Developerstemplate <>
330610037SARM gem5 Developersuint64_t
330710037SARM gem5 DevelopersfplibMin(uint64_t op1, uint64_t op2, FPSCR &fpscr)
330810037SARM gem5 Developers{
330910037SARM gem5 Developers    int mode = modeConv(fpscr);
331010037SARM gem5 Developers    int flags = 0;
331110037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
331210037SARM gem5 Developers    uint64_t mnt1, mnt2, x, result;
331310037SARM gem5 Developers
331410037SARM gem5 Developers    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
331510037SARM gem5 Developers    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
331610037SARM gem5 Developers
331710037SARM gem5 Developers    if ((x = fp64_process_NaNs(op1, op2, mode, &flags))) {
331810037SARM gem5 Developers        result = x;
331910037SARM gem5 Developers    } else {
332010037SARM gem5 Developers        result = ((sgn1 != sgn2 ? sgn1 : sgn1 ^ (op1 < op2)) ?
332110037SARM gem5 Developers                  fp64_repack(sgn1, exp1, mnt1) :
332210037SARM gem5 Developers                  fp64_repack(sgn2, exp2, mnt2));
332310037SARM gem5 Developers    }
332410037SARM gem5 Developers    set_fpscr0(fpscr, flags);
332510037SARM gem5 Developers    return result;
332610037SARM gem5 Developers}
332710037SARM gem5 Developers
332810037SARM gem5 Developerstemplate <>
332913118SEdmund.Grimley-Evans@arm.comuint16_t
333013118SEdmund.Grimley-Evans@arm.comfplibMinNum(uint16_t op1, uint16_t op2, FPSCR &fpscr)
333113118SEdmund.Grimley-Evans@arm.com{
333213118SEdmund.Grimley-Evans@arm.com    fp16_minmaxnum(&op1, &op2, 0);
333313118SEdmund.Grimley-Evans@arm.com    return fplibMin<uint16_t>(op1, op2, fpscr);
333413118SEdmund.Grimley-Evans@arm.com}
333513118SEdmund.Grimley-Evans@arm.com
333613118SEdmund.Grimley-Evans@arm.comtemplate <>
333710037SARM gem5 Developersuint32_t
333810037SARM gem5 DevelopersfplibMinNum(uint32_t op1, uint32_t op2, FPSCR &fpscr)
333910037SARM gem5 Developers{
334010037SARM gem5 Developers    fp32_minmaxnum(&op1, &op2, 0);
334110037SARM gem5 Developers    return fplibMin<uint32_t>(op1, op2, fpscr);
334210037SARM gem5 Developers}
334310037SARM gem5 Developers
334410037SARM gem5 Developerstemplate <>
334510037SARM gem5 Developersuint64_t
334610037SARM gem5 DevelopersfplibMinNum(uint64_t op1, uint64_t op2, FPSCR &fpscr)
334710037SARM gem5 Developers{
334810037SARM gem5 Developers    fp64_minmaxnum(&op1, &op2, 0);
334910037SARM gem5 Developers    return fplibMin<uint64_t>(op1, op2, fpscr);
335010037SARM gem5 Developers}
335110037SARM gem5 Developers
335210037SARM gem5 Developerstemplate <>
335313118SEdmund.Grimley-Evans@arm.comuint16_t
335413118SEdmund.Grimley-Evans@arm.comfplibMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
335513118SEdmund.Grimley-Evans@arm.com{
335613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
335713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_mul(op1, op2, modeConv(fpscr), &flags);
335813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
335913118SEdmund.Grimley-Evans@arm.com    return result;
336013118SEdmund.Grimley-Evans@arm.com}
336113118SEdmund.Grimley-Evans@arm.com
336213118SEdmund.Grimley-Evans@arm.comtemplate <>
336310037SARM gem5 Developersuint32_t
336410037SARM gem5 DevelopersfplibMul(uint32_t op1, uint32_t op2, FPSCR &fpscr)
336510037SARM gem5 Developers{
336610037SARM gem5 Developers    int flags = 0;
336710037SARM gem5 Developers    uint32_t result = fp32_mul(op1, op2, modeConv(fpscr), &flags);
336810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
336910037SARM gem5 Developers    return result;
337010037SARM gem5 Developers}
337110037SARM gem5 Developers
337210037SARM gem5 Developerstemplate <>
337310037SARM gem5 Developersuint64_t
337410037SARM gem5 DevelopersfplibMul(uint64_t op1, uint64_t op2, FPSCR &fpscr)
337510037SARM gem5 Developers{
337610037SARM gem5 Developers    int flags = 0;
337710037SARM gem5 Developers    uint64_t result = fp64_mul(op1, op2, modeConv(fpscr), &flags);
337810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
337910037SARM gem5 Developers    return result;
338010037SARM gem5 Developers}
338110037SARM gem5 Developers
338210037SARM gem5 Developerstemplate <>
338313118SEdmund.Grimley-Evans@arm.comuint16_t
338413118SEdmund.Grimley-Evans@arm.comfplibMulX(uint16_t op1, uint16_t op2, FPSCR &fpscr)
338513118SEdmund.Grimley-Evans@arm.com{
338613118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
338713118SEdmund.Grimley-Evans@arm.com    int flags = 0;
338813118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
338913118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2, result;
339013118SEdmund.Grimley-Evans@arm.com
339113118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
339213118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
339313118SEdmund.Grimley-Evans@arm.com
339413118SEdmund.Grimley-Evans@arm.com    result = fp16_process_NaNs(op1, op2, mode, &flags);
339513118SEdmund.Grimley-Evans@arm.com    if (!result) {
339613118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP16_EXP_INF && !mnt2) ||
339713118SEdmund.Grimley-Evans@arm.com            (exp2 == FP16_EXP_INF && !mnt1)) {
339813118SEdmund.Grimley-Evans@arm.com            result = fp16_FPTwo(sgn1 ^ sgn2);
339913118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
340013118SEdmund.Grimley-Evans@arm.com            result = fp16_infinity(sgn1 ^ sgn2);
340113118SEdmund.Grimley-Evans@arm.com        } else if (!mnt1 || !mnt2) {
340213118SEdmund.Grimley-Evans@arm.com            result = fp16_zero(sgn1 ^ sgn2);
340313118SEdmund.Grimley-Evans@arm.com        } else {
340413118SEdmund.Grimley-Evans@arm.com            result = fp16_mul(op1, op2, mode, &flags);
340513118SEdmund.Grimley-Evans@arm.com        }
340613118SEdmund.Grimley-Evans@arm.com    }
340713118SEdmund.Grimley-Evans@arm.com
340813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
340913118SEdmund.Grimley-Evans@arm.com
341013118SEdmund.Grimley-Evans@arm.com    return result;
341113118SEdmund.Grimley-Evans@arm.com}
341213118SEdmund.Grimley-Evans@arm.com
341313118SEdmund.Grimley-Evans@arm.comtemplate <>
341410037SARM gem5 Developersuint32_t
341510037SARM gem5 DevelopersfplibMulX(uint32_t op1, uint32_t op2, FPSCR &fpscr)
341610037SARM gem5 Developers{
341710037SARM gem5 Developers    int mode = modeConv(fpscr);
341810037SARM gem5 Developers    int flags = 0;
341910037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
342010037SARM gem5 Developers    uint32_t mnt1, mnt2, result;
342110037SARM gem5 Developers
342210037SARM gem5 Developers    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
342310037SARM gem5 Developers    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
342410037SARM gem5 Developers
342510037SARM gem5 Developers    result = fp32_process_NaNs(op1, op2, mode, &flags);
342610037SARM gem5 Developers    if (!result) {
342713118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP32_EXP_INF && !mnt2) ||
342813118SEdmund.Grimley-Evans@arm.com            (exp2 == FP32_EXP_INF && !mnt1)) {
342910037SARM gem5 Developers            result = fp32_FPTwo(sgn1 ^ sgn2);
343013118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
343110037SARM gem5 Developers            result = fp32_infinity(sgn1 ^ sgn2);
343210037SARM gem5 Developers        } else if (!mnt1 || !mnt2) {
343310037SARM gem5 Developers            result = fp32_zero(sgn1 ^ sgn2);
343410037SARM gem5 Developers        } else {
343510037SARM gem5 Developers            result = fp32_mul(op1, op2, mode, &flags);
343610037SARM gem5 Developers        }
343710037SARM gem5 Developers    }
343810037SARM gem5 Developers
343910037SARM gem5 Developers    set_fpscr0(fpscr, flags);
344010037SARM gem5 Developers
344110037SARM gem5 Developers    return result;
344210037SARM gem5 Developers}
344310037SARM gem5 Developers
344410037SARM gem5 Developerstemplate <>
344510037SARM gem5 Developersuint64_t
344610037SARM gem5 DevelopersfplibMulX(uint64_t op1, uint64_t op2, FPSCR &fpscr)
344710037SARM gem5 Developers{
344810037SARM gem5 Developers    int mode = modeConv(fpscr);
344910037SARM gem5 Developers    int flags = 0;
345010037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
345110037SARM gem5 Developers    uint64_t mnt1, mnt2, result;
345210037SARM gem5 Developers
345310037SARM gem5 Developers    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
345410037SARM gem5 Developers    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
345510037SARM gem5 Developers
345610037SARM gem5 Developers    result = fp64_process_NaNs(op1, op2, mode, &flags);
345710037SARM gem5 Developers    if (!result) {
345813118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP64_EXP_INF && !mnt2) ||
345913118SEdmund.Grimley-Evans@arm.com            (exp2 == FP64_EXP_INF && !mnt1)) {
346010037SARM gem5 Developers            result = fp64_FPTwo(sgn1 ^ sgn2);
346113118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
346210037SARM gem5 Developers            result = fp64_infinity(sgn1 ^ sgn2);
346310037SARM gem5 Developers        } else if (!mnt1 || !mnt2) {
346410037SARM gem5 Developers            result = fp64_zero(sgn1 ^ sgn2);
346510037SARM gem5 Developers        } else {
346610037SARM gem5 Developers            result = fp64_mul(op1, op2, mode, &flags);
346710037SARM gem5 Developers        }
346810037SARM gem5 Developers    }
346910037SARM gem5 Developers
347010037SARM gem5 Developers    set_fpscr0(fpscr, flags);
347110037SARM gem5 Developers
347210037SARM gem5 Developers    return result;
347310037SARM gem5 Developers}
347410037SARM gem5 Developers
347510037SARM gem5 Developerstemplate <>
347613118SEdmund.Grimley-Evans@arm.comuint16_t
347713118SEdmund.Grimley-Evans@arm.comfplibNeg(uint16_t op)
347813118SEdmund.Grimley-Evans@arm.com{
347913118SEdmund.Grimley-Evans@arm.com    return op ^ 1ULL << (FP16_BITS - 1);
348013118SEdmund.Grimley-Evans@arm.com}
348113118SEdmund.Grimley-Evans@arm.com
348213118SEdmund.Grimley-Evans@arm.comtemplate <>
348310037SARM gem5 Developersuint32_t
348410037SARM gem5 DevelopersfplibNeg(uint32_t op)
348510037SARM gem5 Developers{
348613118SEdmund.Grimley-Evans@arm.com    return op ^ 1ULL << (FP32_BITS - 1);
348710037SARM gem5 Developers}
348810037SARM gem5 Developers
348910037SARM gem5 Developerstemplate <>
349010037SARM gem5 Developersuint64_t
349110037SARM gem5 DevelopersfplibNeg(uint64_t op)
349210037SARM gem5 Developers{
349313118SEdmund.Grimley-Evans@arm.com    return op ^ 1ULL << (FP64_BITS - 1);
349410037SARM gem5 Developers}
349510037SARM gem5 Developers
349610037SARM gem5 Developersstatic const uint8_t recip_sqrt_estimate[256] = {
349710037SARM gem5 Developers    255, 253, 251, 249, 247, 245, 243, 242, 240, 238, 236, 234, 233, 231, 229, 228,
349810037SARM gem5 Developers    226, 224, 223, 221, 219, 218, 216, 215, 213, 212, 210, 209, 207, 206, 204, 203,
349910037SARM gem5 Developers    201, 200, 198, 197, 196, 194, 193, 192, 190, 189, 188, 186, 185, 184, 183, 181,
350010037SARM gem5 Developers    180, 179, 178, 176, 175, 174, 173, 172, 170, 169, 168, 167, 166, 165, 164, 163,
350110037SARM gem5 Developers    162, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146,
350210037SARM gem5 Developers    145, 144, 143, 142, 141, 140, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131,
350310037SARM gem5 Developers    131, 130, 129, 128, 127, 126, 126, 125, 124, 123, 122, 121, 121, 120, 119, 118,
350410037SARM gem5 Developers    118, 117, 116, 115, 114, 114, 113, 112, 111, 111, 110, 109, 109, 108, 107, 106,
350510037SARM gem5 Developers    105, 104, 103, 101, 100,  99,  97,  96,  95,  93,  92,  91,  90,  88,  87,  86,
350610037SARM gem5 Developers    85,  84,  82,  81,  80,  79,  78,  77,  76,  75,  74,  72,  71,  70,  69,  68,
350710037SARM gem5 Developers    67,  66,  65,  64,  63,  62,  61,  60,  60,  59,  58,  57,  56,  55,  54,  53,
350810037SARM gem5 Developers    52,  51,  51,  50,  49,  48,  47,  46,  46,  45,  44,  43,  42,  42,  41,  40,
350910037SARM gem5 Developers    39,  38,  38,  37,  36,  35,  35,  34,  33,  33,  32,  31,  30,  30,  29,  28,
351010037SARM gem5 Developers    28,  27,  26,  26,  25,  24,  24,  23,  22,  22,  21,  20,  20,  19,  19,  18,
351110037SARM gem5 Developers    17,  17,  16,  16,  15,  14,  14,  13,  13,  12,  11,  11,  10,  10,   9,   9,
351210037SARM gem5 Developers    8,   8,   7,   6,   6,   5,   5,   4,   4,   3,   3,   2,   2,   1,   1,   0
351310037SARM gem5 Developers};
351410037SARM gem5 Developers
351510037SARM gem5 Developerstemplate <>
351613118SEdmund.Grimley-Evans@arm.comuint16_t
351713118SEdmund.Grimley-Evans@arm.comfplibRSqrtEstimate(uint16_t op, FPSCR &fpscr)
351813118SEdmund.Grimley-Evans@arm.com{
351913118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
352013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
352113118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
352213118SEdmund.Grimley-Evans@arm.com    uint16_t mnt, result;
352313118SEdmund.Grimley-Evans@arm.com
352413118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
352513118SEdmund.Grimley-Evans@arm.com
352613118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
352713118SEdmund.Grimley-Evans@arm.com        result = fp16_process_NaN(op, mode, &flags);
352813118SEdmund.Grimley-Evans@arm.com    } else if (!mnt) {
352913118SEdmund.Grimley-Evans@arm.com        result = fp16_infinity(sgn);
353013118SEdmund.Grimley-Evans@arm.com        flags |= FPLIB_DZC;
353113118SEdmund.Grimley-Evans@arm.com    } else if (sgn) {
353213118SEdmund.Grimley-Evans@arm.com        result = fp16_defaultNaN();
353313118SEdmund.Grimley-Evans@arm.com        flags |= FPLIB_IOC;
353413118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP16_EXP_INF) {
353513118SEdmund.Grimley-Evans@arm.com        result = fp16_zero(0);
353613118SEdmund.Grimley-Evans@arm.com    } else {
353713118SEdmund.Grimley-Evans@arm.com        exp += FP16_EXP_BITS;
353813118SEdmund.Grimley-Evans@arm.com        mnt = fp16_normalise(mnt, &exp);
353913118SEdmund.Grimley-Evans@arm.com        mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
354013118SEdmund.Grimley-Evans@arm.com                                  (mnt >> (FP16_BITS - 8) & 127)];
354113118SEdmund.Grimley-Evans@arm.com        result = fp16_pack(0, (3 * FP16_EXP_BIAS - exp - 1) >> 1,
354213118SEdmund.Grimley-Evans@arm.com                           mnt << (FP16_MANT_BITS - 8));
354313118SEdmund.Grimley-Evans@arm.com    }
354413118SEdmund.Grimley-Evans@arm.com
354513118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
354613118SEdmund.Grimley-Evans@arm.com
354713118SEdmund.Grimley-Evans@arm.com    return result;
354813118SEdmund.Grimley-Evans@arm.com}
354913118SEdmund.Grimley-Evans@arm.com
355013118SEdmund.Grimley-Evans@arm.comtemplate <>
355110037SARM gem5 Developersuint32_t
355210037SARM gem5 DevelopersfplibRSqrtEstimate(uint32_t op, FPSCR &fpscr)
355310037SARM gem5 Developers{
355410037SARM gem5 Developers    int mode = modeConv(fpscr);
355510037SARM gem5 Developers    int flags = 0;
355610037SARM gem5 Developers    int sgn, exp;
355710037SARM gem5 Developers    uint32_t mnt, result;
355810037SARM gem5 Developers
355910037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
356010037SARM gem5 Developers
356113118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
356210037SARM gem5 Developers        result = fp32_process_NaN(op, mode, &flags);
356310037SARM gem5 Developers    } else if (!mnt) {
356410037SARM gem5 Developers        result = fp32_infinity(sgn);
356510037SARM gem5 Developers        flags |= FPLIB_DZC;
356610037SARM gem5 Developers    } else if (sgn) {
356710037SARM gem5 Developers        result = fp32_defaultNaN();
356810037SARM gem5 Developers        flags |= FPLIB_IOC;
356913118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP32_EXP_INF) {
357010037SARM gem5 Developers        result = fp32_zero(0);
357110037SARM gem5 Developers    } else {
357213118SEdmund.Grimley-Evans@arm.com        exp += FP32_EXP_BITS;
357310037SARM gem5 Developers        mnt = fp32_normalise(mnt, &exp);
357413118SEdmund.Grimley-Evans@arm.com        mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
357513118SEdmund.Grimley-Evans@arm.com                                  (mnt >> (FP32_BITS - 8) & 127)];
357613118SEdmund.Grimley-Evans@arm.com        result = fp32_pack(0, (3 * FP32_EXP_BIAS - exp - 1) >> 1,
357713118SEdmund.Grimley-Evans@arm.com                           mnt << (FP32_MANT_BITS - 8));
357810037SARM gem5 Developers    }
357910037SARM gem5 Developers
358010037SARM gem5 Developers    set_fpscr0(fpscr, flags);
358110037SARM gem5 Developers
358210037SARM gem5 Developers    return result;
358310037SARM gem5 Developers}
358410037SARM gem5 Developers
358510037SARM gem5 Developerstemplate <>
358610037SARM gem5 Developersuint64_t
358710037SARM gem5 DevelopersfplibRSqrtEstimate(uint64_t op, FPSCR &fpscr)
358810037SARM gem5 Developers{
358910037SARM gem5 Developers    int mode = modeConv(fpscr);
359010037SARM gem5 Developers    int flags = 0;
359110037SARM gem5 Developers    int sgn, exp;
359210037SARM gem5 Developers    uint64_t mnt, result;
359310037SARM gem5 Developers
359410037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
359510037SARM gem5 Developers
359613118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
359710037SARM gem5 Developers        result = fp64_process_NaN(op, mode, &flags);
359810037SARM gem5 Developers    } else if (!mnt) {
359910037SARM gem5 Developers        result = fp64_infinity(sgn);
360010037SARM gem5 Developers        flags |= FPLIB_DZC;
360110037SARM gem5 Developers    } else if (sgn) {
360210037SARM gem5 Developers        result = fp64_defaultNaN();
360310037SARM gem5 Developers        flags |= FPLIB_IOC;
360413118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP64_EXP_INF) {
360510037SARM gem5 Developers        result = fp32_zero(0);
360610037SARM gem5 Developers    } else {
360713118SEdmund.Grimley-Evans@arm.com        exp += FP64_EXP_BITS;
360810037SARM gem5 Developers        mnt = fp64_normalise(mnt, &exp);
360913118SEdmund.Grimley-Evans@arm.com        mnt = recip_sqrt_estimate[(~exp & 1) << 7 |
361013118SEdmund.Grimley-Evans@arm.com                                  (mnt >> (FP64_BITS - 8) & 127)];
361113118SEdmund.Grimley-Evans@arm.com        result = fp64_pack(0, (3 * FP64_EXP_BIAS - exp - 1) >> 1,
361213118SEdmund.Grimley-Evans@arm.com                           mnt << (FP64_MANT_BITS - 8));
361313118SEdmund.Grimley-Evans@arm.com    }
361413118SEdmund.Grimley-Evans@arm.com
361513118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
361613118SEdmund.Grimley-Evans@arm.com
361713118SEdmund.Grimley-Evans@arm.com    return result;
361813118SEdmund.Grimley-Evans@arm.com}
361913118SEdmund.Grimley-Evans@arm.com
362013118SEdmund.Grimley-Evans@arm.comtemplate <>
362113118SEdmund.Grimley-Evans@arm.comuint16_t
362213118SEdmund.Grimley-Evans@arm.comfplibRSqrtStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
362313118SEdmund.Grimley-Evans@arm.com{
362413118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
362513118SEdmund.Grimley-Evans@arm.com    int flags = 0;
362613118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
362713118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2, result;
362813118SEdmund.Grimley-Evans@arm.com
362913118SEdmund.Grimley-Evans@arm.com    op1 = fplibNeg<uint16_t>(op1);
363013118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
363113118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
363213118SEdmund.Grimley-Evans@arm.com
363313118SEdmund.Grimley-Evans@arm.com    result = fp16_process_NaNs(op1, op2, mode, &flags);
363413118SEdmund.Grimley-Evans@arm.com    if (!result) {
363513118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP16_EXP_INF && !mnt2) ||
363613118SEdmund.Grimley-Evans@arm.com            (exp2 == FP16_EXP_INF && !mnt1)) {
363713118SEdmund.Grimley-Evans@arm.com            result = fp16_FPOnePointFive(0);
363813118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
363913118SEdmund.Grimley-Evans@arm.com            result = fp16_infinity(sgn1 ^ sgn2);
364013118SEdmund.Grimley-Evans@arm.com        } else {
364113118SEdmund.Grimley-Evans@arm.com            result = fp16_muladd(fp16_FPThree(0), op1, op2, -1, mode, &flags);
364213118SEdmund.Grimley-Evans@arm.com        }
364310037SARM gem5 Developers    }
364410037SARM gem5 Developers
364510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
364610037SARM gem5 Developers
364710037SARM gem5 Developers    return result;
364810037SARM gem5 Developers}
364910037SARM gem5 Developers
365010037SARM gem5 Developerstemplate <>
365110037SARM gem5 Developersuint32_t
365210037SARM gem5 DevelopersfplibRSqrtStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr)
365310037SARM gem5 Developers{
365410037SARM gem5 Developers    int mode = modeConv(fpscr);
365510037SARM gem5 Developers    int flags = 0;
365610037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
365710037SARM gem5 Developers    uint32_t mnt1, mnt2, result;
365810037SARM gem5 Developers
365910037SARM gem5 Developers    op1 = fplibNeg<uint32_t>(op1);
366010037SARM gem5 Developers    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
366110037SARM gem5 Developers    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
366210037SARM gem5 Developers
366310037SARM gem5 Developers    result = fp32_process_NaNs(op1, op2, mode, &flags);
366410037SARM gem5 Developers    if (!result) {
366513118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP32_EXP_INF && !mnt2) ||
366613118SEdmund.Grimley-Evans@arm.com            (exp2 == FP32_EXP_INF && !mnt1)) {
366710037SARM gem5 Developers            result = fp32_FPOnePointFive(0);
366813118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
366910037SARM gem5 Developers            result = fp32_infinity(sgn1 ^ sgn2);
367010037SARM gem5 Developers        } else {
367110037SARM gem5 Developers            result = fp32_muladd(fp32_FPThree(0), op1, op2, -1, mode, &flags);
367210037SARM gem5 Developers        }
367310037SARM gem5 Developers    }
367410037SARM gem5 Developers
367510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
367610037SARM gem5 Developers
367710037SARM gem5 Developers    return result;
367810037SARM gem5 Developers}
367910037SARM gem5 Developers
368010037SARM gem5 Developerstemplate <>
368110037SARM gem5 Developersuint64_t
368210037SARM gem5 DevelopersfplibRSqrtStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr)
368310037SARM gem5 Developers{
368410037SARM gem5 Developers    int mode = modeConv(fpscr);
368510037SARM gem5 Developers    int flags = 0;
368610037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
368710037SARM gem5 Developers    uint64_t mnt1, mnt2, result;
368810037SARM gem5 Developers
368910037SARM gem5 Developers    op1 = fplibNeg<uint64_t>(op1);
369010037SARM gem5 Developers    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
369110037SARM gem5 Developers    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
369210037SARM gem5 Developers
369310037SARM gem5 Developers    result = fp64_process_NaNs(op1, op2, mode, &flags);
369410037SARM gem5 Developers    if (!result) {
369513118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP64_EXP_INF && !mnt2) ||
369613118SEdmund.Grimley-Evans@arm.com            (exp2 == FP64_EXP_INF && !mnt1)) {
369710037SARM gem5 Developers            result = fp64_FPOnePointFive(0);
369813118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
369910037SARM gem5 Developers            result = fp64_infinity(sgn1 ^ sgn2);
370010037SARM gem5 Developers        } else {
370110037SARM gem5 Developers            result = fp64_muladd(fp64_FPThree(0), op1, op2, -1, mode, &flags);
370210037SARM gem5 Developers        }
370310037SARM gem5 Developers    }
370410037SARM gem5 Developers
370510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
370610037SARM gem5 Developers
370710037SARM gem5 Developers    return result;
370810037SARM gem5 Developers}
370910037SARM gem5 Developers
371010037SARM gem5 Developerstemplate <>
371113118SEdmund.Grimley-Evans@arm.comuint16_t
371213118SEdmund.Grimley-Evans@arm.comfplibRecipEstimate(uint16_t op, FPSCR &fpscr)
371310037SARM gem5 Developers{
371410037SARM gem5 Developers    int mode = modeConv(fpscr);
371510037SARM gem5 Developers    int flags = 0;
371613118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
371713118SEdmund.Grimley-Evans@arm.com    uint16_t mnt, result;
371813118SEdmund.Grimley-Evans@arm.com
371913118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
372013118SEdmund.Grimley-Evans@arm.com
372113118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
372213118SEdmund.Grimley-Evans@arm.com        result = fp16_process_NaN(op, mode, &flags);
372313118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP16_EXP_INF) {
372413118SEdmund.Grimley-Evans@arm.com        result = fp16_zero(sgn);
372513118SEdmund.Grimley-Evans@arm.com    } else if (!mnt) {
372613118SEdmund.Grimley-Evans@arm.com        result = fp16_infinity(sgn);
372713118SEdmund.Grimley-Evans@arm.com        flags |= FPLIB_DZC;
372813118SEdmund.Grimley-Evans@arm.com    } else if (!((uint16_t)(op << 1) >> (FP16_MANT_BITS - 1))) {
372913118SEdmund.Grimley-Evans@arm.com        bool overflow_to_inf = false;
373013118SEdmund.Grimley-Evans@arm.com        switch (FPCRRounding(fpscr)) {
373113118SEdmund.Grimley-Evans@arm.com          case FPRounding_TIEEVEN:
373213118SEdmund.Grimley-Evans@arm.com            overflow_to_inf = true;
373313118SEdmund.Grimley-Evans@arm.com            break;
373413118SEdmund.Grimley-Evans@arm.com          case FPRounding_POSINF:
373513118SEdmund.Grimley-Evans@arm.com            overflow_to_inf = !sgn;
373613118SEdmund.Grimley-Evans@arm.com            break;
373713118SEdmund.Grimley-Evans@arm.com          case FPRounding_NEGINF:
373813118SEdmund.Grimley-Evans@arm.com            overflow_to_inf = sgn;
373913118SEdmund.Grimley-Evans@arm.com            break;
374013118SEdmund.Grimley-Evans@arm.com          case FPRounding_ZERO:
374113118SEdmund.Grimley-Evans@arm.com            overflow_to_inf = false;
374213118SEdmund.Grimley-Evans@arm.com            break;
374313118SEdmund.Grimley-Evans@arm.com          default:
374413449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
374510037SARM gem5 Developers        }
374613118SEdmund.Grimley-Evans@arm.com        result = overflow_to_inf ? fp16_infinity(sgn) : fp16_max_normal(sgn);
374713118SEdmund.Grimley-Evans@arm.com        flags |= FPLIB_OFC | FPLIB_IXC;
374813118SEdmund.Grimley-Evans@arm.com    } else if (fpscr.fz16 && exp >= 2 * FP16_EXP_BIAS - 1) {
374913118SEdmund.Grimley-Evans@arm.com        result = fp16_zero(sgn);
375013118SEdmund.Grimley-Evans@arm.com        flags |= FPLIB_UFC;
375113118SEdmund.Grimley-Evans@arm.com    } else {
375213118SEdmund.Grimley-Evans@arm.com        exp += FP16_EXP_BITS;
375313118SEdmund.Grimley-Evans@arm.com        mnt = fp16_normalise(mnt, &exp);
375413118SEdmund.Grimley-Evans@arm.com        int result_exp = 2 * FP16_EXP_BIAS - 1 - exp;
375513118SEdmund.Grimley-Evans@arm.com        uint16_t fraction = (((uint32_t)1 << 19) /
375613118SEdmund.Grimley-Evans@arm.com                             (mnt >> (FP16_BITS - 10) | 1) + 1) >> 1;
375713118SEdmund.Grimley-Evans@arm.com        fraction <<= FP16_MANT_BITS - 8;
375813118SEdmund.Grimley-Evans@arm.com        if (result_exp == 0) {
375913118SEdmund.Grimley-Evans@arm.com            fraction >>= 1;
376013118SEdmund.Grimley-Evans@arm.com        } else if (result_exp == -1) {
376113118SEdmund.Grimley-Evans@arm.com            fraction >>= 2;
376213118SEdmund.Grimley-Evans@arm.com            result_exp = 0;
376313118SEdmund.Grimley-Evans@arm.com        }
376413118SEdmund.Grimley-Evans@arm.com        result = fp16_pack(sgn, result_exp, fraction);
376510037SARM gem5 Developers    }
376610037SARM gem5 Developers
376710037SARM gem5 Developers    set_fpscr0(fpscr, flags);
376810037SARM gem5 Developers
376910037SARM gem5 Developers    return result;
377010037SARM gem5 Developers}
377110037SARM gem5 Developers
377210037SARM gem5 Developerstemplate <>
377310037SARM gem5 Developersuint32_t
377410037SARM gem5 DevelopersfplibRecipEstimate(uint32_t op, FPSCR &fpscr)
377510037SARM gem5 Developers{
377610037SARM gem5 Developers    int mode = modeConv(fpscr);
377710037SARM gem5 Developers    int flags = 0;
377810037SARM gem5 Developers    int sgn, exp;
377910037SARM gem5 Developers    uint32_t mnt, result;
378010037SARM gem5 Developers
378110037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
378210037SARM gem5 Developers
378313118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
378410037SARM gem5 Developers        result = fp32_process_NaN(op, mode, &flags);
378513118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP32_EXP_INF) {
378610037SARM gem5 Developers        result = fp32_zero(sgn);
378710037SARM gem5 Developers    } else if (!mnt) {
378810037SARM gem5 Developers        result = fp32_infinity(sgn);
378910037SARM gem5 Developers        flags |= FPLIB_DZC;
379013118SEdmund.Grimley-Evans@arm.com    } else if (!((uint32_t)(op << 1) >> (FP32_MANT_BITS - 1))) {
379110104Smitch.hayenga@arm.com        bool overflow_to_inf = false;
379210037SARM gem5 Developers        switch (FPCRRounding(fpscr)) {
379310037SARM gem5 Developers          case FPRounding_TIEEVEN:
379410037SARM gem5 Developers            overflow_to_inf = true;
379510037SARM gem5 Developers            break;
379610037SARM gem5 Developers          case FPRounding_POSINF:
379710037SARM gem5 Developers            overflow_to_inf = !sgn;
379810037SARM gem5 Developers            break;
379910037SARM gem5 Developers          case FPRounding_NEGINF:
380010037SARM gem5 Developers            overflow_to_inf = sgn;
380110037SARM gem5 Developers            break;
380210037SARM gem5 Developers          case FPRounding_ZERO:
380310037SARM gem5 Developers            overflow_to_inf = false;
380410037SARM gem5 Developers            break;
380510037SARM gem5 Developers          default:
380613449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
380710037SARM gem5 Developers        }
380810037SARM gem5 Developers        result = overflow_to_inf ? fp32_infinity(sgn) : fp32_max_normal(sgn);
380910037SARM gem5 Developers        flags |= FPLIB_OFC | FPLIB_IXC;
381013118SEdmund.Grimley-Evans@arm.com    } else if (fpscr.fz && exp >= 2 * FP32_EXP_BIAS - 1) {
381110037SARM gem5 Developers        result = fp32_zero(sgn);
381210037SARM gem5 Developers        flags |= FPLIB_UFC;
381310037SARM gem5 Developers    } else {
381413118SEdmund.Grimley-Evans@arm.com        exp += FP32_EXP_BITS;
381510037SARM gem5 Developers        mnt = fp32_normalise(mnt, &exp);
381613118SEdmund.Grimley-Evans@arm.com        int result_exp = 2 * FP32_EXP_BIAS - 1 - exp;
381713118SEdmund.Grimley-Evans@arm.com        uint32_t fraction = (((uint32_t)1 << 19) /
381813118SEdmund.Grimley-Evans@arm.com                             (mnt >> (FP32_BITS - 10) | 1) + 1) >> 1;
381913118SEdmund.Grimley-Evans@arm.com        fraction <<= FP32_MANT_BITS - 8;
382010037SARM gem5 Developers        if (result_exp == 0) {
382110037SARM gem5 Developers            fraction >>= 1;
382210037SARM gem5 Developers        } else if (result_exp == -1) {
382310037SARM gem5 Developers            fraction >>= 2;
382410037SARM gem5 Developers            result_exp = 0;
382510037SARM gem5 Developers        }
382610037SARM gem5 Developers        result = fp32_pack(sgn, result_exp, fraction);
382710037SARM gem5 Developers    }
382810037SARM gem5 Developers
382910037SARM gem5 Developers    set_fpscr0(fpscr, flags);
383010037SARM gem5 Developers
383110037SARM gem5 Developers    return result;
383210037SARM gem5 Developers}
383310037SARM gem5 Developers
383410037SARM gem5 Developerstemplate <>
383510037SARM gem5 Developersuint64_t
383610037SARM gem5 DevelopersfplibRecipEstimate(uint64_t op, FPSCR &fpscr)
383710037SARM gem5 Developers{
383810037SARM gem5 Developers    int mode = modeConv(fpscr);
383910037SARM gem5 Developers    int flags = 0;
384010037SARM gem5 Developers    int sgn, exp;
384110037SARM gem5 Developers    uint64_t mnt, result;
384210037SARM gem5 Developers
384310037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
384410037SARM gem5 Developers
384513118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
384610037SARM gem5 Developers        result = fp64_process_NaN(op, mode, &flags);
384713118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP64_EXP_INF) {
384810037SARM gem5 Developers        result = fp64_zero(sgn);
384910037SARM gem5 Developers    } else if (!mnt) {
385010037SARM gem5 Developers        result = fp64_infinity(sgn);
385110037SARM gem5 Developers        flags |= FPLIB_DZC;
385213118SEdmund.Grimley-Evans@arm.com    } else if (!((uint64_t)(op << 1) >> (FP64_MANT_BITS - 1))) {
385310104Smitch.hayenga@arm.com        bool overflow_to_inf = false;
385410037SARM gem5 Developers        switch (FPCRRounding(fpscr)) {
385510037SARM gem5 Developers          case FPRounding_TIEEVEN:
385610037SARM gem5 Developers            overflow_to_inf = true;
385710037SARM gem5 Developers            break;
385810037SARM gem5 Developers          case FPRounding_POSINF:
385910037SARM gem5 Developers            overflow_to_inf = !sgn;
386010037SARM gem5 Developers            break;
386110037SARM gem5 Developers          case FPRounding_NEGINF:
386210037SARM gem5 Developers            overflow_to_inf = sgn;
386310037SARM gem5 Developers            break;
386410037SARM gem5 Developers          case FPRounding_ZERO:
386510037SARM gem5 Developers            overflow_to_inf = false;
386610037SARM gem5 Developers            break;
386710037SARM gem5 Developers          default:
386813449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
386910037SARM gem5 Developers        }
387010037SARM gem5 Developers        result = overflow_to_inf ? fp64_infinity(sgn) : fp64_max_normal(sgn);
387110037SARM gem5 Developers        flags |= FPLIB_OFC | FPLIB_IXC;
387213118SEdmund.Grimley-Evans@arm.com    } else if (fpscr.fz && exp >= 2 * FP64_EXP_BIAS - 1) {
387310037SARM gem5 Developers        result = fp64_zero(sgn);
387410037SARM gem5 Developers        flags |= FPLIB_UFC;
387510037SARM gem5 Developers    } else {
387613118SEdmund.Grimley-Evans@arm.com        exp += FP64_EXP_BITS;
387710037SARM gem5 Developers        mnt = fp64_normalise(mnt, &exp);
387813118SEdmund.Grimley-Evans@arm.com        int result_exp = 2 * FP64_EXP_BIAS - 1 - exp;
387913118SEdmund.Grimley-Evans@arm.com        uint64_t fraction = (((uint32_t)1 << 19) /
388013118SEdmund.Grimley-Evans@arm.com                             (mnt >> (FP64_BITS - 10) | 1) + 1) >> 1;
388113118SEdmund.Grimley-Evans@arm.com        fraction <<= FP64_MANT_BITS - 8;
388210037SARM gem5 Developers        if (result_exp == 0) {
388310037SARM gem5 Developers            fraction >>= 1;
388410037SARM gem5 Developers        } else if (result_exp == -1) {
388510037SARM gem5 Developers            fraction >>= 2;
388610037SARM gem5 Developers            result_exp = 0;
388710037SARM gem5 Developers        }
388810037SARM gem5 Developers        result = fp64_pack(sgn, result_exp, fraction);
388910037SARM gem5 Developers    }
389010037SARM gem5 Developers
389110037SARM gem5 Developers    set_fpscr0(fpscr, flags);
389210037SARM gem5 Developers
389310037SARM gem5 Developers    return result;
389410037SARM gem5 Developers}
389510037SARM gem5 Developers
389610037SARM gem5 Developerstemplate <>
389713118SEdmund.Grimley-Evans@arm.comuint16_t
389813118SEdmund.Grimley-Evans@arm.comfplibRecipStepFused(uint16_t op1, uint16_t op2, FPSCR &fpscr)
389913118SEdmund.Grimley-Evans@arm.com{
390013118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
390113118SEdmund.Grimley-Evans@arm.com    int flags = 0;
390213118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
390313118SEdmund.Grimley-Evans@arm.com    uint16_t mnt1, mnt2, result;
390413118SEdmund.Grimley-Evans@arm.com
390513118SEdmund.Grimley-Evans@arm.com    op1 = fplibNeg<uint16_t>(op1);
390613118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
390713118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
390813118SEdmund.Grimley-Evans@arm.com
390913118SEdmund.Grimley-Evans@arm.com    result = fp16_process_NaNs(op1, op2, mode, &flags);
391013118SEdmund.Grimley-Evans@arm.com    if (!result) {
391113118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP16_EXP_INF && !mnt2) ||
391213118SEdmund.Grimley-Evans@arm.com            (exp2 == FP16_EXP_INF && !mnt1)) {
391313118SEdmund.Grimley-Evans@arm.com            result = fp16_FPTwo(0);
391413118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP16_EXP_INF || exp2 == FP16_EXP_INF) {
391513118SEdmund.Grimley-Evans@arm.com            result = fp16_infinity(sgn1 ^ sgn2);
391613118SEdmund.Grimley-Evans@arm.com        } else {
391713118SEdmund.Grimley-Evans@arm.com            result = fp16_muladd(fp16_FPTwo(0), op1, op2, 0, mode, &flags);
391813118SEdmund.Grimley-Evans@arm.com        }
391913118SEdmund.Grimley-Evans@arm.com    }
392013118SEdmund.Grimley-Evans@arm.com
392113118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
392213118SEdmund.Grimley-Evans@arm.com
392313118SEdmund.Grimley-Evans@arm.com    return result;
392413118SEdmund.Grimley-Evans@arm.com}
392513118SEdmund.Grimley-Evans@arm.com
392613118SEdmund.Grimley-Evans@arm.comtemplate <>
392713118SEdmund.Grimley-Evans@arm.comuint32_t
392813118SEdmund.Grimley-Evans@arm.comfplibRecipStepFused(uint32_t op1, uint32_t op2, FPSCR &fpscr)
392913118SEdmund.Grimley-Evans@arm.com{
393013118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
393113118SEdmund.Grimley-Evans@arm.com    int flags = 0;
393213118SEdmund.Grimley-Evans@arm.com    int sgn1, exp1, sgn2, exp2;
393313118SEdmund.Grimley-Evans@arm.com    uint32_t mnt1, mnt2, result;
393413118SEdmund.Grimley-Evans@arm.com
393513118SEdmund.Grimley-Evans@arm.com    op1 = fplibNeg<uint32_t>(op1);
393613118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
393713118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
393813118SEdmund.Grimley-Evans@arm.com
393913118SEdmund.Grimley-Evans@arm.com    result = fp32_process_NaNs(op1, op2, mode, &flags);
394013118SEdmund.Grimley-Evans@arm.com    if (!result) {
394113118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP32_EXP_INF && !mnt2) ||
394213118SEdmund.Grimley-Evans@arm.com            (exp2 == FP32_EXP_INF && !mnt1)) {
394313118SEdmund.Grimley-Evans@arm.com            result = fp32_FPTwo(0);
394413118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP32_EXP_INF || exp2 == FP32_EXP_INF) {
394513118SEdmund.Grimley-Evans@arm.com            result = fp32_infinity(sgn1 ^ sgn2);
394613118SEdmund.Grimley-Evans@arm.com        } else {
394713118SEdmund.Grimley-Evans@arm.com            result = fp32_muladd(fp32_FPTwo(0), op1, op2, 0, mode, &flags);
394813118SEdmund.Grimley-Evans@arm.com        }
394913118SEdmund.Grimley-Evans@arm.com    }
395013118SEdmund.Grimley-Evans@arm.com
395113118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
395213118SEdmund.Grimley-Evans@arm.com
395313118SEdmund.Grimley-Evans@arm.com    return result;
395413118SEdmund.Grimley-Evans@arm.com}
395513118SEdmund.Grimley-Evans@arm.com
395613118SEdmund.Grimley-Evans@arm.comtemplate <>
395710037SARM gem5 Developersuint64_t
395810037SARM gem5 DevelopersfplibRecipStepFused(uint64_t op1, uint64_t op2, FPSCR &fpscr)
395910037SARM gem5 Developers{
396010037SARM gem5 Developers    int mode = modeConv(fpscr);
396110037SARM gem5 Developers    int flags = 0;
396210037SARM gem5 Developers    int sgn1, exp1, sgn2, exp2;
396310037SARM gem5 Developers    uint64_t mnt1, mnt2, result;
396410037SARM gem5 Developers
396510037SARM gem5 Developers    op1 = fplibNeg<uint64_t>(op1);
396610037SARM gem5 Developers    fp64_unpack(&sgn1, &exp1, &mnt1, op1, mode, &flags);
396710037SARM gem5 Developers    fp64_unpack(&sgn2, &exp2, &mnt2, op2, mode, &flags);
396810037SARM gem5 Developers
396910037SARM gem5 Developers    result = fp64_process_NaNs(op1, op2, mode, &flags);
397010037SARM gem5 Developers    if (!result) {
397113118SEdmund.Grimley-Evans@arm.com        if ((exp1 == FP64_EXP_INF && !mnt2) ||
397213118SEdmund.Grimley-Evans@arm.com            (exp2 == FP64_EXP_INF && !mnt1)) {
397310037SARM gem5 Developers            result = fp64_FPTwo(0);
397413118SEdmund.Grimley-Evans@arm.com        } else if (exp1 == FP64_EXP_INF || exp2 == FP64_EXP_INF) {
397510037SARM gem5 Developers            result = fp64_infinity(sgn1 ^ sgn2);
397610037SARM gem5 Developers        } else {
397710037SARM gem5 Developers            result = fp64_muladd(fp64_FPTwo(0), op1, op2, 0, mode, &flags);
397810037SARM gem5 Developers        }
397910037SARM gem5 Developers    }
398010037SARM gem5 Developers
398110037SARM gem5 Developers    set_fpscr0(fpscr, flags);
398210037SARM gem5 Developers
398310037SARM gem5 Developers    return result;
398410037SARM gem5 Developers}
398510037SARM gem5 Developers
398610037SARM gem5 Developerstemplate <>
398713118SEdmund.Grimley-Evans@arm.comuint16_t
398813118SEdmund.Grimley-Evans@arm.comfplibRecpX(uint16_t op, FPSCR &fpscr)
398913118SEdmund.Grimley-Evans@arm.com{
399013118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
399113118SEdmund.Grimley-Evans@arm.com    int flags = 0;
399213118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
399313118SEdmund.Grimley-Evans@arm.com    uint16_t mnt, result;
399413118SEdmund.Grimley-Evans@arm.com
399513118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
399613118SEdmund.Grimley-Evans@arm.com
399713118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
399813118SEdmund.Grimley-Evans@arm.com        result = fp16_process_NaN(op, mode, &flags);
399913118SEdmund.Grimley-Evans@arm.com    }
400013118SEdmund.Grimley-Evans@arm.com    else {
400113118SEdmund.Grimley-Evans@arm.com        if (!mnt) { // Zero and denormals
400213118SEdmund.Grimley-Evans@arm.com            result = fp16_pack(sgn, FP16_EXP_INF - 1, 0);
400313118SEdmund.Grimley-Evans@arm.com        } else { // Infinities and normals
400413118SEdmund.Grimley-Evans@arm.com            result = fp16_pack(sgn, exp ^ FP16_EXP_INF, 0);
400513118SEdmund.Grimley-Evans@arm.com        }
400613118SEdmund.Grimley-Evans@arm.com    }
400713118SEdmund.Grimley-Evans@arm.com
400813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
400913118SEdmund.Grimley-Evans@arm.com
401013118SEdmund.Grimley-Evans@arm.com    return result;
401113118SEdmund.Grimley-Evans@arm.com}
401213118SEdmund.Grimley-Evans@arm.com
401313118SEdmund.Grimley-Evans@arm.comtemplate <>
401410037SARM gem5 Developersuint32_t
401510037SARM gem5 DevelopersfplibRecpX(uint32_t op, FPSCR &fpscr)
401610037SARM gem5 Developers{
401710037SARM gem5 Developers    int mode = modeConv(fpscr);
401810037SARM gem5 Developers    int flags = 0;
401910037SARM gem5 Developers    int sgn, exp;
402010037SARM gem5 Developers    uint32_t mnt, result;
402110037SARM gem5 Developers
402210037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
402310037SARM gem5 Developers
402413118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
402510037SARM gem5 Developers        result = fp32_process_NaN(op, mode, &flags);
402610037SARM gem5 Developers    }
402710037SARM gem5 Developers    else {
402810037SARM gem5 Developers        if (!mnt) { // Zero and denormals
402913118SEdmund.Grimley-Evans@arm.com            result = fp32_pack(sgn, FP32_EXP_INF - 1, 0);
403010037SARM gem5 Developers        } else { // Infinities and normals
403113118SEdmund.Grimley-Evans@arm.com            result = fp32_pack(sgn, exp ^ FP32_EXP_INF, 0);
403210037SARM gem5 Developers        }
403310037SARM gem5 Developers    }
403410037SARM gem5 Developers
403510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
403610037SARM gem5 Developers
403710037SARM gem5 Developers    return result;
403810037SARM gem5 Developers}
403910037SARM gem5 Developers
404010037SARM gem5 Developerstemplate <>
404110037SARM gem5 Developersuint64_t
404210037SARM gem5 DevelopersfplibRecpX(uint64_t op, FPSCR &fpscr)
404310037SARM gem5 Developers{
404410037SARM gem5 Developers    int mode = modeConv(fpscr);
404510037SARM gem5 Developers    int flags = 0;
404610037SARM gem5 Developers    int sgn, exp;
404710037SARM gem5 Developers    uint64_t mnt, result;
404810037SARM gem5 Developers
404910037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
405010037SARM gem5 Developers
405113118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
405210037SARM gem5 Developers        result = fp64_process_NaN(op, mode, &flags);
405310037SARM gem5 Developers    }
405410037SARM gem5 Developers    else {
405510037SARM gem5 Developers        if (!mnt) { // Zero and denormals
405613118SEdmund.Grimley-Evans@arm.com            result = fp64_pack(sgn, FP64_EXP_INF - 1, 0);
405710037SARM gem5 Developers        } else { // Infinities and normals
405813118SEdmund.Grimley-Evans@arm.com            result = fp64_pack(sgn, exp ^ FP64_EXP_INF, 0);
405910037SARM gem5 Developers        }
406010037SARM gem5 Developers    }
406110037SARM gem5 Developers
406210037SARM gem5 Developers    set_fpscr0(fpscr, flags);
406310037SARM gem5 Developers
406410037SARM gem5 Developers    return result;
406510037SARM gem5 Developers}
406610037SARM gem5 Developers
406710037SARM gem5 Developerstemplate <>
406813118SEdmund.Grimley-Evans@arm.comuint16_t
406913118SEdmund.Grimley-Evans@arm.comfplibRoundInt(uint16_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
407013118SEdmund.Grimley-Evans@arm.com{
407113118SEdmund.Grimley-Evans@arm.com    int expint = FP16_EXP_BIAS + FP16_MANT_BITS;
407210037SARM gem5 Developers    int mode = modeConv(fpscr);
407310037SARM gem5 Developers    int flags = 0;
407410037SARM gem5 Developers    int sgn, exp;
407513118SEdmund.Grimley-Evans@arm.com    uint16_t mnt, result;
407610037SARM gem5 Developers
407710037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
407813118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, mode, &flags);
407910037SARM gem5 Developers
408010037SARM gem5 Developers    // Handle NaNs, infinities and zeroes:
408113118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
408213118SEdmund.Grimley-Evans@arm.com        result = fp16_process_NaN(op, mode, &flags);
408313118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP16_EXP_INF) {
408413118SEdmund.Grimley-Evans@arm.com        result = fp16_infinity(sgn);
408510037SARM gem5 Developers    } else if (!mnt) {
408613118SEdmund.Grimley-Evans@arm.com        result = fp16_zero(sgn);
408713118SEdmund.Grimley-Evans@arm.com    } else if (exp >= expint) {
408810037SARM gem5 Developers        // There are no fractional bits
408910037SARM gem5 Developers        result = op;
409010037SARM gem5 Developers    } else {
409110037SARM gem5 Developers        // Truncate towards zero:
409213118SEdmund.Grimley-Evans@arm.com        uint16_t x = expint - exp >= FP16_BITS ? 0 : mnt >> (expint - exp);
409313118SEdmund.Grimley-Evans@arm.com        int err = exp < expint - FP16_BITS ? 1 :
409413118SEdmund.Grimley-Evans@arm.com            ((mnt << 1 >> (expint - exp - 1) & 3) |
409513118SEdmund.Grimley-Evans@arm.com             ((uint16_t)(mnt << 2 << (FP16_BITS + exp - expint)) != 0));
409610037SARM gem5 Developers        switch (rounding) {
409710037SARM gem5 Developers          case FPRounding_TIEEVEN:
409810037SARM gem5 Developers            x += (err == 3 || (err == 2 && (x & 1)));
409910037SARM gem5 Developers            break;
410010037SARM gem5 Developers          case FPRounding_POSINF:
410110037SARM gem5 Developers            x += err && !sgn;
410210037SARM gem5 Developers            break;
410310037SARM gem5 Developers          case FPRounding_NEGINF:
410410037SARM gem5 Developers            x += err && sgn;
410510037SARM gem5 Developers            break;
410610037SARM gem5 Developers          case FPRounding_ZERO:
410710037SARM gem5 Developers            break;
410810037SARM gem5 Developers          case FPRounding_TIEAWAY:
410910037SARM gem5 Developers            x += err >> 1;
411010037SARM gem5 Developers            break;
411110037SARM gem5 Developers          default:
411213449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
411310037SARM gem5 Developers        }
411410037SARM gem5 Developers
411510037SARM gem5 Developers        if (x == 0) {
411613118SEdmund.Grimley-Evans@arm.com            result = fp16_zero(sgn);
411710037SARM gem5 Developers        } else {
411813118SEdmund.Grimley-Evans@arm.com            exp = expint;
411913118SEdmund.Grimley-Evans@arm.com            mnt = fp16_normalise(x, &exp);
412013118SEdmund.Grimley-Evans@arm.com            result = fp16_pack(sgn, exp + FP16_EXP_BITS, mnt >> FP16_EXP_BITS);
412110037SARM gem5 Developers        }
412210037SARM gem5 Developers
412310037SARM gem5 Developers        if (err && exact)
412410037SARM gem5 Developers            flags |= FPLIB_IXC;
412510037SARM gem5 Developers    }
412610037SARM gem5 Developers
412710037SARM gem5 Developers    set_fpscr0(fpscr, flags);
412810037SARM gem5 Developers
412910037SARM gem5 Developers    return result;
413010037SARM gem5 Developers}
413110037SARM gem5 Developers
413210037SARM gem5 Developerstemplate <>
413313118SEdmund.Grimley-Evans@arm.comuint32_t
413413118SEdmund.Grimley-Evans@arm.comfplibRoundInt(uint32_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
413513118SEdmund.Grimley-Evans@arm.com{
413613118SEdmund.Grimley-Evans@arm.com    int expint = FP32_EXP_BIAS + FP32_MANT_BITS;
413710037SARM gem5 Developers    int mode = modeConv(fpscr);
413810037SARM gem5 Developers    int flags = 0;
413910037SARM gem5 Developers    int sgn, exp;
414013118SEdmund.Grimley-Evans@arm.com    uint32_t mnt, result;
414110037SARM gem5 Developers
414210037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
414313118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn, &exp, &mnt, op, mode, &flags);
414410037SARM gem5 Developers
414510037SARM gem5 Developers    // Handle NaNs, infinities and zeroes:
414613118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
414713118SEdmund.Grimley-Evans@arm.com        result = fp32_process_NaN(op, mode, &flags);
414813118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP32_EXP_INF) {
414913118SEdmund.Grimley-Evans@arm.com        result = fp32_infinity(sgn);
415010037SARM gem5 Developers    } else if (!mnt) {
415113118SEdmund.Grimley-Evans@arm.com        result = fp32_zero(sgn);
415213118SEdmund.Grimley-Evans@arm.com    } else if (exp >= expint) {
415310037SARM gem5 Developers        // There are no fractional bits
415410037SARM gem5 Developers        result = op;
415510037SARM gem5 Developers    } else {
415610037SARM gem5 Developers        // Truncate towards zero:
415713118SEdmund.Grimley-Evans@arm.com        uint32_t x = expint - exp >= FP32_BITS ? 0 : mnt >> (expint - exp);
415813118SEdmund.Grimley-Evans@arm.com        int err = exp < expint - FP32_BITS ? 1 :
415913118SEdmund.Grimley-Evans@arm.com            ((mnt << 1 >> (expint - exp - 1) & 3) |
416013118SEdmund.Grimley-Evans@arm.com             ((uint32_t)(mnt << 2 << (FP32_BITS + exp - expint)) != 0));
416110037SARM gem5 Developers        switch (rounding) {
416210037SARM gem5 Developers          case FPRounding_TIEEVEN:
416310037SARM gem5 Developers            x += (err == 3 || (err == 2 && (x & 1)));
416410037SARM gem5 Developers            break;
416510037SARM gem5 Developers          case FPRounding_POSINF:
416610037SARM gem5 Developers            x += err && !sgn;
416710037SARM gem5 Developers            break;
416810037SARM gem5 Developers          case FPRounding_NEGINF:
416910037SARM gem5 Developers            x += err && sgn;
417010037SARM gem5 Developers            break;
417110037SARM gem5 Developers          case FPRounding_ZERO:
417210037SARM gem5 Developers            break;
417310037SARM gem5 Developers          case FPRounding_TIEAWAY:
417410037SARM gem5 Developers            x += err >> 1;
417510037SARM gem5 Developers            break;
417610037SARM gem5 Developers          default:
417713449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
417810037SARM gem5 Developers        }
417910037SARM gem5 Developers
418010037SARM gem5 Developers        if (x == 0) {
418113118SEdmund.Grimley-Evans@arm.com            result = fp32_zero(sgn);
418210037SARM gem5 Developers        } else {
418313118SEdmund.Grimley-Evans@arm.com            exp = expint;
418413118SEdmund.Grimley-Evans@arm.com            mnt = fp32_normalise(x, &exp);
418513118SEdmund.Grimley-Evans@arm.com            result = fp32_pack(sgn, exp + FP32_EXP_BITS, mnt >> FP32_EXP_BITS);
418610037SARM gem5 Developers        }
418710037SARM gem5 Developers
418810037SARM gem5 Developers        if (err && exact)
418910037SARM gem5 Developers            flags |= FPLIB_IXC;
419010037SARM gem5 Developers    }
419110037SARM gem5 Developers
419210037SARM gem5 Developers    set_fpscr0(fpscr, flags);
419310037SARM gem5 Developers
419410037SARM gem5 Developers    return result;
419510037SARM gem5 Developers}
419610037SARM gem5 Developers
419710037SARM gem5 Developerstemplate <>
419813118SEdmund.Grimley-Evans@arm.comuint64_t
419913118SEdmund.Grimley-Evans@arm.comfplibRoundInt(uint64_t op, FPRounding rounding, bool exact, FPSCR &fpscr)
420013118SEdmund.Grimley-Evans@arm.com{
420113118SEdmund.Grimley-Evans@arm.com    int expint = FP64_EXP_BIAS + FP64_MANT_BITS;
420213118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
420313118SEdmund.Grimley-Evans@arm.com    int flags = 0;
420413118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
420513118SEdmund.Grimley-Evans@arm.com    uint64_t mnt, result;
420613118SEdmund.Grimley-Evans@arm.com
420713118SEdmund.Grimley-Evans@arm.com    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
420813118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&sgn, &exp, &mnt, op, mode, &flags);
420913118SEdmund.Grimley-Evans@arm.com
421013118SEdmund.Grimley-Evans@arm.com    // Handle NaNs, infinities and zeroes:
421113118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
421213118SEdmund.Grimley-Evans@arm.com        result = fp64_process_NaN(op, mode, &flags);
421313118SEdmund.Grimley-Evans@arm.com    } else if (exp == FP64_EXP_INF) {
421413118SEdmund.Grimley-Evans@arm.com        result = fp64_infinity(sgn);
421513118SEdmund.Grimley-Evans@arm.com    } else if (!mnt) {
421613118SEdmund.Grimley-Evans@arm.com        result = fp64_zero(sgn);
421713118SEdmund.Grimley-Evans@arm.com    } else if (exp >= expint) {
421813118SEdmund.Grimley-Evans@arm.com        // There are no fractional bits
421913118SEdmund.Grimley-Evans@arm.com        result = op;
422013118SEdmund.Grimley-Evans@arm.com    } else {
422113118SEdmund.Grimley-Evans@arm.com        // Truncate towards zero:
422213118SEdmund.Grimley-Evans@arm.com        uint64_t x = expint - exp >= FP64_BITS ? 0 : mnt >> (expint - exp);
422313118SEdmund.Grimley-Evans@arm.com        int err = exp < expint - FP64_BITS ? 1 :
422413118SEdmund.Grimley-Evans@arm.com            ((mnt << 1 >> (expint - exp - 1) & 3) |
422513118SEdmund.Grimley-Evans@arm.com             ((uint64_t)(mnt << 2 << (FP64_BITS + exp - expint)) != 0));
422613118SEdmund.Grimley-Evans@arm.com        switch (rounding) {
422713118SEdmund.Grimley-Evans@arm.com          case FPRounding_TIEEVEN:
422813118SEdmund.Grimley-Evans@arm.com            x += (err == 3 || (err == 2 && (x & 1)));
422913118SEdmund.Grimley-Evans@arm.com            break;
423013118SEdmund.Grimley-Evans@arm.com          case FPRounding_POSINF:
423113118SEdmund.Grimley-Evans@arm.com            x += err && !sgn;
423213118SEdmund.Grimley-Evans@arm.com            break;
423313118SEdmund.Grimley-Evans@arm.com          case FPRounding_NEGINF:
423413118SEdmund.Grimley-Evans@arm.com            x += err && sgn;
423513118SEdmund.Grimley-Evans@arm.com            break;
423613118SEdmund.Grimley-Evans@arm.com          case FPRounding_ZERO:
423713118SEdmund.Grimley-Evans@arm.com            break;
423813118SEdmund.Grimley-Evans@arm.com          case FPRounding_TIEAWAY:
423913118SEdmund.Grimley-Evans@arm.com            x += err >> 1;
424013118SEdmund.Grimley-Evans@arm.com            break;
424113118SEdmund.Grimley-Evans@arm.com          default:
424213449Sgabeblack@google.com            panic("Unrecognized FP rounding mode");
424313118SEdmund.Grimley-Evans@arm.com        }
424413118SEdmund.Grimley-Evans@arm.com
424513118SEdmund.Grimley-Evans@arm.com        if (x == 0) {
424613118SEdmund.Grimley-Evans@arm.com            result = fp64_zero(sgn);
424713118SEdmund.Grimley-Evans@arm.com        } else {
424813118SEdmund.Grimley-Evans@arm.com            exp = expint;
424913118SEdmund.Grimley-Evans@arm.com            mnt = fp64_normalise(x, &exp);
425013118SEdmund.Grimley-Evans@arm.com            result = fp64_pack(sgn, exp + FP64_EXP_BITS, mnt >> FP64_EXP_BITS);
425113118SEdmund.Grimley-Evans@arm.com        }
425213118SEdmund.Grimley-Evans@arm.com
425313118SEdmund.Grimley-Evans@arm.com        if (err && exact)
425413118SEdmund.Grimley-Evans@arm.com            flags |= FPLIB_IXC;
425513118SEdmund.Grimley-Evans@arm.com    }
425613118SEdmund.Grimley-Evans@arm.com
425713118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
425813118SEdmund.Grimley-Evans@arm.com
425913118SEdmund.Grimley-Evans@arm.com    return result;
426013118SEdmund.Grimley-Evans@arm.com}
426113118SEdmund.Grimley-Evans@arm.com
426213118SEdmund.Grimley-Evans@arm.comtemplate <>
426313118SEdmund.Grimley-Evans@arm.comuint16_t
426413118SEdmund.Grimley-Evans@arm.comfplibScale(uint16_t op1, uint16_t op2, FPSCR &fpscr)
426513118SEdmund.Grimley-Evans@arm.com{
426613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
426713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_scale(op1, (int16_t)op2, modeConv(fpscr), &flags);
426813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
426913118SEdmund.Grimley-Evans@arm.com    return result;
427013118SEdmund.Grimley-Evans@arm.com}
427113118SEdmund.Grimley-Evans@arm.com
427213118SEdmund.Grimley-Evans@arm.comtemplate <>
427313118SEdmund.Grimley-Evans@arm.comuint32_t
427413118SEdmund.Grimley-Evans@arm.comfplibScale(uint32_t op1, uint32_t op2, FPSCR &fpscr)
427513118SEdmund.Grimley-Evans@arm.com{
427613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
427713118SEdmund.Grimley-Evans@arm.com    uint32_t result = fp32_scale(op1, (int32_t)op2, modeConv(fpscr), &flags);
427813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
427913118SEdmund.Grimley-Evans@arm.com    return result;
428013118SEdmund.Grimley-Evans@arm.com}
428113118SEdmund.Grimley-Evans@arm.com
428213118SEdmund.Grimley-Evans@arm.comtemplate <>
428313118SEdmund.Grimley-Evans@arm.comuint64_t
428413118SEdmund.Grimley-Evans@arm.comfplibScale(uint64_t op1, uint64_t op2, FPSCR &fpscr)
428513118SEdmund.Grimley-Evans@arm.com{
428613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
428713118SEdmund.Grimley-Evans@arm.com    uint64_t result = fp64_scale(op1, (int64_t)op2, modeConv(fpscr), &flags);
428813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
428913118SEdmund.Grimley-Evans@arm.com    return result;
429013118SEdmund.Grimley-Evans@arm.com}
429113118SEdmund.Grimley-Evans@arm.com
429213118SEdmund.Grimley-Evans@arm.comtemplate <>
429313118SEdmund.Grimley-Evans@arm.comuint16_t
429413118SEdmund.Grimley-Evans@arm.comfplibSqrt(uint16_t op, FPSCR &fpscr)
429513118SEdmund.Grimley-Evans@arm.com{
429613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
429713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_sqrt(op, modeConv(fpscr), &flags);
429813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
429913118SEdmund.Grimley-Evans@arm.com    return result;
430013118SEdmund.Grimley-Evans@arm.com}
430113118SEdmund.Grimley-Evans@arm.com
430213118SEdmund.Grimley-Evans@arm.comtemplate <>
430310037SARM gem5 Developersuint32_t
430410037SARM gem5 DevelopersfplibSqrt(uint32_t op, FPSCR &fpscr)
430510037SARM gem5 Developers{
430610037SARM gem5 Developers    int flags = 0;
430710037SARM gem5 Developers    uint32_t result = fp32_sqrt(op, modeConv(fpscr), &flags);
430810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
430910037SARM gem5 Developers    return result;
431010037SARM gem5 Developers}
431110037SARM gem5 Developers
431210037SARM gem5 Developerstemplate <>
431310037SARM gem5 Developersuint64_t
431410037SARM gem5 DevelopersfplibSqrt(uint64_t op, FPSCR &fpscr)
431510037SARM gem5 Developers{
431610037SARM gem5 Developers    int flags = 0;
431710037SARM gem5 Developers    uint64_t result = fp64_sqrt(op, modeConv(fpscr), &flags);
431810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
431910037SARM gem5 Developers    return result;
432010037SARM gem5 Developers}
432110037SARM gem5 Developers
432210037SARM gem5 Developerstemplate <>
432313118SEdmund.Grimley-Evans@arm.comuint16_t
432413118SEdmund.Grimley-Evans@arm.comfplibSub(uint16_t op1, uint16_t op2, FPSCR &fpscr)
432513118SEdmund.Grimley-Evans@arm.com{
432613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
432713118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_add(op1, op2, 1, modeConv(fpscr), &flags);
432813118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
432913118SEdmund.Grimley-Evans@arm.com    return result;
433013118SEdmund.Grimley-Evans@arm.com}
433113118SEdmund.Grimley-Evans@arm.com
433213118SEdmund.Grimley-Evans@arm.comtemplate <>
433310037SARM gem5 Developersuint32_t
433410037SARM gem5 DevelopersfplibSub(uint32_t op1, uint32_t op2, FPSCR &fpscr)
433510037SARM gem5 Developers{
433610037SARM gem5 Developers    int flags = 0;
433710037SARM gem5 Developers    uint32_t result = fp32_add(op1, op2, 1, modeConv(fpscr), &flags);
433810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
433910037SARM gem5 Developers    return result;
434010037SARM gem5 Developers}
434110037SARM gem5 Developers
434210037SARM gem5 Developerstemplate <>
434310037SARM gem5 Developersuint64_t
434410037SARM gem5 DevelopersfplibSub(uint64_t op1, uint64_t op2, FPSCR &fpscr)
434510037SARM gem5 Developers{
434610037SARM gem5 Developers    int flags = 0;
434710037SARM gem5 Developers    uint64_t result = fp64_add(op1, op2, 1, modeConv(fpscr), &flags);
434810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
434910037SARM gem5 Developers    return result;
435010037SARM gem5 Developers}
435110037SARM gem5 Developers
435213118SEdmund.Grimley-Evans@arm.comtemplate <>
435313118SEdmund.Grimley-Evans@arm.comuint16_t
435413118SEdmund.Grimley-Evans@arm.comfplibTrigMulAdd(uint8_t coeff_index, uint16_t op1, uint16_t op2, FPSCR &fpscr)
435513118SEdmund.Grimley-Evans@arm.com{
435613118SEdmund.Grimley-Evans@arm.com    static uint16_t coeff[2][8] = {
435713118SEdmund.Grimley-Evans@arm.com        {
435813118SEdmund.Grimley-Evans@arm.com            0x3c00,
435913118SEdmund.Grimley-Evans@arm.com            0xb155,
436013118SEdmund.Grimley-Evans@arm.com            0x2030,
436113118SEdmund.Grimley-Evans@arm.com            0x0000,
436213118SEdmund.Grimley-Evans@arm.com            0x0000,
436313118SEdmund.Grimley-Evans@arm.com            0x0000,
436413118SEdmund.Grimley-Evans@arm.com            0x0000,
436513118SEdmund.Grimley-Evans@arm.com            0x0000,
436613118SEdmund.Grimley-Evans@arm.com        },
436713118SEdmund.Grimley-Evans@arm.com        {
436813118SEdmund.Grimley-Evans@arm.com            0x3c00,
436913118SEdmund.Grimley-Evans@arm.com            0xb800,
437013118SEdmund.Grimley-Evans@arm.com            0x293a,
437113118SEdmund.Grimley-Evans@arm.com            0x0000,
437213118SEdmund.Grimley-Evans@arm.com            0x0000,
437313118SEdmund.Grimley-Evans@arm.com            0x0000,
437413118SEdmund.Grimley-Evans@arm.com            0x0000,
437513118SEdmund.Grimley-Evans@arm.com            0x0000
437613118SEdmund.Grimley-Evans@arm.com        }
437713118SEdmund.Grimley-Evans@arm.com    };
437813118SEdmund.Grimley-Evans@arm.com    int flags = 0;
437913118SEdmund.Grimley-Evans@arm.com    uint16_t result =
438013118SEdmund.Grimley-Evans@arm.com        fp16_muladd(coeff[op2 >> (FP16_BITS - 1)][coeff_index], op1,
438113118SEdmund.Grimley-Evans@arm.com                    fplibAbs(op2), 0, modeConv(fpscr), &flags);
438213118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
438313118SEdmund.Grimley-Evans@arm.com    return result;
438413118SEdmund.Grimley-Evans@arm.com}
438513118SEdmund.Grimley-Evans@arm.com
438613118SEdmund.Grimley-Evans@arm.comtemplate <>
438713118SEdmund.Grimley-Evans@arm.comuint32_t
438813118SEdmund.Grimley-Evans@arm.comfplibTrigMulAdd(uint8_t coeff_index, uint32_t op1, uint32_t op2, FPSCR &fpscr)
438913118SEdmund.Grimley-Evans@arm.com{
439013118SEdmund.Grimley-Evans@arm.com    static uint32_t coeff[2][8] = {
439113118SEdmund.Grimley-Evans@arm.com        {
439213118SEdmund.Grimley-Evans@arm.com            0x3f800000,
439313118SEdmund.Grimley-Evans@arm.com            0xbe2aaaab,
439413118SEdmund.Grimley-Evans@arm.com            0x3c088886,
439513118SEdmund.Grimley-Evans@arm.com            0xb95008b9,
439613118SEdmund.Grimley-Evans@arm.com            0x36369d6d,
439713118SEdmund.Grimley-Evans@arm.com            0x00000000,
439813118SEdmund.Grimley-Evans@arm.com            0x00000000,
439913118SEdmund.Grimley-Evans@arm.com            0x00000000
440013118SEdmund.Grimley-Evans@arm.com        },
440113118SEdmund.Grimley-Evans@arm.com        {
440213118SEdmund.Grimley-Evans@arm.com            0x3f800000,
440313118SEdmund.Grimley-Evans@arm.com            0xbf000000,
440413118SEdmund.Grimley-Evans@arm.com            0x3d2aaaa6,
440513118SEdmund.Grimley-Evans@arm.com            0xbab60705,
440613118SEdmund.Grimley-Evans@arm.com            0x37cd37cc,
440713118SEdmund.Grimley-Evans@arm.com            0x00000000,
440813118SEdmund.Grimley-Evans@arm.com            0x00000000,
440913118SEdmund.Grimley-Evans@arm.com            0x00000000
441013118SEdmund.Grimley-Evans@arm.com        }
441113118SEdmund.Grimley-Evans@arm.com    };
441213118SEdmund.Grimley-Evans@arm.com    int flags = 0;
441313118SEdmund.Grimley-Evans@arm.com    uint32_t result =
441413118SEdmund.Grimley-Evans@arm.com        fp32_muladd(coeff[op2 >> (FP32_BITS - 1)][coeff_index], op1,
441513118SEdmund.Grimley-Evans@arm.com                    fplibAbs(op2), 0, modeConv(fpscr), &flags);
441613118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
441713118SEdmund.Grimley-Evans@arm.com    return result;
441813118SEdmund.Grimley-Evans@arm.com}
441913118SEdmund.Grimley-Evans@arm.com
442013118SEdmund.Grimley-Evans@arm.comtemplate <>
442113118SEdmund.Grimley-Evans@arm.comuint64_t
442213118SEdmund.Grimley-Evans@arm.comfplibTrigMulAdd(uint8_t coeff_index, uint64_t op1, uint64_t op2, FPSCR &fpscr)
442313118SEdmund.Grimley-Evans@arm.com{
442413118SEdmund.Grimley-Evans@arm.com    static uint64_t coeff[2][8] = {
442513118SEdmund.Grimley-Evans@arm.com        {
442613118SEdmund.Grimley-Evans@arm.com            0x3ff0000000000000ULL,
442713118SEdmund.Grimley-Evans@arm.com            0xbfc5555555555543ULL,
442813118SEdmund.Grimley-Evans@arm.com            0x3f8111111110f30cULL,
442913118SEdmund.Grimley-Evans@arm.com            0xbf2a01a019b92fc6ULL,
443013118SEdmund.Grimley-Evans@arm.com            0x3ec71de351f3d22bULL,
443113118SEdmund.Grimley-Evans@arm.com            0xbe5ae5e2b60f7b91ULL,
443213118SEdmund.Grimley-Evans@arm.com            0x3de5d8408868552fULL,
443313118SEdmund.Grimley-Evans@arm.com            0x0000000000000000ULL
443413118SEdmund.Grimley-Evans@arm.com        },
443513118SEdmund.Grimley-Evans@arm.com        {
443613118SEdmund.Grimley-Evans@arm.com            0x3ff0000000000000ULL,
443713118SEdmund.Grimley-Evans@arm.com            0xbfe0000000000000ULL,
443813118SEdmund.Grimley-Evans@arm.com            0x3fa5555555555536ULL,
443913118SEdmund.Grimley-Evans@arm.com            0xbf56c16c16c13a0bULL,
444013118SEdmund.Grimley-Evans@arm.com            0x3efa01a019b1e8d8ULL,
444113118SEdmund.Grimley-Evans@arm.com            0xbe927e4f7282f468ULL,
444213118SEdmund.Grimley-Evans@arm.com            0x3e21ee96d2641b13ULL,
444313118SEdmund.Grimley-Evans@arm.com            0xbda8f76380fbb401ULL
444413118SEdmund.Grimley-Evans@arm.com        }
444513118SEdmund.Grimley-Evans@arm.com    };
444613118SEdmund.Grimley-Evans@arm.com    int flags = 0;
444713118SEdmund.Grimley-Evans@arm.com    uint64_t result =
444813118SEdmund.Grimley-Evans@arm.com        fp64_muladd(coeff[op2 >> (FP64_BITS - 1)][coeff_index], op1,
444913118SEdmund.Grimley-Evans@arm.com                    fplibAbs(op2), 0, modeConv(fpscr), &flags);
445013118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
445113118SEdmund.Grimley-Evans@arm.com    return result;
445213118SEdmund.Grimley-Evans@arm.com}
445313118SEdmund.Grimley-Evans@arm.com
445413118SEdmund.Grimley-Evans@arm.comtemplate <>
445513118SEdmund.Grimley-Evans@arm.comuint16_t
445613118SEdmund.Grimley-Evans@arm.comfplibTrigSMul(uint16_t op1, uint16_t op2, FPSCR &fpscr)
445713118SEdmund.Grimley-Evans@arm.com{
445813118SEdmund.Grimley-Evans@arm.com    int flags = 0;
445913118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
446013118SEdmund.Grimley-Evans@arm.com    uint16_t mnt;
446113118SEdmund.Grimley-Evans@arm.com
446213118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
446313118SEdmund.Grimley-Evans@arm.com    uint16_t result = fp16_mul(op1, op1, mode, &flags);
446413118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
446513118SEdmund.Grimley-Evans@arm.com
446613118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, result, mode, &flags);
446713118SEdmund.Grimley-Evans@arm.com    if (!fp16_is_NaN(exp, mnt)) {
446813118SEdmund.Grimley-Evans@arm.com        result = (result & ~(1ULL << (FP16_BITS - 1))) |
446913118SEdmund.Grimley-Evans@arm.com            op2 << (FP16_BITS - 1);
447013118SEdmund.Grimley-Evans@arm.com    }
447113118SEdmund.Grimley-Evans@arm.com    return result;
447213118SEdmund.Grimley-Evans@arm.com}
447313118SEdmund.Grimley-Evans@arm.com
447413118SEdmund.Grimley-Evans@arm.comtemplate <>
447513118SEdmund.Grimley-Evans@arm.comuint32_t
447613118SEdmund.Grimley-Evans@arm.comfplibTrigSMul(uint32_t op1, uint32_t op2, FPSCR &fpscr)
447713118SEdmund.Grimley-Evans@arm.com{
447813118SEdmund.Grimley-Evans@arm.com    int flags = 0;
447913118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
448013118SEdmund.Grimley-Evans@arm.com    uint32_t mnt;
448113118SEdmund.Grimley-Evans@arm.com
448213118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
448313118SEdmund.Grimley-Evans@arm.com    uint32_t result = fp32_mul(op1, op1, mode, &flags);
448413118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
448513118SEdmund.Grimley-Evans@arm.com
448613118SEdmund.Grimley-Evans@arm.com    fp32_unpack(&sgn, &exp, &mnt, result, mode, &flags);
448713118SEdmund.Grimley-Evans@arm.com    if (!fp32_is_NaN(exp, mnt)) {
448813118SEdmund.Grimley-Evans@arm.com        result = (result & ~(1ULL << (FP32_BITS - 1))) | op2 << (FP32_BITS - 1);
448913118SEdmund.Grimley-Evans@arm.com    }
449013118SEdmund.Grimley-Evans@arm.com    return result;
449113118SEdmund.Grimley-Evans@arm.com}
449213118SEdmund.Grimley-Evans@arm.com
449313118SEdmund.Grimley-Evans@arm.comtemplate <>
449413118SEdmund.Grimley-Evans@arm.comuint64_t
449513118SEdmund.Grimley-Evans@arm.comfplibTrigSMul(uint64_t op1, uint64_t op2, FPSCR &fpscr)
449613118SEdmund.Grimley-Evans@arm.com{
449713118SEdmund.Grimley-Evans@arm.com    int flags = 0;
449813118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
449913118SEdmund.Grimley-Evans@arm.com    uint64_t mnt;
450013118SEdmund.Grimley-Evans@arm.com
450113118SEdmund.Grimley-Evans@arm.com    int mode = modeConv(fpscr);
450213118SEdmund.Grimley-Evans@arm.com    uint64_t result = fp64_mul(op1, op1, mode, &flags);
450313118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
450413118SEdmund.Grimley-Evans@arm.com
450513118SEdmund.Grimley-Evans@arm.com    fp64_unpack(&sgn, &exp, &mnt, result, mode, &flags);
450613118SEdmund.Grimley-Evans@arm.com    if (!fp64_is_NaN(exp, mnt)) {
450713118SEdmund.Grimley-Evans@arm.com        result = (result & ~(1ULL << (FP64_BITS - 1))) | op2 << (FP64_BITS - 1);
450813118SEdmund.Grimley-Evans@arm.com    }
450913118SEdmund.Grimley-Evans@arm.com    return result;
451013118SEdmund.Grimley-Evans@arm.com}
451113118SEdmund.Grimley-Evans@arm.com
451213118SEdmund.Grimley-Evans@arm.comtemplate <>
451313118SEdmund.Grimley-Evans@arm.comuint16_t
451413118SEdmund.Grimley-Evans@arm.comfplibTrigSSel(uint16_t op1, uint16_t op2, FPSCR &fpscr)
451513118SEdmund.Grimley-Evans@arm.com{
451613118SEdmund.Grimley-Evans@arm.com    static constexpr uint16_t fpOne =
451713118SEdmund.Grimley-Evans@arm.com        (uint16_t)FP16_EXP_BIAS << FP16_MANT_BITS; // 1.0
451813118SEdmund.Grimley-Evans@arm.com    if (op2 & 1)
451913118SEdmund.Grimley-Evans@arm.com        op1 = fpOne;
452013118SEdmund.Grimley-Evans@arm.com    return op1 ^ ((op2 >> 1) << (FP16_BITS - 1));
452113118SEdmund.Grimley-Evans@arm.com}
452213118SEdmund.Grimley-Evans@arm.com
452313118SEdmund.Grimley-Evans@arm.comtemplate <>
452413118SEdmund.Grimley-Evans@arm.comuint32_t
452513118SEdmund.Grimley-Evans@arm.comfplibTrigSSel(uint32_t op1, uint32_t op2, FPSCR &fpscr)
452613118SEdmund.Grimley-Evans@arm.com{
452713118SEdmund.Grimley-Evans@arm.com    static constexpr uint32_t fpOne =
452813118SEdmund.Grimley-Evans@arm.com        (uint32_t)FP32_EXP_BIAS << FP32_MANT_BITS; // 1.0
452913118SEdmund.Grimley-Evans@arm.com    if (op2 & 1)
453013118SEdmund.Grimley-Evans@arm.com        op1 = fpOne;
453113118SEdmund.Grimley-Evans@arm.com    return op1 ^ ((op2 >> 1) << (FP32_BITS - 1));
453213118SEdmund.Grimley-Evans@arm.com}
453313118SEdmund.Grimley-Evans@arm.com
453413118SEdmund.Grimley-Evans@arm.comtemplate <>
453513118SEdmund.Grimley-Evans@arm.comuint64_t
453613118SEdmund.Grimley-Evans@arm.comfplibTrigSSel(uint64_t op1, uint64_t op2, FPSCR &fpscr)
453713118SEdmund.Grimley-Evans@arm.com{
453813118SEdmund.Grimley-Evans@arm.com    static constexpr uint64_t fpOne =
453913118SEdmund.Grimley-Evans@arm.com        (uint64_t)FP64_EXP_BIAS << FP64_MANT_BITS; // 1.0
454013118SEdmund.Grimley-Evans@arm.com    if (op2 & 1)
454113118SEdmund.Grimley-Evans@arm.com        op1 = fpOne;
454213118SEdmund.Grimley-Evans@arm.com    return op1 ^ ((op2 >> 1) << (FP64_BITS - 1));
454313118SEdmund.Grimley-Evans@arm.com}
454413118SEdmund.Grimley-Evans@arm.com
454510037SARM gem5 Developersstatic uint64_t
454610037SARM gem5 DevelopersFPToFixed_64(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
454710037SARM gem5 Developers             int *flags)
454810037SARM gem5 Developers{
454913118SEdmund.Grimley-Evans@arm.com    int expmax = FP64_EXP_BIAS + FP64_BITS - 1;
455010037SARM gem5 Developers    uint64_t x;
455110037SARM gem5 Developers    int err;
455210037SARM gem5 Developers
455313118SEdmund.Grimley-Evans@arm.com    if (exp > expmax) {
455410037SARM gem5 Developers        *flags = FPLIB_IOC;
455513118SEdmund.Grimley-Evans@arm.com        return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
455610037SARM gem5 Developers    }
455710037SARM gem5 Developers
455813118SEdmund.Grimley-Evans@arm.com    x = lsr64(mnt << FP64_EXP_BITS, expmax - exp);
455913118SEdmund.Grimley-Evans@arm.com    err = (exp > expmax - 2 ? 0 :
456013118SEdmund.Grimley-Evans@arm.com           (lsr64(mnt << FP64_EXP_BITS, expmax - 2 - exp) & 3) |
456113118SEdmund.Grimley-Evans@arm.com           !!(mnt << FP64_EXP_BITS & (lsl64(1, expmax - 2 - exp) - 1)));
456210037SARM gem5 Developers
456310037SARM gem5 Developers    switch (rounding) {
456410037SARM gem5 Developers      case FPRounding_TIEEVEN:
456510037SARM gem5 Developers        x += (err == 3 || (err == 2 && (x & 1)));
456610037SARM gem5 Developers        break;
456710037SARM gem5 Developers      case FPRounding_POSINF:
456810037SARM gem5 Developers        x += err && !sgn;
456910037SARM gem5 Developers        break;
457010037SARM gem5 Developers      case FPRounding_NEGINF:
457110037SARM gem5 Developers        x += err && sgn;
457210037SARM gem5 Developers        break;
457310037SARM gem5 Developers      case FPRounding_ZERO:
457410037SARM gem5 Developers        break;
457510037SARM gem5 Developers      case FPRounding_TIEAWAY:
457610037SARM gem5 Developers        x += err >> 1;
457710037SARM gem5 Developers        break;
457810037SARM gem5 Developers      default:
457913449Sgabeblack@google.com        panic("Unrecognized FP rounding mode");
458010037SARM gem5 Developers    }
458110037SARM gem5 Developers
458213118SEdmund.Grimley-Evans@arm.com    if (u ? sgn && x : x > (1ULL << (FP64_BITS - 1)) - !sgn) {
458310037SARM gem5 Developers        *flags = FPLIB_IOC;
458413118SEdmund.Grimley-Evans@arm.com        return ((uint64_t)!u << (FP64_BITS - 1)) - !sgn;
458510037SARM gem5 Developers    }
458610037SARM gem5 Developers
458710037SARM gem5 Developers    if (err) {
458810037SARM gem5 Developers        *flags = FPLIB_IXC;
458910037SARM gem5 Developers    }
459010037SARM gem5 Developers
459110037SARM gem5 Developers    return sgn ? -x : x;
459210037SARM gem5 Developers}
459310037SARM gem5 Developers
459410037SARM gem5 Developersstatic uint32_t
459510037SARM gem5 DevelopersFPToFixed_32(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
459610037SARM gem5 Developers             int *flags)
459710037SARM gem5 Developers{
459810037SARM gem5 Developers    uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
459913118SEdmund.Grimley-Evans@arm.com    if (u ? x >= 1ULL << FP32_BITS :
460013118SEdmund.Grimley-Evans@arm.com        !(x < 1ULL << (FP32_BITS - 1) ||
460113118SEdmund.Grimley-Evans@arm.com          (uint64_t)-x <= (uint64_t)1 << (FP32_BITS - 1))) {
460210037SARM gem5 Developers        *flags = FPLIB_IOC;
460313118SEdmund.Grimley-Evans@arm.com        x = ((uint32_t)!u << (FP32_BITS - 1)) - !sgn;
460410037SARM gem5 Developers    }
460510037SARM gem5 Developers    return x;
460610037SARM gem5 Developers}
460710037SARM gem5 Developers
460813118SEdmund.Grimley-Evans@arm.comstatic uint16_t
460913118SEdmund.Grimley-Evans@arm.comFPToFixed_16(int sgn, int exp, uint64_t mnt, bool u, FPRounding rounding,
461013118SEdmund.Grimley-Evans@arm.com             int *flags)
461113118SEdmund.Grimley-Evans@arm.com{
461213118SEdmund.Grimley-Evans@arm.com    uint64_t x = FPToFixed_64(sgn, exp, mnt, u, rounding, flags);
461313118SEdmund.Grimley-Evans@arm.com    if (u ? x >= 1ULL << FP16_BITS :
461413118SEdmund.Grimley-Evans@arm.com        !(x < 1ULL << (FP16_BITS - 1) ||
461513118SEdmund.Grimley-Evans@arm.com          (uint64_t)-x <= (uint64_t)1 << (FP16_BITS - 1))) {
461613118SEdmund.Grimley-Evans@arm.com        *flags = FPLIB_IOC;
461713118SEdmund.Grimley-Evans@arm.com        x = ((uint16_t)!u << (FP16_BITS - 1)) - !sgn;
461813118SEdmund.Grimley-Evans@arm.com    }
461913118SEdmund.Grimley-Evans@arm.com    return x;
462013118SEdmund.Grimley-Evans@arm.com}
462113118SEdmund.Grimley-Evans@arm.com
462213118SEdmund.Grimley-Evans@arm.comtemplate <>
462313118SEdmund.Grimley-Evans@arm.comuint16_t
462413118SEdmund.Grimley-Evans@arm.comfplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
462513118SEdmund.Grimley-Evans@arm.com               FPSCR &fpscr)
462613118SEdmund.Grimley-Evans@arm.com{
462713118SEdmund.Grimley-Evans@arm.com    int flags = 0;
462813118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
462913118SEdmund.Grimley-Evans@arm.com    uint16_t mnt, result;
463013118SEdmund.Grimley-Evans@arm.com
463113118SEdmund.Grimley-Evans@arm.com    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
463213118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
463313118SEdmund.Grimley-Evans@arm.com
463413118SEdmund.Grimley-Evans@arm.com    // If NaN, set cumulative flag or take exception:
463513118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
463613118SEdmund.Grimley-Evans@arm.com        flags = FPLIB_IOC;
463713118SEdmund.Grimley-Evans@arm.com        result = 0;
463813118SEdmund.Grimley-Evans@arm.com    } else {
463913118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
464013118SEdmund.Grimley-Evans@arm.com        // Infinity is treated as an ordinary normalised number that saturates.
464113118SEdmund.Grimley-Evans@arm.com        result =
464213118SEdmund.Grimley-Evans@arm.com            FPToFixed_16(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
464313118SEdmund.Grimley-Evans@arm.com                         (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
464413118SEdmund.Grimley-Evans@arm.com                         u, rounding, &flags);
464513118SEdmund.Grimley-Evans@arm.com    }
464613118SEdmund.Grimley-Evans@arm.com
464713118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
464813118SEdmund.Grimley-Evans@arm.com
464913118SEdmund.Grimley-Evans@arm.com    return result;
465013118SEdmund.Grimley-Evans@arm.com}
465113118SEdmund.Grimley-Evans@arm.com
465213118SEdmund.Grimley-Evans@arm.comtemplate <>
465313118SEdmund.Grimley-Evans@arm.comuint32_t
465413118SEdmund.Grimley-Evans@arm.comfplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
465513118SEdmund.Grimley-Evans@arm.com               FPSCR &fpscr)
465613118SEdmund.Grimley-Evans@arm.com{
465713118SEdmund.Grimley-Evans@arm.com    int flags = 0;
465813118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
465913118SEdmund.Grimley-Evans@arm.com    uint16_t mnt;
466013118SEdmund.Grimley-Evans@arm.com    uint32_t result;
466113118SEdmund.Grimley-Evans@arm.com
466213118SEdmund.Grimley-Evans@arm.com    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
466313118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
466413118SEdmund.Grimley-Evans@arm.com
466513118SEdmund.Grimley-Evans@arm.com    // If NaN, set cumulative flag or take exception:
466613118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
466713118SEdmund.Grimley-Evans@arm.com        flags = FPLIB_IOC;
466813118SEdmund.Grimley-Evans@arm.com        result = 0;
466913118SEdmund.Grimley-Evans@arm.com    } else {
467013118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
467113118SEdmund.Grimley-Evans@arm.com        if (exp == FP16_EXP_INF)
467213118SEdmund.Grimley-Evans@arm.com            exp = 255; // infinity: make it big enough to saturate
467313118SEdmund.Grimley-Evans@arm.com        result =
467413118SEdmund.Grimley-Evans@arm.com            FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
467513118SEdmund.Grimley-Evans@arm.com                         (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
467613118SEdmund.Grimley-Evans@arm.com                         u, rounding, &flags);
467713118SEdmund.Grimley-Evans@arm.com    }
467813118SEdmund.Grimley-Evans@arm.com
467913118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
468013118SEdmund.Grimley-Evans@arm.com
468113118SEdmund.Grimley-Evans@arm.com    return result;
468213118SEdmund.Grimley-Evans@arm.com}
468313118SEdmund.Grimley-Evans@arm.com
468410037SARM gem5 Developerstemplate <>
468510037SARM gem5 Developersuint32_t
468610037SARM gem5 DevelopersfplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
468710037SARM gem5 Developers{
468810037SARM gem5 Developers    int flags = 0;
468910037SARM gem5 Developers    int sgn, exp;
469010037SARM gem5 Developers    uint32_t mnt, result;
469110037SARM gem5 Developers
469210037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
469310037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
469410037SARM gem5 Developers
469510037SARM gem5 Developers    // If NaN, set cumulative flag or take exception:
469613118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
469710037SARM gem5 Developers        flags = FPLIB_IOC;
469810037SARM gem5 Developers        result = 0;
469910037SARM gem5 Developers    } else {
470013118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
470113118SEdmund.Grimley-Evans@arm.com        // Infinity is treated as an ordinary normalised number that saturates.
470213118SEdmund.Grimley-Evans@arm.com        result =
470313118SEdmund.Grimley-Evans@arm.com            FPToFixed_32(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
470413118SEdmund.Grimley-Evans@arm.com                         (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
470513118SEdmund.Grimley-Evans@arm.com                         u, rounding, &flags);
470610037SARM gem5 Developers    }
470710037SARM gem5 Developers
470810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
470910037SARM gem5 Developers
471010037SARM gem5 Developers    return result;
471110037SARM gem5 Developers}
471210037SARM gem5 Developers
471310037SARM gem5 Developerstemplate <>
471410037SARM gem5 Developersuint32_t
471510037SARM gem5 DevelopersfplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
471610037SARM gem5 Developers{
471710037SARM gem5 Developers    int flags = 0;
471810037SARM gem5 Developers    int sgn, exp;
471910037SARM gem5 Developers    uint64_t mnt;
472010037SARM gem5 Developers    uint32_t result;
472110037SARM gem5 Developers
472210037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
472310037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
472410037SARM gem5 Developers
472510037SARM gem5 Developers    // If NaN, set cumulative flag or take exception:
472613118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
472710037SARM gem5 Developers        flags = FPLIB_IOC;
472810037SARM gem5 Developers        result = 0;
472910037SARM gem5 Developers    } else {
473013118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
473113118SEdmund.Grimley-Evans@arm.com        // Infinity is treated as an ordinary normalised number that saturates.
473210037SARM gem5 Developers        result = FPToFixed_32(sgn, exp + fbits, mnt, u, rounding, &flags);
473310037SARM gem5 Developers    }
473410037SARM gem5 Developers
473510037SARM gem5 Developers    set_fpscr0(fpscr, flags);
473610037SARM gem5 Developers
473710037SARM gem5 Developers    return result;
473810037SARM gem5 Developers}
473910037SARM gem5 Developers
474010037SARM gem5 Developerstemplate <>
474110037SARM gem5 Developersuint64_t
474213118SEdmund.Grimley-Evans@arm.comfplibFPToFixed(uint16_t op, int fbits, bool u, FPRounding rounding,
474313118SEdmund.Grimley-Evans@arm.com               FPSCR &fpscr)
474413118SEdmund.Grimley-Evans@arm.com{
474513118SEdmund.Grimley-Evans@arm.com    int flags = 0;
474613118SEdmund.Grimley-Evans@arm.com    int sgn, exp;
474713118SEdmund.Grimley-Evans@arm.com    uint16_t mnt;
474813118SEdmund.Grimley-Evans@arm.com    uint64_t result;
474913118SEdmund.Grimley-Evans@arm.com
475013118SEdmund.Grimley-Evans@arm.com    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
475113118SEdmund.Grimley-Evans@arm.com    fp16_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
475213118SEdmund.Grimley-Evans@arm.com
475313118SEdmund.Grimley-Evans@arm.com    // If NaN, set cumulative flag or take exception:
475413118SEdmund.Grimley-Evans@arm.com    if (fp16_is_NaN(exp, mnt)) {
475513118SEdmund.Grimley-Evans@arm.com        flags = FPLIB_IOC;
475613118SEdmund.Grimley-Evans@arm.com        result = 0;
475713118SEdmund.Grimley-Evans@arm.com    } else {
475813118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
475913118SEdmund.Grimley-Evans@arm.com        if (exp == FP16_EXP_INF)
476013118SEdmund.Grimley-Evans@arm.com            exp = 255; // infinity: make it big enough to saturate
476113118SEdmund.Grimley-Evans@arm.com        result =
476213118SEdmund.Grimley-Evans@arm.com            FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP16_EXP_BIAS + fbits,
476313118SEdmund.Grimley-Evans@arm.com                         (uint64_t)mnt << (FP64_MANT_BITS - FP16_MANT_BITS),
476413118SEdmund.Grimley-Evans@arm.com                         u, rounding, &flags);
476513118SEdmund.Grimley-Evans@arm.com    }
476613118SEdmund.Grimley-Evans@arm.com
476713118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
476813118SEdmund.Grimley-Evans@arm.com
476913118SEdmund.Grimley-Evans@arm.com    return result;
477013118SEdmund.Grimley-Evans@arm.com}
477113118SEdmund.Grimley-Evans@arm.com
477213118SEdmund.Grimley-Evans@arm.comtemplate <>
477313118SEdmund.Grimley-Evans@arm.comuint64_t
477410037SARM gem5 DevelopersfplibFPToFixed(uint32_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
477510037SARM gem5 Developers{
477610037SARM gem5 Developers    int flags = 0;
477710037SARM gem5 Developers    int sgn, exp;
477810037SARM gem5 Developers    uint32_t mnt;
477910037SARM gem5 Developers    uint64_t result;
478010037SARM gem5 Developers
478110037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
478210037SARM gem5 Developers    fp32_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
478310037SARM gem5 Developers
478410037SARM gem5 Developers    // If NaN, set cumulative flag or take exception:
478513118SEdmund.Grimley-Evans@arm.com    if (fp32_is_NaN(exp, mnt)) {
478610037SARM gem5 Developers        flags = FPLIB_IOC;
478710037SARM gem5 Developers        result = 0;
478810037SARM gem5 Developers    } else {
478913118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
479013118SEdmund.Grimley-Evans@arm.com        // Infinity is treated as an ordinary normalised number that saturates.
479113118SEdmund.Grimley-Evans@arm.com        result =
479213118SEdmund.Grimley-Evans@arm.com            FPToFixed_64(sgn, exp + FP64_EXP_BIAS - FP32_EXP_BIAS + fbits,
479313118SEdmund.Grimley-Evans@arm.com                         (uint64_t)mnt << (FP64_MANT_BITS - FP32_MANT_BITS),
479413118SEdmund.Grimley-Evans@arm.com                         u, rounding, &flags);
479510037SARM gem5 Developers    }
479610037SARM gem5 Developers
479710037SARM gem5 Developers    set_fpscr0(fpscr, flags);
479810037SARM gem5 Developers
479910037SARM gem5 Developers    return result;
480010037SARM gem5 Developers}
480110037SARM gem5 Developers
480210037SARM gem5 Developerstemplate <>
480310037SARM gem5 Developersuint64_t
480410037SARM gem5 DevelopersfplibFPToFixed(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
480510037SARM gem5 Developers{
480610037SARM gem5 Developers    int flags = 0;
480710037SARM gem5 Developers    int sgn, exp;
480810037SARM gem5 Developers    uint64_t mnt, result;
480910037SARM gem5 Developers
481010037SARM gem5 Developers    // Unpack using FPCR to determine if subnormals are flushed-to-zero:
481110037SARM gem5 Developers    fp64_unpack(&sgn, &exp, &mnt, op, modeConv(fpscr), &flags);
481210037SARM gem5 Developers
481310037SARM gem5 Developers    // If NaN, set cumulative flag or take exception:
481413118SEdmund.Grimley-Evans@arm.com    if (fp64_is_NaN(exp, mnt)) {
481510037SARM gem5 Developers        flags = FPLIB_IOC;
481610037SARM gem5 Developers        result = 0;
481710037SARM gem5 Developers    } else {
481813118SEdmund.Grimley-Evans@arm.com        assert(fbits >= 0);
481913118SEdmund.Grimley-Evans@arm.com        // Infinity is treated as an ordinary normalised number that saturates.
482010037SARM gem5 Developers        result = FPToFixed_64(sgn, exp + fbits, mnt, u, rounding, &flags);
482110037SARM gem5 Developers    }
482210037SARM gem5 Developers
482310037SARM gem5 Developers    set_fpscr0(fpscr, flags);
482410037SARM gem5 Developers
482510037SARM gem5 Developers    return result;
482610037SARM gem5 Developers}
482710037SARM gem5 Developers
482813118SEdmund.Grimley-Evans@arm.comstatic uint16_t
482913118SEdmund.Grimley-Evans@arm.comfp16_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
483013118SEdmund.Grimley-Evans@arm.com{
483113118SEdmund.Grimley-Evans@arm.com    int x_sgn = !u && a >> (FP64_BITS - 1);
483213118SEdmund.Grimley-Evans@arm.com    int x_exp = FP16_EXP_BIAS + FP64_BITS - 1 - fbits;
483313118SEdmund.Grimley-Evans@arm.com    uint64_t x_mnt = x_sgn ? -a : a;
483413118SEdmund.Grimley-Evans@arm.com
483513118SEdmund.Grimley-Evans@arm.com    // Handle zero:
483613118SEdmund.Grimley-Evans@arm.com    if (!x_mnt) {
483713118SEdmund.Grimley-Evans@arm.com        return fp16_zero(0);
483813118SEdmund.Grimley-Evans@arm.com    }
483913118SEdmund.Grimley-Evans@arm.com
484013118SEdmund.Grimley-Evans@arm.com    // Normalise into FP16_BITS bits, collapsing error into bottom bit:
484113118SEdmund.Grimley-Evans@arm.com    x_mnt = fp64_normalise(x_mnt, &x_exp);
484213118SEdmund.Grimley-Evans@arm.com    x_mnt = (x_mnt >> (FP64_BITS - FP16_BITS - 1) |
484313118SEdmund.Grimley-Evans@arm.com             !!(x_mnt & ((1ULL << (FP64_BITS - FP16_BITS - 1)) - 1)));
484413118SEdmund.Grimley-Evans@arm.com
484513118SEdmund.Grimley-Evans@arm.com    return fp16_round(x_sgn, x_exp, x_mnt, mode, flags);
484613118SEdmund.Grimley-Evans@arm.com}
484713118SEdmund.Grimley-Evans@arm.com
484810037SARM gem5 Developersstatic uint32_t
484910037SARM gem5 Developersfp32_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
485010037SARM gem5 Developers{
485113118SEdmund.Grimley-Evans@arm.com    int x_sgn = !u && a >> (FP64_BITS - 1);
485213118SEdmund.Grimley-Evans@arm.com    int x_exp = FP32_EXP_BIAS + FP64_BITS - 1 - fbits;
485310037SARM gem5 Developers    uint64_t x_mnt = x_sgn ? -a : a;
485410037SARM gem5 Developers
485510037SARM gem5 Developers    // Handle zero:
485610037SARM gem5 Developers    if (!x_mnt) {
485710037SARM gem5 Developers        return fp32_zero(0);
485810037SARM gem5 Developers    }
485910037SARM gem5 Developers
486013118SEdmund.Grimley-Evans@arm.com    // Normalise into FP32_BITS bits, collapsing error into bottom bit:
486110037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
486213118SEdmund.Grimley-Evans@arm.com    x_mnt = (x_mnt >> (FP64_BITS - FP32_BITS - 1) |
486313118SEdmund.Grimley-Evans@arm.com             !!(x_mnt & ((1ULL << (FP64_BITS - FP32_BITS - 1)) - 1)));
486410037SARM gem5 Developers
486510037SARM gem5 Developers    return fp32_round(x_sgn, x_exp, x_mnt, mode, flags);
486610037SARM gem5 Developers}
486710037SARM gem5 Developers
486810037SARM gem5 Developersstatic uint64_t
486910037SARM gem5 Developersfp64_cvtf(uint64_t a, int fbits, int u, int mode, int *flags)
487010037SARM gem5 Developers{
487113118SEdmund.Grimley-Evans@arm.com    int x_sgn = !u && a >> (FP64_BITS - 1);
487213118SEdmund.Grimley-Evans@arm.com    int x_exp = FP64_EXP_BIAS + FP64_BITS - 1 - fbits;
487310037SARM gem5 Developers    uint64_t x_mnt = x_sgn ? -a : a;
487410037SARM gem5 Developers
487510037SARM gem5 Developers    // Handle zero:
487610037SARM gem5 Developers    if (!x_mnt) {
487710037SARM gem5 Developers        return fp64_zero(0);
487810037SARM gem5 Developers    }
487910037SARM gem5 Developers
488010037SARM gem5 Developers    x_mnt = fp64_normalise(x_mnt, &x_exp);
488110037SARM gem5 Developers
488210037SARM gem5 Developers    return fp64_round(x_sgn, x_exp, x_mnt << 1, mode, flags);
488310037SARM gem5 Developers}
488410037SARM gem5 Developers
488510037SARM gem5 Developerstemplate <>
488613118SEdmund.Grimley-Evans@arm.comuint16_t
488713118SEdmund.Grimley-Evans@arm.comfplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding,
488813118SEdmund.Grimley-Evans@arm.com               FPSCR &fpscr)
488913118SEdmund.Grimley-Evans@arm.com{
489013118SEdmund.Grimley-Evans@arm.com    int flags = 0;
489113118SEdmund.Grimley-Evans@arm.com    uint16_t res = fp16_cvtf(op, fbits, u,
489213118SEdmund.Grimley-Evans@arm.com                             (int)rounding | ((uint32_t)fpscr >> 22 & 12),
489313118SEdmund.Grimley-Evans@arm.com                             &flags);
489413118SEdmund.Grimley-Evans@arm.com    set_fpscr0(fpscr, flags);
489513118SEdmund.Grimley-Evans@arm.com    return res;
489613118SEdmund.Grimley-Evans@arm.com}
489713118SEdmund.Grimley-Evans@arm.com
489813118SEdmund.Grimley-Evans@arm.comtemplate <>
489910037SARM gem5 Developersuint32_t
490010037SARM gem5 DevelopersfplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
490110037SARM gem5 Developers{
490210037SARM gem5 Developers    int flags = 0;
490310037SARM gem5 Developers    uint32_t res = fp32_cvtf(op, fbits, u,
490410037SARM gem5 Developers                             (int)rounding | ((uint32_t)fpscr >> 22 & 12),
490510037SARM gem5 Developers                             &flags);
490610037SARM gem5 Developers    set_fpscr0(fpscr, flags);
490710037SARM gem5 Developers    return res;
490810037SARM gem5 Developers}
490910037SARM gem5 Developers
491010037SARM gem5 Developerstemplate <>
491110037SARM gem5 Developersuint64_t
491210037SARM gem5 DevelopersfplibFixedToFP(uint64_t op, int fbits, bool u, FPRounding rounding, FPSCR &fpscr)
491310037SARM gem5 Developers{
491410037SARM gem5 Developers    int flags = 0;
491510037SARM gem5 Developers    uint64_t res = fp64_cvtf(op, fbits, u,
491610037SARM gem5 Developers                             (int)rounding | ((uint32_t)fpscr >> 22 & 12),
491710037SARM gem5 Developers                             &flags);
491810037SARM gem5 Developers    set_fpscr0(fpscr, flags);
491910037SARM gem5 Developers    return res;
492010037SARM gem5 Developers}
492110037SARM gem5 Developers
492213118SEdmund.Grimley-Evans@arm.comtemplate <>
492313118SEdmund.Grimley-Evans@arm.comuint16_t
492413118SEdmund.Grimley-Evans@arm.comfplibInfinity(int sgn)
492513118SEdmund.Grimley-Evans@arm.com{
492613118SEdmund.Grimley-Evans@arm.com    return fp16_infinity(sgn);
492713118SEdmund.Grimley-Evans@arm.com}
492813118SEdmund.Grimley-Evans@arm.com
492913118SEdmund.Grimley-Evans@arm.comtemplate <>
493013118SEdmund.Grimley-Evans@arm.comuint32_t
493113118SEdmund.Grimley-Evans@arm.comfplibInfinity(int sgn)
493213118SEdmund.Grimley-Evans@arm.com{
493313118SEdmund.Grimley-Evans@arm.com    return fp32_infinity(sgn);
493413118SEdmund.Grimley-Evans@arm.com}
493513118SEdmund.Grimley-Evans@arm.com
493613118SEdmund.Grimley-Evans@arm.comtemplate <>
493713118SEdmund.Grimley-Evans@arm.comuint64_t
493813118SEdmund.Grimley-Evans@arm.comfplibInfinity(int sgn)
493913118SEdmund.Grimley-Evans@arm.com{
494013118SEdmund.Grimley-Evans@arm.com    return fp64_infinity(sgn);
494113118SEdmund.Grimley-Evans@arm.com}
494213118SEdmund.Grimley-Evans@arm.com
494313118SEdmund.Grimley-Evans@arm.comtemplate <>
494413118SEdmund.Grimley-Evans@arm.comuint16_t
494513118SEdmund.Grimley-Evans@arm.comfplibDefaultNaN()
494613118SEdmund.Grimley-Evans@arm.com{
494713118SEdmund.Grimley-Evans@arm.com    return fp16_defaultNaN();
494813118SEdmund.Grimley-Evans@arm.com}
494913118SEdmund.Grimley-Evans@arm.com
495013118SEdmund.Grimley-Evans@arm.comtemplate <>
495113118SEdmund.Grimley-Evans@arm.comuint32_t
495213118SEdmund.Grimley-Evans@arm.comfplibDefaultNaN()
495313118SEdmund.Grimley-Evans@arm.com{
495413118SEdmund.Grimley-Evans@arm.com    return fp32_defaultNaN();
495513118SEdmund.Grimley-Evans@arm.com}
495613118SEdmund.Grimley-Evans@arm.com
495713118SEdmund.Grimley-Evans@arm.comtemplate <>
495813118SEdmund.Grimley-Evans@arm.comuint64_t
495913118SEdmund.Grimley-Evans@arm.comfplibDefaultNaN()
496013118SEdmund.Grimley-Evans@arm.com{
496113118SEdmund.Grimley-Evans@arm.com    return fp64_defaultNaN();
496213118SEdmund.Grimley-Evans@arm.com}
496313118SEdmund.Grimley-Evans@arm.com
496413118SEdmund.Grimley-Evans@arm.com}
4965