1 // This file determines MIPS features a processor supports.
2 //
3 // We return:
4 // - 0 if the machine matches the asked-for feature.
5 // - 1 if the machine does not.
6 // - 2 if the asked-for feature isn't recognised (this will be the case for
7 //     any feature if run on a non-MIPS machine).
8 // - 3 if there was a usage error (it also prints an error message).
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <assert.h>
13 
14 #define FEATURE_PRESENT       0
15 #define FEATURE_NOT_PRESENT   1
16 #define UNRECOGNISED_FEATURE  2
17 #define USAGE_ERROR           3
18 
19 #if defined(VGA_mips32) || defined(VGA_mips64)
mipsCPUInfo(const char * search_string)20 static int mipsCPUInfo(const char *search_string) {
21    const char *file_name = "/proc/cpuinfo";
22    /* Simple detection of MIPS DSP ASE at runtime for Linux.
23    * It is based on /proc/cpuinfo, which reveals hardware configuration
24    * to user-space applications. */
25 
26    char cpuinfo_line[256];
27 
28    FILE *f = NULL;
29    if ((f = fopen (file_name, "r")) == NULL)
30      return 0;
31 
32    while (fgets (cpuinfo_line, sizeof (cpuinfo_line), f) != NULL)
33    {
34      if (strstr (cpuinfo_line, search_string) != NULL)
35      {
36          fclose (f);
37          return 1;
38      }
39    }
40 
41    fclose (f);
42 
43    /* Did not find string in the /proc/cpuinfo file. */
44    return 0;
45 }
46 
go(char * feature)47 static int go(char *feature)
48 {
49    int cpuinfo;
50    if (strcmp(feature, "fpu") == 0) {
51 #if defined(__mips_hard_float)
52       /* This is not a runtime detection.
53          If mips_features is built as hard-float, the assumption is that
54          the target MIPS platform has a floating-point unit. */
55       return FEATURE_PRESENT;
56 #else
57       return FEATURE_NOT_PRESENT;
58 #endif
59    } else if (strcmp(feature, "mips-msa") == 0) {
60       const char *msa = "msa";
61       cpuinfo = mipsCPUInfo(msa);
62       if (cpuinfo == 1) {
63          return FEATURE_PRESENT;
64       } else{
65          return FEATURE_NOT_PRESENT;
66       }
67    } else if (strcmp(feature, "mips32-dsp") == 0) {
68       const char *dsp = "dsp";
69       cpuinfo = mipsCPUInfo(dsp);
70       if (cpuinfo == 1) {
71          return FEATURE_PRESENT;
72       } else{
73          return FEATURE_NOT_PRESENT;
74       }
75    } else if (strcmp(feature, "mips32-dspr2") == 0) {
76       const char *dsp2 = "dsp2";
77       cpuinfo = mipsCPUInfo(dsp2);
78       if (cpuinfo == 1) {
79          return FEATURE_PRESENT;
80       } else{
81          return FEATURE_NOT_PRESENT;
82       }
83    } else if (strcmp(feature, "cavium-octeon") == 0) {
84       const char *cavium = "Cavium Octeon";
85       cpuinfo = mipsCPUInfo(cavium);
86       if (cpuinfo == 1) {
87          return FEATURE_PRESENT;
88       } else{
89          return FEATURE_NOT_PRESENT;
90       }
91    } else if (strcmp(feature, "cavium-octeon2") == 0) {
92       const char *cavium2 = "Cavium Octeon II";
93       cpuinfo = mipsCPUInfo(cavium2);
94       if (cpuinfo == 1) {
95          return FEATURE_PRESENT;
96       } else{
97          return FEATURE_NOT_PRESENT;
98       }
99    } else if (strcmp(feature, "mips-be") == 0) {
100 #if defined (_MIPSEB)
101      return FEATURE_PRESENT;
102 #else
103      return FEATURE_NOT_PRESENT;
104 #endif
105    } else if (strcmp(feature, "mipsr6") == 0) {
106 #if (__mips_isa_rev < 6)
107       return FEATURE_NOT_PRESENT;
108 #else
109       return FEATURE_PRESENT;
110 #endif
111    } else {
112       return UNRECOGNISED_FEATURE;
113    }
114 
115 }
116 
117 #else
118 
go(char * feature)119 static int go(char *feature)
120 {
121    /* Feature is not recognised. (non-MIPS machine!) */
122    return UNRECOGNISED_FEATURE;
123 }
124 
125 #endif
126 
127 
128 //---------------------------------------------------------------------------
129 // main
130 //---------------------------------------------------------------------------
main(int argc,char ** argv)131 int main(int argc, char **argv)
132 {
133    if (argc != 2) {
134       fprintf( stderr, "usage: mips_features <feature>\n" );
135       exit(USAGE_ERROR);
136    }
137    return go(argv[1]);
138 }
139