1 // Copyright 2017 Google Inc.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
19 #include "cpu_features_macros.h"
20 #include "cpuinfo_aarch64.h"
21 #include "cpuinfo_arm.h"
22 #include "cpuinfo_mips.h"
23 #include "cpuinfo_ppc.h"
24 #include "cpuinfo_x86.h"
26 static void PrintEscapedAscii(const char* str) {
28 for (; str && *str; ++str) {
45 static void PrintVoid(void) {}
46 static void PrintComma(void) { putchar(','); }
47 static void PrintLineFeed(void) { putchar('\n'); }
48 static void PrintOpenBrace(void) { putchar('{'); }
49 static void PrintCloseBrace(void) { putchar('}'); }
50 static void PrintOpenBracket(void) { putchar('['); }
51 static void PrintCloseBracket(void) { putchar(']'); }
52 static void PrintString(const char* field) { printf("%s", field); }
53 static void PrintAlignedHeader(const char* field) { printf("%-15s : ", field); }
54 static void PrintIntValue(int value) { printf("%d", value); }
55 static void PrintDecHexValue(int value) {
56 printf("%3d (0x%02X)", value, value);
58 static void PrintJsonHeader(const char* field) {
59 PrintEscapedAscii(field);
65 void (*ArrayStart)(void);
66 void (*ArraySeparator)(void);
67 void (*ArrayEnd)(void);
68 void (*PrintString)(const char* value);
69 void (*PrintValue)(int value);
70 void (*EndField)(void);
71 void (*StartField)(const char* field);
75 static Printer getJsonPrinter(void) {
77 .Start = &PrintOpenBrace,
78 .ArrayStart = &PrintOpenBracket,
79 .ArraySeparator = &PrintComma,
80 .ArrayEnd = &PrintCloseBracket,
81 .PrintString = &PrintEscapedAscii,
82 .PrintValue = &PrintIntValue,
83 .EndField = &PrintComma,
84 .StartField = &PrintJsonHeader,
85 .End = &PrintCloseBrace,
89 static Printer getTextPrinter(void) {
92 .ArrayStart = &PrintVoid,
93 .ArraySeparator = &PrintComma,
94 .ArrayEnd = &PrintVoid,
95 .PrintString = &PrintString,
96 .PrintValue = &PrintDecHexValue,
97 .EndField = &PrintLineFeed,
98 .StartField = &PrintAlignedHeader,
103 // Prints a named numeric value in both decimal and hexadecimal.
104 static void PrintN(const Printer p, const char* field, int value) {
110 // Prints a named string.
111 static void PrintS(const Printer p, const char* field, const char* value) {
113 p.PrintString(value);
117 static int cmp(const void* p1, const void* p2) {
118 return strcmp(*(const char* const*)p1, *(const char* const*)p2);
121 #define DEFINE_PRINT_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \
122 static void PrintFlags(const Printer p, const FeatureType* features) { \
124 const char* ptrs[LastEnum] = {0}; \
126 for (i = 0; i < LastEnum; ++i) { \
127 if (HasFeature(features, i)) { \
128 ptrs[count] = FeatureName(i); \
132 qsort(ptrs, count, sizeof(char*), cmp); \
133 p.StartField("flags"); \
135 for (i = 0; i < count; ++i) { \
136 if (i > 0) p.ArraySeparator(); \
137 p.PrintString(ptrs[i]); \
142 #if defined(CPU_FEATURES_ARCH_X86)
143 DEFINE_PRINT_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features,
145 #elif defined(CPU_FEATURES_ARCH_ARM)
146 DEFINE_PRINT_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures,
148 #elif defined(CPU_FEATURES_ARCH_AARCH64)
149 DEFINE_PRINT_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName,
150 Aarch64Features, AARCH64_LAST_)
151 #elif defined(CPU_FEATURES_ARCH_MIPS)
152 DEFINE_PRINT_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName,
153 MipsFeatures, MIPS_LAST_)
154 #elif defined(CPU_FEATURES_ARCH_PPC)
155 DEFINE_PRINT_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures,
159 static void PrintFeatures(const Printer printer) {
160 #if defined(CPU_FEATURES_ARCH_X86)
161 char brand_string[49];
162 const X86Info info = GetX86Info();
163 FillX86BrandString(brand_string);
164 PrintS(printer, "arch", "x86");
165 PrintS(printer, "brand", brand_string);
166 PrintN(printer, "family", info.family);
167 PrintN(printer, "model", info.model);
168 PrintN(printer, "stepping", info.stepping);
169 PrintS(printer, "uarch",
170 GetX86MicroarchitectureName(GetX86Microarchitecture(&info)));
171 PrintFlags(printer, &info.features);
172 #elif defined(CPU_FEATURES_ARCH_ARM)
173 const ArmInfo info = GetArmInfo();
174 PrintS(printer, "arch", "ARM");
175 PrintN(printer, "implementer", info.implementer);
176 PrintN(printer, "architecture", info.architecture);
177 PrintN(printer, "variant", info.variant);
178 PrintN(printer, "part", info.part);
179 PrintN(printer, "revision", info.revision);
180 PrintFlags(printer, &info.features);
181 #elif defined(CPU_FEATURES_ARCH_AARCH64)
182 const Aarch64Info info = GetAarch64Info();
183 PrintS(printer, "arch", "aarch64");
184 PrintN(printer, "implementer", info.implementer);
185 PrintN(printer, "variant", info.variant);
186 PrintN(printer, "part", info.part);
187 PrintN(printer, "revision", info.revision);
188 PrintFlags(printer, &info.features);
189 #elif defined(CPU_FEATURES_ARCH_MIPS)
190 const MipsInfo info = GetMipsInfo();
191 PrintS(printer, "arch", "mips");
192 PrintFlags(printer, &info.features);
193 #elif defined(CPU_FEATURES_ARCH_PPC)
194 const PPCInfo info = GetPPCInfo();
195 const PPCPlatformStrings strings = GetPPCPlatformStrings();
196 PrintS(printer, "arch", "ppc");
197 PrintS(printer, "platform", strings.platform);
198 PrintS(printer, "model", strings.model);
199 PrintS(printer, "machine", strings.machine);
200 PrintS(printer, "cpu", strings.cpu);
201 PrintS(printer, "instruction set", strings.type.platform);
202 PrintS(printer, "microarchitecture", strings.type.base_platform);
203 PrintFlags(printer, &info.features);
207 static void showUsage(const char* name) {
210 "Usage: %s [options]\n"
212 " -h | --help Show help message.\n"
213 " -j | --json Format output as json instead of plain text.\n"
218 int main(int argc, char** argv) {
219 Printer printer = getTextPrinter();
221 for (; i < argc; ++i) {
222 const char* arg = argv[i];
223 if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) {
224 printer = getJsonPrinter();
227 if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0)
233 PrintFeatures(printer);