1 | #!/usr/bin/perl -w |
---|
2 | # |
---|
3 | # Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>. |
---|
4 | # |
---|
5 | # This program is free software; you can redistribute it and/or |
---|
6 | # modify it under the terms of the GNU General Public License as |
---|
7 | # published by the Free Software Foundation; either version 2 of the |
---|
8 | # License, or any later version. |
---|
9 | # |
---|
10 | # This program is distributed in the hope that it will be useful, but |
---|
11 | # WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
13 | # General Public License for more details. |
---|
14 | # |
---|
15 | # You should have received a copy of the GNU General Public License |
---|
16 | # along with this program; if not, write to the Free Software |
---|
17 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
18 | |
---|
19 | use strict; |
---|
20 | use warnings; |
---|
21 | |
---|
22 | my $offsets = {}; |
---|
23 | my $defaults = {}; |
---|
24 | my $structures = {}; |
---|
25 | my $structure = ""; |
---|
26 | |
---|
27 | while ( <> ) { |
---|
28 | chomp; |
---|
29 | if ( /^\#define (\S+)_OFFS (\S+)$/ ) { |
---|
30 | $structure = $1; |
---|
31 | $offsets->{$structure} = $2; |
---|
32 | } elsif ( /^\#define ${structure}_DEF (\S+)$/ ) { |
---|
33 | $defaults->{$structure} = $1; |
---|
34 | } elsif ( /^\#define ${structure}_(\S+)_LSB (\S+)$/ ) { |
---|
35 | $structures->{$structure}->{$1}->{LSB} = $2; |
---|
36 | } elsif ( /^\#define ${structure}_(\S+)_MSB (\S+)$/ ) { |
---|
37 | $structures->{$structure}->{$1}->{MSB} = $2; |
---|
38 | } elsif ( /^\#define ${structure}_(\S+)_RMASK (\S+)$/ ) { |
---|
39 | $structures->{$structure}->{$1}->{RMASK} = $2; |
---|
40 | } elsif ( /^\s*$/ ) { |
---|
41 | # Do nothing |
---|
42 | } else { |
---|
43 | print "$_\n"; |
---|
44 | } |
---|
45 | } |
---|
46 | |
---|
47 | my $data = [ map { { name => $_, offset => $offsets->{$_}, |
---|
48 | default => $defaults->{$_} }; } |
---|
49 | sort { hex ( $offsets->{$a} ) <=> hex ( $offsets->{$b} ) } |
---|
50 | keys %$offsets ]; |
---|
51 | |
---|
52 | foreach my $datum ( @$data ) { |
---|
53 | next unless exists $structures->{$datum->{name}}; |
---|
54 | $structure = $structures->{$datum->{name}}; |
---|
55 | my $fields = [ map { { name => $_, lsb => $structure->{$_}->{LSB}, |
---|
56 | msb => $structure->{$_}->{MSB}, |
---|
57 | rmask => $structure->{$_}->{RMASK} }; } |
---|
58 | sort { hex ( $structure->{$a}->{LSB} ) <=> |
---|
59 | hex ( $structure->{$b}->{LSB} ) } |
---|
60 | keys %$structure ]; |
---|
61 | $datum->{fields} = $fields; |
---|
62 | } |
---|
63 | |
---|
64 | print "\n/* This file has been further processed by $0 */\n\n"; |
---|
65 | print "FILE_LICENCE ( GPL2_ONLY );\n\n"; |
---|
66 | |
---|
67 | foreach my $datum ( @$data ) { |
---|
68 | printf "#define %s_offset 0x%08xUL\n", |
---|
69 | $datum->{name}, hex ( $datum->{offset} ); |
---|
70 | if ( exists $datum->{fields} ) { |
---|
71 | my $lsb = 0; |
---|
72 | my $reserved_idx = 0; |
---|
73 | printf "struct %s_pb {\n", $datum->{name}; |
---|
74 | foreach my $field ( @{$datum->{fields}} ) { |
---|
75 | my $pad_width = ( hex ( $field->{lsb} ) - $lsb ); |
---|
76 | die "Inconsistent LSB/RMASK in $datum->{name} before $field->{name}\n" |
---|
77 | if $pad_width < 0; |
---|
78 | printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width |
---|
79 | if $pad_width; |
---|
80 | $lsb += $pad_width; |
---|
81 | # Damn Perl can't cope with 64-bit hex constants |
---|
82 | my $width = 0; |
---|
83 | die "Missing RMASK in $datum->{name}.$field->{name}\n" |
---|
84 | unless defined $field->{rmask}; |
---|
85 | my $rmask = $field->{rmask}; |
---|
86 | while ( $rmask =~ /^(0x.+)f$/i ) { |
---|
87 | $width += 4; |
---|
88 | $rmask = $1; |
---|
89 | } |
---|
90 | $rmask = hex ( $rmask ); |
---|
91 | while ( $rmask ) { |
---|
92 | $width++; |
---|
93 | $rmask >>= 1; |
---|
94 | } |
---|
95 | if ( defined $field->{msb} ) { |
---|
96 | my $msb_width = ( hex ( $field->{msb} ) - $lsb + 1 ); |
---|
97 | $width ||= $msb_width; |
---|
98 | die "Inconsistent LSB/MSB/RMASK in $datum->{name}.$field->{name}\n" |
---|
99 | unless $width == $msb_width; |
---|
100 | } |
---|
101 | printf "\tpseudo_bit_t %s[%u];\n", $field->{name}, $width; |
---|
102 | $lsb += $width; |
---|
103 | } |
---|
104 | my $pad_width = ( 64 - $lsb ); |
---|
105 | die "Inconsistent LSB/RMASK in $datum->{name} final field\n" |
---|
106 | if $pad_width < 0; |
---|
107 | printf "\tpseudo_bit_t _unused_%u[%u];\n", $reserved_idx++, $pad_width |
---|
108 | if $pad_width; |
---|
109 | printf "};\n"; |
---|
110 | printf "struct %s {\n\tPSEUDO_BIT_STRUCT ( struct %s_pb );\n};\n", |
---|
111 | $datum->{name}, $datum->{name}; |
---|
112 | } |
---|
113 | printf "/* Default value: %s */\n", $datum->{default} |
---|
114 | if defined $datum->{default}; |
---|
115 | print "\n"; |
---|
116 | } |
---|