• 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
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