1#!/usr/bin/env perl 2############################################################################# 3## 4## Copyright (C) 2018 Intel Corporation. 5## Contact: https://www.qt.io/licensing/ 6## 7## This file is part of the build configuration tools of the Qt Toolkit. 8## 9## $QT_BEGIN_LICENSE:MIT$ 10## Permission is hereby granted, free of charge, to any person obtaining a copy 11## of this software and associated documentation files (the "Software"), to deal 12## in the Software without restriction, including without limitation the rights 13## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14## copies of the Software, and to permit persons to whom the Software is 15## furnished to do so, subject to the following conditions: 16## 17## The above copyright notice and this permission notice shall be included in 18## all copies or substantial portions of the Software. 19## 20## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26## THE SOFTWARE. 27## $QT_END_LICENSE$ 28## 29############################################################################# 30 31use strict; 32$\ = "\n"; 33$/ = "\n"; 34my %leaves = ( 35 Leaf1EDX => "CPUID Leaf 1, EDX", 36 Leaf1ECX => "CPUID Leaf 1, ECX", 37 Leaf7_0EBX => "CPUID Leaf 7, Sub-leaf 0, EBX", 38 Leaf7_0ECX => "CPUID Leaf 7, Sub-leaf 0, ECX", 39 Leaf7_0EDX => "CPUID Leaf 7, Sub-leaf 0, EDX", 40); 41my @leafNames = sort keys %leaves; 42 43# Read data from stdin 44my $i = 1; 45my @features; 46while (<STDIN>) { 47 s/#.*$//; 48 chomp; 49 next if $_ eq ""; 50 51 my ($name, $function, $bit, $depends) = split /\s+/; 52 die("Unknown CPUID function \"$function\"") 53 unless grep $function, @leafNames; 54 55 my $id = uc($name); 56 $id =~ s/[^A-Z0-9_]/_/g; 57 push @features, 58 { name => $name, depends => $depends, id => $id, bit => $bit, leaf => $function }; 59 ++$i; 60} 61 62if (my $h = shift @ARGV) { 63 open HEADER, ">", $h; 64 select HEADER; 65} 66 67# Print the qsimd_x86_p.h output 68print q{// This is a generated file. DO NOT EDIT. 69// Please see util/x86simdgen/generate.pl"; 70#ifndef QSIMD_P_H 71# error "Please include <private/qsimd_p.h> instead" 72#endif 73#ifndef QSIMD_X86_P_H 74#define QSIMD_X86_P_H 75 76#include "qsimd_p.h" 77 78// 79// W A R N I N G 80// ------------- 81// 82// This file is not part of the Qt API. It exists purely as an 83// implementation detail. This header file may change from version to 84// version without notice, or even be removed. 85// 86// We mean it. 87// 88 89QT_BEGIN_NAMESPACE 90 91// used only to indicate that the CPU detection was initialized 92#define QSimdInitialized (Q_UINT64_C(1) << 0)}; 93 94# Print the enum 95my $lastleaf; 96for (my $i = 0; $i < scalar @features; ++$i) { 97 my $feature = $features[$i]; 98 # Leaf header: 99 printf "\n// in %s:\n", $leaves{$feature->{leaf}} 100 if $feature->{leaf} ne $lastleaf; 101 $lastleaf = $feature->{leaf}; 102 103 # Feature 104 printf "#define CpuFeature%-33s (Q_UINT64_C(1) << %d)\n", $feature->{id}, $i + 1; 105 106 # Feature string names for Clang and GCC 107 my $str = $feature->{name}; 108 $str .= ",$feature->{depends}" if defined($feature->{depends}); 109 printf "#define QT_FUNCTION_TARGET_STRING_%-17s \"%s\"\n", 110 $feature->{id}, $str; 111} 112 113print q{ 114static const quint64 qCompilerCpuFeatures = 0}; 115 116# And print the compiler-enabled features part: 117for (my $i = 0; $i < scalar @features; ++$i) { 118 my $feature = $features[$i]; 119 printf 120 "#ifdef __%s__\n" . 121 " | CpuFeature%s\n" . 122 "#endif\n", 123 $feature->{id}, $feature->{id}; 124} 125 126print q{ ; 127 128QT_END_NAMESPACE 129 130#endif // QSIMD_X86_P_H 131}; 132 133if (my $cpp = shift @ARGV) { 134 open CPP, ">", $cpp; 135 select CPP; 136} else { 137 print q{ 138 139---- cut here, paste the rest into qsimd_x86.cpp --- 140 141 142}; 143}; 144 145print "// This is a generated file. DO NOT EDIT."; 146print "// Please see util/x86simdgen/generate.pl"; 147print '#include "qsimd_p.h"'; 148print ""; 149 150# Now generate the string table and bit-location array 151my $offset = 0; 152my @offsets; 153print "static const char features_string[] ="; 154for my $feature (@features) { 155 print " \" $feature->{name}\\0\""; 156 push @offsets, $offset; 157 $offset += 2 + length($feature->{name}); 158} 159print " \"\\0\";"; 160 161# Print the string offset table 162printf "\nstatic const %s features_indices[] = {\n %3d", 163 $offset > 255 ? "quint16" : "quint8", $offset; 164for (my $j = 0; $j < scalar @offsets; ++$j) { 165 printf ",%s%3d", 166 ($j + 1) % 8 ? " " : "\n ", $offsets[$j]; 167} 168print "\n};"; 169 170# Print the locator enum and table 171print "\nenum X86CpuidLeaves {"; 172map { print " $_," } @leafNames; 173print " X86CpuidMaxLeaf\n};"; 174 175my $type = scalar %leaves > 8 ? "quint16" : "quint8"; 176printf "\nstatic const %s x86_locators[] = {", 177 $type, $type; 178my $lastname; 179for (my $j = 0; $j < scalar @features; ++$j) { 180 my $feature = $features[$j]; 181 printf ", // %s", $lastname 182 if defined($lastname); 183 printf "\n %s*32 + %2d", 184 $feature->{leaf}, $feature->{bit}; 185 $lastname = $feature->{name}; 186} 187printf qq{ // $lastname 188\}; 189 190// List of AVX512 features (see detectProcessorFeatures()) 191static const quint64 AllAVX512 = 0}; 192 193# Print AVX512 features 194for (my $j = 0; $j < scalar @features; ++$j) { 195 my $feature = $features[$j]; 196 $_ = $feature->{id}; 197 printf "\n | CpuFeature%s", $_ if /AVX512/; 198} 199print ";"; 200