1
2XEN_ROOT ?= $(CURDIR)/../../..
3include $(XEN_ROOT)/tools/Rules.mk
4
5TARGET := test_x86_emulator
6
7.PHONY: all
8all:
9
10.PHONY: run
11run: $(TARGET)
12	./$(TARGET)
13
14# Add libx86 to the build
15vpath %.c $(XEN_ROOT)/xen/lib/x86
16
17CFLAGS += $(CFLAGS_xeninclude)
18
19SIMD := 3dnow sse sse2 sse4 avx avx2 xop avx512f avx512bw avx512dq avx512er avx512vbmi
20FMA := fma4 fma
21SG := avx2-sg avx512f-sg avx512vl-sg
22AES := ssse3-aes avx-aes avx2-vaes avx512bw-vaes
23CLMUL := ssse3-pclmul avx-pclmul avx2-vpclmulqdq avx512bw-vpclmulqdq avx512vbmi2-vpclmulqdq
24SHA := sse4-sha avx-sha avx512f-sha
25GF := sse2-gf avx2-gf avx512bw-gf
26TESTCASES := blowfish $(SIMD) $(FMA) $(SG) $(AES) $(CLMUL) $(SHA) $(GF)
27
28OPMASK := avx512f avx512dq avx512bw
29
30ifeq ($(origin XEN_COMPILE_ARCH),override)
31
32HOSTCFLAGS += -m32
33
34else
35
36blowfish-cflags := ""
37blowfish-cflags-x86_32 := "-mno-accumulate-outgoing-args -Dstatic="
38
393dnow-vecs := 8
403dnow-ints :=
413dnow-flts := 4
42sse-vecs := 16
43sse-ints :=
44sse-flts := 4
45sse2-vecs := $(sse-vecs)
46sse2-ints := 1 2 4 8
47sse2-flts := 4 8
48sse4-vecs := $(sse2-vecs)
49sse4-ints := $(sse2-ints)
50sse4-flts := $(sse2-flts)
51avx-vecs := 16 32
52avx-ints :=
53avx-flts := 4 8
54fma4-vecs := $(avx-vecs)
55fma4-ints :=
56fma4-flts := $(avx-flts)
57fma-vecs := $(avx-vecs)
58fma-ints :=
59fma-flts := $(avx-flts)
60avx2-vecs := $(avx-vecs)
61avx2-ints := 1 2 4 8
62avx2-flts := 4 8
63avx2-sg-vecs := $(avx2-vecs)
64avx2-sg-idxs := 4 8
65avx2-sg-ints := 4 8
66avx2-sg-flts := 4 8
67xop-vecs := $(avx-vecs)
68xop-ints := 1 2 4 8
69xop-flts := $(avx-flts)
70avx512f-vecs := 64 16 32
71avx512f-ints := 4 8
72avx512f-flts := 4 8
73avx512f-sg-vecs := 64
74avx512f-sg-idxs := 4 8
75avx512f-sg-ints := $(avx512f-ints)
76avx512f-sg-flts := $(avx512f-flts)
77avx512vl-sg-vecs := 16 32
78avx512vl-sg-idxs := $(avx512f-sg-idxs)
79avx512vl-sg-ints := $(avx512f-ints)
80avx512vl-sg-flts := $(avx512f-flts)
81avx512bw-vecs := $(avx512f-vecs)
82avx512bw-ints := 1 2
83avx512bw-flts :=
84avx512dq-vecs := $(avx512f-vecs)
85avx512dq-ints := $(avx512f-ints)
86avx512dq-flts := $(avx512f-flts)
87avx512er-vecs := 64
88avx512er-ints :=
89avx512er-flts := 4 8
90avx512vbmi-vecs := $(avx512bw-vecs)
91avx512vbmi-ints := $(avx512bw-ints)
92avx512vbmi-flts := $(avx512bw-flts)
93avx512vbmi2-vecs := $(avx512bw-vecs)
94
95avx512f-opmask-vecs := 2
96avx512dq-opmask-vecs := 1 2
97avx512bw-opmask-vecs := 4 8
98
99# Suppress building by default of the harness if the compiler can't deal
100# with some of the extensions used.  Don't alter the "run" target dependencies
101# though, as this target needs to be specified manually, and things may work
102# partially even with older compilers.
103TARGET-y := $(TARGET)
104
105ifeq ($(filter run%,$(MAKECMDGOALS)),)
106
107define simd-check-cc
108TARGET-$(shell echo 'int i;' | $(CC) -x c -c -o /dev/null -m$(1) - || echo y) :=
109endef
110
111$(foreach flavor,$(SIMD) $(FMA),$(eval $(call simd-check-cc,$(flavor))))
112
113# Also explicitly check for {evex} pseudo-prefix support, which got introduced
114# only after AVX512F and some of its extensions.
115TARGET-$(shell echo 'asm("{evex} vmovaps %xmm0$(comma)%xmm0");' | $(CC) -x c -c -o /dev/null - || echo y) :=
116
117ifeq ($(TARGET-y),)
118$(warning Test harness not built, use newer compiler than "$(CC)" (version $(shell $(CC) -dumpversion)) and an "{evex}" capable assembler)
119endif
120
121endif
122
123all: $(TARGET-y)
124
125# For AVX and later, have the compiler avoid XMM0 to widen coverage of
126# the VEX.vvvv checks in the emulator.  For 3DNow!, however, force SSE
127# use for floating point operations, to avoid mixing MMX and FPU register
128# uses.  Also enable 3DNow! extensions, but note that we can't use 3dnowa
129# as the test flavor right away since -m3dnowa is being understood only
130# by gcc 7.x and newer (older ones want a specific machine model instead).
1313dnowa := $(call cc-option,$(CC),-m3dnowa,-march=k8)
132non-sse = $(if $(filter sse%,$(1)),,$(if $(filter 3dnow%,$(1)),-msse -mfpmath=sse $(3dnowa),-ffixed-xmm0))
133
134define simd-defs
135$(1)-cflags := \
136	$(foreach vec,$($(1)-vecs), \
137	  $(foreach int,$($(1)-ints), \
138	    "-D_$(vec)i$(int) -m$(1) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec) -DINT_SIZE=$(int)" \
139	    "-D_$(vec)u$(int) -m$(1) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec) -DUINT_SIZE=$(int)") \
140	  $(foreach flt,$($(1)-flts), \
141	    "-D_$(vec)f$(flt) -m$(1) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec) -DFLOAT_SIZE=$(flt)")) \
142	$(foreach flt,$($(1)-flts), \
143	  "-D_f$(flt) -m$(1) $(call non-sse,$(1)) -mfpmath=sse -Os -DFLOAT_SIZE=$(flt)")
144endef
145define simd-sg-defs
146$(1)-cflags := \
147	$(foreach vec,$($(1)-vecs), \
148	  $(foreach idx,$($(1)-idxs), \
149	   $(foreach int,$($(1)-ints), \
150	     "-D_$(vec)x$(idx)i$(int) -m$(1:-sg=) $(call non-sse,$(1)) -Os -DVEC_MAX=$(vec) -DIDX_SIZE=$(idx) -DINT_SIZE=$(int)") \
151	   $(foreach flt,$($(1)-flts), \
152	     "-D_$(vec)x$(idx)f$(flt) -m$(1:-sg=) $(call non-sse,$(1)) -Os -DVEC_MAX=$(vec) -DIDX_SIZE=$(idx) -DFLOAT_SIZE=$(flt)")))
153endef
154define simd-aes-defs
155$(1)-cflags := $(foreach vec,$($(patsubst %-aes,sse,$(1))-vecs) $($(patsubst %-vaes,%,$(1))-vecs), \
156	         "-D_$(vec) -maes $(addprefix -m,$(subst -,$(space),$(1))) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec)")
157endef
158define simd-clmul-defs
159$(1)-cflags := $(foreach vec,$($(patsubst %-pclmul,sse,$(1))-vecs) $($(patsubst %-vpclmulqdq,%,$(1))-vecs), \
160	         "-D_$(vec) -mpclmul $(addprefix -m,$(subst -,$(space),$(1))) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec)")
161endef
162define simd-sha-defs
163$(1)-cflags := $(foreach vec,$(sse-vecs), \
164	         "-D_$(vec) $(addprefix -m,$(subst -,$(space),$(1))) -Os -DVEC_SIZE=$(vec)")
165endef
166define simd-gf-defs
167$(1)-cflags := $(foreach vec,$($(1:-gf=)-vecs), \
168	         "-D_$(vec) -mgfni -m$(1:-gf=) $(call non-sse,$(1)) -Os -DVEC_SIZE=$(vec)")
169endef
170define opmask-defs
171$(1)-opmask-cflags := $(foreach vec,$($(1)-opmask-vecs), "-D_$(vec) -m$(1) -Os -DSIZE=$(vec)")
172endef
173
174$(foreach flavor,$(SIMD) $(FMA),$(eval $(call simd-defs,$(flavor))))
175$(foreach flavor,$(SG),$(eval $(call simd-sg-defs,$(flavor))))
176$(foreach flavor,$(AES),$(eval $(call simd-aes-defs,$(flavor))))
177$(foreach flavor,$(CLMUL),$(eval $(call simd-clmul-defs,$(flavor))))
178$(foreach flavor,$(SHA),$(eval $(call simd-sha-defs,$(flavor))))
179$(foreach flavor,$(GF),$(eval $(call simd-gf-defs,$(flavor))))
180$(foreach flavor,$(OPMASK),$(eval $(call opmask-defs,$(flavor))))
181
182first-string = $(shell for s in $(1); do echo "$$s"; break; done)
183
184avx2-sg-cflags-x86_64    := "-D_high $(foreach n,7 6 5 4 3 2 1,-ffixed-ymm$(n)) $(call first-string,$(avx2-sg-cflags))"
185avx512f-sg-cflags-x86_64 := "-D_higher $(foreach n,7 6 5 4 3 2 1,-ffixed-zmm$(n)) $(call first-string,$(avx512f-sg-cflags))"
186avx512f-sg-cflags-x86_64 += "-D_highest $(foreach n,15 14 13 12 11 10 9 8,-ffixed-zmm$(n)) $(call first-string,$(avx512f-sg-cflags-x86_64))"
187
188$(addsuffix .h,$(TESTCASES)): %.h: %.c testcase.mk Makefile
189	rm -f $@.new $*.bin
190	$(foreach arch,$(filter-out $(XEN_COMPILE_ARCH),x86_32) $(XEN_COMPILE_ARCH), \
191	    for cflags in $($*-cflags) $($*-cflags-$(arch)); do \
192		$(MAKE) -f testcase.mk TESTCASE=$* XEN_TARGET_ARCH=$(arch) $*-cflags="$$cflags" all; \
193		prefix=$(shell echo $(subst -,_,$*) | sed -e 's,^\([0-9]\),_\1,'); \
194		flavor=$$(echo $${cflags} | sed -e 's, .*,,' -e 'y,-=,__,') ; \
195		(echo 'static const unsigned int __attribute__((section(".test, \"ax\", @progbits #")))' \
196		      "$${prefix}_$(arch)$${flavor}[] = {"; \
197		 od -v -t x $*.bin | sed -e 's/^[0-9]* /0x/' -e 's/ /, 0x/g' -e 's/$$/,/'; \
198		 echo "};"; \
199		 echo "asm(\".type $${prefix}_$(arch)$${flavor}, STT_NOTYPE;\");"; \
200		 echo "asm(\".type $${prefix}_$(arch)$${flavor}, STT_FUNC;\");"; \
201		) >>$@.new; \
202		rm -f $*.bin; \
203	    done; \
204	)
205	mv $@.new $@
206
207$(addsuffix -opmask.h,$(OPMASK)): %.h: opmask.S testcase.mk Makefile
208	rm -f $@.new $*.bin
209	$(foreach arch,$(filter-out $(XEN_COMPILE_ARCH),x86_32) $(XEN_COMPILE_ARCH), \
210	    for cflags in $($*-cflags) $($*-cflags-$(arch)); do \
211		$(MAKE) -f testcase.mk TESTCASE=$* XEN_TARGET_ARCH=$(arch) $*-cflags="$$cflags" all; \
212		prefix=$(shell echo $(subst -,_,$*) | sed -e 's,^\([0-9]\),_\1,'); \
213		flavor=$$(echo $${cflags} | sed -e 's, .*,,' -e 'y,-=,__,') ; \
214		(echo 'static const unsigned int __attribute__((section(".test, \"ax\", @progbits #")))' \
215		      "$${prefix}_$(arch)$${flavor}[] = {"; \
216		 od -v -t x $*.bin | sed -e 's/^[0-9]* /0x/' -e 's/ /, 0x/g' -e 's/$$/,/'; \
217		 echo "};"; \
218		 echo "asm(\".type $${prefix}_$(arch)$${flavor}, STT_NOTYPE;\");"; \
219		 echo "asm(\".type $${prefix}_$(arch)$${flavor}, STT_FUNC;\");"; \
220		) >>$@.new; \
221		rm -f $*.bin; \
222	    done; \
223	)
224	mv $@.new $@
225
226$(addsuffix .c,$(SIMD)):
227	ln -sf simd.c $@
228
229$(addsuffix .c,$(FMA)):
230	ln -sf simd-fma.c $@
231
232$(addsuffix .c,$(SG)):
233	ln -sf simd-sg.c $@
234
235$(addsuffix .c,$(AES)):
236	ln -sf simd-aes.c $@
237
238$(addsuffix .c,$(CLMUL)):
239	ln -sf simd-clmul.c $@
240
241$(addsuffix .c,$(SHA)):
242	ln -sf simd-sha.c $@
243
244$(addsuffix .c,$(GF)):
245	ln -sf simd-gf.c $@
246
247$(addsuffix .h,$(SIMD) $(FMA) $(SG) $(AES) $(CLMUL) $(SHA) $(GF)): simd.h
248
249xop.h avx512f.h: simd-fma.c
250
251endif # 32-bit override
252
253$(TARGET): x86-emulate.o cpuid.o test_x86_emulator.o evex-disp8.o predicates.o wrappers.o
254	$(HOSTCC) $(HOSTCFLAGS) -o $@ $^
255
256.PHONY: clean
257clean:
258	rm -rf $(TARGET) *.o *~ core *.bin x86_emulate
259	rm -rf $(TARGET) $(addsuffix .h,$(TESTCASES)) $(addsuffix -opmask.h,$(OPMASK))
260
261.PHONY: distclean
262distclean: clean
263
264.PHONY: install uninstall
265install uninstall:
266
267.PHONY: run32 clean32
268ifeq ($(XEN_COMPILE_ARCH),x86_64)
269run32: $(addsuffix .h,$(TESTCASES)) $(addsuffix -opmask.h,$(OPMASK))
270run32 clean32: %32:
271	$(MAKE) -C 32 HOSTCC=$(HOSTCC) $*
272clean: clean32
273else
274run32 clean32: %32: %
275endif
276
277x86_emulate:
278	[ -L $@ ] || ln -sf $(XEN_ROOT)/xen/arch/x86/$@
279
280x86_emulate/%: x86_emulate ;
281
282HOSTCFLAGS-x86_64 := -fno-PIE
283$(call cc-option-add,HOSTCFLAGS-x86_64,HOSTCC,-no-pie)
284HOSTCFLAGS += $(CFLAGS_xeninclude) -I. $(HOSTCFLAGS-$(XEN_COMPILE_ARCH))
285
286x86.h := $(addprefix $(XEN_ROOT)/tools/include/xen/asm/,\
287                     x86-vendors.h x86-defns.h msr-index.h) \
288         $(addprefix $(XEN_ROOT)/tools/include/xen/lib/x86/, \
289                     cpuid.h cpuid-autogen.h)
290x86_emulate.h := x86-emulate.h x86_emulate/x86_emulate.h $(x86.h)
291
292x86-emulate.o cpuid.o test_x86_emulator.o evex-disp8.o predicates.o wrappers.o: %.o: %.c $(x86_emulate.h)
293	$(HOSTCC) $(HOSTCFLAGS) -c -g -o $@ $<
294
295x86-emulate.o: x86_emulate/x86_emulate.c
296x86-emulate.o: HOSTCFLAGS += -D__XEN_TOOLS__
297
298test_x86_emulator.o: $(addsuffix .h,$(TESTCASES)) $(addsuffix -opmask.h,$(OPMASK))
299