xref: /linux-6.15/scripts/dtc/dtc-parser.y (revision 12d638f4)
112869ecdSRob Herring // SPDX-License-Identifier: GPL-2.0-or-later
29fffb55fSDavid Gibson /*
39fffb55fSDavid Gibson  * (C) Copyright David Gibson <[email protected]>, IBM Corporation.  2005.
49fffb55fSDavid Gibson  */
50cec114eSRob Herring %locations
60cec114eSRob Herring 
79fffb55fSDavid Gibson %{
89fffb55fSDavid Gibson #include <stdio.h>
96f05afcbSRob Herring #include <inttypes.h>
109fffb55fSDavid Gibson 
119fffb55fSDavid Gibson #include "dtc.h"
129fffb55fSDavid Gibson #include "srcpos.h"
139fffb55fSDavid Gibson 
149fffb55fSDavid Gibson extern int yylex(void);
15658f29a5SJohn Bonesio extern void yyerror(char const *s);
1647605971SRob Herring #define ERROR(loc, ...) \
1747605971SRob Herring 	do { \
1847605971SRob Herring 		srcpos_error((loc), "Error", __VA_ARGS__); \
1947605971SRob Herring 		treesource_error = true; \
2047605971SRob Herring 	} while (0)
219fffb55fSDavid Gibson 
220cec114eSRob Herring #define YYERROR_CALL(msg) yyerror(msg)
230cec114eSRob Herring 
246f05afcbSRob Herring extern struct dt_info *parser_output;
2547605971SRob Herring extern bool treesource_error;
26ea3723a5SRob Herring 
is_ref_relative(const char * ref)27ea3723a5SRob Herring static bool is_ref_relative(const char *ref)
28ea3723a5SRob Herring {
29ea3723a5SRob Herring 	return ref[0] != '/' && strchr(&ref[1], '/');
30ea3723a5SRob Herring }
31ea3723a5SRob Herring 
329fffb55fSDavid Gibson %}
339fffb55fSDavid Gibson 
349fffb55fSDavid Gibson %union {
359fffb55fSDavid Gibson 	char *propnodename;
369fffb55fSDavid Gibson 	char *labelref;
379fffb55fSDavid Gibson 	uint8_t byte;
389fffb55fSDavid Gibson 	struct data data;
399fffb55fSDavid Gibson 
40cd296721SStephen Warren 	struct {
41cd296721SStephen Warren 		struct data	data;
42cd296721SStephen Warren 		int		bits;
43cd296721SStephen Warren 	} array;
44cd296721SStephen Warren 
459fffb55fSDavid Gibson 	struct property *prop;
469fffb55fSDavid Gibson 	struct property *proplist;
479fffb55fSDavid Gibson 	struct node *node;
489fffb55fSDavid Gibson 	struct node *nodelist;
499fffb55fSDavid Gibson 	struct reserve_info *re;
50cd296721SStephen Warren 	uint64_t integer;
516f05afcbSRob Herring 	unsigned int flags;
529fffb55fSDavid Gibson }
539fffb55fSDavid Gibson 
549fffb55fSDavid Gibson %token DT_V1
556f05afcbSRob Herring %token DT_PLUGIN
569fffb55fSDavid Gibson %token DT_MEMRESERVE
57cd296721SStephen Warren %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
58cd296721SStephen Warren %token DT_BITS
59cd296721SStephen Warren %token DT_DEL_PROP
60cd296721SStephen Warren %token DT_DEL_NODE
6150aafd60SRob Herring %token DT_OMIT_NO_REF
629fffb55fSDavid Gibson %token <propnodename> DT_PROPNODENAME
6347605971SRob Herring %token <integer> DT_LITERAL
6447605971SRob Herring %token <integer> DT_CHAR_LITERAL
659fffb55fSDavid Gibson %token <byte> DT_BYTE
669fffb55fSDavid Gibson %token <data> DT_STRING
679fffb55fSDavid Gibson %token <labelref> DT_LABEL
68c2e7075cSRob Herring %token <labelref> DT_LABEL_REF
69c2e7075cSRob Herring %token <labelref> DT_PATH_REF
709fffb55fSDavid Gibson %token DT_INCBIN
719fffb55fSDavid Gibson 
729fffb55fSDavid Gibson %type <data> propdata
739fffb55fSDavid Gibson %type <data> propdataprefix
746f05afcbSRob Herring %type <flags> header
756f05afcbSRob Herring %type <flags> headers
769fffb55fSDavid Gibson %type <re> memreserve
779fffb55fSDavid Gibson %type <re> memreserves
78cd296721SStephen Warren %type <array> arrayprefix
799fffb55fSDavid Gibson %type <data> bytestring
809fffb55fSDavid Gibson %type <prop> propdef
819fffb55fSDavid Gibson %type <proplist> proplist
82c2e7075cSRob Herring %type <labelref> dt_ref
839fffb55fSDavid Gibson 
849fffb55fSDavid Gibson %type <node> devicetree
859fffb55fSDavid Gibson %type <node> nodedef
869fffb55fSDavid Gibson %type <node> subnode
879fffb55fSDavid Gibson %type <nodelist> subnodes
889fffb55fSDavid Gibson 
89cd296721SStephen Warren %type <integer> integer_prim
90cd296721SStephen Warren %type <integer> integer_unary
91cd296721SStephen Warren %type <integer> integer_mul
92cd296721SStephen Warren %type <integer> integer_add
93cd296721SStephen Warren %type <integer> integer_shift
94cd296721SStephen Warren %type <integer> integer_rela
95cd296721SStephen Warren %type <integer> integer_eq
96cd296721SStephen Warren %type <integer> integer_bitand
97cd296721SStephen Warren %type <integer> integer_bitxor
98cd296721SStephen Warren %type <integer> integer_bitor
99cd296721SStephen Warren %type <integer> integer_and
100cd296721SStephen Warren %type <integer> integer_or
101cd296721SStephen Warren %type <integer> integer_trinary
102cd296721SStephen Warren %type <integer> integer_expr
103cd296721SStephen Warren 
1049fffb55fSDavid Gibson %%
1059fffb55fSDavid Gibson 
1069fffb55fSDavid Gibson sourcefile:
1076f05afcbSRob Herring 	  headers memreserves devicetree
1089fffb55fSDavid Gibson 		{
1096f05afcbSRob Herring 			parser_output = build_dt_info($1, $2, $3,
1106f05afcbSRob Herring 			                              guess_boot_cpuid($3));
1116f05afcbSRob Herring 		}
1126f05afcbSRob Herring 	;
1136f05afcbSRob Herring 
1146f05afcbSRob Herring header:
1156f05afcbSRob Herring 	  DT_V1 ';'
1166f05afcbSRob Herring 		{
1176f05afcbSRob Herring 			$$ = DTSF_V1;
1186f05afcbSRob Herring 		}
1196f05afcbSRob Herring 	| DT_V1 ';' DT_PLUGIN ';'
1206f05afcbSRob Herring 		{
1216f05afcbSRob Herring 			$$ = DTSF_V1 | DTSF_PLUGIN;
1226f05afcbSRob Herring 		}
1236f05afcbSRob Herring 	;
1246f05afcbSRob Herring 
1256f05afcbSRob Herring headers:
1266f05afcbSRob Herring 	  header
1276f05afcbSRob Herring 	| header headers
1286f05afcbSRob Herring 		{
1296f05afcbSRob Herring 			if ($2 != $1)
1306f05afcbSRob Herring 				ERROR(&@2, "Header flags don't match earlier ones");
1316f05afcbSRob Herring 			$$ = $1;
1329fffb55fSDavid Gibson 		}
1339fffb55fSDavid Gibson 	;
1349fffb55fSDavid Gibson 
1359fffb55fSDavid Gibson memreserves:
1369fffb55fSDavid Gibson 	  /* empty */
1379fffb55fSDavid Gibson 		{
1389fffb55fSDavid Gibson 			$$ = NULL;
1399fffb55fSDavid Gibson 		}
1409fffb55fSDavid Gibson 	| memreserve memreserves
1419fffb55fSDavid Gibson 		{
1429fffb55fSDavid Gibson 			$$ = chain_reserve_entry($1, $2);
1439fffb55fSDavid Gibson 		}
1449fffb55fSDavid Gibson 	;
1459fffb55fSDavid Gibson 
1469fffb55fSDavid Gibson memreserve:
147cd296721SStephen Warren 	  DT_MEMRESERVE integer_prim integer_prim ';'
1489fffb55fSDavid Gibson 		{
149658f29a5SJohn Bonesio 			$$ = build_reserve_entry($2, $3);
1509fffb55fSDavid Gibson 		}
151658f29a5SJohn Bonesio 	| DT_LABEL memreserve
1529fffb55fSDavid Gibson 		{
153658f29a5SJohn Bonesio 			add_label(&$2->labels, $1);
154658f29a5SJohn Bonesio 			$$ = $2;
1559fffb55fSDavid Gibson 		}
1569fffb55fSDavid Gibson 	;
1579fffb55fSDavid Gibson 
158c2e7075cSRob Herring dt_ref: DT_LABEL_REF | DT_PATH_REF;
159c2e7075cSRob Herring 
1609fffb55fSDavid Gibson devicetree:
1619fffb55fSDavid Gibson 	  '/' nodedef
1629fffb55fSDavid Gibson 		{
163658f29a5SJohn Bonesio 			$$ = name_node($2, "");
164658f29a5SJohn Bonesio 		}
165658f29a5SJohn Bonesio 	| devicetree '/' nodedef
166658f29a5SJohn Bonesio 		{
167658f29a5SJohn Bonesio 			$$ = merge_nodes($1, $3);
168658f29a5SJohn Bonesio 		}
169c2e7075cSRob Herring 	| dt_ref nodedef
1709130ba88SRob Herring 		{
1719130ba88SRob Herring 			/*
1729130ba88SRob Herring 			 * We rely on the rule being always:
1739130ba88SRob Herring 			 *   versioninfo plugindecl memreserves devicetree
1749130ba88SRob Herring 			 * so $-1 is what we want (plugindecl)
1759130ba88SRob Herring 			 */
1769130ba88SRob Herring 			if (!($<flags>-1 & DTSF_PLUGIN))
1779130ba88SRob Herring 				ERROR(&@2, "Label or path %s not found", $1);
178ea3723a5SRob Herring 			else if (is_ref_relative($1))
179ea3723a5SRob Herring 				ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
180c2e7075cSRob Herring 			$$ = add_orphan_node(
181c2e7075cSRob Herring 					name_node(build_node(NULL, NULL, NULL),
182c2e7075cSRob Herring 						  ""),
183c2e7075cSRob Herring 					$2, $1);
1849130ba88SRob Herring 		}
185c2e7075cSRob Herring 	| devicetree DT_LABEL dt_ref nodedef
18647605971SRob Herring 		{
18747605971SRob Herring 			struct node *target = get_node_by_ref($1, $3);
18847605971SRob Herring 
189ea3723a5SRob Herring 			if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
190ea3723a5SRob Herring 				ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
191ea3723a5SRob Herring 
19289d12310SRob Herring 			if (target) {
19347605971SRob Herring 				add_label(&target->labels, $2);
19447605971SRob Herring 				merge_nodes(target, $4);
19589d12310SRob Herring 			} else
19647605971SRob Herring 				ERROR(&@3, "Label or path %s not found", $3);
19747605971SRob Herring 			$$ = $1;
19847605971SRob Herring 		}
199c2e7075cSRob Herring 	| devicetree DT_PATH_REF nodedef
200658f29a5SJohn Bonesio 		{
2014201d057SRob Herring 			/*
2024201d057SRob Herring 			 * We rely on the rule being always:
2034201d057SRob Herring 			 *   versioninfo plugindecl memreserves devicetree
2044201d057SRob Herring 			 * so $-1 is what we want (plugindecl)
2054201d057SRob Herring 			 */
20650aafd60SRob Herring 			if ($<flags>-1 & DTSF_PLUGIN) {
207ea3723a5SRob Herring 				if (is_ref_relative($2))
208ea3723a5SRob Herring 					ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
2094201d057SRob Herring 				add_orphan_node($1, $3, $2);
21050aafd60SRob Herring 			} else {
21150aafd60SRob Herring 				struct node *target = get_node_by_ref($1, $2);
21250aafd60SRob Herring 
21350aafd60SRob Herring 				if (target)
21450aafd60SRob Herring 					merge_nodes(target, $3);
215658f29a5SJohn Bonesio 				else
21647605971SRob Herring 					ERROR(&@2, "Label or path %s not found", $2);
2174201d057SRob Herring 			}
218658f29a5SJohn Bonesio 			$$ = $1;
2199fffb55fSDavid Gibson 		}
220c2e7075cSRob Herring 	| devicetree DT_LABEL_REF nodedef
221c2e7075cSRob Herring 		{
222c2e7075cSRob Herring 			struct node *target = get_node_by_ref($1, $2);
223c2e7075cSRob Herring 
224c2e7075cSRob Herring 			if (target) {
225c2e7075cSRob Herring 				merge_nodes(target, $3);
226c2e7075cSRob Herring 			} else {
227c2e7075cSRob Herring 				/*
228c2e7075cSRob Herring 				 * We rely on the rule being always:
229c2e7075cSRob Herring 				 *   versioninfo plugindecl memreserves devicetree
230c2e7075cSRob Herring 				 * so $-1 is what we want (plugindecl)
231c2e7075cSRob Herring 				 */
232c2e7075cSRob Herring 				if ($<flags>-1 & DTSF_PLUGIN)
233c2e7075cSRob Herring 					add_orphan_node($1, $3, $2);
234c2e7075cSRob Herring 				else
235c2e7075cSRob Herring 					ERROR(&@2, "Label or path %s not found", $2);
236c2e7075cSRob Herring 			}
237c2e7075cSRob Herring 			$$ = $1;
238c2e7075cSRob Herring 		}
239c2e7075cSRob Herring 	| devicetree DT_DEL_NODE dt_ref ';'
240cd296721SStephen Warren 		{
241cd296721SStephen Warren 			struct node *target = get_node_by_ref($1, $3);
242cd296721SStephen Warren 
24347605971SRob Herring 			if (target)
244cd296721SStephen Warren 				delete_node(target);
24547605971SRob Herring 			else
24647605971SRob Herring 				ERROR(&@3, "Label or path %s not found", $3);
24747605971SRob Herring 
248cd296721SStephen Warren 
249cd296721SStephen Warren 			$$ = $1;
250cd296721SStephen Warren 		}
251c2e7075cSRob Herring 	| devicetree DT_OMIT_NO_REF dt_ref ';'
25250aafd60SRob Herring 		{
25350aafd60SRob Herring 			struct node *target = get_node_by_ref($1, $3);
25450aafd60SRob Herring 
25550aafd60SRob Herring 			if (target)
25650aafd60SRob Herring 				omit_node_if_unused(target);
25750aafd60SRob Herring 			else
25850aafd60SRob Herring 				ERROR(&@3, "Label or path %s not found", $3);
25950aafd60SRob Herring 
26050aafd60SRob Herring 
26150aafd60SRob Herring 			$$ = $1;
26250aafd60SRob Herring 		}
2639fffb55fSDavid Gibson 	;
2649fffb55fSDavid Gibson 
2659fffb55fSDavid Gibson nodedef:
2669fffb55fSDavid Gibson 	  '{' proplist subnodes '}' ';'
2679fffb55fSDavid Gibson 		{
268c2e7075cSRob Herring 			$$ = build_node($2, $3, &@$);
2699fffb55fSDavid Gibson 		}
2709fffb55fSDavid Gibson 	;
2719fffb55fSDavid Gibson 
2729fffb55fSDavid Gibson proplist:
2739fffb55fSDavid Gibson 	  /* empty */
2749fffb55fSDavid Gibson 		{
2759fffb55fSDavid Gibson 			$$ = NULL;
2769fffb55fSDavid Gibson 		}
2779fffb55fSDavid Gibson 	| proplist propdef
2789fffb55fSDavid Gibson 		{
2799fffb55fSDavid Gibson 			$$ = chain_property($2, $1);
2809fffb55fSDavid Gibson 		}
2819fffb55fSDavid Gibson 	;
2829fffb55fSDavid Gibson 
2839fffb55fSDavid Gibson propdef:
284658f29a5SJohn Bonesio 	  DT_PROPNODENAME '=' propdata ';'
2859fffb55fSDavid Gibson 		{
286c2e7075cSRob Herring 			$$ = build_property($1, $3, &@$);
287*12d638f4SRob Herring (Arm) 			free($1);
2889fffb55fSDavid Gibson 		}
289658f29a5SJohn Bonesio 	| DT_PROPNODENAME ';'
2909fffb55fSDavid Gibson 		{
291c2e7075cSRob Herring 			$$ = build_property($1, empty_data, &@$);
292*12d638f4SRob Herring (Arm) 			free($1);
293658f29a5SJohn Bonesio 		}
294cd296721SStephen Warren 	| DT_DEL_PROP DT_PROPNODENAME ';'
295cd296721SStephen Warren 		{
296cd296721SStephen Warren 			$$ = build_property_delete($2);
297*12d638f4SRob Herring (Arm) 			free($2);
298cd296721SStephen Warren 		}
299658f29a5SJohn Bonesio 	| DT_LABEL propdef
300658f29a5SJohn Bonesio 		{
301658f29a5SJohn Bonesio 			add_label(&$2->labels, $1);
302658f29a5SJohn Bonesio 			$$ = $2;
3039fffb55fSDavid Gibson 		}
3049fffb55fSDavid Gibson 	;
3059fffb55fSDavid Gibson 
3069fffb55fSDavid Gibson propdata:
3079fffb55fSDavid Gibson 	  propdataprefix DT_STRING
3089fffb55fSDavid Gibson 		{
3099fffb55fSDavid Gibson 			$$ = data_merge($1, $2);
3109fffb55fSDavid Gibson 		}
311cd296721SStephen Warren 	| propdataprefix arrayprefix '>'
3129fffb55fSDavid Gibson 		{
313cd296721SStephen Warren 			$$ = data_merge($1, $2.data);
3149fffb55fSDavid Gibson 		}
3159fffb55fSDavid Gibson 	| propdataprefix '[' bytestring ']'
3169fffb55fSDavid Gibson 		{
3179fffb55fSDavid Gibson 			$$ = data_merge($1, $3);
3189fffb55fSDavid Gibson 		}
319c2e7075cSRob Herring 	| propdataprefix dt_ref
3209fffb55fSDavid Gibson 		{
321f858927fSRob Herring 			$1 = data_add_marker($1, TYPE_STRING, $2);
3229fffb55fSDavid Gibson 			$$ = data_add_marker($1, REF_PATH, $2);
3239fffb55fSDavid Gibson 		}
324cd296721SStephen Warren 	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
3259fffb55fSDavid Gibson 		{
326658f29a5SJohn Bonesio 			FILE *f = srcfile_relative_open($4.val, NULL);
327658f29a5SJohn Bonesio 			struct data d;
3289fffb55fSDavid Gibson 
3299fffb55fSDavid Gibson 			if ($6 != 0)
330658f29a5SJohn Bonesio 				if (fseek(f, $6, SEEK_SET) != 0)
33147605971SRob Herring 					die("Couldn't seek to offset %llu in \"%s\": %s",
33247605971SRob Herring 					    (unsigned long long)$6, $4.val,
333658f29a5SJohn Bonesio 					    strerror(errno));
3349fffb55fSDavid Gibson 
335658f29a5SJohn Bonesio 			d = data_copy_file(f, $8);
3369fffb55fSDavid Gibson 
3379fffb55fSDavid Gibson 			$$ = data_merge($1, d);
338658f29a5SJohn Bonesio 			fclose(f);
3399fffb55fSDavid Gibson 		}
3409fffb55fSDavid Gibson 	| propdataprefix DT_INCBIN '(' DT_STRING ')'
3419fffb55fSDavid Gibson 		{
342658f29a5SJohn Bonesio 			FILE *f = srcfile_relative_open($4.val, NULL);
3439fffb55fSDavid Gibson 			struct data d = empty_data;
3449fffb55fSDavid Gibson 
345658f29a5SJohn Bonesio 			d = data_copy_file(f, -1);
3469fffb55fSDavid Gibson 
3479fffb55fSDavid Gibson 			$$ = data_merge($1, d);
348658f29a5SJohn Bonesio 			fclose(f);
3499fffb55fSDavid Gibson 		}
3509fffb55fSDavid Gibson 	| propdata DT_LABEL
3519fffb55fSDavid Gibson 		{
3529fffb55fSDavid Gibson 			$$ = data_add_marker($1, LABEL, $2);
3539fffb55fSDavid Gibson 		}
3549fffb55fSDavid Gibson 	;
3559fffb55fSDavid Gibson 
3569fffb55fSDavid Gibson propdataprefix:
3579fffb55fSDavid Gibson 	  /* empty */
3589fffb55fSDavid Gibson 		{
3599fffb55fSDavid Gibson 			$$ = empty_data;
3609fffb55fSDavid Gibson 		}
3619fffb55fSDavid Gibson 	| propdata ','
3629fffb55fSDavid Gibson 		{
3639fffb55fSDavid Gibson 			$$ = $1;
3649fffb55fSDavid Gibson 		}
3659fffb55fSDavid Gibson 	| propdataprefix DT_LABEL
3669fffb55fSDavid Gibson 		{
3679fffb55fSDavid Gibson 			$$ = data_add_marker($1, LABEL, $2);
3689fffb55fSDavid Gibson 		}
3699fffb55fSDavid Gibson 	;
3709fffb55fSDavid Gibson 
371cd296721SStephen Warren arrayprefix:
372cd296721SStephen Warren 	DT_BITS DT_LITERAL '<'
3739fffb55fSDavid Gibson 		{
37447605971SRob Herring 			unsigned long long bits;
375f858927fSRob Herring 			enum markertype type = TYPE_UINT32;
376cd296721SStephen Warren 
37747605971SRob Herring 			bits = $2;
37847605971SRob Herring 
379f858927fSRob Herring 			switch (bits) {
380f858927fSRob Herring 			case 8: type = TYPE_UINT8; break;
381f858927fSRob Herring 			case 16: type = TYPE_UINT16; break;
382f858927fSRob Herring 			case 32: type = TYPE_UINT32; break;
383f858927fSRob Herring 			case 64: type = TYPE_UINT64; break;
384f858927fSRob Herring 			default:
38547605971SRob Herring 				ERROR(&@2, "Array elements must be"
38647605971SRob Herring 				      " 8, 16, 32 or 64-bits");
38747605971SRob Herring 				bits = 32;
3889fffb55fSDavid Gibson 			}
38947605971SRob Herring 
390f858927fSRob Herring 			$$.data = data_add_marker(empty_data, type, NULL);
39147605971SRob Herring 			$$.bits = bits;
3929fffb55fSDavid Gibson 		}
393cd296721SStephen Warren 	| '<'
3949fffb55fSDavid Gibson 		{
395f858927fSRob Herring 			$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
396cd296721SStephen Warren 			$$.bits = 32;
3979fffb55fSDavid Gibson 		}
398cd296721SStephen Warren 	| arrayprefix integer_prim
3999fffb55fSDavid Gibson 		{
400cd296721SStephen Warren 			if ($1.bits < 64) {
401cd296721SStephen Warren 				uint64_t mask = (1ULL << $1.bits) - 1;
402cd296721SStephen Warren 				/*
403cd296721SStephen Warren 				 * Bits above mask must either be all zero
404cd296721SStephen Warren 				 * (positive within range of mask) or all one
405cd296721SStephen Warren 				 * (negative and sign-extended). The second
406cd296721SStephen Warren 				 * condition is true if when we set all bits
407cd296721SStephen Warren 				 * within the mask to one (i.e. | in the
408cd296721SStephen Warren 				 * mask), all bits are one.
409cd296721SStephen Warren 				 */
410ec340077SRob Herring 				if (($2 > mask) && (($2 | mask) != -1ULL)) {
411ec340077SRob Herring 					char *loc = srcpos_string(&@2);
412ec340077SRob Herring 					fprintf(stderr,
413ec340077SRob Herring 						"WARNING: %s: Value 0x%016" PRIx64
414ec340077SRob Herring 						" truncated to 0x%0*" PRIx64 "\n",
415ec340077SRob Herring 						loc, $2, $1.bits / 4, ($2 & mask));
416ec340077SRob Herring 					free(loc);
417ec340077SRob Herring 				}
418cd296721SStephen Warren 			}
419cd296721SStephen Warren 
420cd296721SStephen Warren 			$$.data = data_append_integer($1.data, $2, $1.bits);
421cd296721SStephen Warren 		}
422c2e7075cSRob Herring 	| arrayprefix dt_ref
423cd296721SStephen Warren 		{
424cd296721SStephen Warren 			uint64_t val = ~0ULL >> (64 - $1.bits);
425cd296721SStephen Warren 
426cd296721SStephen Warren 			if ($1.bits == 32)
427cd296721SStephen Warren 				$1.data = data_add_marker($1.data,
428cd296721SStephen Warren 							  REF_PHANDLE,
429cd296721SStephen Warren 							  $2);
430cd296721SStephen Warren 			else
43147605971SRob Herring 				ERROR(&@2, "References are only allowed in "
432cd296721SStephen Warren 					    "arrays with 32-bit elements.");
433cd296721SStephen Warren 
434cd296721SStephen Warren 			$$.data = data_append_integer($1.data, val, $1.bits);
435cd296721SStephen Warren 		}
436cd296721SStephen Warren 	| arrayprefix DT_LABEL
437cd296721SStephen Warren 		{
438cd296721SStephen Warren 			$$.data = data_add_marker($1.data, LABEL, $2);
4399fffb55fSDavid Gibson 		}
4409fffb55fSDavid Gibson 	;
4419fffb55fSDavid Gibson 
442cd296721SStephen Warren integer_prim:
4439fffb55fSDavid Gibson 	  DT_LITERAL
444cd296721SStephen Warren 	| DT_CHAR_LITERAL
445cd296721SStephen Warren 	| '(' integer_expr ')'
446cd296721SStephen Warren 		{
447cd296721SStephen Warren 			$$ = $2;
448cd296721SStephen Warren 		}
449cd296721SStephen Warren 	;
450cd296721SStephen Warren 
451cd296721SStephen Warren integer_expr:
452cd296721SStephen Warren 	integer_trinary
453cd296721SStephen Warren 	;
454cd296721SStephen Warren 
455cd296721SStephen Warren integer_trinary:
456cd296721SStephen Warren 	  integer_or
457cd296721SStephen Warren 	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
458cd296721SStephen Warren 	;
459cd296721SStephen Warren 
460cd296721SStephen Warren integer_or:
461cd296721SStephen Warren 	  integer_and
462cd296721SStephen Warren 	| integer_or DT_OR integer_and { $$ = $1 || $3; }
463cd296721SStephen Warren 	;
464cd296721SStephen Warren 
465cd296721SStephen Warren integer_and:
466cd296721SStephen Warren 	  integer_bitor
467cd296721SStephen Warren 	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
468cd296721SStephen Warren 	;
469cd296721SStephen Warren 
470cd296721SStephen Warren integer_bitor:
471cd296721SStephen Warren 	  integer_bitxor
472cd296721SStephen Warren 	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
473cd296721SStephen Warren 	;
474cd296721SStephen Warren 
475cd296721SStephen Warren integer_bitxor:
476cd296721SStephen Warren 	  integer_bitand
477cd296721SStephen Warren 	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
478cd296721SStephen Warren 	;
479cd296721SStephen Warren 
480cd296721SStephen Warren integer_bitand:
481cd296721SStephen Warren 	  integer_eq
482cd296721SStephen Warren 	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
483cd296721SStephen Warren 	;
484cd296721SStephen Warren 
485cd296721SStephen Warren integer_eq:
486cd296721SStephen Warren 	  integer_rela
487cd296721SStephen Warren 	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
488cd296721SStephen Warren 	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
489cd296721SStephen Warren 	;
490cd296721SStephen Warren 
491cd296721SStephen Warren integer_rela:
492cd296721SStephen Warren 	  integer_shift
493cd296721SStephen Warren 	| integer_rela '<' integer_shift { $$ = $1 < $3; }
494cd296721SStephen Warren 	| integer_rela '>' integer_shift { $$ = $1 > $3; }
495cd296721SStephen Warren 	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
496cd296721SStephen Warren 	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
497cd296721SStephen Warren 	;
498cd296721SStephen Warren 
499cd296721SStephen Warren integer_shift:
5006e9c9686SRob Herring 	  integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
5016e9c9686SRob Herring 	| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
502cd296721SStephen Warren 	| integer_add
503cd296721SStephen Warren 	;
504cd296721SStephen Warren 
505cd296721SStephen Warren integer_add:
506cd296721SStephen Warren 	  integer_add '+' integer_mul { $$ = $1 + $3; }
507cd296721SStephen Warren 	| integer_add '-' integer_mul { $$ = $1 - $3; }
508cd296721SStephen Warren 	| integer_mul
509cd296721SStephen Warren 	;
510cd296721SStephen Warren 
511cd296721SStephen Warren integer_mul:
512cd296721SStephen Warren 	  integer_mul '*' integer_unary { $$ = $1 * $3; }
51391feabc2SRob Herring 	| integer_mul '/' integer_unary
51491feabc2SRob Herring 		{
51591feabc2SRob Herring 			if ($3 != 0) {
51691feabc2SRob Herring 				$$ = $1 / $3;
51791feabc2SRob Herring 			} else {
51891feabc2SRob Herring 				ERROR(&@$, "Division by zero");
51991feabc2SRob Herring 				$$ = 0;
52091feabc2SRob Herring 			}
52191feabc2SRob Herring 		}
52291feabc2SRob Herring 	| integer_mul '%' integer_unary
52391feabc2SRob Herring 		{
52491feabc2SRob Herring 			if ($3 != 0) {
52591feabc2SRob Herring 				$$ = $1 % $3;
52691feabc2SRob Herring 			} else {
52791feabc2SRob Herring 				ERROR(&@$, "Division by zero");
52891feabc2SRob Herring 				$$ = 0;
52991feabc2SRob Herring 			}
53091feabc2SRob Herring 		}
531cd296721SStephen Warren 	| integer_unary
532cd296721SStephen Warren 	;
533cd296721SStephen Warren 
534cd296721SStephen Warren integer_unary:
535cd296721SStephen Warren 	  integer_prim
536cd296721SStephen Warren 	| '-' integer_unary { $$ = -$2; }
537cd296721SStephen Warren 	| '~' integer_unary { $$ = ~$2; }
538cd296721SStephen Warren 	| '!' integer_unary { $$ = !$2; }
5399fffb55fSDavid Gibson 	;
5409fffb55fSDavid Gibson 
5419fffb55fSDavid Gibson bytestring:
5429fffb55fSDavid Gibson 	  /* empty */
5439fffb55fSDavid Gibson 		{
544f858927fSRob Herring 			$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
5459fffb55fSDavid Gibson 		}
5469fffb55fSDavid Gibson 	| bytestring DT_BYTE
5479fffb55fSDavid Gibson 		{
5489fffb55fSDavid Gibson 			$$ = data_append_byte($1, $2);
5499fffb55fSDavid Gibson 		}
5509fffb55fSDavid Gibson 	| bytestring DT_LABEL
5519fffb55fSDavid Gibson 		{
5529fffb55fSDavid Gibson 			$$ = data_add_marker($1, LABEL, $2);
5539fffb55fSDavid Gibson 		}
5549fffb55fSDavid Gibson 	;
5559fffb55fSDavid Gibson 
5569fffb55fSDavid Gibson subnodes:
5579fffb55fSDavid Gibson 	  /* empty */
5589fffb55fSDavid Gibson 		{
5599fffb55fSDavid Gibson 			$$ = NULL;
5609fffb55fSDavid Gibson 		}
5619fffb55fSDavid Gibson 	| subnode subnodes
5629fffb55fSDavid Gibson 		{
5639fffb55fSDavid Gibson 			$$ = chain_node($1, $2);
5649fffb55fSDavid Gibson 		}
5659fffb55fSDavid Gibson 	| subnode propdef
5669fffb55fSDavid Gibson 		{
56747605971SRob Herring 			ERROR(&@2, "Properties must precede subnodes");
5689fffb55fSDavid Gibson 			YYERROR;
5699fffb55fSDavid Gibson 		}
5709fffb55fSDavid Gibson 	;
5719fffb55fSDavid Gibson 
5729fffb55fSDavid Gibson subnode:
573658f29a5SJohn Bonesio 	  DT_PROPNODENAME nodedef
5749fffb55fSDavid Gibson 		{
575658f29a5SJohn Bonesio 			$$ = name_node($2, $1);
576*12d638f4SRob Herring (Arm) 			free($1);
5779fffb55fSDavid Gibson 		}
578cd296721SStephen Warren 	| DT_DEL_NODE DT_PROPNODENAME ';'
579cd296721SStephen Warren 		{
580c2e7075cSRob Herring 			$$ = name_node(build_node_delete(&@$), $2);
581*12d638f4SRob Herring (Arm) 			free($2);
582cd296721SStephen Warren 		}
58350aafd60SRob Herring 	| DT_OMIT_NO_REF subnode
58450aafd60SRob Herring 		{
58550aafd60SRob Herring 			$$ = omit_node_if_unused($2);
58650aafd60SRob Herring 		}
587658f29a5SJohn Bonesio 	| DT_LABEL subnode
5889fffb55fSDavid Gibson 		{
589658f29a5SJohn Bonesio 			add_label(&$2->labels, $1);
590658f29a5SJohn Bonesio 			$$ = $2;
5919fffb55fSDavid Gibson 		}
5929fffb55fSDavid Gibson 	;
5939fffb55fSDavid Gibson 
5949fffb55fSDavid Gibson %%
5959fffb55fSDavid Gibson 
59647605971SRob Herring void yyerror(char const *s)
5979fffb55fSDavid Gibson {
59847605971SRob Herring 	ERROR(&yylloc, "%s", s);
599cd296721SStephen Warren }
600