xref: /aosp_15_r20/external/libpng/contrib/arm-neon/linux.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
1*a67afe4dSAndroid Build Coastguard Worker /* contrib/arm-neon/linux.c
2*a67afe4dSAndroid Build Coastguard Worker  *
3*a67afe4dSAndroid Build Coastguard Worker  * Copyright (c) 2014, 2017 Glenn Randers-Pehrson
4*a67afe4dSAndroid Build Coastguard Worker  * Written by John Bowler, 2014, 2017.
5*a67afe4dSAndroid Build Coastguard Worker  *
6*a67afe4dSAndroid Build Coastguard Worker  * This code is released under the libpng license.
7*a67afe4dSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the disclaimer
8*a67afe4dSAndroid Build Coastguard Worker  * and license in png.h
9*a67afe4dSAndroid Build Coastguard Worker  *
10*a67afe4dSAndroid Build Coastguard Worker  * SEE contrib/arm-neon/README before reporting bugs
11*a67afe4dSAndroid Build Coastguard Worker  *
12*a67afe4dSAndroid Build Coastguard Worker  * STATUS: SUPPORTED
13*a67afe4dSAndroid Build Coastguard Worker  * BUG REPORTS: [email protected]
14*a67afe4dSAndroid Build Coastguard Worker  *
15*a67afe4dSAndroid Build Coastguard Worker  * png_have_neon implemented for Linux by reading the widely available
16*a67afe4dSAndroid Build Coastguard Worker  * pseudo-file /proc/cpuinfo.
17*a67afe4dSAndroid Build Coastguard Worker  *
18*a67afe4dSAndroid Build Coastguard Worker  * This code is strict ANSI-C and is probably moderately portable; it does
19*a67afe4dSAndroid Build Coastguard Worker  * however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
20*a67afe4dSAndroid Build Coastguard Worker  */
21*a67afe4dSAndroid Build Coastguard Worker 
22*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
23*a67afe4dSAndroid Build Coastguard Worker 
24*a67afe4dSAndroid Build Coastguard Worker static int
png_have_neon(png_structp png_ptr)25*a67afe4dSAndroid Build Coastguard Worker png_have_neon(png_structp png_ptr)
26*a67afe4dSAndroid Build Coastguard Worker {
27*a67afe4dSAndroid Build Coastguard Worker    FILE *f = fopen("/proc/cpuinfo", "rb");
28*a67afe4dSAndroid Build Coastguard Worker 
29*a67afe4dSAndroid Build Coastguard Worker    if (f != NULL)
30*a67afe4dSAndroid Build Coastguard Worker    {
31*a67afe4dSAndroid Build Coastguard Worker       /* This is a simple state machine which reads the input byte-by-byte until
32*a67afe4dSAndroid Build Coastguard Worker        * it gets a match on the 'neon' feature or reaches the end of the stream.
33*a67afe4dSAndroid Build Coastguard Worker        */
34*a67afe4dSAndroid Build Coastguard Worker       static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 };
35*a67afe4dSAndroid Build Coastguard Worker       static const char ch_neon[] = { 78, 69, 79, 78 };
36*a67afe4dSAndroid Build Coastguard Worker 
37*a67afe4dSAndroid Build Coastguard Worker       enum
38*a67afe4dSAndroid Build Coastguard Worker       {
39*a67afe4dSAndroid Build Coastguard Worker          StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine
40*a67afe4dSAndroid Build Coastguard Worker       }  state;
41*a67afe4dSAndroid Build Coastguard Worker       int counter;
42*a67afe4dSAndroid Build Coastguard Worker 
43*a67afe4dSAndroid Build Coastguard Worker       for (state=StartLine, counter=0;;)
44*a67afe4dSAndroid Build Coastguard Worker       {
45*a67afe4dSAndroid Build Coastguard Worker          int ch = fgetc(f);
46*a67afe4dSAndroid Build Coastguard Worker 
47*a67afe4dSAndroid Build Coastguard Worker          if (ch == EOF)
48*a67afe4dSAndroid Build Coastguard Worker          {
49*a67afe4dSAndroid Build Coastguard Worker             /* EOF means error or end-of-file, return false; neon at EOF is
50*a67afe4dSAndroid Build Coastguard Worker              * assumed to be a mistake.
51*a67afe4dSAndroid Build Coastguard Worker              */
52*a67afe4dSAndroid Build Coastguard Worker             fclose(f);
53*a67afe4dSAndroid Build Coastguard Worker             return 0;
54*a67afe4dSAndroid Build Coastguard Worker          }
55*a67afe4dSAndroid Build Coastguard Worker 
56*a67afe4dSAndroid Build Coastguard Worker          switch (state)
57*a67afe4dSAndroid Build Coastguard Worker          {
58*a67afe4dSAndroid Build Coastguard Worker             case StartLine:
59*a67afe4dSAndroid Build Coastguard Worker                /* Match spaces at the start of line */
60*a67afe4dSAndroid Build Coastguard Worker                if (ch <= 32) /* skip control characters and space */
61*a67afe4dSAndroid Build Coastguard Worker                   break;
62*a67afe4dSAndroid Build Coastguard Worker 
63*a67afe4dSAndroid Build Coastguard Worker                counter=0;
64*a67afe4dSAndroid Build Coastguard Worker                state = Feature;
65*a67afe4dSAndroid Build Coastguard Worker                /* FALLTHROUGH */
66*a67afe4dSAndroid Build Coastguard Worker 
67*a67afe4dSAndroid Build Coastguard Worker             case Feature:
68*a67afe4dSAndroid Build Coastguard Worker                /* Match 'FEATURE', ASCII case insensitive. */
69*a67afe4dSAndroid Build Coastguard Worker                if ((ch & ~0x20) == ch_feature[counter])
70*a67afe4dSAndroid Build Coastguard Worker                {
71*a67afe4dSAndroid Build Coastguard Worker                   if (++counter == (sizeof ch_feature))
72*a67afe4dSAndroid Build Coastguard Worker                      state = Colon;
73*a67afe4dSAndroid Build Coastguard Worker                   break;
74*a67afe4dSAndroid Build Coastguard Worker                }
75*a67afe4dSAndroid Build Coastguard Worker 
76*a67afe4dSAndroid Build Coastguard Worker                /* did not match 'feature' */
77*a67afe4dSAndroid Build Coastguard Worker                state = SkipLine;
78*a67afe4dSAndroid Build Coastguard Worker                /* FALLTHROUGH */
79*a67afe4dSAndroid Build Coastguard Worker 
80*a67afe4dSAndroid Build Coastguard Worker             case SkipLine:
81*a67afe4dSAndroid Build Coastguard Worker             skipLine:
82*a67afe4dSAndroid Build Coastguard Worker                /* Skip everything until we see linefeed or carriage return */
83*a67afe4dSAndroid Build Coastguard Worker                if (ch != 10 && ch != 13)
84*a67afe4dSAndroid Build Coastguard Worker                   break;
85*a67afe4dSAndroid Build Coastguard Worker 
86*a67afe4dSAndroid Build Coastguard Worker                state = StartLine;
87*a67afe4dSAndroid Build Coastguard Worker                break;
88*a67afe4dSAndroid Build Coastguard Worker 
89*a67afe4dSAndroid Build Coastguard Worker             case Colon:
90*a67afe4dSAndroid Build Coastguard Worker                /* Match any number of space or tab followed by ':' */
91*a67afe4dSAndroid Build Coastguard Worker                if (ch == 32 || ch == 9)
92*a67afe4dSAndroid Build Coastguard Worker                   break;
93*a67afe4dSAndroid Build Coastguard Worker 
94*a67afe4dSAndroid Build Coastguard Worker                if (ch == 58) /* i.e. ':' */
95*a67afe4dSAndroid Build Coastguard Worker                {
96*a67afe4dSAndroid Build Coastguard Worker                   state = StartTag;
97*a67afe4dSAndroid Build Coastguard Worker                   break;
98*a67afe4dSAndroid Build Coastguard Worker                }
99*a67afe4dSAndroid Build Coastguard Worker 
100*a67afe4dSAndroid Build Coastguard Worker                /* Either a bad line format or a 'feature' prefix followed by
101*a67afe4dSAndroid Build Coastguard Worker                 * other characters.
102*a67afe4dSAndroid Build Coastguard Worker                 */
103*a67afe4dSAndroid Build Coastguard Worker                state = SkipLine;
104*a67afe4dSAndroid Build Coastguard Worker                goto skipLine;
105*a67afe4dSAndroid Build Coastguard Worker 
106*a67afe4dSAndroid Build Coastguard Worker             case StartTag:
107*a67afe4dSAndroid Build Coastguard Worker                /* Skip space characters before a tag */
108*a67afe4dSAndroid Build Coastguard Worker                if (ch == 32 || ch == 9)
109*a67afe4dSAndroid Build Coastguard Worker                   break;
110*a67afe4dSAndroid Build Coastguard Worker 
111*a67afe4dSAndroid Build Coastguard Worker                state = Neon;
112*a67afe4dSAndroid Build Coastguard Worker                counter = 0;
113*a67afe4dSAndroid Build Coastguard Worker                /* FALLTHROUGH */
114*a67afe4dSAndroid Build Coastguard Worker 
115*a67afe4dSAndroid Build Coastguard Worker             case Neon:
116*a67afe4dSAndroid Build Coastguard Worker                /* Look for 'neon' tag */
117*a67afe4dSAndroid Build Coastguard Worker                if ((ch & ~0x20) == ch_neon[counter])
118*a67afe4dSAndroid Build Coastguard Worker                {
119*a67afe4dSAndroid Build Coastguard Worker                   if (++counter == (sizeof ch_neon))
120*a67afe4dSAndroid Build Coastguard Worker                      state = HaveNeon;
121*a67afe4dSAndroid Build Coastguard Worker                   break;
122*a67afe4dSAndroid Build Coastguard Worker                }
123*a67afe4dSAndroid Build Coastguard Worker 
124*a67afe4dSAndroid Build Coastguard Worker                state = SkipTag;
125*a67afe4dSAndroid Build Coastguard Worker                /* FALLTHROUGH */
126*a67afe4dSAndroid Build Coastguard Worker 
127*a67afe4dSAndroid Build Coastguard Worker             case SkipTag:
128*a67afe4dSAndroid Build Coastguard Worker                /* Skip non-space characters */
129*a67afe4dSAndroid Build Coastguard Worker                if (ch == 10 || ch == 13)
130*a67afe4dSAndroid Build Coastguard Worker                   state = StartLine;
131*a67afe4dSAndroid Build Coastguard Worker 
132*a67afe4dSAndroid Build Coastguard Worker                else if (ch == 32 || ch == 9)
133*a67afe4dSAndroid Build Coastguard Worker                   state = StartTag;
134*a67afe4dSAndroid Build Coastguard Worker                break;
135*a67afe4dSAndroid Build Coastguard Worker 
136*a67afe4dSAndroid Build Coastguard Worker             case HaveNeon:
137*a67afe4dSAndroid Build Coastguard Worker                /* Have seen a 'neon' prefix, but there must be a space or new
138*a67afe4dSAndroid Build Coastguard Worker                 * line character to terminate it.
139*a67afe4dSAndroid Build Coastguard Worker                 */
140*a67afe4dSAndroid Build Coastguard Worker                if (ch == 10 || ch == 13 || ch == 32 || ch == 9)
141*a67afe4dSAndroid Build Coastguard Worker                {
142*a67afe4dSAndroid Build Coastguard Worker                   fclose(f);
143*a67afe4dSAndroid Build Coastguard Worker                   return 1;
144*a67afe4dSAndroid Build Coastguard Worker                }
145*a67afe4dSAndroid Build Coastguard Worker 
146*a67afe4dSAndroid Build Coastguard Worker                state = SkipTag;
147*a67afe4dSAndroid Build Coastguard Worker                break;
148*a67afe4dSAndroid Build Coastguard Worker 
149*a67afe4dSAndroid Build Coastguard Worker             default:
150*a67afe4dSAndroid Build Coastguard Worker                png_error(png_ptr, "png_have_neon: internal error (bug)");
151*a67afe4dSAndroid Build Coastguard Worker          }
152*a67afe4dSAndroid Build Coastguard Worker       }
153*a67afe4dSAndroid Build Coastguard Worker    }
154*a67afe4dSAndroid Build Coastguard Worker 
155*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_WARNINGS_SUPPORTED
156*a67afe4dSAndroid Build Coastguard Worker    else
157*a67afe4dSAndroid Build Coastguard Worker       png_warning(png_ptr, "/proc/cpuinfo open failed");
158*a67afe4dSAndroid Build Coastguard Worker #endif
159*a67afe4dSAndroid Build Coastguard Worker 
160*a67afe4dSAndroid Build Coastguard Worker    return 0;
161*a67afe4dSAndroid Build Coastguard Worker }
162