1 /*
2  *  Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef IDEF_PARSER_H
19 #define IDEF_PARSER_H
20 
21 #include <inttypes.h>
22 #include <stdio.h>
23 #include <stdbool.h>
24 #include <glib.h>
25 
26 #define TCGV_NAME_SIZE 7
27 #define MAX_WRITTEN_REGS 32
28 #define OFFSET_STR_LEN 32
29 #define ALLOC_LIST_LEN 32
30 #define ALLOC_NAME_SIZE 32
31 #define INIT_LIST_LEN 32
32 #define OUT_BUF_LEN (1024 * 1024)
33 #define SIGNATURE_BUF_LEN (128 * 1024)
34 #define HEADER_BUF_LEN (128 * 1024)
35 
36 /* Variadic macros to wrap the buffer printing functions */
37 #define EMIT(c, ...)                                                           \
38     do {                                                                       \
39         g_string_append_printf((c)->out_str, __VA_ARGS__);                     \
40     } while (0)
41 
42 #define EMIT_SIG(c, ...)                                                       \
43     do {                                                                       \
44         g_string_append_printf((c)->signature_str, __VA_ARGS__);               \
45     } while (0)
46 
47 #define EMIT_HEAD(c, ...)                                                      \
48     do {                                                                       \
49         g_string_append_printf((c)->header_str, __VA_ARGS__);                  \
50     } while (0)
51 
52 /**
53  * Type of register, assigned to the HexReg.type field
54  */
55 typedef enum { GENERAL_PURPOSE, CONTROL, MODIFIER, DOTNEW } HexRegType;
56 
57 typedef enum { UNKNOWN_SIGNEDNESS, SIGNED, UNSIGNED } HexSignedness;
58 
59 /**
60  * Semantic record of the REG tokens, identifying registers
61  */
62 typedef struct HexReg {
63     uint8_t id;                 /**< Identifier of the register               */
64     HexRegType type;            /**< Type of the register                     */
65     unsigned bit_width;         /**< Bit width of the reg, 32 or 64 bits      */
66 } HexReg;
67 
68 /**
69  * Data structure, identifying a TCGv temporary value
70  */
71 typedef struct HexTmp {
72     unsigned index;             /**< Index of the TCGv temporary value        */
73 } HexTmp;
74 
75 /**
76  * Enum of the possible immediate, an immediate is a value which is known
77  * at tinycode generation time, e.g. an integer value, not a TCGv
78  */
79 enum ImmUnionTag {
80     I,
81     VARIABLE,
82     VALUE,
83     QEMU_TMP,
84     IMM_PC,
85     IMM_CONSTEXT,
86 };
87 
88 /**
89  * Semantic record of the IMM token, identifying an immediate constant
90  */
91 typedef struct HexImm {
92     union {
93         char id;                /**< Identifier, used when type is VARIABLE   */
94         uint64_t value;         /**< Immediate value, used when type is VALUE */
95         uint64_t index;         /**< Index, used when type is QEMU_TMP        */
96     };
97     enum ImmUnionTag type;      /**< Type of the immediate                    */
98 } HexImm;
99 
100 /**
101  * Semantic record of the PRED token, identifying a predicate
102  */
103 typedef struct HexPred {
104     char id;                    /**< Identifier of the predicate              */
105 } HexPred;
106 
107 /**
108  * Semantic record of the SAT token, identifying the saturate operator
109  * Note: All saturates are assumed to implicitly set overflow.
110  */
111 typedef struct HexSat {
112     HexSignedness signedness;   /**< Signedness of the sat. op.               */
113 } HexSat;
114 
115 /**
116  * Semantic record of the CAST token, identifying the cast operator
117  */
118 typedef struct HexCast {
119     unsigned bit_width;         /**< Bit width of the cast operator           */
120     HexSignedness signedness;   /**< Unsigned flag for the cast operator      */
121 } HexCast;
122 
123 /**
124  * Semantic record of the EXTRACT token, identifying the cast operator
125  */
126 typedef struct HexExtract {
127     unsigned bit_width;         /**< Bit width of the extract operator        */
128     unsigned storage_bit_width; /**< Actual bit width of the extract operator */
129     HexSignedness signedness;   /**< Unsigned flag for the extract operator   */
130 } HexExtract;
131 
132 /**
133  * Semantic record of the MPY token, identifying the fMPY multiplication
134  * operator
135  */
136 typedef struct HexMpy {
137     unsigned first_bit_width;        /**< Bit width of 1st operand of fMPY    */
138     unsigned second_bit_width;       /**< Bit width of 2nd operand of fMPY    */
139     HexSignedness first_signedness;  /**< Signedness of 1st operand of fMPY   */
140     HexSignedness second_signedness; /**< Signedness of 2nd operand of fMPY   */
141 } HexMpy;
142 
143 /**
144  * Semantic record of the VARID token, identifying declared variables
145  * of the input language
146  */
147 typedef struct HexVar {
148     GString *name;              /**< Name of the VARID variable               */
149 } HexVar;
150 
151 /**
152  * Data structure uniquely identifying a declared VARID variable, used for
153  * keeping track of declared variable, so that any variable is declared only
154  * once, and its properties are propagated through all the subsequent instances
155  * of that variable
156  */
157 typedef struct Var {
158     GString *name;              /**< Name of the VARID variable               */
159     uint8_t bit_width;          /**< Bit width of the VARID variable          */
160     HexSignedness signedness;   /**< Unsigned flag for the VARID var          */
161 } Var;
162 
163 /**
164  * Enum of the possible rvalue types, used in the HexValue.type field
165  */
166 typedef enum RvalueUnionTag {
167     REGISTER, REGISTER_ARG, TEMP, IMMEDIATE, PREDICATE, VARID
168 } RvalueUnionTag;
169 
170 /**
171  * Semantic record of the rvalue token, identifying any numeric value,
172  * immediate or register based. The rvalue tokens are combined together
173  * through the use of several operators, to encode expressions
174  */
175 typedef struct HexValue {
176     union {
177         HexReg reg;             /**< rvalue of register type                  */
178         HexTmp tmp;             /**< rvalue of temporary type                 */
179         HexImm imm;             /**< rvalue of immediate type                 */
180         HexPred pred;           /**< rvalue of predicate type                 */
181         HexVar var;             /**< rvalue of declared variable type         */
182     };
183     RvalueUnionTag type;        /**< Type of the rvalue                       */
184     unsigned bit_width;         /**< Bit width of the rvalue                  */
185     HexSignedness signedness;   /**< Unsigned flag for the rvalue             */
186     bool is_dotnew;             /**< rvalue of predicate type is dotnew?      */
187 } HexValue;
188 
189 /**
190  * State of ternary operator
191  */
192 typedef enum TernaryState { IN_LEFT, IN_RIGHT } TernaryState;
193 
194 /**
195  * Data structure used to handle side effects inside ternary operators
196  */
197 typedef struct Ternary {
198     TernaryState state;
199     HexValue cond;
200 } Ternary;
201 
202 /**
203  * Operator type, used for referencing the correct operator when calling the
204  * gen_bin_op() function, which in turn will generate the correct code to
205  * execute the operation between the two rvalues
206  */
207 typedef enum OpType {
208     ADD_OP, SUB_OP, MUL_OP, ASL_OP, ASR_OP, LSR_OP, ANDB_OP, ORB_OP,
209     XORB_OP, ANDL_OP, MINI_OP, MAXI_OP
210 } OpType;
211 
212 /**
213  * Data structure including instruction specific information, to be cleared
214  * out after the compilation of each instruction
215  */
216 typedef struct Inst {
217     GString *name;              /**< Name of the compiled instruction         */
218     char *code_begin;           /**< Beginning of instruction input code      */
219     char *code_end;             /**< End of instruction input code            */
220     unsigned tmp_count;         /**< Index of the last declared TCGv temp     */
221     unsigned qemu_tmp_count;    /**< Index of the last declared int temp      */
222     unsigned if_count;          /**< Index of the last declared if label      */
223     unsigned error_count;       /**< Number of generated errors               */
224     GArray *allocated;          /**< Allocated declaredVARID vars             */
225     GArray *init_list;          /**< List of initialized registers            */
226     GArray *strings;            /**< Strings allocated by the instruction     */
227 } Inst;
228 
229 /**
230  * Data structure representing the whole translation context, which in a
231  * reentrant flex/bison parser just like ours is passed between the scanner
232  * and the parser, holding all the necessary information to perform the
233  * parsing, this data structure survives between the compilation of different
234  * instructions
235  */
236 typedef struct Context {
237     void *scanner;              /**< Reentrant parser state pointer           */
238     char *input_buffer;         /**< Buffer containing the input code         */
239     GString *out_str;           /**< String containing the output code        */
240     GString *signature_str;     /**< String containing the signatures code    */
241     GString *header_str;        /**< String containing the header code        */
242     FILE *defines_file;         /**< FILE * of the generated header           */
243     FILE *output_file;          /**< FILE * of the C output file              */
244     FILE *enabled_file;         /**< FILE * of the list of enabled inst       */
245     GArray *ternary;            /**< Array to track nesting of ternary ops    */
246     unsigned total_insn;        /**< Number of instructions in input file     */
247     unsigned implemented_insn;  /**< Instruction compiled without errors      */
248     Inst inst;                  /**< Parsing data of the current inst         */
249 } Context;
250 
251 #endif /* IDEF_PARSER_H */
252