dtc: Add support for variable sized elements

Elements of size 8, 16, 32, and 64 bits are supported.  The new
/bits/ syntax was selected so as to not pollute the reserved
keyword space with uint8/uint16/... type names.

With this patch the following property assignment:

    property = /bits/ 16 <0x1234 0x5678 0x0 0xffff>;

is equivalent to:

    property = <0x12345678 0x0000ffff>;

It is now also possible to directly specify a 64 bit literal in a
cell list, also known as an array using:

    property = /bits/ 64 <0xdeadbeef00000000>;

It is an error to attempt to store a literal into an element that is
too small to hold the literal, and the compiler will generate an
error when it detects this.  For instance:

    property = /bits/ 8 <256>;

Will fail to compile.  It is also an error to attempt to place a
reference in a non 32-bit element.

The documentation has been changed to reflect that the cell list
is now an array of elements that can be of sizes other than the
default 32-bit cell size.

The sized_cells test tests the creation and access of 8, 16, 32,
and 64-bit sized elements.  It also tests that the creation of two
properties, one with 16 bit elements and one with 32 bit elements
result in the same property contents.

Signed-off-by: Anton Staaf <robotboy@chromium.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
diff --git a/dtc-parser.y b/dtc-parser.y
index 554f11a..348616b 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -45,8 +45,12 @@
 	uint8_t byte;
 	struct data data;
 
+	struct {
+		struct data	data;
+		int		bits;
+	} array;
+
 	uint64_t addr;
-	cell_t cell;
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
@@ -56,6 +60,7 @@
 
 %token DT_V1
 %token DT_MEMRESERVE
+%token DT_BITS
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
 %token <literal> DT_CHAR_LITERAL
@@ -71,8 +76,7 @@
 %type <re> memreserve
 %type <re> memreserves
 %type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
 %type <data> bytestring
 %type <prop> propdef
 %type <proplist> proplist
@@ -182,9 +186,9 @@
 		{
 			$$ = data_merge($1, $2);
 		}
-	| propdataprefix '<' celllist '>'
+	| propdataprefix arrayprefix '>'
 		{
-			$$ = data_merge($1, $3);
+			$$ = data_merge($1, $2.data);
 		}
 	| propdataprefix '[' bytestring ']'
 		{
@@ -242,34 +246,56 @@
 		}
 	;
 
-celllist:
-	  /* empty */
+arrayprefix:
+	DT_BITS DT_LITERAL '<'
 		{
-			$$ = empty_data;
-		}
-	| celllist cellval
-		{
-			$$ = data_append_cell($1, $2);
-		}
-	| celllist DT_REF
-		{
-			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
-							      $2), -1);
-		}
-	| celllist DT_LABEL
-		{
-			$$ = data_add_marker($1, LABEL, $2);
-		}
-	;
+			$$.data = empty_data;
+			$$.bits = eval_literal($2, 0, 7);
 
-cellval:
-	  DT_LITERAL
-		{
-			$$ = eval_literal($1, 0, 32);
+			if (($$.bits !=  8) &&
+			    ($$.bits != 16) &&
+			    ($$.bits != 32) &&
+			    ($$.bits != 64))
+			{
+				print_error("Only 8, 16, 32 and 64-bit elements"
+					    " are currently supported");
+				$$.bits = 32;
+			}
 		}
-	| DT_CHAR_LITERAL
+	| '<'
 		{
-			$$ = eval_char_literal($1);
+			$$.data = empty_data;
+			$$.bits = 32;
+		}
+	| arrayprefix DT_LITERAL
+		{
+			uint64_t val = eval_literal($2, 0, $1.bits);
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
+		}
+	| arrayprefix DT_CHAR_LITERAL
+		{
+			uint64_t val = eval_char_literal($2);
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
+		}
+	| arrayprefix DT_REF
+		{
+			uint64_t val = ~0ULL >> (64 - $1.bits);
+
+			if ($1.bits == 32)
+				$1.data = data_add_marker($1.data,
+							  REF_PHANDLE,
+							  $2);
+			else
+				print_error("References are only allowed in "
+					    "arrays with 32-bit elements.");
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
+		}
+	| arrayprefix DT_LABEL
+		{
+			$$.data = data_add_marker($1.data, LABEL, $2);
 		}
 	;