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