You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
3.2KB

  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "libavutil/cpu.h"
  19. #include "libavutil/cpu_internal.h"
  20. #include "config.h"
  21. #if defined __linux__ || defined __ANDROID__
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <sys/auxv.h>
  26. #include "asmdefs.h"
  27. #include "libavutil/avstring.h"
  28. #endif
  29. #if defined __linux__ || defined __ANDROID__
  30. #define HWCAP_LOONGSON_CPUCFG (1 << 14)
  31. static int cpucfg_available(void)
  32. {
  33. return getauxval(AT_HWCAP) & HWCAP_LOONGSON_CPUCFG;
  34. }
  35. /* Most toolchains have no CPUCFG support yet */
  36. static uint32_t read_cpucfg(uint32_t reg)
  37. {
  38. uint32_t __res;
  39. __asm__ __volatile__(
  40. "parse_r __res,%0\n\t"
  41. "parse_r reg,%1\n\t"
  42. ".insn \n\t"
  43. ".word (0xc8080118 | (reg << 21) | (__res << 11))\n\t"
  44. :"=r"(__res)
  45. :"r"(reg)
  46. :
  47. );
  48. return __res;
  49. }
  50. #define LOONGSON_CFG1 0x1
  51. #define LOONGSON_CFG1_MMI (1 << 4)
  52. #define LOONGSON_CFG1_MSA1 (1 << 5)
  53. static int cpu_flags_cpucfg(void)
  54. {
  55. int flags = 0;
  56. uint32_t cfg1 = read_cpucfg(LOONGSON_CFG1);
  57. if (cfg1 & LOONGSON_CFG1_MMI)
  58. flags |= AV_CPU_FLAG_MMI;
  59. if (cfg1 & LOONGSON_CFG1_MSA1)
  60. flags |= AV_CPU_FLAG_MSA;
  61. return flags;
  62. }
  63. static int cpu_flags_cpuinfo(void)
  64. {
  65. FILE *f = fopen("/proc/cpuinfo", "r");
  66. char buf[200];
  67. int flags = 0;
  68. if (!f)
  69. return -1;
  70. while (fgets(buf, sizeof(buf), f)) {
  71. /* Legacy kernel may not export MMI in ASEs implemented */
  72. if (av_strstart(buf, "cpu model", NULL)) {
  73. if (strstr(buf, "Loongson-3 "))
  74. flags |= AV_CPU_FLAG_MMI;
  75. }
  76. if (av_strstart(buf, "ASEs implemented", NULL)) {
  77. if (strstr(buf, " loongson-mmi"))
  78. flags |= AV_CPU_FLAG_MMI;
  79. if (strstr(buf, " msa"))
  80. flags |= AV_CPU_FLAG_MSA;
  81. break;
  82. }
  83. }
  84. fclose(f);
  85. return flags;
  86. }
  87. #endif
  88. int ff_get_cpu_flags_mips(void)
  89. {
  90. #if defined __linux__ || defined __ANDROID__
  91. if (cpucfg_available())
  92. return cpu_flags_cpucfg();
  93. else
  94. return cpu_flags_cpuinfo();
  95. #else
  96. /* Assume no SIMD ASE supported */
  97. return 0;
  98. #endif
  99. }
  100. size_t ff_get_cpu_max_align_mips(void)
  101. {
  102. int flags = av_get_cpu_flags();
  103. if (flags & AV_CPU_FLAG_MSA)
  104. return 16;
  105. /*
  106. * MMI itself is 64-bit but quad word load & store
  107. * needs 128-bit align.
  108. */
  109. if (flags & AV_CPU_FLAG_MMI)
  110. return 16;
  111. return 8;
  112. }