@@ -78,33 +78,62 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, int index) {
7878}
7979
8080#define is_signed (typecode ) (typecode > 'Z')
81- mp_obj_t mp_binary_get_val_unaligned (char typecode , byte * * ptr ) {
82- char type = '<' ;
81+ mp_obj_t mp_binary_get_val (char struct_type , char val_type , byte * * ptr ) {
8382 byte * p = * ptr ;
84- uint size = 0 , align = 0 ;
85- switch (type ) {
83+ uint size = 0 ;
84+ switch (struct_type ) {
8685 case '<' : case '>' :
87- switch (typecode ) {
86+ switch (val_type ) {
8887 case 'b' : case 'B' :
8988 size = 1 ; break ;
9089 case 'h' : case 'H' :
9190 size = 2 ; break ;
9291 case 'i' : case 'I' :
9392 size = 4 ; break ;
93+ case 'l' : case 'L' :
94+ size = 4 ; break ;
95+ }
96+ break ;
97+ case '@' : {
98+ // TODO:
99+ // The simplest heuristic for alignment is to align by value
100+ // size, but that doesn't work for "bigger than int" types,
101+ // for example, long long may very well have long alignment
102+ // So, we introduce separate alignment handling, but having
103+ // formal support for that is different from actually supporting
104+ // particular (or any) ABI.
105+ uint align = 0 ;
106+ switch (val_type ) {
107+ case 'b' : case 'B' :
108+ align = size = 1 ; break ;
109+ case 'h' : case 'H' :
110+ align = size = sizeof (short ); break ;
111+ case 'i' : case 'I' :
112+ align = size = sizeof (int ); break ;
113+ case 'l' : case 'L' :
114+ align = size = sizeof (long ); break ;
94115 }
116+ // Make pointer aligned
117+ p = (byte * )(((machine_uint_t )p + align - 1 ) & ~(align - 1 ));
118+ #if MP_ENDIANNESS_LITTLE
119+ struct_type = '<' ;
120+ #else
121+ struct_type = '>' ;
122+ #endif
95123 break ;
124+ }
96125 }
97126
98127 int delta ;
99- if (type == '<' ) {
128+ if (struct_type == '<' ) {
100129 delta = -1 ;
101130 p += size - 1 ;
102131 } else {
103132 delta = 1 ;
104133 }
105134
106135 machine_int_t val = 0 ;
107- if (is_signed (typecode ) && * p & 0x80 ) {
136+ if (is_signed (val_type ) && * p & 0x80 ) {
108137 val = -1 ;
109138 }
110139 for (uint i = 0 ; i < size ; i ++ ) {
@@ -113,8 +142,8 @@ mp_obj_t mp_binary_get_val_unaligned(char typecode, byte **ptr) {
113142 p += delta ;
114143 }
115144
116- * ptr += size + align ;
117- if (is_signed (typecode )) {
145+ * ptr += size ;
146+ if (is_signed (val_type )) {
118147 return mp_obj_new_int (val );
119148 } else {
120149 return mp_obj_new_int_from_uint (val );
0 commit comments