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)
20static 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
47static 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   }
60   else if (strcmp(feature, "mips32-dsp") == 0) {
61      const char *dsp = "dsp";
62      cpuinfo = mipsCPUInfo(dsp);
63      if (cpuinfo == 1) {
64         return FEATURE_PRESENT;
65      } else{
66         return FEATURE_NOT_PRESENT;
67      }
68   } else if (strcmp(feature, "mips32-dspr2") == 0) {
69      const char *dsp2 = "dsp2";
70      cpuinfo = mipsCPUInfo(dsp2);
71      if (cpuinfo == 1) {
72         return FEATURE_PRESENT;
73      } else{
74         return FEATURE_NOT_PRESENT;
75      }
76   } else if (strcmp(feature, "cavium-octeon") == 0) {
77      const char *cavium = "Cavium Octeon";
78      cpuinfo = mipsCPUInfo(cavium);
79      if (cpuinfo == 1) {
80         return FEATURE_PRESENT;
81      } else{
82         return FEATURE_NOT_PRESENT;
83      }
84   } else if (strcmp(feature, "cavium-octeon2") == 0) {
85      const char *cavium2 = "Cavium Octeon II";
86      cpuinfo = mipsCPUInfo(cavium2);
87      if (cpuinfo == 1) {
88         return FEATURE_PRESENT;
89      } else{
90         return FEATURE_NOT_PRESENT;
91      }
92   } else if (strcmp(feature, "mips-be") == 0) {
93#if defined (_MIPSEB)
94     return FEATURE_PRESENT;
95#else
96     return FEATURE_NOT_PRESENT;
97#endif
98   } else {
99      return UNRECOGNISED_FEATURE;
100   }
101
102}
103
104#else
105
106static int go(char *feature)
107{
108   /* Feature is not recognised. (non-MIPS machine!) */
109   return UNRECOGNISED_FEATURE;
110}
111
112#endif
113
114
115//---------------------------------------------------------------------------
116// main
117//---------------------------------------------------------------------------
118int main(int argc, char **argv)
119{
120   if (argc != 2) {
121      fprintf( stderr, "usage: mips_features <feature>\n" );
122      exit(USAGE_ERROR);
123   }
124   return go(argv[1]);
125}
126