$rcsid = q~$Id$~;
($junk, $file, $version, $date, $time, $programmer, $status)
- = split(/\s+/, $rcsid);
+ = split(/\s+/, $rcsid);
($programName) = ($file =~ /(\S+),v/);
-if ($#ARGV != 0) {
- Usage();
+if ($#ARGV < 0 || $#ARGV > 1 ) {
+ Usage();
}
+$processor = shift;
+$path = shift;
+
+$processor = uc $processor;
+$path = "/usr/share/gpasm" if ($path eq '');
#
# Read the symbols at the end of this file.
#
while (<DATA>) {
- next if /^\s*#/;
+ next if /^\s*#/;
- if (/^alias\s+(\S+)\s+(\S+)/) {
- #
- # Set an alias for a special function register.
- # Some MPASM include files are not entirely consistent
- # with sfr names.
- #
- $alias{$2} = $1;
- } elsif (/^address\s+(\S+)\s+(\S+)/) {
- #
- # Set a default address for a special function register.
- # Some MPASM include files don't specify the address
- # of all registers.
- #
- $addr{"$1"} = $2;
- } elsif (/^(\S+)/) {
- $type = $1;
- } else {
- foreach $key (split) {
- eval "\$type{'$key'} = $type;";
- }
+ if (/^\s*alias\s+(\S+)\s+(\S+)/) {
+ #
+ # Set an alias for a special function register.
+ # Some MPASM include files are not entirely consistent
+ # with sfr names.
+ #
+ $alias{$2} = $1;
+ } elsif (/^\s*address\s+(\S+)\s+(\S+)/) {
+ #
+ # Set a default address for a special function register.
+ # Some MPASM include files don't specify the address
+ # of all registers.
+ #
+ # $addr{"$1"} = $2;
+ foreach $device (split(/[,\s]+/, $devices)) {
+ $addr{"p$device", "$1"} = $2;
+ }
+ } elsif (/^\s*bitmask\s+(\S+)\s+/) {
+ #
+ # Set the bitmask that will be used in the 'memmap' pragma.
+ #
+ $bitmask = "$1";
+ foreach $register (split(/\s+/, $')) {
+ $bitmask{"$register"} = $bitmask;
+ }
+ } elsif (/^\s*ram\s+(\S+)\s+(\S+)\s+(\S+)/) {
+ $lo = $1;
+ $hi = $2;
+ $bitmask = $3;
+ foreach $device (split(/[,\s]+/, $devices)) {
+ $ram{"p$device"} .= "#pragma memmap $lo $hi RAM $bitmask$'";
+ }
+ } elsif (/^\s*processor\s+/) {
+ $devices = $';
+ $type = '';
+ } elsif (/^\s*(\S+)/) {
+ $type = $1;
+ $_ = $';
+ foreach $key (split) {
+ eval "\$type{'$key'} = $type;";
+ }
+ } else {
+ foreach $key (split) {
+ eval "\$type{'$key'} = $type;";
}
+ }
}
#
-# Print the header.
+# Read the linker file.
#
-print <<EOT;
+# $linkFile = "$path/lkr/" . lc $processor . ".lkr";
+# open(LINK, "<$linkFile")
+# || die "$programName: Error: Cannot open linker file $linkFile ($!)\n";
+# while (<LINK>) {
+# if (/^(\S+)\s+NAME=(\S+)\s+START=(\S+)\s+END=(\S+)\s+(PROTECTED)?/) {
+# $type = $1;
+# $name = $2;
+# $start = $3;
+# $end = $4;
+# $protected = 1 if ($5 =~ /protected/i);
+
+# if ($type =~ /(SHAREBANK)|(DATABANK)/i) {
+# $ram{"p$processor"} .=
+# sprintf("#pragma memmap %7s %7s RAM 0x000\t// $name\n",
+# $start, $end);
+# }
+# } elsif (/^SECTION\s+NAME=(\S+)\s+ROM=(\S+)\s+/) {
+# }
+# }
+
+#
+# Convert the file.
+#
+$defaultType = 'other';
+$includeFile = "$path/header/p" . lc $processor . ".inc";
+open(HEADER, "<$includeFile")
+ || die "$programName: Error: Cannot open include file $includeFile ($!)\n";
+
+while (<HEADER>) {
+ if (/^;-* (\S+) Bits/i) {
+ if (defined($alias{$1})) {
+ $defaultType = "bits $alias{$1}";
+ } else {
+ $defaultType = "bits $1";
+ }
+ s/;/\/\//;
+ $body .= "$_";
+ } elsif (/^;-* Register Files/i) {
+ $defaultType = 'sfr';
+ s/;/\/\//;
+ $body .= "$_";
+ } elsif (/^;=*/i) {
+ $defaultType = '';
+ s/;/\/\//;
+ $body .= "$_";
+ } elsif (/^\s*;/) {
+ #
+ # Convert ASM comments to C style.
+ #
+ $body .= "//$'";
+ } elsif (/^\s*IFNDEF __(\S+)/) {
+ #
+ # Processor type.
+ #
+ $processor = $1;
+ $body .= "//$_";
+ } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
+ #
+ # Useful bit of information.
+ #
+ $name = $1;
+ $value = $2;
+ $rest = $';
+ $rest =~ s/;/\/\//;
+ chomp($rest);
+
+ if (defined($type{"p$processor", "$name"})) {
+ $type = $type{"p$processor", "$name"};
+ } elsif (defined($type{"$name"})) {
+ $type = $type{"$name"};
+ } else {
+ $type = $defaultType;
+ }
+
+ if (defined($bitmask{"p$processor", "$name"})) {
+ $bitmask = $bitmask{"p$processor", "$name"};
+# } elsif (defined($bitmask{"$name"})) {
+# $bitmask = $bitmask{"$name"};
+ } else {
+ $bitmask = "0x000";
+ }
+
+ if ($type eq 'sfr') {
+ #
+ # A special function register.
+ #
+ $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
+ . "SFR %s\t// %s\n",
+ $name, $name, $bitmask, $name);
+ if (defined $addr{"p$processor", "$name"}) {
+ $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
+ } else {
+ $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
+ }
+ $body .= sprintf("sfr at %-30s %s;$rest\n", "${name}_ADDR", $name);
+ $addr{"p$processor", "$name"} = "0x$value";
+ } elsif ($type eq 'volatile') {
+ #
+ # A location that can change without
+ # direct program manipulation.
+ #
+ $pragmas .= sprintf("#pragma memmap %s_ADDR %s_ADDR "
+ . "SFR %s\t// %s\n",
+ $name, $name, $bitmask, $name);
+ $body .= sprintf("data at %-30s %s;$rest\n", "${name}_ADDR volatile char", $name);
+ if (defined $addr{"p$processor", "$name"}) {
+ $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $addr{"p$processor", "$name"});
+ } else {
+ $addresses .= sprintf("#define %s_ADDR\t0x%s\n", $name, $value);
+ }
+ } elsif ($type =~ /^bits/) {
+ ($junk, $register) = split(/\s/, $type);
+ $bit = hex($value);
+ $addr = $addr{"$register"};
+ $body .= "BIT_AT(${register}_ADDR,$bit)\t$name;$rest\n";
+ } else {
+ #
+ # Other registers, bits and/or configurations.
+ #
+ if ($type eq 'other') {
+ #
+ # A known symbol.
+ #
+ $body .= sprintf("#define %-20s 0x%s$rest\n", $name, $value);
+ } else {
+ #
+ # A symbol that isn't defined in the data
+ # section at the end of the file. Let's
+ # add a comment so that we can add it later.
+ #
+ $body .= sprintf("#define %-20s 0x%s$rest\n",
+ $name, $value);
+ }
+ }
+ } elsif (/^\s*$/) {
+ #
+ # Blank line.
+ #
+ $body .= "\n";
+ } elsif (/__MAXRAM\s+H'([0-9a-fA-F]+)'/) {
+ $maxram .= "//\n// Memory organization.\n//\n"
+ . sprintf("#pragma maxram 0x%s\n\n", $1);
+ $pragmas = $maxram
+ . $ram{"p$processor"} . "\n"
+ . $pragmas;
+ $body .= "// $_";
+ } else {
+ #
+ # Anything else we'll just comment out.
+ #
+ $body .= "// $_";
+ }
+}
+$header .= <<EOT;
+//
+// Register Declarations for Microchip $processor Processor
+//
//
// This header file was automatically generated by:
//
//\t$programName V$version
//
+//\tCopyright (c) 2002, Kevin L. Pauba, All Rights Reserved
+//
+//\tSDCC is licensed under the GNU Public license (GPL) v2. Note that
+//\tthis license covers the code to the compiler and other executables,
+//\tbut explicitly does not cover any code or objects generated by sdcc.
+//\tWe have not yet decided on a license for the run time libraries, but
+//\tit will not put any requirements on code linked against it. See:
//
+//\thttp://www.gnu.org/copyleft/gpl/html
+//
+//\tSee http://sdcc.sourceforge.net/ for the latest information on sdcc.
+//
+//
+#ifndef P${processor}_H
+#define P${processor}_H
#ifndef BIT_AT
#define BIT_AT(base,bitno) bit at ((base<<3)+bitno)
#endif
-
+//
+// Register addresses.
+//
EOT
-#
-# Convert the file.
-#
-$defaultType = 'other';
-while (<>) {
- if (/^;-* (\S+) Bits/i) {
- if (defined($alias{$1})) {
- $defaultType = "bits $alias{$1}";
- } else {
- $defaultType = "bits $1";
- }
- s/;/\/\//;
- print "$_";
- } elsif (/^;-* Register Files/i) {
- $defaultType = 'sfr';
- s/;/\/\//;
- print "$_";
- } elsif (/^;=*/i) {
- $defaultType = '';
- s/;/\/\//;
- print "$_";
- } elsif (/^\s*;/) {
- #
- # Convert ASM comments to C style.
- #
- print "//$'";
- } elsif (/^\s*IFNDEF __(\S+)/) {
- #
- # Processor type.
- #
- $processor = $1;
- print "//$_";
- } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
- #
- # Useful bit of information.
- #
- $name = $1;
- $value = $2;
- $rest = $';
- $rest =~ s/;/\/\//;
- chomp($rest);
-
- if (defined($type{"$name"})) {
- $type = $type{"$name"};
- } else {
- $type = $defaultType;
- }
-
- if ($type eq 'sfr') {
- #
- # A special function register.
- #
- printf("sfr at 0x%s %s;$rest\n", $value, $name);
- $addr{"$name"} = "0x$value";
- } elsif ($type eq 'volatile') {
- #
- # A location that can change without
- # direct program manipulation.
- #
- printf("data at 0x%s volatile char %s;$rest\n", $value, $name);
- } elsif ($type =~ /^bits/) {
- ($junk, $register) = split(/\s/, $type);
- $bit = hex($value);
- $addr = $addr{"$register"};
- printf("BIT_AT($addr,$bit) $name;$rest\n");
- } else {
- #
- # Other registers, bits and/or configurations.
- #
- if ($type eq 'other') {
- #
- # A known symbol.
- #
- printf("#define %-20s 0x%s$rest\n", $name, $value);
- } else {
- #
- # A symbol that isn't defined in the data
- # section at the end of the file. Let's
- # add a comment so that we can add it later.
- #
- printf("#define %-20s 0x%s$rest\n",
- $name, $value);
- }
- }
- } elsif (/^\s*$/) {
- #
- # Blank line.
- #
- print;
- } else {
- #
- # Anything else we'll just comment out.
- #
- print "// $_";
- }
-}
+print $header
+ . $addresses . "\n"
+ . $pragmas . "\n\n"
+ . $body
+ . "#endif\n";
sub Usage {
print STDERR <<EOT;
http://www.gnu.org/copyleft/gpl.html See http://sdcc.sourceforge.net/
for the latest information on sdcc.
-Usage: $programName [file]
+Usage: $programName processor [path]
where:
- file A MPASM include file name. If none is supplied, the
- standard input will be used.
+ processor The name of the processor (16f84, 16f877, etc.)
- The header file will be written to the standard output.
+ path The path to the parent of the "header" and "lkr"
+ directories. The default is "/usr/share/gpasm".
+ The header file will be written to the standard output.
+ $#ARGV
EOT
exit;
}
__END__
+#
+# processor <processor_name>
+# address <register_name> <hex_address>
+# bitmask <bitmask> <register_list>
+# ram <lo_address> <hi_address> <bitmask>
+# sfr <register_list>
+# volatile <address_list>
+# bit <address_list>
+#
+
alias OPTION_REG OPTION
-address OPTION_REG 0x0081
+volatile INDF PCL
+
+#
+# bitmask settings.
+#
+processor 16F84
+ bitmask 0x080 INDF PCL STATUS FSR PCLATH INTCON
+
+processor 16F873, 16F874, 16F877, 16F627, 16F628, 16F876
+ bitmask 0x180 INDF PCL STATUS FSR PCLATH INTCON
+ bitmask 0x100 TMR0 OPTION_REG PORTB TRISB
+
+#
+# Memory maps.
+#
+processor 16F84
+ ram 0x000C 0x004f 0x080
-sfr
+processor 16F627, 16F628
+ ram 0x0020 0x006f 0x000
+ ram 0x0070 0x007f 0x180
+ ram 0x00a0 0x00ef 0x000
+ ram 0x0120 0x014f 0x000
-volatile
- INDF PCL
+processor 16F876, 16F877
+ ram 0x0020 0x006f 0x000
+ ram 0x0070 0x007f 0x180
+ ram 0x00a0 0x00ef 0x000
+ ram 0x0110 0x016f 0x000
+ ram 0x0190 0x01ef 0x000
-bit
+processor 16F873, 16F874
+ ram 0x0020 0x007f 0x100
+ ram 0x00a0 0x00ff 0x100