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