• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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