a4lg.com

AX_GCC_ARCHFLAG x86 rewrite details (2014-08-16...2014-11-02)

This is a memo which may (or may not) help reading/writing new versions of AX_GCC_ARCHFLAG Autoconf macro.

UPDATE: The proposed patch of mine was applied to the latest version of autoconf-archive and new version (based on my new CPUID research) will be pull-requested.

CPUID Pattern Simplifications

There are some notable changes regarding pattern simplifications.

  • Some CPUID patterns for K7 and K8-based AMD processors were "too fine" and there's no need to test because most of compilers merge support for minor differences.
    • Removed distinct CPUID patterns for "too fine" cases. Most of compilers MERGE AND IGNORE support for minor differences (except microprocessor and specification changes). For instance, all athlon64, opteron and k8 options are used to specify K8-based processors (without SSE3 support) but frequently used versions of GCC, Clang and Open64 handle them equivalently. Even if we have differences, they are no longer significant.
      • K7 (Palomino and later) : athlon-4 and athlon-fx
      • K8 (before SSE3 support) : k8, athlon64 and opteron
      • K8 (after SSE3 support) : k8-sse3, athlon64-sse3 and opteron-sse3
    • Removed L2 size test (for Palomino-based K7 processors) because of the reason described above.
  • Removed $host_cpu test for "nocona" and "prescott" because all Nocona is 64-bit Prescott-based architecture option (strictly, "prescott" option is a 32-bit variant of "nocona" in GCC) and thus we can simplify the test by testing both "nocona" and "prescott" without testing the architecture.
  • Removed "too fine" CPUID test for Intel family 06 model 0A. The original version tested additional bits to identify unknown Pentium II-based processors. Although they might be engineering sample versions of "Pentium II Xeon" but THEY ARE NEVER RELEASED. So we can handle Intel family 06 model 0A as "Pentium III Xeon" as documented in the Intel's CPUID specification.

CPU Architectures and Compiler Flags

Older versions of this page contained complete list of CPUIDs used. Now it has been moved to another page (x86 Families and Models) and "architecture" choices list is minimized. See corresponding "architecture name" in x86 Families and Models page.

VendorArchitectureChoices
Intel486
IntelQuark
IntelPentiumpentium
IntelPentium MMXpentium-mmx
IntelPentium Propentiumpro
IntelPentium IIpentium2
IntelPentium IIIpentium3
IntelPentium 4pentium4
IntelNocona / Prescottnocona / prescott
IntelPentium Mpentium-m
IntelCore (Yonah)yonah / pentium-m
IntelCore 2core2
IntelCore 2 (Penryn)penryn / core2
IntelNehalemnehalem / corei7
IntelWestmerewestmere / corei7
IntelSandy Bridgesandybridge / corei7-avx
IntelIvy Bridgeivybridge / core-avx-i
IntelHaswellhaswell / core-avx2
IntelBroadwellbroadwell / core-avx2
IntelBonnellbonnell / atom
IntelSilvermontsilvermont / slm / atom
AMDAm486
AMDAm5x86
AMDK5
AMDK6k6
AMDK6-2k6-2
AMDK6-3k6-3
AMDK7athlon
AMDK7 (Thunderbird)athlon-tbird
AMDK7 (Palomino+)athlon-xp
AMDK8athlon64
AMDK8 (rev.E+)athlon64-sse3
AMDK10barcelona / amdfam10
AMDBulldozerbdver1
AMDPiledriverbdver2
AMDSteamrollerbdver3
AMDBobcatbtver1
AMDJaguarbtver2
CentaurWinChip C6winchip-c6
CentaurWinChip 2winchip2
CentaurWinChip 3winchip2
CentaurWinChip-basedwinchip2
CentaurC3winchip2
CentaurC3-2c3-2
CentaurC7c3-2
CentaurIsaiahc3-2

CPU Models: Cannot be Confirmed

These patterns are removed from the original version of AX_GCC_ARCHFLAG macro. If "Remove All?" column is no, some of (not all) patterns are removed from the original version.

VendorFamily (hex)Model (hex)Remove All?ArchBrand namesChoices
Intel0604Yes
Intel060ANoPentium IIISee corresponding paragraph for detailspentium3
AMD0600Yes

Pattern Generator Code

The following code is used to generate pattern. This will work on Arch Linux + Python3. The license of this script is the ISC License (a variant of 2-clause BSD License).

#! /usr/bin/env python
#
#
# CPUID pattern generator
#
# Copyright (C) 2014 Tsukasa OI.
#
# Permission to use, copy, modify, and/or distribute this software for
# any purpose with or without fee is hereby granted, provided that the
# above copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
#
import sys
import re

# pattern to simplify:
# - O (oh)   : reserved bits as prefixes
# - 0 (zero) : zero
# - ?        : reserved or "any"
# - 1-9a-f   : corresponding hex representation
def simplify_pattern(pattern):
    pattern = re.sub('^([O]+[?]*|[O]*[?]+)', '*', pattern)
    return subsimplify_pattern(pattern)

def subsimplify_pattern(pattern):
    if (pattern.startswith('*0') or pattern.startswith('?0')) \
            and pattern != '*0' and pattern != '?0':
        return pattern + '|' + subsimplify_pattern(re.sub('^..', '', pattern))
    if pattern.startswith('0') and pattern != '0':
        return subsimplify_pattern(pattern[1:])
    if pattern.startswith('?') and pattern != '?':
        return pattern + '|' + subsimplify_pattern(pattern[1:])
    return pattern

def identify_intel(args):
    display_family = int(args[0], 16)
    display_model  = int(args[1], 16) if len(args) > 1 else '??'
    print('Identification for Intel:')
    print('\tDisplay Family : {:02x}'.format(display_family))
    if display_model == '??':
        print('\tDisplay Model  : ??')
    else:
        print('\tDisplay Model  : {:02x}'.format(display_model))
    if display_family >= 0x0f:
        family_0 = 'f'
        family_1 = '{:02x}'.format(display_family - 0x0f)
    else:
        family_0 = '{:01x}'.format(display_family)
        family_1 = 'OO'
    if display_model == '??':
        model_1 = '?'
        model_0 = '?'
    elif display_family >= 0x0f or display_family == 0x06:
        model_1 = '{:01x}'.format(display_model >> 4)
        model_0 = '{:01x}'.format(display_model & 0x0f)
    else:
        if display_model >= 0x10:
            raise ValueError()
        model_1 = 'O'
        model_0 = '{:01x}'.format(display_model)
    pattern = 'O{}{}?{}{}?'.format(family_1, model_1, family_0, model_0)
    print('\tPattern        : {}'.format(pattern))
    print('\tPatterns simpl : {}'.format(simplify_pattern(pattern)))

def identify_amd(args):
    display_family = int(args[0], 16)
    display_model  = int(args[1], 16) if len(args) > 1 else '??'
    print('Identification for AMD:')
    print('\tDisplay Family : {:02x}'.format(display_family))
    if display_model == '??':
        print('\tDisplay Model  : ??')
    else:
        print('\tDisplay Model  : {:02x}'.format(display_model))
    if display_family >= 0x0f:
        family_0 = 'f'
        family_1 = '{:02x}'.format(display_family - 0x0f)
    else:
        family_0 = '{:01x}'.format(display_family)
        family_1 = 'OO'
    if display_model == '??':
        model_1 = '?'
        model_0 = '?'
    elif display_family >= 0x0f:
        model_1 = '{:01x}'.format(display_model >> 4)
        model_0 = '{:01x}'.format(display_model & 0x0f)
    else:
        if display_model >= 0x10:
            raise ValueError()
        model_1 = 'O'
        model_0 = '{:01x}'.format(display_model)
    pattern = 'O{}{}?{}{}?'.format(family_1, model_1, family_0, model_0)
    print('\tPattern        : {}'.format(pattern))
    print('\tPatterns simpl : {}'.format(simplify_pattern(pattern)))

def identify_other_x86(args):
    display_family = int(args[0], 16)
    display_model  = int(args[1], 16) if len(args) > 1 else '?'
    print('Identification for VIA and other processors without extended family/model:')
    print('\tDisplay Family : {:01x}'.format(display_family))
    if display_model == '?':
        print('\tDisplay Model  : ?')
    else:
        print('\tDisplay Model  : {:01x}'.format(display_model))
    if display_family >= 0x10:
        raise ValueError()
    if display_model  >= 0x10:
        raise ValueError()
    pattern = 'OOO?{:01x}{}?'.format(display_family, '?' if display_model == '?' else '{:01x}'.format(display_model))
    print('\tPattern        : {}'.format(pattern))
    print('\tPatterns simpl : {}'.format(simplify_pattern(pattern)))

def identify_bitmask(hexsize, args):
    bitpos = int(args[0])
    bitval = 1
    if len(args) > 1:
        bitval = int(args[1])
    hexpos = bitpos % 4
    hexary = []
    print('Identification for {}-bit mask:'.format(hexsize*4))
    for i in range(16):
        if (i & (1 << hexpos)) == (bitval << hexpos):
            hexary.append('{:01x}'.format(i))
    for x in hexary:
        print('\tPattern : {}'.format(simplify_pattern((hexsize - 1 - bitpos//4) * 'O' + x + (bitpos//4) * '?')))

if sys.argv[1] == 'intel':
    identify_intel(sys.argv[2:])
elif sys.argv[1] == 'amd':
    identify_amd(sys.argv[2:])
elif sys.argv[1] == 'other':
    identify_other_x86(sys.argv[2:])
elif sys.argv[1] == '32bit':
    identify_bitmask(8, sys.argv[2:])