CMakeLists.txt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. macro(simd_fail message)
  2. if(REQUIRE_SIMD)
  3. message(FATAL_ERROR "${message}.")
  4. else()
  5. message(WARNING "${message}. Performance will suffer.")
  6. set(WITH_SIMD 0 PARENT_SCOPE)
  7. endif()
  8. endmacro()
  9. ###############################################################################
  10. # x86[-64] (NASM)
  11. ###############################################################################
  12. if(CPU_TYPE STREQUAL "x86_64" OR CPU_TYPE STREQUAL "i386")
  13. set(CMAKE_ASM_NASM_FLAGS_DEBUG_INIT "-g")
  14. set(CMAKE_ASM_NASM_FLAGS_RELWITHDEBINFO_INIT "-g")
  15. # Allow the location of the NASM executable to be specified using the ASM_NASM
  16. # environment variable. This should happen automatically, but unfortunately
  17. # enable_language(ASM_NASM) doesn't parse the ASM_NASM environment variable
  18. # until after CMAKE_ASM_NASM_COMPILER has been populated with the results of
  19. # searching for NASM or YASM in the PATH.
  20. if(NOT DEFINED CMAKE_ASM_NASM_COMPILER AND DEFINED ENV{ASM_NASM})
  21. set(CMAKE_ASM_NASM_COMPILER $ENV{ASM_NASM})
  22. endif()
  23. if(CPU_TYPE STREQUAL "x86_64")
  24. if(CYGWIN)
  25. set(CMAKE_ASM_NASM_OBJECT_FORMAT win64)
  26. endif()
  27. elseif(CPU_TYPE STREQUAL "i386")
  28. if(BORLAND)
  29. set(CMAKE_ASM_NASM_OBJECT_FORMAT obj)
  30. elseif(CYGWIN)
  31. set(CMAKE_ASM_NASM_OBJECT_FORMAT win32)
  32. endif()
  33. endif()
  34. if(NOT REQUIRE_SIMD)
  35. include(CheckLanguage)
  36. check_language(ASM_NASM)
  37. if(NOT CMAKE_ASM_NASM_COMPILER)
  38. simd_fail("SIMD extensions disabled: could not find NASM compiler")
  39. return()
  40. endif()
  41. endif()
  42. enable_language(ASM_NASM)
  43. message(STATUS "CMAKE_ASM_NASM_COMPILER = ${CMAKE_ASM_NASM_COMPILER}")
  44. if(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "macho*")
  45. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DMACHO")
  46. elseif(CMAKE_ASM_NASM_OBJECT_FORMAT MATCHES "elf*")
  47. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DELF")
  48. set(CMAKE_ASM_NASM_DEBUG_FORMAT "dwarf2")
  49. endif()
  50. if(CPU_TYPE STREQUAL "x86_64")
  51. if(WIN32 OR CYGWIN)
  52. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DWIN64")
  53. endif()
  54. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -D__x86_64__")
  55. elseif(CPU_TYPE STREQUAL "i386")
  56. if(BORLAND)
  57. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DOBJ32")
  58. elseif(WIN32 OR CYGWIN)
  59. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DWIN32")
  60. endif()
  61. endif()
  62. message(STATUS "CMAKE_ASM_NASM_OBJECT_FORMAT = ${CMAKE_ASM_NASM_OBJECT_FORMAT}")
  63. if(NOT CMAKE_ASM_NASM_OBJECT_FORMAT)
  64. simd_fail("SIMD extensions disabled: could not determine NASM object format")
  65. return()
  66. endif()
  67. get_filename_component(CMAKE_ASM_NASM_COMPILER_TYPE
  68. "${CMAKE_ASM_NASM_COMPILER}" NAME_WE)
  69. if(CMAKE_ASM_NASM_COMPILER_TYPE MATCHES "yasm")
  70. foreach(var CMAKE_ASM_NASM_FLAGS_DEBUG CMAKE_ASM_NASM_FLAGS_RELWITHDEBINFO)
  71. if(${var} STREQUAL "-g")
  72. if(CMAKE_ASM_NASM_DEBUG_FORMAT)
  73. set_property(CACHE ${var} PROPERTY VALUE "-g ${CMAKE_ASM_NASM_DEBUG_FORMAT}")
  74. else()
  75. set_property(CACHE ${var} PROPERTY VALUE "")
  76. endif()
  77. endif()
  78. endforeach()
  79. endif()
  80. if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED))
  81. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -DPIC")
  82. endif()
  83. string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
  84. set(EFFECTIVE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} ${CMAKE_ASM_NASM_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
  85. message(STATUS "CMAKE_ASM_NASM_FLAGS = ${EFFECTIVE_ASM_NASM_FLAGS}")
  86. set(CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS} -I\"${CMAKE_CURRENT_SOURCE_DIR}/nasm/\" -I\"${CMAKE_CURRENT_SOURCE_DIR}/${CPU_TYPE}/\"")
  87. set(GREP grep)
  88. if(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
  89. set(GREP ggrep)
  90. endif()
  91. add_custom_target(jsimdcfg COMMAND
  92. ${CMAKE_C_COMPILER} -E -I${CMAKE_BINARY_DIR} -I${CMAKE_CURRENT_BINARY_DIR}
  93. -I${CMAKE_CURRENT_SOURCE_DIR}
  94. ${CMAKE_CURRENT_SOURCE_DIR}/nasm/jsimdcfg.inc.h |
  95. ${GREP} -E '^[\;%]|^\ %' | sed 's%_cpp_protection_%%' |
  96. sed 's@% define@%define@g' >${CMAKE_CURRENT_SOURCE_DIR}/nasm/jsimdcfg.inc)
  97. if(CPU_TYPE STREQUAL "x86_64")
  98. set(SIMD_SOURCES x86_64/jsimdcpu.asm x86_64/jfdctflt-sse.asm
  99. x86_64/jccolor-sse2.asm x86_64/jcgray-sse2.asm x86_64/jchuff-sse2.asm
  100. x86_64/jcphuff-sse2.asm x86_64/jcsample-sse2.asm x86_64/jdcolor-sse2.asm
  101. x86_64/jdmerge-sse2.asm x86_64/jdsample-sse2.asm x86_64/jfdctfst-sse2.asm
  102. x86_64/jfdctint-sse2.asm x86_64/jidctflt-sse2.asm x86_64/jidctfst-sse2.asm
  103. x86_64/jidctint-sse2.asm x86_64/jidctred-sse2.asm x86_64/jquantf-sse2.asm
  104. x86_64/jquanti-sse2.asm
  105. x86_64/jccolor-avx2.asm x86_64/jcgray-avx2.asm x86_64/jcsample-avx2.asm
  106. x86_64/jdcolor-avx2.asm x86_64/jdmerge-avx2.asm x86_64/jdsample-avx2.asm
  107. x86_64/jfdctint-avx2.asm x86_64/jidctint-avx2.asm x86_64/jquanti-avx2.asm)
  108. else()
  109. set(SIMD_SOURCES i386/jsimdcpu.asm i386/jfdctflt-3dn.asm
  110. i386/jidctflt-3dn.asm i386/jquant-3dn.asm
  111. i386/jccolor-mmx.asm i386/jcgray-mmx.asm i386/jcsample-mmx.asm
  112. i386/jdcolor-mmx.asm i386/jdmerge-mmx.asm i386/jdsample-mmx.asm
  113. i386/jfdctfst-mmx.asm i386/jfdctint-mmx.asm i386/jidctfst-mmx.asm
  114. i386/jidctint-mmx.asm i386/jidctred-mmx.asm i386/jquant-mmx.asm
  115. i386/jfdctflt-sse.asm i386/jidctflt-sse.asm i386/jquant-sse.asm
  116. i386/jccolor-sse2.asm i386/jcgray-sse2.asm i386/jchuff-sse2.asm
  117. i386/jcphuff-sse2.asm i386/jcsample-sse2.asm i386/jdcolor-sse2.asm
  118. i386/jdmerge-sse2.asm i386/jdsample-sse2.asm i386/jfdctfst-sse2.asm
  119. i386/jfdctint-sse2.asm i386/jidctflt-sse2.asm i386/jidctfst-sse2.asm
  120. i386/jidctint-sse2.asm i386/jidctred-sse2.asm i386/jquantf-sse2.asm
  121. i386/jquanti-sse2.asm
  122. i386/jccolor-avx2.asm i386/jcgray-avx2.asm i386/jcsample-avx2.asm
  123. i386/jdcolor-avx2.asm i386/jdmerge-avx2.asm i386/jdsample-avx2.asm
  124. i386/jfdctint-avx2.asm i386/jidctint-avx2.asm i386/jquanti-avx2.asm)
  125. endif()
  126. if(MSVC_IDE)
  127. set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
  128. string(REGEX REPLACE " " ";" CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS}")
  129. elseif(XCODE)
  130. set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}")
  131. string(REGEX REPLACE " " ";" CMAKE_ASM_NASM_FLAGS "${CMAKE_ASM_NASM_FLAGS}")
  132. endif()
  133. file(GLOB INC_FILES nasm/*.inc)
  134. foreach(file ${SIMD_SOURCES})
  135. set(OBJECT_DEPENDS "")
  136. if(${file} MATCHES jccolor)
  137. string(REGEX REPLACE "jccolor" "jccolext" DEPFILE ${file})
  138. set(OBJECT_DEPENDS ${OBJECT_DEPENDS}
  139. ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE})
  140. endif()
  141. if(${file} MATCHES jcgray)
  142. string(REGEX REPLACE "jcgray" "jcgryext" DEPFILE ${file})
  143. set(OBJECT_DEPENDS ${OBJECT_DEPENDS}
  144. ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE})
  145. endif()
  146. if(${file} MATCHES jdcolor)
  147. string(REGEX REPLACE "jdcolor" "jdcolext" DEPFILE ${file})
  148. set(OBJECT_DEPENDS ${OBJECT_DEPENDS}
  149. ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE})
  150. endif()
  151. if(${file} MATCHES jdmerge)
  152. string(REGEX REPLACE "jdmerge" "jdmrgext" DEPFILE ${file})
  153. set(OBJECT_DEPENDS ${OBJECT_DEPENDS}
  154. ${CMAKE_CURRENT_SOURCE_DIR}/${DEPFILE})
  155. endif()
  156. set(OBJECT_DEPENDS ${OBJECT_DEPENDS} ${INC_FILES})
  157. if(MSVC_IDE OR XCODE)
  158. # The CMake Visual Studio generators do not work properly with the ASM_NASM
  159. # language, so we have to go rogue here and use a custom command like we
  160. # did in prior versions of libjpeg-turbo. (This is why we can't have nice
  161. # things.)
  162. string(REGEX REPLACE "${CPU_TYPE}/" "" filename ${file})
  163. set(SIMD_OBJ ${OBJDIR}/${filename}${CMAKE_C_OUTPUT_EXTENSION})
  164. add_custom_command(OUTPUT ${SIMD_OBJ} DEPENDS ${file} ${OBJECT_DEPENDS}
  165. COMMAND ${CMAKE_ASM_NASM_COMPILER} -f${CMAKE_ASM_NASM_OBJECT_FORMAT}
  166. ${CMAKE_ASM_NASM_FLAGS} ${CMAKE_CURRENT_SOURCE_DIR}/${file}
  167. -o${SIMD_OBJ})
  168. set(SIMD_OBJS ${SIMD_OBJS} ${SIMD_OBJ})
  169. else()
  170. set_source_files_properties(${file} PROPERTIES OBJECT_DEPENDS
  171. "${OBJECT_DEPENDS}")
  172. endif()
  173. endforeach()
  174. if(MSVC_IDE OR XCODE)
  175. set(SIMD_OBJS ${SIMD_OBJS} PARENT_SCOPE)
  176. add_library(simd OBJECT ${CPU_TYPE}/jsimd.c)
  177. add_custom_target(simd-objs DEPENDS ${SIMD_OBJS})
  178. add_dependencies(simd simd-objs)
  179. else()
  180. add_library(simd OBJECT ${SIMD_SOURCES} ${CPU_TYPE}/jsimd.c)
  181. endif()
  182. if(NOT WIN32 AND (CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED))
  183. set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
  184. endif()
  185. ###############################################################################
  186. # ARM (GAS)
  187. ###############################################################################
  188. elseif(CPU_TYPE STREQUAL "arm64" OR CPU_TYPE STREQUAL "arm")
  189. enable_language(ASM)
  190. set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ASM_FLAGS}")
  191. string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
  192. set(EFFECTIVE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${CMAKE_ASM_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
  193. message(STATUS "CMAKE_ASM_FLAGS = ${EFFECTIVE_ASM_FLAGS}")
  194. # Test whether we need gas-preprocessor.pl
  195. if(CPU_TYPE STREQUAL "arm")
  196. file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/gastest.S "
  197. .text
  198. .fpu neon
  199. .arch armv7a
  200. .object_arch armv4
  201. .arm
  202. pld [r0]
  203. vmovn.u16 d0, q0")
  204. else()
  205. file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/gastest.S "
  206. .text
  207. MYVAR .req x0
  208. movi v0.16b, #100
  209. mov MYVAR, #100
  210. .unreq MYVAR")
  211. endif()
  212. separate_arguments(CMAKE_ASM_FLAGS_SEP UNIX_COMMAND "${CMAKE_ASM_FLAGS}")
  213. execute_process(COMMAND ${CMAKE_ASM_COMPILER} ${CMAKE_ASM_FLAGS_SEP}
  214. -x assembler-with-cpp -c ${CMAKE_CURRENT_BINARY_DIR}/gastest.S
  215. RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)
  216. if(NOT RESULT EQUAL 0)
  217. message(STATUS "GAS appears to be broken. Trying gas-preprocessor.pl ...")
  218. execute_process(COMMAND gas-preprocessor.pl ${CMAKE_ASM_COMPILER}
  219. ${CMAKE_ASM_FLAGS_SEP} -x assembler-with-cpp -c
  220. ${CMAKE_CURRENT_BINARY_DIR}/gastest.S
  221. RESULT_VARIABLE RESULT OUTPUT_VARIABLE OUTPUT ERROR_VARIABLE ERROR)
  222. if(NOT RESULT EQUAL 0)
  223. simd_fail("SIMD extensions disabled: GAS is not working properly")
  224. return()
  225. else()
  226. message(STATUS "Using gas-preprocessor.pl")
  227. configure_file(gas-preprocessor.in gas-preprocessor @ONLY)
  228. set(CMAKE_ASM_COMPILER ${CMAKE_CURRENT_BINARY_DIR}/gas-preprocessor)
  229. endif()
  230. else()
  231. message(STATUS "GAS is working properly")
  232. endif()
  233. file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/gastest.S)
  234. add_library(simd OBJECT ${CPU_TYPE}/jsimd_neon.S ${CPU_TYPE}/jsimd.c)
  235. if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
  236. set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
  237. endif()
  238. ###############################################################################
  239. # MIPS (GAS)
  240. ###############################################################################
  241. elseif(CPU_TYPE STREQUAL "mips" OR CPU_TYPE STREQUAL "mipsel")
  242. enable_language(ASM)
  243. string(TOUPPER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_UC)
  244. set(EFFECTIVE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${CMAKE_ASM_FLAGS_${CMAKE_BUILD_TYPE_UC}}")
  245. message(STATUS "CMAKE_ASM_FLAGS = ${EFFECTIVE_ASM_FLAGS}")
  246. set(CMAKE_REQUIRED_FLAGS -mdspr2)
  247. check_c_source_compiles("
  248. #if !(defined(__mips__) && __mips_isa_rev >= 2)
  249. #error MIPS DSPr2 is currently only available on MIPS32r2 platforms.
  250. #endif
  251. int main(void) {
  252. int c = 0, a = 0, b = 0;
  253. __asm__ __volatile__ (
  254. \"precr.qb.ph %[c], %[a], %[b]\"
  255. : [c] \"=r\" (c)
  256. : [a] \"r\" (a), [b] \"r\" (b)
  257. );
  258. return c;
  259. }" HAVE_DSPR2)
  260. unset(CMAKE_REQUIRED_FLAGS)
  261. if(NOT HAVE_DSPR2)
  262. simd_fail("SIMD extensions not available for this CPU")
  263. return()
  264. endif()
  265. add_library(simd OBJECT mips/jsimd_dspr2.S mips/jsimd.c)
  266. if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
  267. set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
  268. endif()
  269. ###############################################################################
  270. # Loongson (Intrinsics)
  271. ###############################################################################
  272. elseif(CPU_TYPE STREQUAL "loongson")
  273. set(SIMD_SOURCES loongson/jccolor-mmi.c loongson/jcsample-mmi.c
  274. loongson/jdcolor-mmi.c loongson/jdsample-mmi.c loongson/jfdctint-mmi.c
  275. loongson/jidctint-mmi.c loongson/jquanti-mmi.c)
  276. if(CMAKE_COMPILER_IS_GNUCC)
  277. foreach(file ${SIMD_SOURCES})
  278. set_property(SOURCE ${file} APPEND_STRING PROPERTY COMPILE_FLAGS
  279. " -fno-strict-aliasing")
  280. endforeach()
  281. endif()
  282. add_library(simd OBJECT ${SIMD_SOURCES} loongson/jsimd.c)
  283. if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
  284. set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
  285. endif()
  286. ###############################################################################
  287. # PowerPC (Intrinsics)
  288. ###############################################################################
  289. elseif(CPU_TYPE STREQUAL "powerpc")
  290. set(CMAKE_REQUIRED_FLAGS -maltivec)
  291. check_c_source_compiles("
  292. #include <altivec.h>
  293. int main(void) {
  294. __vector int vi = { 0, 0, 0, 0 };
  295. int i[4];
  296. vec_st(vi, 0, i);
  297. return i[0];
  298. }" HAVE_ALTIVEC)
  299. unset(CMAKE_REQUIRED_FLAGS)
  300. if(NOT HAVE_ALTIVEC)
  301. simd_fail("SIMD extensions not available for this CPU (PowerPC SPE)")
  302. return()
  303. endif()
  304. set(SIMD_SOURCES powerpc/jccolor-altivec.c powerpc/jcgray-altivec.c
  305. powerpc/jcsample-altivec.c powerpc/jdcolor-altivec.c
  306. powerpc/jdmerge-altivec.c powerpc/jdsample-altivec.c
  307. powerpc/jfdctfst-altivec.c powerpc/jfdctint-altivec.c
  308. powerpc/jidctfst-altivec.c powerpc/jidctint-altivec.c
  309. powerpc/jquanti-altivec.c)
  310. set_source_files_properties(${SIMD_SOURCES} PROPERTIES
  311. COMPILE_FLAGS -maltivec)
  312. add_library(simd OBJECT ${SIMD_SOURCES} powerpc/jsimd.c)
  313. if(CMAKE_POSITION_INDEPENDENT_CODE OR ENABLE_SHARED)
  314. set_target_properties(simd PROPERTIES POSITION_INDEPENDENT_CODE 1)
  315. endif()
  316. ###############################################################################
  317. # None
  318. ###############################################################################
  319. else()
  320. simd_fail("SIMD extensions not available for this CPU (${CMAKE_SYSTEM_PROCESSOR})")
  321. endif() # CPU_TYPE