Skip to content

Commit

Permalink
mips: improve FPU detection also for MIPS64 (zherczeg#205)
Browse files Browse the repository at this point in the history
The original check relies on a feature not implemented until r2
so extend the previous fix for MIPS32 to correct detection in
MIPS64.

Redefine the value from SLJIT_IS_FPU_AVAILABLE to indicate the
register width if enabled.

While at it, make sure all feature flags are always accurate.
  • Loading branch information
carenas committed Sep 20, 2023
1 parent 6d1376f commit ff4c772
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 60 deletions.
4 changes: 2 additions & 2 deletions sljit_src/sljitNativeARM_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_FPU:
case SLJIT_HAS_F64_AS_F32_PAIR:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand All @@ -1015,7 +1015,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
return 0;
#else
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativeARM_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_FPU:
case SLJIT_HAS_SIMD:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativeARM_T2_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
case SLJIT_HAS_F64_AS_F32_PAIR:
case SLJIT_HAS_SIMD:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativeLOONGARCH_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
{
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand Down
90 changes: 38 additions & 52 deletions sljit_src/sljitNativeMIPS_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,8 +367,8 @@ static const sljit_u8 freg_map[SLJIT_NUMBER_OF_FLOAT_REGISTERS + 4] = {
#define UIMM_MAX (0xffff)

#define CPU_FEATURE_DETECTED (1 << 0)
#define CPU_FEATURE_FP32 (1 << 1)
#define CPU_FEATURE_FPU (1 << 2)
#define CPU_FEATURE_FPU (1 << 1)
#define CPU_FEATURE_FP64 (1 << 2)
#define CPU_FEATURE_FR (1 << 3)

static sljit_u32 cpu_feature_list = 0;
Expand All @@ -390,72 +390,75 @@ static sljit_s32 function_check_is_freg(struct sljit_compiler *compiler, sljit_s

#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_ARGUMENT_CHECKS */

#if !defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE
static void get_cpu_features(void)
{
#if defined(__GNUC__)
#if !defined(SLJIT_IS_FPU_AVAILABLE) && defined(__GNUC__)
sljit_u32 fir = 0;
#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
#if (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1) \
&& (!defined(SLJIT_MIPS_REV) || (defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV < 6))
sljit_s32 flag = -1;
#endif
#endif /* SLJIT_CONFIG_MIPS_32 */
#endif /* __GNUC__ */
#endif /* !SLJIT_IS_FPU_AVAILABLE && __GNUC__ */
sljit_u32 feature_list = CPU_FEATURE_DETECTED;

#if defined(__GNUC__) || !defined(SLJIT_IS_FPU_AVAILABLE)
#if defined(SLJIT_IS_FPU_AVAILABLE)
#if SLJIT_IS_FPU_AVAILABLE
feature_list |= CPU_FEATURE_FPU;
#if SLJIT_IS_FPU_AVAILABLE == 64
feature_list |= CPU_FEATURE_FP64;
#endif /* SLJIT_IS_FPU_AVAILABLE == 64 */
#endif /* SLJIT_IS_FPU_AVAILABLE */
#elif defined(__GNUC__)
__asm__ ("cfc1 %0, $0" : "=r"(fir));
if ((fir & (1 << 22)))
if ((fir & (0x3 << 16)) == (0x3 << 16))
feature_list |= CPU_FEATURE_FPU;
#else /* SLJIT_IS_FPU_AVAILABLE */
feature_list |= CPU_FEATURE_FPU;
#endif

if (!(feature_list & CPU_FEATURE_FPU) && (fir & (1 << 17)) && (fir & (1 << 21)))
feature_list |= CPU_FEATURE_FP32;
#if (defined(SLJIT_CONFIG_MIPS_64) && SLJIT_CONFIG_MIPS_64) \
&& (!defined(SLJIT_MIPS_REV) || SLJIT_MIPS_REV < 2)
if ((feature_list & CPU_FEATURE_FPU))
feature_list |= CPU_FEATURE_FP64;
#else /* SLJIT_CONFIG_MIPS32 || SLJIT_MIPS_REV >= 2 */
if ((fir & (1 << 22)))
feature_list |= CPU_FEATURE_FP64;
#endif /* SLJIT_CONFIG_MIPS_64 && SLJIT_MIPS_REV < 2 */
#endif /* SLJIT_IS_FPU_AVAILABLE */

if ((feature_list & CPU_FEATURE_FPU) && (feature_list & CPU_FEATURE_FP64)) {
#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
if ((feature_list & CPU_FEATURE_FPU) && (!(feature_list & CPU_FEATURE_FP32))) {
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 6
feature_list |= CPU_FEATURE_FR;
#elif defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 0
#if defined(SLJIT_MIPS_REV) && SLJIT_MIPS_REV >= 5
feature_list |= CPU_FEATURE_FR;
#endif /* SLJIT_MIPS_REV >= 5 */
#else
#ifdef PR_GET_FP_MODE
sljit_s32 flag = -1;
#ifndef FR_GET_FP_MODE
sljit_f64 zero = 0.0;
#else /* PR_GET_FP_MODE */
flag = prctl(PR_GET_FP_MODE);

if (flag > 0)
feature_list |= CPU_FEATURE_FR;
#endif /* FP_GET_PR_MODE */
#if ((defined(SLJIT_DETECT_FR) && SLJIT_DETECT_FR == 2) \
|| (!defined(PR_GET_FP_MODE) && (!defined(SLJIT_DETECT_FR) || SLJIT_DETECT_FR >= 1))) \
&& (defined(__GNUC__) && (defined(__mips) && __mips >= 2))
if (flag < 0) {
SLJIT_ASSERT(freg_map[TMP_FREG3] == 16);
__asm__ (
".data\n"
"0:\n"
" .quad 0\n"
".text\n"
".set oddspreg\n"
" mtc1 %0, $f17\n"
" ldc1 $f16, 0b\n"
" nop\n"
" mfc1 %0, $f17\n"
: "+r" (flag) : : "$f16", "$f17");
__asm__ (".set oddspreg\n"
"lwc1 $f17, %0\n"
"ldc1 $f16, %1\n"
"swc1 $f17, %0\n"
: "+m" (flag) : "m" (zero) : "$f16", "$f17");
if (flag)
feature_list |= CPU_FEATURE_FR;
}
#endif /* (!PR_GET_FP_MODE || (PR_GET_FP_MODE && SLJIT_DETECT_FR == 2)) && __GNUC__ */
#endif /* SLJIT_MIPS_REV >= 6 */
}
#else /* !SLJIT_CONFIG_MIPS_32 */
/* StatusFR=1 is the only mode supported by the code in MIPS64 */
feature_list |= CPU_FEATURE_FR;
#endif /* SLJIT_CONFIG_MIPS_32 */
}

cpu_feature_list = feature_list;
}
#endif /* SLJIT_IS_FPU_AVAILABLE */

/* dest_reg is the absolute name of the register
Useful for reordering instructions in the delay slot. */
Expand Down Expand Up @@ -850,10 +853,6 @@ SLJIT_API_FUNC_ATTRIBUTE void* sljit_generate_code(struct sljit_compiler *compil

SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
{
#ifndef SLJIT_IS_FPU_AVAILABLE
sljit_s32 fpu_is_valid;
#endif

switch (feature_type) {
#if (defined SLJIT_CONFIG_MIPS_32 && SLJIT_CONFIG_MIPS_32) \
&& (!defined(SLJIT_IS_FPU_AVAILABLE) || SLJIT_IS_FPU_AVAILABLE)
Expand All @@ -864,23 +863,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
return (cpu_feature_list & CPU_FEATURE_FR) != 0;
#endif /* SLJIT_CONFIG_MIPS_32 && SLJIT_IS_FPU_AVAILABLE */
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
#if SLJIT_IS_FPU_AVAILABLE
if (!cpu_feature_list)
get_cpu_features();
#endif /* SLJIT_IS_FPU_AVAILABLE */
return SLJIT_IS_FPU_AVAILABLE;
#else
if (!cpu_feature_list)
get_cpu_features();

fpu_is_valid = (cpu_feature_list & CPU_FEATURE_FPU) != 0;
#if defined(SLJIT_CONFIG_MIPS_32) && SLJIT_CONFIG_MIPS_32
if (!fpu_is_valid)
fpu_is_valid = (cpu_feature_list & CPU_FEATURE_FP32) != 0;
#endif /* SLJIT_CONFIG_MIPS_32 */
return fpu_is_valid;
#endif /* SLJIT_IS_FPU_AVAILABLE */
return (cpu_feature_list & CPU_FEATURE_FPU) != 0;
case SLJIT_HAS_ZERO_REGISTER:
case SLJIT_HAS_COPY_F32:
case SLJIT_HAS_COPY_F64:
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativePPC_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
switch (feature_type) {
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
/* Available by default. */
return 1;
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativeRISCV_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
switch (feature_type) {
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#elif defined(__riscv_float_abi_soft)
return 0;
#else
Expand Down
8 changes: 8 additions & 0 deletions sljit_src/sljitNativeS390X.c
Original file line number Diff line number Diff line change
Expand Up @@ -1663,15 +1663,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
/* TODO(mundaym): implement all */
switch (feature_type) {
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#else
return 1;
#endif /* SLJIT_IS_FPU_AVAILABLE */

case SLJIT_HAS_CLZ:
case SLJIT_HAS_REV:
case SLJIT_HAS_ROT:
case SLJIT_HAS_PREFETCH:
case SLJIT_HAS_COPY_F32:
case SLJIT_HAS_COPY_F64:
return 1;

case SLJIT_HAS_CTZ:
return 2;

case SLJIT_HAS_CMOV:
return have_lscond1() ? 1 : 0;
}
Expand Down
2 changes: 1 addition & 1 deletion sljit_src/sljitNativeX86_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -800,7 +800,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_s32 sljit_has_cpu_feature(sljit_s32 feature_type)
switch (feature_type) {
case SLJIT_HAS_FPU:
#ifdef SLJIT_IS_FPU_AVAILABLE
return SLJIT_IS_FPU_AVAILABLE;
return (SLJIT_IS_FPU_AVAILABLE) != 0;
#elif (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2)
if (cpu_feature_list == 0)
get_cpu_features();
Expand Down

0 comments on commit ff4c772

Please sign in to comment.