xref: /llvm-project/compiler-rt/lib/builtins/loongarch/fp_mode.c (revision 2b15c63fb73011610ae83c05d0260e2dccf299fc)
16e6704b0SYouling Tang //=== lib/builtins/loongarch/fp_mode.c - Floaing-point mode utilities -*- C -*-===//
26e6704b0SYouling Tang //
36e6704b0SYouling Tang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46e6704b0SYouling Tang // See https://llvm.org/LICENSE.txt for license information.
56e6704b0SYouling Tang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66e6704b0SYouling Tang //
76e6704b0SYouling Tang //===----------------------------------------------------------------------===//
86e6704b0SYouling Tang #include "../fp_mode.h"
96e6704b0SYouling Tang 
106e6704b0SYouling Tang #define LOONGARCH_TONEAREST  0x0000
116e6704b0SYouling Tang #define LOONGARCH_TOWARDZERO 0x0100
126e6704b0SYouling Tang #define LOONGARCH_UPWARD     0x0200
136e6704b0SYouling Tang #define LOONGARCH_DOWNWARD   0x0300
146e6704b0SYouling Tang 
156e6704b0SYouling Tang #define LOONGARCH_RMODE_MASK (LOONGARCH_TONEAREST | LOONGARCH_TOWARDZERO | \
166e6704b0SYouling Tang                               LOONGARCH_UPWARD | LOONGARCH_DOWNWARD)
176e6704b0SYouling Tang 
186e6704b0SYouling Tang #define LOONGARCH_INEXACT    0x10000
196e6704b0SYouling Tang 
__fe_getround(void)206e6704b0SYouling Tang CRT_FE_ROUND_MODE __fe_getround(void) {
216e6704b0SYouling Tang #if __loongarch_frlen != 0
226e6704b0SYouling Tang   int fcsr;
23*2b15c63fSYouling Tang #  ifdef __clang__
246e6704b0SYouling Tang   __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr));
25*2b15c63fSYouling Tang #  else
26*2b15c63fSYouling Tang   __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr));
27*2b15c63fSYouling Tang #  endif
286e6704b0SYouling Tang   fcsr &= LOONGARCH_RMODE_MASK;
296e6704b0SYouling Tang   switch (fcsr) {
306e6704b0SYouling Tang   case LOONGARCH_TOWARDZERO:
316e6704b0SYouling Tang     return CRT_FE_TOWARDZERO;
326e6704b0SYouling Tang   case LOONGARCH_DOWNWARD:
336e6704b0SYouling Tang     return CRT_FE_DOWNWARD;
346e6704b0SYouling Tang   case LOONGARCH_UPWARD:
356e6704b0SYouling Tang     return CRT_FE_UPWARD;
366e6704b0SYouling Tang   case LOONGARCH_TONEAREST:
376e6704b0SYouling Tang   default:
386e6704b0SYouling Tang     return CRT_FE_TONEAREST;
396e6704b0SYouling Tang   }
406e6704b0SYouling Tang #else
416e6704b0SYouling Tang   return CRT_FE_TONEAREST;
426e6704b0SYouling Tang #endif
436e6704b0SYouling Tang }
446e6704b0SYouling Tang 
__fe_raise_inexact(void)456e6704b0SYouling Tang int __fe_raise_inexact(void) {
466e6704b0SYouling Tang #if __loongarch_frlen != 0
476e6704b0SYouling Tang   int fcsr;
48*2b15c63fSYouling Tang #  ifdef __clang__
496e6704b0SYouling Tang   __asm__ __volatile__("movfcsr2gr %0, $fcsr0" : "=r" (fcsr));
506e6704b0SYouling Tang   __asm__ __volatile__(
516e6704b0SYouling Tang       "movgr2fcsr $fcsr0, %0" :: "r" (fcsr | LOONGARCH_INEXACT));
52*2b15c63fSYouling Tang #  else
53*2b15c63fSYouling Tang   __asm__ __volatile__("movfcsr2gr %0, $r0" : "=r" (fcsr));
54*2b15c63fSYouling Tang   __asm__ __volatile__(
55*2b15c63fSYouling Tang       "movgr2fcsr $r0, %0" :: "r" (fcsr | LOONGARCH_INEXACT));
56*2b15c63fSYouling Tang #  endif
576e6704b0SYouling Tang #endif
586e6704b0SYouling Tang   return 0;
596e6704b0SYouling Tang }
60