3 # Copyright (c) 2002 Kevin L. Pauba
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:
14 # http://www.gnu.org/copyleft/gpl.html
16 # See http://sdcc.sourceforge.net/ for the latest information on sdcc.
20 ($junk, $file, $version, $date, $time, $programmer, $status)
21 = split(/\s+/, $rcsid);
22 ($programName) = ($file =~ /(\S+)/);
24 if ($#ARGV < 0 || $#ARGV > 1 ) {
27 $processor = uc(shift);
31 # just in time fixes for some register names
34 $name =~ s/COMCON/CMCON/ig;
35 # use OPTION_REG instead of OPTION as OPTION is a assembler directive
36 $name =~ s/OPTION(_REG)?/OPTION_REG/ig;
37 # often declared as LCDDATn, but bits defined for LCDDATAn, 0 <= n <= 10
38 $name =~ s/LCDDAT([^A])/LCDDATA$1/ig;
39 # LCDSE2 is missing in some headers, but LCDSE3 is declared...
40 $name =~ s/LCDSE3/LCDSE2/ig;
41 # XXX: should this be named LININTF or LINPRT?
42 $name =~ s/LININTF/LINPRT/ig;
43 # FIXME: duplicate declarations for n in {0,1,2}
44 $name =~ s/UEPn/UEP0/ig;
51 if (not exists $sfrs{$name}) {
52 print "SFR $name not defined (yet).\n";
54 if (exists $sfrs{$name."0"}) {
55 print " but ".$name."0 exists---using that instead.\n";
60 if (exists $sfrs{$try}) {
61 print " but $try exists---using that instead.\n";
64 die "Not found a similar SFR---aborting.\n";
69 # exists clone for arrays---does this not exist in Perl?!?
74 foreach my $item (@$arr) {
75 return 1 if ($name eq $item);
81 if ($^O eq 'MSWin32') {
83 if (defined($path = $ENV{'GPUTILS_HEADER_PATH'}) || defined($path = $ENV{'GPUTILS_LKR_PATH'})) {
87 die "Could not find gpasm includes.\n";
93 # Nathan Hurst <njh@mail.csse.monash.edu.au>: find gputils on Debian
95 if ( -x "/usr/share/gputils") {
96 $path = "/usr/share/gputils";
97 } elsif ( -x "/usr/share/gpasm") {
98 $path = "/usr/share/gpasm";
99 } elsif ( -x "/usr/local/share/gputils") {
100 $path = "/usr/local/share/gputils";
102 die "Could not find gpasm includes.\n";
109 # Read the symbols at the end of this file.
114 if (/^\s*alias\s+(\S+)\s+(\S+)/) {
116 # Set an alias for a special function register.
117 # Some MPASM include files are not entirely consistent
120 $alias{fixname($2)} = fixname($1);
121 } elsif (/^\s*address\s+(\S+)\s+(\S+)/) {
123 # Set a default address for a special function register.
124 # Some MPASM include files don't specify the address
128 foreach $device (split(/[,\s]+/, $devices)) {
129 $addr{"p$device", "$1"} = $2;
131 } elsif (/^\s*bitmask\s+(\S+)\s+/) {
133 # Set the bitmask that will be used in the 'memmap' pragma.
136 foreach $register (split(/\s+/, $')) {
137 $bitmask{"$register"} = $bitmask;
139 } elsif (/^\s*ram\s+(\S+)\s+(\S+)\s+(\S+)/) {
140 # This info is now provided in "include/pic/pic14devices.txt".
144 #foreach $device (split(/[,\s]+/, $devices)) {
145 # $ram{"p$device"} .= "#pragma memmap $lo $hi RAM $bitmask$'";
147 } elsif (/^\s*processor\s+/) {
150 } elsif (/^\s*(\S+)/) {
153 foreach $key (split) {
154 eval "\$type{'$key'} = $type;";
157 foreach $key (split) {
158 eval "\$type{'$key'} = $type;";
164 # Read the linker file.
166 # $linkFile = "$path/lkr/" . lc $processor . ".lkr";
167 # open(LINK, "<$linkFile")
168 # || die "$programName: Error: Cannot open linker file $linkFile ($!)\n";
170 # if (/^(\S+)\s+NAME=(\S+)\s+START=(\S+)\s+END=(\S+)\s+(PROTECTED)?/) {
175 # $protected = 1 if ($5 =~ /protected/i);
177 # if ($type =~ /(SHAREBANK)|(DATABANK)/i) {
178 # $ram{"p$processor"} .=
179 # sprintf("#pragma memmap %7s %7s RAM 0x000\t// $name\n",
182 # } elsif (/^SECTION\s+NAME=(\S+)\s+ROM=(\S+)\s+/) {
186 # Create header for pic${processor}.c file
187 $lcproc = "pic" . lc($processor);
189 /* Register definitions for $lcproc.
190 * This file was automatically generated by:
191 * $programName V$version
192 * Copyright (c) 2002, Kevin L. Pauba, All Rights Reserved
194 #include <${lcproc}.h>
202 $defaultType = 'other';
203 $includeFile = $path.$path_delim.'header'.$path_delim.'p'.lc($processor).'.inc';
204 $headFile = "pic" . lc($processor) . ".h";
205 $defsFile = "pic" . lc($processor) . ".c";
206 open(HEADER, "<$includeFile")
207 || die "$programName: Error: Cannot open include file $includeFile ($!)\n";
211 if (/^;-+ Register Files/i) {
212 $defaultType = 'sfr';
215 } elsif (/^;-+\s*(\S+)\s+Bits/i || /^;-+\s*(\S+)\s+-+/i) {
216 # The second case is usually bits, but the word Bits is missing
217 # also accept "UIE/UIR Bits"
218 foreach $name (split(/\//, $1)) {
219 $name = fixname($name);
220 $name = checkname($name);
222 if (defined($alias{$name})) {
223 $defaultType = "bits $alias{$name}";
225 $defaultType = "bits $name";
236 # Convert ASM comments to C style.
239 } elsif (/^\s*IFNDEF\s+__(\S+)/) {
245 } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
247 # Useful bit of information.
255 if (defined($type{"p$processor", "$name"})) {
256 $type = $type{"p$processor", "$name"};
257 } elsif (defined($type{"$name"})) {
258 $type = $type{"$name"};
260 $type = $defaultType;
263 if (defined($bitmask{"p$processor", "$name"})) {
264 $bitmask = $bitmask{"p$processor", "$name"};
265 # } elsif (defined($bitmask{"$name"})) {
266 # $bitmask = $bitmask{"$name"};
271 if ($type eq 'sfr') {
273 # A special function register.
275 # $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
276 # . "SFR %s\t// %s\n",
277 # $name, $name, $bitmask, $name);
278 $name = fixname($name);
279 if (defined $addr{"p$processor", "$name"}) {
280 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
282 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
284 $body .= sprintf("extern __sfr __at %-30s $name;$rest\n", "(${name}_ADDR)" );
285 $c_head .= sprintf("__sfr __at %-30s $name;\n", "(${name}_ADDR)");
286 $addr{"p$processor", "$name"} = "0x$value";
288 } elsif ($type eq 'volatile') {
290 # A location that can change without
291 # direct program manipulation.
293 $name = fixname($name);
294 # $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
295 # . "SFR %s\t// %s\n",
296 # $name, $name, $bitmask, $name);
297 $body .= sprintf("extern __data __at %-30s $name;$rest\n", "(${name}_ADDR) volatile char");
298 $c_head .= sprintf("__data __at %-30s $name;\n", "(${name}_ADDR) volatile char");
299 if (defined $addr{"p$processor", "$name"}) {
300 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
302 $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
304 } elsif ($type =~ /^bits/) {
305 ($junk, $register) = split(/\s/, $type);
307 $addr = $addr{"$register"};
308 # prepare struct declaration
309 for ($k=0; $k < scalar @{$bits{"$register"}->{oct($bit)}}; $k++) {
310 $name = "" if ($bits{"$register"}->{oct($bit)} eq $name)
313 and (1 != contained($name, \@{$bits{"$register"}->{oct($bit)}}))
315 push @{$bits{"$register"}->{oct($bit)}}, $name;
319 # Other registers, bits and/or configurations.
321 $name = fixname($name);
322 if ($type eq 'other') {
326 $body .= sprintf("#define %-20s 0x%s$rest\n", $name, $value);
329 # A symbol that isn't defined in the data
330 # section at the end of the file. Let's
331 # add a comment so that we can add it later.
333 $body .= sprintf("#define %-20s 0x%s$rest\n",
342 } elsif (/__MAXRAM\s+H'([0-9a-fA-F]+)'/) {
343 $maxram .= "//\n// Memory organization.\n//\n";
345 . $ram{"p$processor"} . "\n"
350 # Anything else we'll just comment out.
357 // Register Declarations for Microchip $processor Processor
360 // This header file was automatically generated by:
362 //\t$programName V$version
364 //\tCopyright (c) 2002, Kevin L. Pauba, All Rights Reserved
366 //\tSDCC is licensed under the GNU Public license (GPL) v2. Note that
367 //\tthis license covers the code to the compiler and other executables,
368 //\tbut explicitly does not cover any code or objects generated by sdcc.
369 //\tWe have not yet decided on a license for the run time libraries, but
370 //\tit will not put any requirements on code linked against it. See:
372 //\thttp://www.gnu.org/copyleft/gpl/html
374 //\tSee http://sdcc.sourceforge.net/ for the latest information on sdcc.
377 #ifndef P${processor}_H
378 #define P${processor}_H
381 // Register addresses.
388 // bitfield definitions
392 # Add PORT* and TRIS* bit entries
395 # * A0-5,B0-7,C0-7,D0-7,E0-2
398 my $defpinfo = undef;
399 open(P14PORTS, "< pic14ports.txt") && do {
402 if(/^\s*(\*|\w*)\s*([ABCDE0-7,-]+)\s*$/) {
403 if(lc($1) eq lc($processor)) {
404 die if defined $pinfo;
407 die if defined $defpinfo;
410 } elsif(/^\s*#/ || /^\s*$/) {
411 # ignore blanks, comments
413 die "bad line in pic14ports '$_'";
418 $defpinfo = "A0-5,B0-7,C0-7,D0-7,E0-2" unless defined $defpinfo;
419 $pinfo = $defpinfo unless defined $pinfo;
422 foreach (split /,/, $pinfo) {
423 if(/^([ABCDE])([0-7])-([0-7])$/) {
424 my($prt, $low, $high) = ($1, $2, $3);
425 next unless defined $sfrs{"PORT$prt"} && defined $sfrs{"TRIS$prt"};
426 next if defined $bits{"PORT$prt"};
427 for(my $i = $low; $i <= $high; $i++) {
428 push @{$bits{"PORT$prt"}->{oct($i)}}, "R$prt".$i;
430 next if defined $bits{"TRIS$prt"};
431 for(my $i = $low; $i <= $high; $i++) {
432 push @{$bits{"TRIS$prt"}->{oct($i)}}, "TRIS$prt".$i;
440 ## create struct declarations
441 foreach $reg (sort keys %bits)
443 $structs .= "// ----- $reg bits --------------------\n";
444 $structs .= "typedef union {\n";
447 $structs .= " struct {\n";
448 for ($i=0; $i < 8; $i++)
450 @names = @{$bits{$reg}->{oct($i)}};
451 if ($max < scalar @names) { $max = scalar @names; }
452 if ($idx >= scalar @names) {
453 $structs .= " unsigned char :1;\n";
454 } else { # (1 == scalar @names) {
455 $structs .= " unsigned char " . $names[$idx] . ":1;\n";
457 # $structs .= " union {\n";
458 # foreach $name (@names) {
459 # $structs .= " unsigned char " . $name . ":1;\n";
461 # $structs .= " };\n";
466 } while ($idx < $max);
467 $structs .= "} __${reg}_bits_t;\n";
468 #if(defined $sfrs{$reg}) {
469 $structs .= "extern volatile __${reg}_bits_t __at(${reg}_ADDR) ${reg}_bits;\n\n";
470 $c_head .= "volatile __${reg}_bits_t __at(${reg}_ADDR) ${reg}_bits;\n";
473 # emit defines for individual bits
474 for ($i=0; $i < 8; $i++)
476 @names = @{$bits{$reg}->{oct($i)}};
477 foreach $field (@names) {
478 $structs .= sprintf("#define %-20s ${reg}_bits.$field\n", $field);
484 open(HEAD, ">$headFile") or die "Could not open $headFile for writing.";
493 open(DEFS, ">$defsFile") or die "Could not open $defsFile for writing.";
494 print DEFS $c_head . "\n";
500 inc2h.pl - A utility to convert MPASM include files to header files
501 suitable for the SDCC compiler.
503 License: Copyright (c) 2002 Kevin L. Pauba
505 SDCC is licensed under the GNU Public license (GPL) v2; see
506 http://www.gnu.org/copyleft/gpl.html See http://sdcc.sourceforge.net/
507 for the latest information on sdcc.
509 Usage: $programName processor [path]
513 processor The name of the processor (16f84, 16f877, etc.)
515 path The path to the parent of the "header" and "lkr"
516 directories. The default is "/usr/share/gpasm".
518 The header file will be written to the standard output.
528 # processor <processor_name>
529 # address <register_name> <hex_address>
530 # bitmask <bitmask> <register_list>
531 # ram <lo_address> <hi_address> <bitmask>
532 # sfr <register_list>
533 # volatile <address_list>
537 alias OPTION_REG OPTION