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