mirror of
https://github.com/google/cpu_features.git
synced 2025-04-28 15:33:37 +02:00

Some PowerPC machines can operate in a mode that appears different to a process than the actual hardware. AT_PLATFORM indicates the supported instruction set and AT_BASE_PLATFORM indicates the actual microarchitecture of the hardware. Signed-off-by: Rashmica Gupta <rashmica.gupta@au1.ibm.com>
238 lines
8.2 KiB
C
238 lines
8.2 KiB
C
// Copyright 2017 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "cpu_features_macros.h"
|
|
#include "cpuinfo_aarch64.h"
|
|
#include "cpuinfo_arm.h"
|
|
#include "cpuinfo_mips.h"
|
|
#include "cpuinfo_ppc.h"
|
|
#include "cpuinfo_x86.h"
|
|
|
|
static void PrintEscapedAscii(const char* str) {
|
|
putchar('"');
|
|
for (; str && *str; ++str) {
|
|
switch (*str) {
|
|
case '\"':
|
|
case '\\':
|
|
case '/':
|
|
case '\b':
|
|
case '\f':
|
|
case '\n':
|
|
case '\r':
|
|
case '\t':
|
|
putchar('\\');
|
|
}
|
|
putchar(*str);
|
|
}
|
|
putchar('"');
|
|
}
|
|
|
|
static void PrintVoid(void) {}
|
|
static void PrintComma(void) { putchar(','); }
|
|
static void PrintLineFeed(void) { putchar('\n'); }
|
|
static void PrintOpenBrace(void) { putchar('{'); }
|
|
static void PrintCloseBrace(void) { putchar('}'); }
|
|
static void PrintOpenBracket(void) { putchar('['); }
|
|
static void PrintCloseBracket(void) { putchar(']'); }
|
|
static void PrintString(const char* field) { printf("%s", field); }
|
|
static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
|
|
static void PrintIntValue(int value) { printf("%d", value); }
|
|
static void PrintDecHexValue(int value) {
|
|
printf("%3d (0x%02X)", value, value);
|
|
}
|
|
static void PrintJsonHeader(const char* field) {
|
|
PrintEscapedAscii(field);
|
|
putchar(':');
|
|
}
|
|
|
|
typedef struct {
|
|
void (*Start)(void);
|
|
void (*ArrayStart)(void);
|
|
void (*ArraySeparator)(void);
|
|
void (*ArrayEnd)(void);
|
|
void (*PrintString)(const char* value);
|
|
void (*PrintValue)(int value);
|
|
void (*EndField)(void);
|
|
void (*StartField)(const char* field);
|
|
void (*End)(void);
|
|
} Printer;
|
|
|
|
static Printer getJsonPrinter(void) {
|
|
return (Printer){
|
|
.Start = &PrintOpenBrace,
|
|
.ArrayStart = &PrintOpenBracket,
|
|
.ArraySeparator = &PrintComma,
|
|
.ArrayEnd = &PrintCloseBracket,
|
|
.PrintString = &PrintEscapedAscii,
|
|
.PrintValue = &PrintIntValue,
|
|
.EndField = &PrintComma,
|
|
.StartField = &PrintJsonHeader,
|
|
.End = &PrintCloseBrace,
|
|
};
|
|
}
|
|
|
|
static Printer getTextPrinter(void) {
|
|
return (Printer){
|
|
.Start = &PrintVoid,
|
|
.ArrayStart = &PrintVoid,
|
|
.ArraySeparator = &PrintComma,
|
|
.ArrayEnd = &PrintVoid,
|
|
.PrintString = &PrintString,
|
|
.PrintValue = &PrintDecHexValue,
|
|
.EndField = &PrintLineFeed,
|
|
.StartField = &PrintAlignedHeader,
|
|
.End = &PrintVoid,
|
|
};
|
|
}
|
|
|
|
// Prints a named numeric value in both decimal and hexadecimal.
|
|
static void PrintN(const Printer p, const char* field, int value) {
|
|
p.StartField(field);
|
|
p.PrintValue(value);
|
|
p.EndField();
|
|
}
|
|
|
|
// Prints a named string.
|
|
static void PrintS(const Printer p, const char* field, const char* value) {
|
|
p.StartField(field);
|
|
p.PrintString(value);
|
|
p.EndField();
|
|
}
|
|
|
|
static int cmp(const void* p1, const void* p2) {
|
|
return strcmp(*(const char* const*)p1, *(const char* const*)p2);
|
|
}
|
|
|
|
#define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
|
|
static void PrintFlags(const Printer p, const FeatureType* features) { \
|
|
size_t i; \
|
|
const char* ptrs[LastEnum] = {0}; \
|
|
size_t count = 0; \
|
|
for (i = 0; i < LastEnum; ++i) { \
|
|
if (HasFeature(features, i)) { \
|
|
ptrs[count] = FeatureName(i); \
|
|
++count; \
|
|
} \
|
|
} \
|
|
qsort(ptrs, count, sizeof(char*), cmp); \
|
|
p.StartField("flags"); \
|
|
p.ArrayStart(); \
|
|
for (i = 0; i < count; ++i) { \
|
|
if (i > 0) p.ArraySeparator(); \
|
|
p.PrintString(ptrs[i]); \
|
|
} \
|
|
p.ArrayEnd(); \
|
|
}
|
|
|
|
#if defined(CPU_FEATURES_ARCH_X86)
|
|
DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
|
|
X86_LAST_)
|
|
#elif defined(CPU_FEATURES_ARCH_ARM)
|
|
DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
|
|
ARM_LAST_)
|
|
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
|
DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
|
|
Aarch64Features, AARCH64_LAST_)
|
|
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
|
DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
|
|
MipsFeatures, MIPS_LAST_)
|
|
#elif defined(CPU_FEATURES_ARCH_PPC)
|
|
DEFINE_PRINT_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
|
|
PPC_LAST_)
|
|
#endif
|
|
|
|
static void PrintFeatures(const Printer printer) {
|
|
#if defined(CPU_FEATURES_ARCH_X86)
|
|
char brand_string[49];
|
|
const X86Info info = GetX86Info();
|
|
FillX86BrandString(brand_string);
|
|
PrintS(printer, "arch", "x86");
|
|
PrintS(printer, "brand", brand_string);
|
|
PrintN(printer, "family", info.family);
|
|
PrintN(printer, "model", info.model);
|
|
PrintN(printer, "stepping", info.stepping);
|
|
PrintS(printer, "uarch",
|
|
GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
|
|
PrintFlags(printer, &info.features);
|
|
#elif defined(CPU_FEATURES_ARCH_ARM)
|
|
const ArmInfo info = GetArmInfo();
|
|
PrintS(printer, "arch", "ARM");
|
|
PrintN(printer, "implementer", info.implementer);
|
|
PrintN(printer, "architecture", info.architecture);
|
|
PrintN(printer, "variant", info.variant);
|
|
PrintN(printer, "part", info.part);
|
|
PrintN(printer, "revision", info.revision);
|
|
PrintFlags(printer, &info.features);
|
|
#elif defined(CPU_FEATURES_ARCH_AARCH64)
|
|
const Aarch64Info info = GetAarch64Info();
|
|
PrintS(printer, "arch", "aarch64");
|
|
PrintN(printer, "implementer", info.implementer);
|
|
PrintN(printer, "variant", info.variant);
|
|
PrintN(printer, "part", info.part);
|
|
PrintN(printer, "revision", info.revision);
|
|
PrintFlags(printer, &info.features);
|
|
#elif defined(CPU_FEATURES_ARCH_MIPS)
|
|
const MipsInfo info = GetMipsInfo();
|
|
PrintS(printer, "arch", "mips");
|
|
PrintFlags(printer, &info.features);
|
|
#elif defined(CPU_FEATURES_ARCH_PPC)
|
|
const PPCInfo info = GetPPCInfo();
|
|
const PPCPlatformStrings strings = GetPPCPlatformStrings();
|
|
PrintS(printer, "arch", "ppc");
|
|
PrintS(printer, "platform", strings.platform);
|
|
PrintS(printer, "model", strings.model);
|
|
PrintS(printer, "machine", strings.machine);
|
|
PrintS(printer, "cpu", strings.cpu);
|
|
PrintS(printer, "instruction set", strings.type.platform);
|
|
PrintS(printer, "microarchitecture", strings.type.base_platform);
|
|
PrintFlags(printer, &info.features);
|
|
#endif
|
|
}
|
|
|
|
static void showUsage(const char* name) {
|
|
printf(
|
|
"\n"
|
|
"Usage: %s [options]\n"
|
|
" Options:\n"
|
|
" -h | --help Show help message.\n"
|
|
" -j | --json Format output as json instead of plain text.\n"
|
|
"\n",
|
|
name);
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
Printer printer = getTextPrinter();
|
|
int i = 1;
|
|
for (; i < argc; ++i) {
|
|
const char* arg = argv[i];
|
|
if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
|
|
printer = getJsonPrinter();
|
|
} else {
|
|
showUsage(argv[0]);
|
|
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
|
|
return EXIT_SUCCESS;
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|
|
printer.Start();
|
|
PrintFeatures(printer);
|
|
printer.End();
|
|
PrintLineFeed();
|
|
return EXIT_SUCCESS;
|
|
}
|