summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Makefile60
-rw-r--r--README21
-rwxr-xr-xexpand-translations29
-rw-r--r--isa-list164
-rw-r--r--qemu-bad-@NAME@6
-rw-r--r--qemu-bad-SSE26
-rw-r--r--qemu-bad-SSE36
-rw-r--r--qemu-bad-SSE4.16
-rw-r--r--qemu-bad-SSE4.26
-rw-r--r--qemu-good-@NAME@6
-rw-r--r--qemu-good-SSE26
-rw-r--r--qemu-good-SSE36
-rw-r--r--qemu-good-SSE4.16
-rw-r--r--qemu-good-SSE4.26
-rwxr-xr-xrefresh-package144
-rw-r--r--test-@NAME@.c63
-rw-r--r--test-ARMv6.c63
-rw-r--r--test-ARMv6K.c63
-rw-r--r--test-ARMv7.c63
-rw-r--r--test-ARMv8.c63
-rw-r--r--test-SSE2.c63
-rw-r--r--test-VFP.c63
-rw-r--r--test-VFPv2.c63
-rw-r--r--test-VFPv3.c63
-rw-r--r--test-altivec.c63
-rw-r--r--test-neon.c63
26 files changed, 1171 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a2c35d2
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,60 @@
+DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+prefix?=/usr
+exec_prefix?=$(prefix)
+DESTDIR?=
+libexecdir?=$(exec_prefix)/libexec
+archlibexecdir?=$(exec_prefix)/libexec/$(DEB_HOST_MULTIARCH)
+INSTALL?=install
+
+uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
+
+ISAS_ARCH_LIST:=$(shell cat isa-list | grep '^Architecture:' | cut -d ':' -f2 | sort -u)
+ISAS_ARCH_FORUS:=$(call uniq, $(foreach isaarch, $(ISAS_ARCH_LIST), $(shell dpkg-architecture -a $(DEB_HOST_ARCH) -i $(isaarch) && echo $(isaarch))))
+ISAS_ARCH_FORUS_GREP:=$(foreach isa, $(ISAS_ARCH_FORUS), -e '^Architecture:.*[[:space:]]$(isa)')
+
+ISAS:= $(shell cat isa-list | grep -A1 ^Name | grep -B1 $(ISAS_ARCH_FORUS_GREP) -e 'FakeArchIsEmptySet' | grep ^Name | cut -d ' ' -f2)
+
+
+
+TEST_BINARIES = $(foreach isa,$(ISAS),test-$(isa))
+QEMU_BINARIES = $(foreach isa,$(ISAS),qemu-good-$(isa)) $(foreach isa,$(ISAS),qemu-bad-$(isa))
+TEST_SOURCES = $(foreach isa,$(ISAS),test-$(isa).c)
+
+GENERATED_FILES += $(foreach isa,$(ISAS),debian/$(isa).docs)
+GENERATED_FILES += $(foreach isa,$(ISAS),debian/$(isa).lintian-overrides)
+GENERATED_FILES += $(foreach isa,$(ISAS),debian/$(isa).preinst)
+GENERATED_FILES += $(foreach isa,$(ISAS),debian/$(isa).templates)
+GENERATED_FILES += $(TEST_SOURCES)
+ALL_GENERATED_FILES += $(GENERATED_FILES) debian/control
+
+INPUT_FILES = $(wildcard debian/*.in)
+
+CFLAGS ?=
+CFLAGS += -Wall
+CFLAGS += $(shell cat isa-list | sed -e 's/^Name: /Name: test-/' | grep $@ -A3 | grep '^CFLAGS:' | cut -d ' ' -f2-)
+
+all: $(TEST_BINARIES)
+ @:
+
+clean:
+ rm -f $(TEST_BINARIES)
+ rm -f $(GENERATED_FILES)
+ rm -f .last-refresh
+
+install:
+ mkdir -p $(DESTDIR)/$(archlibexecdir)/isa-support
+ for bin in $(TEST_BINARIES); do $(INSTALL) $$bin $(DESTDIR)/$(archlibexecdir)/isa-support; done
+ for bin in $(QEMU_BINARIES); do if test -e $$bin; then $(INSTALL) $$bin $(DESTDIR)/$(archlibexecdir)/isa-support; fi; done
+
+refresh: $(ALL_GENERATED_FILES) $(TEST_SOURCES)
+ @:
+
+$(GENERATED_FILES): .last-refresh
+ @:
+
+.last-refresh: refresh-package $(INPUT_FILES)
+ ./refresh-package
+ touch $@
+
+.PHONY: all clean refresh
diff --git a/README b/README
new file mode 100644
index 0000000..629a1bb
--- /dev/null
+++ b/README
@@ -0,0 +1,21 @@
+This package ensures that the machine has required CPU facilities; users who
+attempt installation on an inadequate processor will receive an error message
+in preinst. This is useful if there's no way to make your package support
+the base ISA for the architecture.
+
+While in general packages are required to at least try, there are situations
+when baseline support is infeasible or a pure waste of time. No one is
+going to run scientific number-crunching software on a pre-SSE2/SSE3
+machine. Or upstream code may use such extensions unconditionally, and
+you don't have the resources to fix that yourself.
+
+You should also consider how likely other software is to use your package.
+A fast strong hash is something with many uses, big and small, so it's a
+priority to port libraries like libhighwayhash to all CPUs. On the other
+hand, a niche piece of software is unlikely to be repurposed for other uses.
+
+
+The check is skipped in two cases:
+* when the target architecture is not executable at all (an ARM SoC mounted
+ into an amd64 machine, etc)
+* when ISA_IGNORE environment variable has a non-empty value
diff --git a/expand-translations b/expand-translations
new file mode 100755
index 0000000..0683507
--- /dev/null
+++ b/expand-translations
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+set -eu
+
+outdir="$1"
+
+mkdir -p "$outdir"
+
+isas=$(cat isa-list | grep ^Name | cut -d " " -f2)
+
+for po in debian/po/*.po ; do
+ po2="$outdir/$(basename "$po")"
+ truncate -s0 "$po2"
+
+ echo "Extending $po: s/&NAME&/\$isa > $po2"
+ csplit --quiet --suppress-matched -f "$po2." -b '%02d.sect' "$po" '/^$/' '{*}'
+ for sect in $(ls -1 $po2*.sect | sort -n) ; do
+ if grep -q '@NAME@' $sect ; then
+ for isa in $isas ; do
+ cat $sect | sed -e "s/@NAME@/$isa/g" >> "$po2"
+ echo >> "$po2"
+ done
+ else
+ cat $sect >> "$po2"
+ echo >> "$po2"
+ fi
+ rm $sect
+ done
+done
diff --git a/isa-list b/isa-list
new file mode 100644
index 0000000..1a357bc
--- /dev/null
+++ b/isa-list
@@ -0,0 +1,164 @@
+# Recognized fields:
+# "Name": the isa extension name, the package will be ${Name}-support
+# "Architecture": archs to build the package on, wildcards are ok
+# "Test": how to detect it, defaults to return !__builtin_cpu_supports("$Name");
+# If the test program dies (SIGILL/etc), that's ok, the answer is "no".
+# CFLAGS: passed to the C compiler, can include link-time flags too.
+# Description: added to package's description.
+
+Name: SSE2
+Architecture: any-i386
+qemu-good: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
+qemu-bad: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-see2,-sse3,-ssse3,-sse4.1,-sse4.2
+Description:
+ Streaming SIMD Extensions (SSE) is a single instruction, multiple data
+ (SIMD) instruction set extension.
+ .
+ SSE2 was an incremental upgrade to SSE intended to fully replace the earlier
+ MMX instruction set. It is available on processors from Pentium 4 onward,
+ including all 64-bit capable ones, but not on Pentium 3, Athlon XP, Via C3,
+ Quark, or older processors.
+
+Name: SSE3
+Architecture: any-i386 any-amd64
+qemu-good: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
+qemu-bad: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse3,-ssse3,-sse4.1,-sse4.2
+Description:
+ Streaming SIMD Extensions (SSE) is a single instruction, multiple data
+ (SIMD) instruction set extension.
+ .
+ SSE3, also called PNI (Prescott New Instructions), is an incremental upgrade
+ to SSE2, adding a handful of new operations useful for processing media. It
+ is available on almost any 64-bit-capable processor except for some early
+ AMD models (Sledgehammer and Clawhammer), but is not available on most
+ 32-bit-only hardware.
+
+Name: SSE4.1
+Architecture: any-i386 any-amd64
+qemu-good: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
+qemu-bad: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse4.1,-sse4.2
+Description:
+ Streaming SIMD Extensions (SSE) is a single instruction, multiple data
+ (SIMD) instruction set extension.
+ .
+ SSE4.1 added a dot product instruction and additional integer instructions.
+ It is available on Intel processors since Penryn (circa 2008), but notably
+ not on anything AMD until the Bulldozer (15h, in 2011) and Jaguar (16h, in
+ 2013) families.
+
+Name: SSE4.2
+Architecture: any-i386 any-amd64
+qemu-good: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
+qemu-bad: qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse4.2
+Description:
+ SSE4.2 added string and text processing instructions that perform character
+ searches and comparison on two operands of 16 bytes at a time. It is
+ available on Intel processors since Nehalem (circa 2008), but notably not
+ on anything AMD until the Bulldozer (15h, in 2011) and Jaguar (16h, in
+ 2013) families.
+
+Name: altivec
+Architecture: powerpc
+Test: asm volatile("vsldoi %v1,%v1,%v1,0");
+Description:
+ AltiVec is a single-precision floating point and integer SIMD instruction
+ set. It is a standard part of the Power ISA v.2.03 specification.
+# gcc-16 has __builtin_cpu_supports("altivec") but it's not reliable: silently
+# gives wrong answer on qemu, wrong versions of glibc, non-glibc, etc.
+# Thus, let's use SIGILL instead.
+
+Name: neon
+Architecture: armhf
+CFLAGS: -mfpu=neon
+Test: asm volatile("VMUL.I16 q0,q0,q1");
+Description:
+ This is a mostly dummy package which checks for Neon and refuses to install
+ on unsupported hardware.
+ .
+ Neon, also known as MPE (Media Processing Engine) or Advanced SIMD, is a
+ combined 64- and 128-bit SIMD instruction set that provides standardised
+ acceleration for media and signal processing applications. It is available
+ on the vast majority of armhf devices but not guaranteed before the 64-bit
+ capable ARMv8.
+
+Name: ARMv6
+Architecture: armel
+Test: return !need_armv_version(6);
+Description:
+ The ARMv6 architecture (not to be confused with product family ARM6) uses
+ physically addressed cache, solving many cache aliasing problems and
+ reducing context switch overhead. Unaligned and mixed-endian data access is
+ supported. This architecture includes the first version of Thumb
+ technology.
+ .
+ This feature is not guaranteed by the architecture baseline, but is
+ available for newer armel machines in the ARM11 product family, including
+ ARM1136J(F)-S, ARM1156T2(F)-S, ARM1176JZ(F)-S, ARM1136EJ(F)-S, and
+ ARM11MPCore processors. Boards include the Raspberry Pi model 1 and
+ Raspberry Pi Zero.
+
+Name: ARMv6K
+Architecture: armel
+Test: return !(need_armv_version(6) && (getauxval(AT_HWCAP) & HWCAP_ARM_TLS));
+Description:
+ ARMv6k is a subarchitecture of ARMV6 adding Symmetric MultiProcessing
+ and Thread Local Storage instruction sets. It is not guaranteed by the
+ architecture baseline, but is available for newer armel machines in the
+ ARM11 product family; boards include the Raspberry Pi model 1 and
+ Raspberry Pi Zero.
+
+Name: ARMv7
+Architecture: armel
+Test: return !need_armv_version(7);
+Description:
+ ARMv7 (not to be confused with product family ARM7) includes Thumb-2
+ technology, adding 32-bit instructions into compressed Thumb mode. It is
+ not guaranteed by the architecture baseline, but is available for newer
+ armel machines (including CPUs that support armhf) since the Cortex-A
+ product family, including Cortex-A5, -A7, -A8, -A9, -A12, -A15, and -A17
+ processors. Boards include the Raspberry Pi 2.
+
+Name: ARMv8
+Architecture: armel armhf
+Test: return !need_armv_version(8);
+Description:
+ ARMv8 (not to be confused with product family ARM8) introduced a large
+ number of ISA enhancements. It is not guaranteed by the architecture
+ baseline, but is available for newer armel machines (including CPUs that
+ support armhf) since the Cortex-A product family, including Cortex-A32, as
+ well as all arm64 processors. Boards include the Raspberry Pi 3 and 4.
+
+Name: VFP
+Architecture: armel
+Test: return !(getauxval(AT_HWCAP) & HWCAP_ARM_VFP)
+Description:
+ VFP (Vector Floating Point) technology is a floating-point unit (FPU)
+ coprocessor extension to the ARM architecture. It provides single- and
+ double-precision floating-point computation fully compliant with IEEE
+ 754-1985.
+
+Name: VFPv2
+Architecture: armel
+Test: return !(need_armv_version(5) && (getauxval(AT_HWCAP) & HWCAP_ARM_VFP))
+Description:
+ VFP (Vector Floating Point) technology is a floating-point unit (FPU)
+ coprocessor extension to the ARM architecture. It provides single- and
+ double-precision floating-point computation fully compliant with IEEE
+ 754-1985.
+ .
+ VFPv2 has 16 64-bit FPU registers. It is available for some ARMv5 and
+ all ARMv6 cores.
+
+Name: VFPv3
+Architecture: armel
+Test: return !(getauxval(AT_HWCAP) & HWCAP_ARM_VFPv3)
+Description:
+ VFP (Vector Floating Point) technology is a floating-point unit (FPU)
+ coprocessor extension to the ARM architecture. It provides single- and
+ double-precision floating-point computation fully compliant with IEEE
+ 754-1985.
+ .
+ VFPv3 has 32 64-bit FPU registers as standard, adds VCVT instructions to
+ convert between scalar, float, and double, and adds immediate mode to VMOV,
+ allowing constants to be loaded into FPU registers. It is available on most
+ Cortex-A8 and -A9 ARMv7 processors.
diff --git a/qemu-bad-@NAME@ b/qemu-bad-@NAME@
new file mode 100644
index 0000000..186d6e1
--- /dev/null
+++ b/qemu-bad-@NAME@
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=@DEB_HOST_ARCH@
+DEB_HOST_ARCH_BITS=@DEB_HOST_ARCH_BITS@
+
+exec @QEMU_BAD@
diff --git a/qemu-bad-SSE2 b/qemu-bad-SSE2
new file mode 100644
index 0000000..60c034c
--- /dev/null
+++ b/qemu-bad-SSE2
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-see2,-sse3,-ssse3,-sse4.1,-sse4.2
diff --git a/qemu-bad-SSE3 b/qemu-bad-SSE3
new file mode 100644
index 0000000..50f5318
--- /dev/null
+++ b/qemu-bad-SSE3
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse3,-ssse3,-sse4.1,-sse4.2
diff --git a/qemu-bad-SSE4.1 b/qemu-bad-SSE4.1
new file mode 100644
index 0000000..9d9d28a
--- /dev/null
+++ b/qemu-bad-SSE4.1
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse4.1,-sse4.2
diff --git a/qemu-bad-SSE4.2 b/qemu-bad-SSE4.2
new file mode 100644
index 0000000..0c2cb9c
--- /dev/null
+++ b/qemu-bad-SSE4.2
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS",-sse4.2
diff --git a/qemu-good-@NAME@ b/qemu-good-@NAME@
new file mode 100644
index 0000000..db74d82
--- /dev/null
+++ b/qemu-good-@NAME@
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=@DEB_HOST_ARCH@
+DEB_HOST_ARCH_BITS=@DEB_HOST_ARCH_BITS@
+
+exec @QEMU_GOOD@
diff --git a/qemu-good-SSE2 b/qemu-good-SSE2
new file mode 100644
index 0000000..bf9d45a
--- /dev/null
+++ b/qemu-good-SSE2
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
diff --git a/qemu-good-SSE3 b/qemu-good-SSE3
new file mode 100644
index 0000000..bf9d45a
--- /dev/null
+++ b/qemu-good-SSE3
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
diff --git a/qemu-good-SSE4.1 b/qemu-good-SSE4.1
new file mode 100644
index 0000000..bf9d45a
--- /dev/null
+++ b/qemu-good-SSE4.1
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
diff --git a/qemu-good-SSE4.2 b/qemu-good-SSE4.2
new file mode 100644
index 0000000..bf9d45a
--- /dev/null
+++ b/qemu-good-SSE4.2
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+DEB_HOST_ARCH=amd64
+DEB_HOST_ARCH_BITS=64
+
+exec qemu-$DEB_HOST_ARCH -cpu "qemu$DEB_HOST_ARCH_BITS"
diff --git a/refresh-package b/refresh-package
new file mode 100755
index 0000000..8f6e4a9
--- /dev/null
+++ b/refresh-package
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+undef $/;
+my $DEB_HOST_MULTIARCH = (split /\n/, qx/dpkg-architecture -qDEB_HOST_MULTIARCH/)[0];
+my $DEB_HOST_ARCH = (split /\n/, qx/dpkg-architecture -qDEB_HOST_ARCH/)[0];
+my $DEB_HOST_ARCH_BITS = (split /\n/, qx/dpkg-architecture -qDEB_HOST_ARCH_BITS/)[0];
+
+sub file_replace
+{
+ my ($f,$name,$lcname)= @_;
+ my $foutname = $f;
+ $foutname =~ s/[@]NAME[@]/$name/;
+ $foutname =~ s/[@]LCNAME[@]/$lcname/;
+ open IN, "<debian/$f.in" or die "Can't read debian/$f.in: $!\n";
+ local $_=<IN>;
+ close IN;
+
+ s/[@]NAME[@]/$name/g;
+ s/[@]LCNAME[@]/$lcname/g;
+ s/[@]DEB_HOST_MULTIARCH[@]/$DEB_HOST_MULTIARCH/g;
+ open OUT, ">debian/$foutname"
+ or die "Can't write debian/$foutname: $!\n";
+ print OUT;
+ close OUT;
+}
+
+my $control;
+
+my $ctemplate;
+my $cfilename = 'test-@NAME@.c';
+open(my $fctemplate, '<', $cfilename) or die "cannot open file $cfilename";
+{
+ local $/ = undef;
+ $ctemplate = <$fctemplate>;
+}
+close($fctemplate);
+
+# dpkg-shlibdeps now looks inside, but is ok with an empty file.
+system("touch debian/control");
+
+my @control_in;
+open IN, "<debian/control.d/control.in" or die "Can't read debian/control.d/control.in: $!\n";
+$_=<IN>;
+@control_in = grep !/^\s*$/s, split /\n\s*\n/s;
+close IN;
+
+open ISA_LIST, "<isa-list" or die "Can't read isa-list: $!\n";
+$_=<ISA_LIST>;
+close ISA_LIST;
+my %archlist;
+
+my @structs;
+foreach my $block (split /\n\s*\n/s)
+{
+ my $lastfield = undef;
+ my %data = ();
+ foreach (split /\n/s, $block) {
+ next if /^#.*/;
+ next if /^\s*$/;
+ if (/^([^\s:]+?)\s*:\s*(.*?)\s*$/) {
+ $key = $1;
+ $value = $2 // '';
+ $data{"$key"} = "$value";
+ $lastfield = "$key";
+ } elsif (/^(\s\S.*?)\s*$/) {
+ $data{$lastfield} .= "\n$1";
+ }
+
+ next;
+ }
+ push @structs, \%data if %data;
+
+}
+
+for (@structs) {
+ my %entry = %$_;
+ $archlist{$entry{'Architecture'}} = 1;
+ my $name=$entry{'Name'};
+ my $lcname=lc($name);
+ $name=~/^[a-zA-Z0-9\.+_]+$/ or die "Bad package/isa name: \"$name\".\n";
+ my $description=$entry{'Description'};
+ $description=~s/\A\s*\n+//m;
+ $description=~s/\A\s+//m;
+
+ my @c = @control_in;
+ foreach (@c) {
+ s/[@]NAME[@]/$name/g;
+ s/[@]LCNAME[@]/$lcname/g;
+ s/[@]ARCHITECTURE[@]/$entry{'Architecture'}/g;
+ s/[@]DEB_HOST_MULTIARCH[@]/$DEB_HOST_MULTIARCH/g;
+ s/[@]DESCRIPTION[@]/$description/g;
+ $control.="\n".$_;
+ }
+
+ open C, '>', "test-$name.c";
+ my $test=$entry{'Test'}//"return !__builtin_cpu_supports(\"$lcname\");";
+ my $cfile = $ctemplate;
+ $cfile =~ s/[@]TEST[@]/$test/g;
+ print C $cfile;
+ close C;
+
+ for my $qemu (qw(qemu-good qemu-bad)) {
+ if (exists $entry{$qemu}) {
+ my $finname = $qemu.'-@NAME@';
+ my $foutname = $finname;
+ $foutname =~ s/[@]NAME[@]/$name/;
+ open IN, "<$finname" or die "Can't read $finname: $!\n";
+ local $_=<IN>;
+ close IN;
+
+ s/[@]NAME[@]/$name/g;
+ s/[@]DEB_HOST_MULTIARCH[@]/$DEB_HOST_MULTIARCH/g;
+ s/[@]DEB_HOST_ARCH[@]/$DEB_HOST_ARCH/g;
+ s/[@]DEB_HOST_ARCH_BITS[@]/$DEB_HOST_ARCH_BITS/g;
+ s/[@]QEMU_GOOD[@]/$entry{'qemu-good'}/g;
+ s/[@]QEMU_BAD[@]/$entry{'qemu-bad'}/g;
+
+ open OUT, ">$foutname"
+ or die "Can't write $foutname: $!\n";
+ print OUT;
+ close OUT;
+ }
+ }
+
+ foreach (qw(@LCNAME@-support.preinst @LCNAME@-support.templates @LCNAME@-support.lintian-overrides @LCNAME@-support.maintscript)) {
+ file_replace($_,$name,$lcname);
+ }
+}
+
+my $all_architectures = join(' ',sort(keys %archlist));
+
+my $control_base;
+my $filename = "debian/control.d/control-base.in";
+open(my $fh, '<', $filename) or die "cannot open file $filename";
+{
+ local $/ = undef;
+ $control_base = <$fh>;
+}
+close($fh);
+$control_base =~ s/[@]ALL_ARCHITECTURES[@]/$all_architectures/g;
+$control=$control_base.$control;
+
+open CONTROL, ">debian/control" or die "Can't write to debian/control: $!\n";
+print CONTROL $control;
+close CONTROL;
diff --git a/test-@NAME@.c b/test-@NAME@.c
new file mode 100644
index 0000000..2900044
--- /dev/null
+++ b/test-@NAME@.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ @TEST@;
+ return 0;
+}
diff --git a/test-ARMv6.c b/test-ARMv6.c
new file mode 100644
index 0000000..a2abf51
--- /dev/null
+++ b/test-ARMv6.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !need_armv_version(6);;
+ return 0;
+}
diff --git a/test-ARMv6K.c b/test-ARMv6K.c
new file mode 100644
index 0000000..537877f
--- /dev/null
+++ b/test-ARMv6K.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !(need_armv_version(6) && (getauxval(AT_HWCAP) & HWCAP_ARM_TLS));;
+ return 0;
+}
diff --git a/test-ARMv7.c b/test-ARMv7.c
new file mode 100644
index 0000000..3587c27
--- /dev/null
+++ b/test-ARMv7.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !need_armv_version(7);;
+ return 0;
+}
diff --git a/test-ARMv8.c b/test-ARMv8.c
new file mode 100644
index 0000000..f22a034
--- /dev/null
+++ b/test-ARMv8.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !need_armv_version(8);;
+ return 0;
+}
diff --git a/test-SSE2.c b/test-SSE2.c
new file mode 100644
index 0000000..3909525
--- /dev/null
+++ b/test-SSE2.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !__builtin_cpu_supports("sse2");;
+ return 0;
+}
diff --git a/test-VFP.c b/test-VFP.c
new file mode 100644
index 0000000..2ba4dd2
--- /dev/null
+++ b/test-VFP.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !(getauxval(AT_HWCAP) & HWCAP_ARM_VFP);
+ return 0;
+}
diff --git a/test-VFPv2.c b/test-VFPv2.c
new file mode 100644
index 0000000..2db7547
--- /dev/null
+++ b/test-VFPv2.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !(need_armv_version(5) && (getauxval(AT_HWCAP) & HWCAP_ARM_VFP));
+ return 0;
+}
diff --git a/test-VFPv3.c b/test-VFPv3.c
new file mode 100644
index 0000000..502a4f3
--- /dev/null
+++ b/test-VFPv3.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ return !(getauxval(AT_HWCAP) & HWCAP_ARM_VFPv3);
+ return 0;
+}
diff --git a/test-altivec.c b/test-altivec.c
new file mode 100644
index 0000000..4c441f8
--- /dev/null
+++ b/test-altivec.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ asm volatile("vsldoi %v1,%v1,%v1,0");;
+ return 0;
+}
diff --git a/test-neon.c b/test-neon.c
new file mode 100644
index 0000000..88a932c
--- /dev/null
+++ b/test-neon.c
@@ -0,0 +1,63 @@
+#include <stdbool.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <sys/auxv.h>
+
+#ifdef AT_PLATFORM
+/* detect ARM ABI version will be optimized away if not used */
+static inline bool need_armv_version(int atleastversion)
+{
+ int version;
+ const char * platform = (const char *)getauxval(AT_PLATFORM);
+ if (platform == NULL)
+ return false;
+ /* at least v5 */
+ if (strlen(platform) < strlen("v5"))
+ return false;
+ if (*(platform++) != 'v')
+ return false;
+
+ char *endstr;
+ errno = 0;
+ version = strtol(platform,&endstr,10);
+ if (errno != 0)
+ return false;
+ if (endstr == platform)
+ return false;
+
+ return (version >= atleastversion);
+
+}
+#endif
+
+const struct rlimit nocore = { 0, 0 };
+
+/* emulate kill by signal */
+void
+termination_handler (int signum)
+{
+ _exit(128+signum);
+}
+
+int main()
+{
+ /* no core */
+ (void) setrlimit(RLIMIT_CORE, &nocore);
+ /* return instead */
+ struct sigaction new_action;
+ new_action.sa_handler = termination_handler;
+ (void) sigemptyset (&new_action.sa_mask);
+ new_action.sa_flags = 0;
+ (void) sigaction (SIGILL, &new_action, NULL);
+ (void) sigaction (SIGBUS, &new_action, NULL);
+ (void) sigaction (SIGSEGV, &new_action, NULL);
+ /* now test */
+ asm volatile("VMUL.I16 q0,q0,q1");;
+ return 0;
+}