* support/scripts/sdcc.nsi: added lib/pic to the package
[fw/sdcc] / support / scripts / inc2h.pl
1 #!/usr/bin/perl
2
3 # Copyright (c) 2002 Kevin L. Pauba
4
5
6 # License:
7 #
8 # SDCC is licensed under the GNU Public license (GPL) v2.  Note that
9 # this license covers the code to the compiler and other executables,
10 # but explicitly does not cover any code or objects generated by sdcc.
11 # We have not yet decided on a license for the run time libraries, but
12 # it will not put any requirements on code linked against it. See:
13
14 # http://www.gnu.org/copyleft/gpl.html
15 #
16 # See http://sdcc.sourceforge.net/ for the latest information on sdcc.
17
18
19 $rcsid = q~$Id$~;
20 ($junk, $file, $version, $date, $time, $programmer, $status)
21     = split(/\s+/, $rcsid);
22 ($programName) = ($file =~ /(\S+),v/);
23
24 if ($#ARGV < 0 || $#ARGV > 1 ) {
25     Usage();
26 }
27 $processor = uc(shift);
28 $path = shift;
29
30 if ($^O eq 'MSWin32') {
31     if ($path eq '') {
32         if (defined($path = $ENV{'GPUTILS_HEADER_PATH'}) || defined($path = $ENV{'GPUTILS_LKR_PATH'})) {
33             $path .= '\\..';
34         }
35         else {
36             die "Could not find gpasm includes.\n";
37         }
38     }
39     $path_delim = '\\';
40 }
41 else {
42     # Nathan Hurst <njh@mail.csse.monash.edu.au>: find gputils on Debian
43     if ($path eq '') {
44         if ( -x "/usr/share/gputils") {
45             $path = "/usr/share/gputils";
46         } elsif ( -x "/usr/share/gpasm") {
47             $path = "/usr/share/gpasm";
48         } else {
49             die "Could not find gpasm includes.\n";
50         }
51     }
52     $path_delim = '/';
53 }
54
55 #
56 # Read the symbols at the end of this file.
57 #
58 while (<DATA>) {
59     next if /^\s*#/;
60
61     if (/^\s*alias\s+(\S+)\s+(\S+)/) {
62         #
63         # Set an alias for a special function register.
64         # Some MPASM include files are not entirely consistent
65         # with sfr names.
66         #
67         $alias{$2} = $1;
68     } elsif (/^\s*address\s+(\S+)\s+(\S+)/) {
69         #
70         # Set a default address for a special function register.
71         # Some MPASM include files don't specify the address
72         # of all registers.
73         # 
74         # $addr{"$1"} = $2;
75         foreach $device (split(/[,\s]+/, $devices)) {
76             $addr{"p$device", "$1"} = $2;
77         }
78     } elsif (/^\s*bitmask\s+(\S+)\s+/) {
79         #
80         # Set the bitmask that will be used in the 'memmap' pragma.
81         #
82         $bitmask = "$1";
83         foreach $register (split(/\s+/, $')) {
84             $bitmask{"$register"} = $bitmask;
85         }
86     } elsif (/^\s*ram\s+(\S+)\s+(\S+)\s+(\S+)/) {
87         $lo = $1;
88         $hi = $2;
89         $bitmask = $3;
90         foreach $device (split(/[,\s]+/, $devices)) {
91             $ram{"p$device"} .= "#pragma memmap $lo $hi RAM $bitmask$'";
92         }
93     } elsif (/^\s*processor\s+/) {
94         $devices = $';
95         $type = '';
96     } elsif (/^\s*(\S+)/) {
97         $type = $1;
98         $_ = $';
99         foreach $key (split) {
100             eval "\$type{'$key'} = $type;";
101         }
102     } else {
103         foreach $key (split) {
104             eval "\$type{'$key'} = $type;";
105         }
106     }
107 }
108
109 #
110 # Read the linker file.
111 #
112 #  $linkFile = "$path/lkr/" . lc $processor . ".lkr";
113 #  open(LINK, "<$linkFile")
114 #      || die "$programName: Error: Cannot open linker file $linkFile ($!)\n";
115 #  while (<LINK>) {
116 #      if (/^(\S+)\s+NAME=(\S+)\s+START=(\S+)\s+END=(\S+)\s+(PROTECTED)?/) {
117 #       $type = $1;
118 #       $name = $2;
119 #       $start = $3;
120 #       $end = $4;
121 #       $protected = 1 if ($5 =~ /protected/i);
122
123 #       if ($type =~ /(SHAREBANK)|(DATABANK)/i) {
124 #           $ram{"p$processor"} .=
125 #               sprintf("#pragma memmap %7s %7s RAM 0x000\t// $name\n",
126 #                       $start, $end);
127 #       }
128 #      } elsif (/^SECTION\s+NAME=(\S+)\s+ROM=(\S+)\s+/) {
129 #      }
130 #  }
131
132 #
133 # Convert the file.
134 #
135 $defaultType = 'other';
136 $includeFile = $path.$path_delim.'header'.$path_delim.'p'.lc($processor).'.inc';
137 open(HEADER, "<$includeFile")
138     || die "$programName: Error: Cannot open include file $includeFile ($!)\n";
139
140 while (<HEADER>) {
141     if (/^;-* (\S+) Bits/i) {
142         if (defined($alias{$1})) {
143             $defaultType = "bits $alias{$1}";
144         } else {
145             $defaultType = "bits $1";
146         }
147         s/;/\/\//;
148         $body .= "$_";
149     } elsif (/^;-* Register Files/i) {
150         $defaultType = 'sfr';
151         s/;/\/\//;
152         $body .= "$_";
153     } elsif (/^;=*/i) {
154         $defaultType = '';
155         s/;/\/\//;
156         $body .= "$_";
157     } elsif (/^\s*;/) {
158         #
159         # Convert ASM comments to C style.
160         #
161         $body .= "//$'";
162     } elsif (/^\s*IFNDEF __(\S+)/) {
163         #
164         # Processor type.
165         #
166         $processor = $1;
167         $body .= "//$_";
168     } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
169         #
170         # Useful bit of information.
171         #
172         $name = $1;
173         $value = $2;
174         $rest = $';
175         $rest =~ s/;/\/\//;
176         chomp($rest);
177
178         if (defined($type{"p$processor", "$name"})) {
179             $type = $type{"p$processor", "$name"};
180         } elsif (defined($type{"$name"})) {
181             $type = $type{"$name"};
182         } else {
183             $type = $defaultType;
184         }
185
186         if (defined($bitmask{"p$processor", "$name"})) {
187             $bitmask = $bitmask{"p$processor", "$name"};
188 #       } elsif (defined($bitmask{"$name"})) {
189 #           $bitmask = $bitmask{"$name"};
190         } else {
191             $bitmask = "0x000";
192         }
193
194         if ($type eq 'sfr') {
195             #
196             # A special function register.
197             #
198             $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
199                                 . "SFR %s\t// %s\n",
200                                 $name, $name, $bitmask, $name);
201             if (defined $addr{"p$processor", "$name"}) {
202                 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
203             } else {
204                 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
205             }
206             $body .= sprintf("sfr  at %-30s %s;$rest\n", "${name}_ADDR", $name);
207             $addr{"p$processor", "$name"} = "0x$value";
208         } elsif ($type eq 'volatile') {
209             #
210             # A location that can change without 
211             # direct program manipulation.
212             #
213             $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
214                                 . "SFR %s\t// %s\n",
215                                 $name, $name, $bitmask, $name);
216             $body .= sprintf("data at %-30s %s;$rest\n", "${name}_ADDR volatile char", $name);
217             if (defined $addr{"p$processor", "$name"}) {
218                 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
219             } else {
220                 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
221             }
222         } elsif ($type =~ /^bits/) {
223             ($junk, $register) = split(/\s/, $type);
224             $bit = hex($value);
225             $addr = $addr{"$register"};
226             $body .= "BIT_AT(${register}_ADDR,$bit)\t$name;$rest\n";
227         } else {
228             #
229             # Other registers, bits and/or configurations.
230             #
231             if ($type eq 'other') {
232                 #
233                 # A known symbol.
234                 #
235                 $body .= sprintf("#define %-20s 0x%s$rest\n", $name, $value);
236             } else {
237                 #
238                 # A symbol that isn't defined in the data
239                 # section at the end of the file.  Let's 
240                 # add a comment so that we can add it later.
241                 #
242                 $body .= sprintf("#define %-20s 0x%s$rest\n",
243                                  $name, $value);
244             }
245         }
246     } elsif (/^\s*$/) {
247         #
248         # Blank line.
249         #
250         $body .= "\n";
251     } elsif (/__MAXRAM\s+H'([0-9a-fA-F]+)'/) {
252         $maxram .= "//\n// Memory organization.\n//\n"
253             . sprintf("#pragma maxram 0x%s\n\n", $1);
254         $pragmas = $maxram
255             . $ram{"p$processor"} . "\n"
256                 . $pragmas;
257         $body .= "// $_";
258     } else {
259         #
260         # Anything else we'll just comment out.
261         #
262         $body .= "// $_";
263     }
264 }
265 $header .= <<EOT;
266 //
267 // Register Declarations for Microchip $processor Processor
268 //
269 //
270 // This header file was automatically generated by:
271 //
272 //\t$programName V$version
273 //
274 //\tCopyright (c) 2002, Kevin L. Pauba, All Rights Reserved
275 //
276 //\tSDCC is licensed under the GNU Public license (GPL) v2.  Note that
277 //\tthis license covers the code to the compiler and other executables,
278 //\tbut explicitly does not cover any code or objects generated by sdcc.
279 //\tWe have not yet decided on a license for the run time libraries, but
280 //\tit will not put any requirements on code linked against it. See:
281 // 
282 //\thttp://www.gnu.org/copyleft/gpl/html
283 //
284 //\tSee http://sdcc.sourceforge.net/ for the latest information on sdcc.
285 //
286 // 
287 #ifndef P${processor}_H
288 #define P${processor}_H
289
290 #ifndef BIT_AT
291 #define BIT_AT(base,bitno) sbit at ((base<<3)+bitno)
292 #endif
293
294 //
295 // Register addresses.
296 //
297 EOT
298
299 print $header
300     . $addresses . "\n"
301     . $pragmas . "\n\n"
302     . $body
303     . "#endif\n";
304
305 sub Usage {
306         print STDERR <<EOT;
307
308 inc2h.pl - A utility to convert MPASM include files to header files
309            suitable for the SDCC compiler.
310
311 License: Copyright (c) 2002 Kevin L. Pauba
312
313          SDCC is licensed under the GNU Public license (GPL) v2; see
314          http://www.gnu.org/copyleft/gpl.html See http://sdcc.sourceforge.net/
315          for the latest information on sdcc.
316
317 Usage:   $programName processor [path]
318
319          where:
320
321          processor      The name of the processor (16f84, 16f877, etc.)
322
323          path           The path to the parent of the "header" and "lkr"
324                         directories.  The default is "/usr/share/gpasm".
325
326          The header file will be written to the standard output.
327
328          $#ARGV
329 EOT
330         exit;
331 }
332
333 __END__
334
335 #
336 # processor <processor_name>
337 # address <register_name> <hex_address>
338 # bitmask <bitmask> <register_list>
339 # ram <lo_address> <hi_address> <bitmask>
340 # sfr <register_list>
341 # volatile <address_list>
342 # bit <address_list>
343 #
344
345 alias OPTION_REG OPTION
346 volatile INDF PCL
347
348 #
349 # bitmask settings.
350 #
351 processor 16F84
352     bitmask 0x080 INDF PCL STATUS FSR PCLATH INTCON
353
354 processor 16F873, 16F874, 16F877, 16F627, 16F628, 16F876
355     bitmask 0x180 INDF PCL STATUS FSR PCLATH INTCON
356     bitmask 0x100 TMR0 OPTION_REG PORTB TRISB
357
358 #
359 # Memory maps.
360 #
361 processor 16F84
362     ram 0x000C 0x004f 0x080
363
364 processor 16F627, 16F628
365     ram 0x0020 0x006f 0x000
366     ram 0x0070 0x007f 0x180
367     ram 0x00a0 0x00ef 0x000
368     ram 0x0120 0x014f 0x000
369
370 processor 16F876, 16F877
371     ram 0x0020 0x006f 0x000
372     ram 0x0070 0x007f 0x180
373     ram 0x00a0 0x00ef 0x000
374     ram 0x0110 0x016f 0x000
375     ram 0x0190 0x01ef 0x000
376
377 processor 16F873, 16F874
378     ram 0x0020 0x007f 0x100
379     ram 0x00a0 0x00ff 0x100
380