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