xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/loongarch/fp_mode.c (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1*bdd1243dSDimitry Andric //=== lib/builtins/loongarch/fp_mode.c - Floaing-point mode utilities -*- C -*-===//
2*bdd1243dSDimitry Andric //
3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*bdd1243dSDimitry Andric //
7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8*bdd1243dSDimitry Andric #include "../fp_mode.h"
9*bdd1243dSDimitry Andric 
10*bdd1243dSDimitry Andric #define LOONGARCH_TONEAREST  0x0000
11*bdd1243dSDimitry Andric #define LOONGARCH_TOWARDZERO 0x0100
12*bdd1243dSDimitry Andric #define LOONGARCH_UPWARD     0x0200
13*bdd1243dSDimitry Andric #define LOONGARCH_DOWNWARD   0x0300
14*bdd1243dSDimitry Andric 
15*bdd1243dSDimitry Andric #define LOONGARCH_RMODE_MASK (LOONGARCH_TONEAREST | LOONGARCH_TOWARDZERO | \
16*bdd1243dSDimitry Andric                               LOONGARCH_UPWARD | LOONGARCH_DOWNWARD)
17*bdd1243dSDimitry Andric 
18*bdd1243dSDimitry Andric #define LOONGARCH_INEXACT    0x10000
19*bdd1243dSDimitry Andric 
__fe_getround(void)20*bdd1243dSDimitry Andric CRT_FE_ROUND_MODE __fe_getround(void) {
21*bdd1243dSDimitry Andric #if __loongarch_frlen != 0
22*bdd1243dSDimitry Andric   int fcsr;
23*bdd1243dSDimitry Andric #  ifdef __clang__
24*bdd1243dSDimitry Andric   __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr));
25*bdd1243dSDimitry Andric #  else
26*bdd1243dSDimitry Andric   __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr));
27*bdd1243dSDimitry Andric #  endif
28*bdd1243dSDimitry Andric   fcsr &= LOONGARCH_RMODE_MASK;
29*bdd1243dSDimitry Andric   switch (fcsr) {
30*bdd1243dSDimitry Andric   case LOONGARCH_TOWARDZERO:
31*bdd1243dSDimitry Andric     return CRT_FE_TOWARDZERO;
32*bdd1243dSDimitry Andric   case LOONGARCH_DOWNWARD:
33*bdd1243dSDimitry Andric     return CRT_FE_DOWNWARD;
34*bdd1243dSDimitry Andric   case LOONGARCH_UPWARD:
35*bdd1243dSDimitry Andric     return CRT_FE_UPWARD;
36*bdd1243dSDimitry Andric   case LOONGARCH_TONEAREST:
37*bdd1243dSDimitry Andric   default:
38*bdd1243dSDimitry Andric     return CRT_FE_TONEAREST;
39*bdd1243dSDimitry Andric   }
40*bdd1243dSDimitry Andric #else
41*bdd1243dSDimitry Andric   return CRT_FE_TONEAREST;
42*bdd1243dSDimitry Andric #endif
43*bdd1243dSDimitry Andric }
44*bdd1243dSDimitry Andric 
__fe_raise_inexact(void)45*bdd1243dSDimitry Andric int __fe_raise_inexact(void) {
46*bdd1243dSDimitry Andric #if __loongarch_frlen != 0
47*bdd1243dSDimitry Andric   int fcsr;
48*bdd1243dSDimitry Andric #  ifdef __clang__
49*bdd1243dSDimitry Andric   __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr));
50*bdd1243dSDimitry Andric   __asm__ __volatile__(
51*bdd1243dSDimitry Andric       "movgr2fcsr $fcsr0, %0" :: "r" (fcsr | LOONGARCH_INEXACT));
52*bdd1243dSDimitry Andric #  else
53*bdd1243dSDimitry Andric   __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr));
54*bdd1243dSDimitry Andric   __asm__ __volatile__(
55*bdd1243dSDimitry Andric       "movgr2fcsr $r0, %0" :: "r" (fcsr | LOONGARCH_INEXACT));
56*bdd1243dSDimitry Andric #  endif
57*bdd1243dSDimitry Andric #endif
58*bdd1243dSDimitry Andric   return 0;
59*bdd1243dSDimitry Andric }
60