commit 047a7a96d92975129ebb27c25ce0ca52954d5f34 Author: Marcin Gasperowicz Date: Fri Dec 21 16:45:26 2012 +0100 Initial commit The compiler is working. That's all :D diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..be91256 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +*.o +*.img diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..610dd9a --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CC = bin/cc65 +AS = bin/ca65 +LD = bin/ld65 +export CPU = 65c02 + +.PHONY: all +all: lib test + +.PHONY: test +test: + make -C test/ + +.PHONY: lib +lib: + make -C lib/ \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..7716e83 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +Nothing to see here. + +Find me on #redpower at espernet IRC. \ No newline at end of file diff --git a/bin/align b/bin/align new file mode 100755 index 0000000..4da0baf --- /dev/null +++ b/bin/align @@ -0,0 +1,14 @@ +#!/bin/bash +BS=128 +COUNT=`wc -c $1` +BYTES=${COUNT//[^0-9]/} +BLOCKS=$(( BYTES / BS )) +SECTORS=$(( BLOCKS + 1 )) +echo "Code size = " $BYTES +echo "Image size = " $SECTORS " * " $BS " = " $(( SECTORS * BS )) +dd if=/dev/zero of=$1.pad bs=$BS count=$SECTORS > /dev/null 2>&1 +dd if=$1 of=$1.pad conv=notrunc > /dev/null 2>&1 +rm $1 +mv $1.pad $1 +#echo $BLOCKS " bytes aligned to " $NEWBLOCKS " blocks" +#dd if=/dev/zero oflag=seek_bytes seek=$BLOCKS of=$1 bs=16 count=$NEWBLOCKS conv=notrunc \ No newline at end of file diff --git a/bin/ar65 b/bin/ar65 new file mode 100755 index 0000000..1fd945c Binary files /dev/null and b/bin/ar65 differ diff --git a/bin/ca65 b/bin/ca65 new file mode 100755 index 0000000..55b20c8 Binary files /dev/null and b/bin/ca65 differ diff --git a/bin/ca65html b/bin/ca65html new file mode 100755 index 0000000..3d82aba --- /dev/null +++ b/bin/ca65html @@ -0,0 +1,1220 @@ +#!/usr/bin/perl +############################################################################### +# # +# ca65html # +# # +# Convert a ca65 source into HTML # +# # +# # +# # +# (C) 2000-2007 Ullrich von Bassewitz # +# Roemerstrasse 52 # +# D-70794 Filderstadt # +# EMail: uz@cc65.org # +# # +# # +# This software is provided 'as-is', without any expressed or implied # +# warranty. In no event will the authors be held liable for any damages # +# arising from the use of this software. # +# # +# Permission is granted to anyone to use this software for any purpose, # +# including commercial applications, and to alter it and redistribute it # +# freely, subject to the following restrictions: # +# # +# 1. The origin of this software must not be misrepresented; you must not # +# claim that you wrote the original software. If you use this software # +# in a product, an acknowledgment in the product documentation would be # +# appreciated but is not required. # +# 2. Altered source versions must be plainly marked as such, and must not # +# be misrepresented as being the original software. # +# 3. This notice may not be removed or altered from any source # +# distribution. # +# # +############################################################################### + + + +# Things currently missing: +# +# - Scoping with .proc/.endproc, .scope/.endscope, .enum/.endenum, +# .struct/.endstruct, .union/endunion, .repeat/.endrep, .local +# - .global is ignored +# - .case is ignored, labels are always case-sensitive +# - .include handling (difficult) +# - The global namespace operator :: +# + + + +use strict 'vars'; +use warnings; + +# Modules +use Getopt::Long; + + + +#-----------------------------------------------------------------------------# +# Variables # +# ----------------------------------------------------------------------------# + + + +# Global variables +my %Files = (); # List of all files. +my $FileCount = 0; # Number of input files +my %Exports = (); # List of exported symbols. +my %Imports = (); # List of imported symbols. +my %Labels = (); # List of all labels +my $LabelNum = 0; # Counter to generate unique labels + +# Command line options +my $BGColor = "#FFFFFF"; # Background color +my $Colorize = 0; # Colorize the output +my $CommentColor = "#B22222"; # Color for comments +my $CRefs = 0; # Add references to the C file +my $CtrlColor = "#228B22"; # Color for control directives +my $CvtTabs = 0; # Convert tabs to spaces +my $TabSize = 8; # This is how god created them +my $Debug = 0; # No debugging +my $Help = 0; # Help flag +my $HTMLDir = ""; # Directory in which to create the files +my $IndexCols = 6; # Columns in the file listing +my $IndexTitle = "Index"; # Title of index page +my $IndexName = "index.html"; # Name of index page +my $IndexPage = 0; # Create an index page +my $KeywordColor = "#A020F0"; # Color for keywords +my $LineLabels = 0; # Add a HTML label to each line +my $LineNumbers = 0; # Add line numbers to the output +my $LinkStyle = 0; # Default link style +my $ReplaceExt = 0; # Replace extension instead of appending +my $StringColor = "#6169C1"; # Color for strings +my $TextColor = "#000000"; # Text color +my $Verbose = 0; # Be quiet + +# Table used to convert the label number into names +my @NameTab = ('A' .. 'Z', '0' .. '9'); + + + +#-----------------------------------------------------------------------------# +# Helper functions # +# ----------------------------------------------------------------------------# + + + +# Terminate with an error +sub Abort { + print STDERR "ca65html: @_\n"; + exit 1; +} + +# Print a message if verbose is true +sub Gabble { + if ($Verbose) { + print "ca65html: @_\n"; + } +} + +# Generate a label and return it +sub GenLabel { + + my $I; + my $L = "";; + my $Num = $LabelNum++; + + # Generate the label + for ($I = 0; $I < 4; $I++) { + $L = $NameTab[$Num % 36] . $L; + $Num /= 36; + } + return $L; +} + +# Make an output file name from an input file name +sub GetOutName { + + # Input name is parameter + my $InName = $_[0]; + + # Create the output file name from the input file name + if ($ReplaceExt && $InName =~ /^(.+)\.([^\.\/]*)$/) { + return "$1.html"; + } else { + return "$InName.html"; + } +} + +# Translate some HTML characters into harmless names. +sub Cleanup { + my $S = shift (@_); + $S =~ s/&/&/g; + $S =~ s//>/g; + $S =~ s/\"/"/g; + return $S; +} + +# Strip a path from a filename and return just the name +sub StripPath { + + # Filename is argument + my $FileName = $_[0]; + + # Remove a path name if we have one + $FileName =~ /^(.*?)([^\/]*)$/; + return $2; +} + + + +#-----------------------------------------------------------------------------# +# Document header and footer # +# ----------------------------------------------------------------------------# + + + +# Print the document header +sub DocHeader { + my $OUT = shift (@_); + my $Asm = shift (@_); + print $OUT "\n"; + print $OUT <<"EOF"; + + + + +$Asm + + + +

$Asm

+EOF +} + +# Print the document footer +sub DocFooter { + my $OUT = shift (@_); + my $Name = shift (@_); + + # Get the current date and time + my $Today = localtime; + + # Print + print $OUT "
\n"; + print $OUT "\n"; + print $OUT "\"Valid
\n"; + print $OUT "$Name; generated on $Today by ca65html
\n"; + print $OUT "uz@cc65.org\n"; + print $OUT "
\n"; + print $OUT "\n"; +} + + + +#-----------------------------------------------------------------------------# +# Colorization # +#-----------------------------------------------------------------------------# + + + +sub ColorizeComment { + if ($Colorize && $_[0] ne "") { + return "$_[0]"; + } else { + return $_[0]; + } +} + + + +sub ColorizeCtrl { + if ($Colorize) { + return "$_[0]"; + } else { + return $_[0]; + } +} + + + +sub ColorizeKeyword { + if ($Colorize) { + return "$_[0]"; + } else { + return $_[0]; + } +} + + + +sub ColorizeString { + if ($Colorize) { + return "$_[0]"; + } else { + return $_[0]; + } +} + + + +#-----------------------------------------------------------------------------# +# File list management # +#-----------------------------------------------------------------------------# + + + +sub AddFile { + + # Argument is file to add + my $FileName = $_[0]; + + # Get just the name (remove a path if there is one) + my $Name = StripPath ($FileName); + + # Check if we have the file already + if (exists ($Files{$Name})) { + Gabble ("File \"$FileName\" already known"); + return; + } + + # Check with the full pathname. If we don't find it, search in the current + # directory + if (-f $FileName && -r _) { + $Files{$Name} = $FileName; + $FileCount++; + } elsif (-f $Name && -r _) { + $Files{$Name} = $Name; + $FileCount++; + } else { + Abort ("$FileName not found or not readable"); + } +} + + + +#-----------------------------------------------------------------------------# +# Referencing and defining labels # +#-----------------------------------------------------------------------------# + + + +# Get a label reference +sub RefLabel { + + # Arguments are: Filename, identifier, item that should be tagged + my $FileName = $_[0]; + my $Id = $_[1]; + my $Item = $_[2]; + + # Search for the identifier in the list of labels + if (exists ($Labels{$FileName}{$Id})) { + # It is a label (in this file) + return sprintf ("%s", $Labels{$FileName}{$Id}, $Item); + } elsif (exists ($Imports{$FileName}{$Id})) { + # It is an import. If LinkStyle is 1, or if the file exporting the + # identifier is not visible, we link to the .import statement in the + # current file. Otherwise we link directly to the referenced symbol + # in the file that exports it. + if ($LinkStyle == 1 or not exists ($Exports{$Id})) { + return sprintf ("%s", $Imports{$FileName}{$Id}, $Item); + } else { + # Get the filename from the export + my $Label; + ($FileName, $Label) = split (/#/, $Exports{$Id}); + if (not defined ($Labels{$FileName}{$Id})) { + # This may currently happen because we don't see .include + # statements, so we may have an export but no definition. + # Link to the .export statement instead + $Label = $Exports{$Id}; + } else { + # Link to the definition in the file + $Label = sprintf ("%s#%s", $FileName, $Labels{$FileName}{$Id}); + } + return sprintf ("%s", $Label, $Item); + } + } else { + # The symbol is unknown, return as is + return $Item; + } +} + + + +#-----------------------------------------------------------------------------# +# Pass 1 # +# ----------------------------------------------------------------------------# + + + +# Process1: Read one file for the first time. +sub Process1 { + + # Variables + my $Line; + my $Id; + + # Filename is parameter + my $InName = shift(@_); + + # Create the output file name from the input file name + my $OutName = GetOutName ($InName); + + # Current cheap local label prefix is empty + my $CheapPrefix = ""; + + # Open a the input file + my $FileName = $Files{$InName}; # Includes path if needed + open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!"); + + # Keep the user happy + Gabble ("$FileName => $OutName"); + + # Read and process all lines from the file + while ($Line = ) { + + # Remove the newline + chomp ($Line); + + # Check for a label + if ($Line =~ /^\s*(([\@?]?)[_a-zA-Z]\w*)\s*(?::=?|=)/) { + + # Is this a local label? + if ($2 ne "") { + # Use the prefix + $Id = "$CheapPrefix$1"; + } else { + # Use as is + $Id = $1; + # Remember the id as new cheap local prefix + $CheapPrefix = $Id; + } + + # Remember the label + $Labels{$OutName}{$Id} = GenLabel(); + + # Check for an import statement + } elsif ($Line =~ /^\s*\.(?:(?:force)?import|importzp)\s+(.*?)\s*(?:;.*)?$/i) { + + # Split into a list of identifiers + my @Ids = split (/\s*(?::\s*[A-Za-z]+\s*)?,\s*/, $1); + + # Remove an address-size specifier, from the last identifier, + # if there is one. + $Ids[$#Ids] =~ s/\s*:\s*[A-Za-z]+//; + + for $Id (@Ids) { + $Imports{$OutName}{$Id} = GenLabel(); + } + + # Check for an export statement + } elsif ($Line =~ /^\s*\.export(?:zp)?\s+(.*?)\s*(?:;.*)?$/i) { + + # Split into a list of identifiers + my @Ids = split (/\s*(?::\s*[A-Za-z]+\s*)?,\s*/, $1); + + # Remove an address-size specifier, from the last identifier, + # if there is one. + $Ids[$#Ids] =~ s/\s*:\s*[A-Za-z]+//; + + for $Id (@Ids) { + $Exports{$Id} = sprintf ("%s#%s", $OutName, GenLabel()); + } + + # Check for an actor statement. + } elsif ($Line =~ /^\s*\.(?:(?:(?:con|de)struc|interrup)tor|condes)\s+([_a-z]\w*)/i) { + $Exports{$1} = sprintf ("%s#%s", $OutName, GenLabel()); + + # Check for a .proc statement + } elsif ($Line =~ /^\s*\.proc\s+([_a-z]\w*)/i) { + + # Remember the ID as the new cheap-local prefix. + $CheapPrefix = $1; + $Labels{$OutName}{$1} = GenLabel(); + } + } + + # Close the input file + close (INPUT); +} + + + +# Pass1: Read all files for the first time. +sub Pass1 () { + + # Keep the user happy + Gabble ("Pass 1"); + + # Walk over the files + for my $InName (keys (%Files)) { + # Process one file + Process1 ($InName); + } +} + + + +#-----------------------------------------------------------------------------# +# Pass 2 # +# ----------------------------------------------------------------------------# + + + +# Process2: Read one file the second time. +sub Process2 { + + # Variables + my $Base; + my $Ext; + my $Line; + my $OutLine; + my $Id; + my $Label; + my $Comment; + my $Trailer; + + # Input file is parameter + my $InName = shift(@_); + + # Create the output file name from the input file name + my $OutName = GetOutName ($InName); + + # Current cheap local label prefix is empty + my $CheapPrefix = ""; + + # Open a the input file + my $FileName = $Files{$InName}; # Includes path if needed + open (INPUT, "<$FileName") or Abort ("Cannot open $FileName: $!"); + + # Open the output file and print the HTML header + open (OUTPUT, ">$HTMLDir$OutName") or Abort ("Cannot open $OutName: $!"); + DocHeader (OUTPUT, $InName); + print OUTPUT "
\n";
+
+    # Keep the user happy
+    Gabble ("$FileName => $OutName");
+
+    # The instructions that will have hyperlinks if a label is used.
+    # And, they will be highlighted when color is used.
+    my $LabelIns = "adc|add|and|asl|bb[rs][0-7]|b[cv][cs]|beq|bge|bit|blt|".
+		 "bmi|bne|bpl|br[akl]|bsr|cmp|cop|cp[axy]|dec|eor|inc|jml|".
+		 "jmp|jsl|jsr|ld[axy]|lsr|mvn|mvp|ora|pe[air]|rep|".
+		 "[rs]mb[0-7]|rol|ror|sbc|sep|st[012axyz]|sub|tai|tam|tdd|".
+		 "ti[ain]|tma|trb|tsb|tst";
+
+    # Instructions that have only the implied-addressing mode -- therefore,
+    # no hyperlinking.  They will be highlighted only, when color is used.
+    my $OtherIns = "cl[acdivxy]|csh|csl|de[axy]|in[axy]|nop|ph[abdkpxy]|".
+		 "pl[abdpxy]|rt[ils]|sax|say|se[cdit]|stp|swa|sxy|ta[dsxy]|".
+		 "tam[0-7]|tcd|tcs|tda|tdc|tma[0-7]|ts[acx]|tx[asy]|tya|tyx|".
+		 "wai|xba|xce";
+
+    # Read the input file, replacing references with hyperlinks; and, mark
+    # labels as link targets.
+    my $LineNo = 0;
+    LINE: while ($Line = ) {
+
+        # Count input lines
+        $LineNo++;
+
+ 	# Remove the newline at the end of line. Don't use chomp to be able to
+        # read dos/windows sources on unices.
+        $Line =~ s/[\r\n]*$//;
+
+        # If requested, convert tabs to spaces
+	if ($CvtTabs) {
+	    # Don't ask me - this is from the perl manual page
+	    1 while ($Line =~ s/\t+/' ' x (length($&) * $TabSize - length($`) % $TabSize)/e) ;
+	}
+
+       	# Clear the output line
+	$OutLine = "";
+
+        # If requested, add a html label to each line with a name "linexxx",
+        # so it can be referenced from the outside (this is the same convention
+        # that is used by c2html). If we have line numbers enabled, add them.
+        if ($LineLabels && $LineNumbers) {
+            $OutLine .= sprintf ("%6d:  ", $LineNo, $LineNo);
+        } elsif ($LineLabels) {
+            $OutLine .= sprintf ("", $LineNo);
+        } elsif ($LineNumbers) {
+            $OutLine .= sprintf ("%6d:  ", $LineNo);
+        }
+
+        # Cut off a comment from the input line. Beware: We have to check for
+        # strings, since these may contain a semicolon that is no comment
+        # start.
+        ($Line, $Comment) = $Line =~ /^((?:[^"';]+|".*?"|'.*?')*)(.*)$/;
+        if ($Comment =~ /^["']/) {
+            # Line with invalid syntax - there's a string start but
+            # no string end.
+            Abort (sprintf ("Invalid input at %s(%d)", $FileName, $LineNo));
+        }
+
+        # Remove trailing whitespace and move it together with the comment
+        # into the $Trailer variable.
+       	$Line =~ s/\s*$//;
+	$Trailer = $& . ColorizeComment (Cleanup ($Comment));
+
+       	# Check for a label at the start of the line. If we have one, process
+        # it, and remove it from the line.
+        if ($Line =~ s/^\s*?(([\@?]?)[_a-zA-Z]\w*)(\s*(?::=?|=))//) {
+
+	    # Is this a local label?
+       	    if ($2 ne "") {
+		# Use the prefix
+	     	$Id = "$CheapPrefix$1";
+	    } else {
+	      	# Use as is
+	      	$Id = $1;
+	      	# Remember the id as new cheap local prefix
+	      	$CheapPrefix = $Id;
+	    }
+
+	    # Get the label for the id
+	    $Label = $Labels{$OutName}{$Id};
+
+	    # Print the label with a tag
+	    $OutLine .= "$1$3";
+
+	    # Is the name explicitly assigned a value?
+	    if ($3 =~ /=$/) {
+		# Print all identifiers if there are any.
+		while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
+		    # Add the non-label stuff.
+		    $OutLine .= Cleanup ($1);
+
+		    # Use the prefix if the label is local.
+		    # Get the reference to that label if we find it.
+		    $OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
+		}
+
+		# Add a remainder if there is one.
+		$OutLine .= Cleanup ($Line);
+
+		# The line is complete; print it.
+		next LINE;
+	    }
+	}
+
+	# Print any leading whitespace and remove it, so we don't have to
+	# care about whitespace below.
+	if ($Line =~ s/^\s+//) {
+      	    $OutLine .= $&;
+	}
+
+	# Handle the import statements
+	if ($Line =~ s/^\.(?:(?:force)?import|importzp)\s+//i) {
+
+	    # Print any fixed stuff from the line and remove it
+       	    $OutLine .= $&;
+
+ 	    # Print all identifiers if there are any
+ 	    while ($Line =~ s/^[_a-zA-Z]\w*//) {
+
+                # Remember the identifier
+       	       	my $Id = $&;
+
+		# Variable to assemble HTML representation
+       	       	my $Contents = "";
+
+		# Make this import a link target
+		if (exists ($Imports{$OutName}{$Id})) {
+       	       	    $Label = $Imports{$OutName}{$Id};
+       	       	    $Contents .= sprintf (" name=\"%s\"", $Label);
+		}
+
+		# If we have an export for this import, add a link to this
+	     	# export definition
+		if (exists ($Exports{$Id})) {
+		    $Label = $Exports{$Id};
+		    $Contents .= sprintf (" href=\"%s\"", $Label);
+		}
+
+     		# Add the HTML stuff to the output line
+		if ($Contents ne "") {
+		    $OutLine .= sprintf ("%s", $Contents, $Id);
+		} else {
+		    $OutLine .= $Id;
+		}
+
+	     	# Check if another identifier follows
+		if ($Line =~ s/^\s*(?::\s*[A-Za-z]+\s*)?,\s*//) {
+     		    $OutLine .= $&;
+       	     	} else {
+		    last;
+      		}
+	    }
+
+	    # Add an remainder if there is one
+	    $OutLine .= Cleanup ($Line);
+
+       	# Handle export statements
+	} elsif ($Line =~ s/^\.export(?:zp)?\s+//i) {
+
+	    # Print the command and the whitespace.
+	    $OutLine .= $&;
+
+	    # Print all identifiers if there are any
+	    while ($Line =~ s/^[_a-zA-Z]\w*//) {
+
+                # Remember the identifier
+       	       	my $Id = $&;
+
+		# Variable to assemble HTML representation
+       	       	my $Contents = "";
+
+		# If we have a definition for this export in this file, add
+		# a link to the definition.
+		if (exists ($Labels{$OutName}{$Id})) {
+		    $Label = $Labels{$OutName}{$Id};
+       	       	    $Contents = sprintf (" href=\"#%s\"", $Label);
+		}
+
+		# If we have this identifier in the list of exports, add a
+		# jump target for the export.
+		if (exists ($Exports{$Id})) {
+		    $Label = $Exports{$Id};
+       	       	    # Be sure to use only the label part
+		    $Label =~ s/^.*#//;
+		    $Contents .= sprintf (" name=\"%s\"", $Label);
+	     	}
+
+     		# Add the HTML stuff to the output line
+		if ($Contents ne "") {
+	     	    $OutLine .= sprintf ("%s", $Contents, $Id);
+		} else {
+		    $OutLine .= $Id;
+		}
+
+     		# Check if another identifier follows
+      	      	if ($Line =~ s/^\s*(?::\s*[A-Za-z]+\s*)?,\s*//) {
+     	    	    $OutLine .= $&;
+     		} else {
+     		    last;
+     		}
+     	    }
+
+     	    # Add an remainder if there is one
+     	    $OutLine .= Cleanup ($Line);
+
+	# Handle actor statements.
+	} elsif ($Line =~ s/^(\.(?:(?:(?:con|de)struc|interrup)tor|condes)\s+)([_a-z]\w*)//i) {
+
+	    # Print the command and the whitespace.
+	    $OutLine .= $1;
+
+	    # Remember the identifier.
+	    $Id = $2;
+
+	    # Variable to assemble HTML representation
+	    my $Contents = "";
+
+	    # If we have a definition for this actor, in this file,
+	    # then add a link to that definition.
+	    if (exists ($Labels{$OutName}{$Id})) {
+		$Contents = sprintf (" href=\"#%s\"", $Labels{$OutName}{$Id});
+	    }
+
+	    # Get the target, for linking from imports in other files.
+	    $Label = $Exports{$Id};
+	    # Be sure to use only the label part.
+	    $Label =~ s/^.*#//;
+
+	    # Add the HTML stuff and the remainder of the actor
+	    # to the output line.
+	    $OutLine .= sprintf ("%s%s", $Label,
+				 $Contents, $Id, Cleanup ($Line));
+
+     	# Check for .faraddr, .addr, .dword, .word, .dbyt, .byt, .byte, .res,
+	# .elseif, .if, .align, and .org.
+     	} elsif ($Line =~ s/^\.(?:(?:far)?addr|d?word|d?byte?|res|(?:else)?if|align|org)\s+//i) {
+
+     	    # Print the command and the white space
+       	    $OutLine .= $&;
+
+     	    # Print all identifiers if there are any
+       	    while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
+                # Add the non label stuff
+                $OutLine .= Cleanup ($1);
+
+		# Use the prefix if the label is local.
+		# Get the reference to that label if we find it.
+		$OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
+     	    }
+
+     	    # Add an remainder if there is one
+     	    $OutLine .= Cleanup ($Line);
+
+	# Handle .proc
+       	} elsif ($Line =~ /^(\.proc)(\s+)([_a-z]\w*)?(.*)$/i) {
+
+	    # Do we have an identifier?
+	    if ($3 ne "") {
+		# Remember the ID as the new cheap-local prefix.
+		$CheapPrefix = $3;
+
+      	      	# Get the label for the id
+	    	$Label = $Labels{$OutName}{$3};
+
+		# Print the label with a tag
+		$OutLine .= "$1$2$3";
+
+	    } else {
+
+		# Print a line that has invalid syntax (its operand isn't
+		# a correctly formed name).
+		$OutLine .= "$1$2";
+            }
+
+            # Add the remainder
+            $OutLine .= Cleanup ($4);
+
+	# Handle .include
+	} elsif ($Line =~ /^(\.include)(\s*)\"((?:[^\"]+?|\\\")+)(\".*)$/i) {
+
+	    # Add the fixed stuff to the output line
+	    $OutLine .= "$1$2"";
+
+	    # Get the filename into a named variable
+	    my $FileName = Cleanup ($3);
+
+	    # Get the name without a path
+	    my $Name = StripPath ($3);
+
+	    # If the include file is among the list of our files, add a link,
+	    # otherwise just add the name as is.
+	    if (exists ($Files{$Name})) {
+	    	$OutLine .= sprintf ("%s", GetOutName ($Name), $FileName);
+	    } else {
+	    	$OutLine .= $FileName;
+	    }
+
+	    # Add the remainder
+	    $OutLine .= Cleanup ($4);
+
+        # Handle .dbg line
+        } elsif ($CRefs && $Line =~ s/^\.dbg\s+//) {
+
+            # Add the fixed stuff to the output line
+            $OutLine .= $&;
+
+            # Check for the type of the .dbg directive
+            if ($Line =~ /^(line,\s*)\"((?:[^\"]+?|\\\")+)\"(,\s*)(\d+)(.*)$/) {
+
+                # Add the fixed stuff to the output line
+                $OutLine .= "$1"";
+
+                # Get the filename and line number into named variables
+                my $DbgFile = $2;
+                my $DbgLine = $4;
+
+                # Remember the remainder
+                $Line = "\"$3$4$5";
+
+                # Get the name without a path
+                my $Name = StripPath ($DbgFile);
+
+                # We don't need FileName any longer as is, so clean it up
+                $DbgFile = Cleanup ($DbgFile);
+
+                # Add a link to the source file
+                $OutLine .= sprintf ("%s", $Name, $DbgLine, $DbgFile);
+
+                # Add the remainder
+                $OutLine .= Cleanup ($Line);
+
+            } elsif ($Line =~ /^(file,\s*)\"((?:[^\"]+?|\\\")+)\"(.*)$/) { #pf FIXME: doesn't handle \" correctly!
+
+                # Get the filename into a named variables
+                my $DbgFile = Cleanup ($2);
+
+                # Get the name without a path
+                my $Name = Cleanup (StripPath ($2));
+
+                # Add the fixed stuff to the output line
+                $OutLine .= sprintf ("%s\"%s\"%s",
+                                     $1, $Name, $DbgFile, $3);
+
+            } else {
+
+                # Add the remainder
+                $OutLine .= Cleanup ($Line);
+
+            }
+
+        } elsif ($CRefs && $Line =~ /^(\.dbg)(\s+line,\s*)\"((?:[^\"]+?|\\\")+)\"(,\s*)(\d+)(.*$)/) {
+
+            # Add the fixed stuff to the output line
+            $OutLine .= "$1$2"";
+
+	    # Get the filename and line number into named variables
+	    my $FileName = $3;
+            my $LineNo   = $5;
+
+	    # Remember the remainder
+	    $Line = "\"$4$5$6";
+
+	    # Get the name without a path
+	    my $Name = StripPath ($FileName);
+
+	    # We don't need FileName any longer as is, so clean it up
+	    $FileName = Cleanup ($FileName);
+
+       	    # Add a link to the source file
+       	    $OutLine .= sprintf ("%s", $Name, $LineNo, $FileName);
+
+	    # Add the remainder
+	    $OutLine .= Cleanup ($Line);
+
+     	# Check for .ifdef, .ifndef, .ifref, and .ifnref.
+     	} elsif ($Line =~ s/^(\.ifn?[dr]ef\s+)(([\@?]?)[_a-z]\w*)?//i) {
+
+     	    # Print the command and the whitespace.
+       	    $OutLine .= $1;
+
+       	    if ($2 ne "") {
+		# Use the prefix if the label is local.
+		# Get the reference to that label if we find it.
+		$OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
+     	    }
+
+     	    # Add a remainder if there is one.
+     	    $OutLine .= Cleanup ($Line);
+
+	# Check for assertions.
+	} elsif ($Line =~ s/^(\.assert\s+)(.+?)(,\s*(?:error|warning)\s*(?:,.*)?)$/$2/i) {
+
+	    # Print the command and the whitespace.
+	    $OutLine .= $1;
+
+	    $Comment = $3;
+
+	    # Print all identifiers if there are any.
+	    while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
+		# Add the non-label stuff.
+		$OutLine .= Cleanup ($1);
+
+		# Use the prefix if the label is local.
+		# Get the reference to that label if we find it.
+		$OutLine .= RefLabel ($OutName, ($3 ne "") ? "$CheapPrefix$2" : $2, $2);
+	    }
+
+	    # Add a remainder if there is one.
+	    $OutLine .= Cleanup ($Line . $Comment);
+
+     	# Check for instructions with labels
+        } elsif ($Line =~ s/^($LabelIns)\b(\s*)//io) {
+
+	    # Print the instruction and white space
+            $OutLine .= ColorizeKeyword ($1) . $2;
+
+	    # Print all identifiers if there are any.
+	    while ($Line =~ s/^([^_a-zA-Z]*?)(([\@?]?)[_a-zA-Z]\w*)//) {
+
+		# Add the non-label stuff.
+		$OutLine .= Cleanup ($1);
+
+		# Is this a local label?
+		if ($3 ne "") {
+		    # Use the prefix
+		    $Id = "$CheapPrefix$2";
+	     	} else {
+	     	    # Use as is
+	     	    $Id = $2;
+	     	}
+
+	     	# Get the reference to this label if we find it
+		$OutLine .= RefLabel ($OutName, $Id, $2);
+	    }
+
+	    # Reassemble and print the line
+     	    $OutLine .= Cleanup ($Line);
+
+     	# Check for all other instructions
+        } elsif ($Line =~ /^($OtherIns)\b(.*)$/io) {
+
+	    # Colorize and print
+            $OutLine .= ColorizeKeyword ($1) . Cleanup ($2);
+
+      	} else {
+
+	    # Nothing known - print the line
+	    $OutLine .= Cleanup ($Line);
+
+	}
+
+    } continue {
+        # Colorize all keywords
+       	$OutLine =~ s/(?\n";
+    DocFooter (OUTPUT, $OutName);
+
+    # Close the files
+    close (INPUT);
+    close (OUTPUT);
+}
+
+
+
+# Pass2: Read all files the second time.
+sub Pass2 () {
+
+    # Keep the user happy
+    Gabble ("Pass 2");
+
+    # Walk over the files
+    for my $InName (keys (%Files)) {
+       	# Process one file
+       	Process2 ($InName);
+    }
+}
+
+
+
+#-----------------------------------------------------------------------------#
+#		   	     Create an index page     			      #
+# ----------------------------------------------------------------------------#
+
+
+
+# Print a list of all files
+sub FileIndex {
+
+    # File is argument
+    my $INDEX = $_[0];
+
+    # Print the file list in a table
+    print $INDEX "

Files

\n"; + print $INDEX "\n"; + my $Count = 0; + for my $File (sort (keys (%Files))) { + + # + if (($Count % $IndexCols) == 0) { + print $INDEX "\n"; + } + printf $INDEX "\n", GetOutName ($File), $File; + if (($Count % $IndexCols) == $IndexCols-1) { + print $INDEX "\n"; + } + $Count++; + } + if (($Count % $IndexCols) != 0) { + print $INDEX "\n"; + } + print $INDEX "
%s


\n"; +} + + + +# Print a list of all exports +sub ExportIndex { + + # File is argument + my $INDEX = $_[0]; + + # Print the file list in a table + print $INDEX "

Exports

\n"; + print $INDEX "\n"; + my $Count = 0; + for my $Export (sort (keys (%Exports))) { + + # Get the export + my $File; + my $Label; + ($File, $Label) = split (/#/, $Exports{$Export}); + + # The label is the label of the export statement. If we can find the + # actual label, use this instead. + if (exists ($Labels{$File}{$Export})) { + $Label = $Labels{$File}{$Export}; + } + + # + if (($Count % $IndexCols) == 0) { + print $INDEX "\n"; + } + printf $INDEX "\n", $File, $Label, $Export; + if (($Count % $IndexCols) == $IndexCols-1) { + print $INDEX "\n"; + } + $Count++; + } + if (($Count % $IndexCols) != 0) { + print $INDEX "\n"; + } + print $INDEX "
%s


\n"; +} + + + +sub CreateIndex { + + # Open the index page file + open (INDEX, ">$HTMLDir$IndexName") or Abort ("Cannot open $IndexName: $!"); + + # Print the header + DocHeader (INDEX, $IndexTitle, 0); + + # Print the file list in a table + FileIndex (INDEX); + ExportIndex (INDEX); + + # Print the document footer + DocFooter (INDEX, $IndexName); + + # Close the index file + close (INDEX); +} + + + +#-----------------------------------------------------------------------------# +# Print usage information # +# ----------------------------------------------------------------------------# + + + +sub Usage { + print "Usage: ca65html [options] file ...\n"; + print "Options:\n"; + print " --bgcolor c Use background color c instead of $BGColor\n"; + print " --colorize Add color highlights to the output\n"; + print " --commentcolor c Use color c for comments instead of $CommentColor\n"; + print " --crefs Generate references to the C source file(s)\n"; + print " --ctrlcolor c Use color c for directives instead of $CtrlColor\n"; + print " --cvttabs Convert tabs to spaces in the output\n"; + print " --help This text\n"; + print " --htmldir dir Specify directory for HTML files\n"; + print " --indexcols n Use n columns on index page (default $IndexCols)\n"; + print " --indexname file Use file for the index file instead of $IndexName\n"; + print " --indexpage Create an index page\n"; + print " --indextitle title Use title as the index title instead of $IndexTitle\n"; + print " --keywordcolor c Use color c for keywords instead of $KeywordColor\n"; + print " --linelabels Generate a linexxx HTML label for each line\n"; + print " --linenumbers Add line numbers to the output\n"; + print " --linkstyle style Use the given link style\n"; + print " --replaceext Replace source extension instead of appending .html\n"; + print " --tabsize n Use n spaces when replacing tabs (default $TabSize)\n"; + print " --textcolor c Use text color c instead of $TextColor\n"; + print " --verbose Be more verbose\n"; +} + + + +#-----------------------------------------------------------------------------# +# Main # +# ----------------------------------------------------------------------------# + + + +# Get program options +GetOptions ("bgcolor=s" => \$BGColor, + "colorize" => \$Colorize, + "commentcolor=s" => \$CommentColor, + "crefs" => \$CRefs, + "ctrlcolor=s" => \$CtrlColor, + "cvttabs" => \$CvtTabs, + "debug!" => \$Debug, + "help" => \$Help, + "htmldir=s" => \$HTMLDir, + "indexcols=i" => \$IndexCols, + "indexname=s" => \$IndexName, + "indexpage" => \$IndexPage, + "indextitle=s" => \$IndexTitle, + "keywordcolor=s" => \$KeywordColor, + "linelabels" => \$LineLabels, + "linenumbers" => \$LineNumbers, + "linkstyle=i" => \$LinkStyle, + "replaceext" => \$ReplaceExt, + "tabsize=i" => \$TabSize, + "textcolor=s" => \$TextColor, + "verbose!" => \$Verbose, + "<>" => \&AddFile); + +# Check some arguments +if ($IndexCols <= 0 || $IndexCols >= 20) { + Abort ("Invalid value for --indexcols option"); +} +if ($TabSize < 1 || $TabSize > 16) { + Abort ("Invalid value for --tabsize option"); +} +if ($HTMLDir ne "" && $HTMLDir =~ /[^\/]$/) { + # Add a trailing path separator + $HTMLDir .= "/"; +} + + + +# Print help if requested +if ($Help) { + Usage (); +} + +# Check if we have input files given +if ($FileCount == 0) { + Abort ("No input files"); +} + +# Convert the documents +Pass1 (); +Pass2 (); + +# Generate an index page if requested +if ($IndexPage) { + CreateIndex (); +} + +# Done +exit 0; diff --git a/bin/cc65 b/bin/cc65 new file mode 100755 index 0000000..a3643d3 Binary files /dev/null and b/bin/cc65 differ diff --git a/bin/cl65 b/bin/cl65 new file mode 100755 index 0000000..6c3fd42 Binary files /dev/null and b/bin/cl65 differ diff --git a/bin/co65 b/bin/co65 new file mode 100755 index 0000000..bea3de1 Binary files /dev/null and b/bin/co65 differ diff --git a/bin/da65 b/bin/da65 new file mode 100755 index 0000000..dcb408d Binary files /dev/null and b/bin/da65 differ diff --git a/bin/ld65 b/bin/ld65 new file mode 100755 index 0000000..8f47c9e Binary files /dev/null and b/bin/ld65 differ diff --git a/bin/od65 b/bin/od65 new file mode 100755 index 0000000..b6d198d Binary files /dev/null and b/bin/od65 differ diff --git a/disk b/disk new file mode 100755 index 0000000..0ee836e --- /dev/null +++ b/disk @@ -0,0 +1,3 @@ +#!/bin/bash + +cp test/$1.img /Applications/MultiMC.app/Contents/Resources/instances/1.2.5\ ftb/minecraft/saves/cpu\ test/redpower/disk_1b63bbbd8ce6001f.img \ No newline at end of file diff --git a/include/console.h b/include/console.h new file mode 100644 index 0000000..561a941 --- /dev/null +++ b/include/console.h @@ -0,0 +1,48 @@ +//console.h + +// 0x00 Memory access row. Used to set which line of characters appears in the display memory window. + +// 0x01 cursor x +// 0x02 cursor y +// 0x03 cursor mode (0: hidden, 1: solid, 2: blink) + +// 0x04 key buffer start (16 byte buffer) +// 0x05 key buffer position +// 0x06 key value at buffer start + +// 0x07 blit mode (1: fill, 2: invert; 3: shift) +// 0x08 blit x start / fill value +// 0x09 blit y start +// 0x0A blit x offset +// 0x0B blit y offset +// 0x0C blit width +// 0x0D blit height + +// 0x10 -> 0x60 display memory window + +typedef struct Console { + char line; + char cursor_x; + char cursor_y; + char cursor_mode; + + char kb_start; + char kb_pos; + char kb_key; + + char blit_mode; + char blit_start_x; + char blit_start_y; + char blit_offset_x; + char blit_offset_y; + char blit_width; + char blit_height; + + unsigned int padding; + + char display[0x50]; +} Console; + +//character with inverted colors +#define inv(c) ((c) | 0x80) + diff --git a/include/disk.h b/include/disk.h new file mode 100644 index 0000000..6fd9ad4 --- /dev/null +++ b/include/disk.h @@ -0,0 +1,29 @@ +//disk.h + +// 0x00-0x7F: Disk sector buffer +// 0x80-0x81: Sector number +// 0x82: Disk command: +// 0: Idle/success +// 1: Read Disk Name +// 2: Write Disk Name +// 3: Read Disk Serial +// 4: Read Disk Sector +// 5: Write Disk Sector +// 0xFF: Command failure + +typedef enum { + IDLE = 0, + READ_NAME = 1, + WRITE_NAME = 2, + READ_SERIAL = 3, + READ = 4, + WRITE = 5, + FAIL = 0xFF +} DiskCommand; + +typedef struct Disk { + char sector[0x80]; + unsigned int sector_num; + DiskCommand command; +} Disk; + diff --git a/include/iox.h b/include/iox.h new file mode 100644 index 0000000..26689f2 --- /dev/null +++ b/include/iox.h @@ -0,0 +1,46 @@ +// iox.h + + +// device struct + +typedef struct Iox { + unsigned int in; + unsigned int out; +} Iox; + +// Bit Dec Hex Color +// 0 1 0x1 White +// 1 2 0x2 Orange +// 2 4 0x4 Magenta +// 3 8 0x8 Light Blue +// 4 16 0x10 Yellow +// 5 32 0x20 Lime +// 6 64 0x40 Pink +// 7 128 0x80 Gray +// 8 256 0x100 Light Gray +// 9 512 0x200 Cyan +// 10 1024 0x400 Purple +// 11 2048 0x800 Blue +// 12 4096 0x1000 Brown +// 13 8192 0x2000 Green +// 14 16384 0x4000 Red +// 15 32768 0x8000 Black + +typedef enum { + WHITE = 0x0001, + ORANGE = 0x0002, + MAGENTA = 0x0004, + LBLUE = 0x0008, + YELLOW = 0x0010, + LIME = 0x0020, + PINK = 0x0040, + GRAY = 0x0080, + LGRAY = 0x0100, + CYAN = 0x0200, + PURPLE = 0x0400, + BLUE = 0x0800, + BROWN = 0x1000, + GREEN = 0x2000, + RED = 0x4000, + BLACK = 0x8000 +} WireColor; \ No newline at end of file diff --git a/include/redbus.h b/include/redbus.h new file mode 100644 index 0000000..344bd75 --- /dev/null +++ b/include/redbus.h @@ -0,0 +1,33 @@ +// redbus.h + +void rb_enable(void); +void rb_disable(void); + +void __fastcall__ rb_set_window(void* address); + +void __fastcall__ rb_map_device(unsigned char id); + + + +// 0x00 Map device in Reg A to redbus window. +// 0x80 Get mapped device to A. + +// 0x01 Redbus Window offset to A +// 0x81 Get RB window offset to A. + +// 0x02 Enable redbus +// 0x82 Disable redbus + +// 0x03 Set external memory mapped window to A. +// 0x83 Get memory mapped window to A. + +// 0x04 Enable external memory mapped window. +// 0x84 Disable external memory mapped window. + +// 0x05 Set BRK address to A +// 0x85 Get BRK address to A + +// 0x06 Set POR address to A +// 0x86 Get POR address to A + +// 0xFF Output A register to MC logfile. \ No newline at end of file diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..b6bf78c --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,21 @@ +AR = ../bin/ar65 +export CPU = 65c02 + + +#.PHONY: all +all: rpc8e.lib + +rpc8e.lib: runtime common rpc8e + rm -f rpc8e.lib + $(AR) a rpc8e.lib runtime/*.o rpc8e/*.o common/*.o + +.PHONY: runtime rpc8e common + +rpc8e: + make -C rpc8e/ + +runtime: + make -C runtime/ + +common: + make -C common/ \ No newline at end of file diff --git a/lib/asminc/mmu.inc b/lib/asminc/mmu.inc new file mode 100644 index 0000000..c45552f --- /dev/null +++ b/lib/asminc/mmu.inc @@ -0,0 +1,4 @@ +.macro mmu command + .byte $EF + .byte command +.endmacro \ No newline at end of file diff --git a/lib/asminc/zeropage.inc b/lib/asminc/zeropage.inc new file mode 100644 index 0000000..a258741 --- /dev/null +++ b/lib/asminc/zeropage.inc @@ -0,0 +1,21 @@ +; +; zeropage.inc +; +; (C) Copyright 2002 Ullrich von Bassewitz (uz@cc65.org) +; + +; Assembler include file that imports the runtime zero page locations used +; by the compiler, ready for usage in asm code. + + .importzp sp, sreg, regsave + .importzp ptr1, ptr2, ptr3, ptr4 + .importzp tmp1, tmp2, tmp3, tmp4 + .importzp regbank + +; The total amount of zero page space used + +zpspace = 26 + + + + diff --git a/lib/common/Makefile b/lib/common/Makefile new file mode 100644 index 0000000..b4a5617 --- /dev/null +++ b/lib/common/Makefile @@ -0,0 +1,217 @@ +# +# makefile for CC65 runtime library +# + +.SUFFIXES: .o .s .c + +#-------------------------------------------------------------------------- +# Programs and flags + +SYS = none + +AS = ../../bin/ca65 +CC = ../../bin/cc65 +LD = ../../bin/ld65 + +AFLAGS = -t $(SYS) --forget-inc-paths -I../asminc --cpu $(CPU) +CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(CPU) + +#-------------------------------------------------------------------------- +# Rules + +%.o: %.c + @$(CC) $(CFLAGS) $< + @$(AS) -g -o $@ $(AFLAGS) $(*).s + +%.o: %.s + @$(AS) -g -o $@ $(AFLAGS) $< + +#-------------------------------------------------------------------------- +# Rules to help us see what code the compiler and assembler make. + +%.s : %.c + @$(CC) $(CFLAGS) -S $< + +%.lst : %.s + @$(AS) $(AFLAGS) -l -o /dev/null $< + +#-------------------------------------------------------------------------- +# Object files + +# From C source-files +# C_OBJS = _afailed.o \ +# _hextab.o \ +# _poserror.o \ +# _scanf.o \ +# abort.o \ +# asctime.o \ +# bsearch.o \ +# errormsg.o \ +# fdopen.o \ +# fgetc.o \ +# fgetpos.o \ +# fgets.o \ +# fputc.o \ +# fputs.o \ +# freopen.o \ +# fseek.o \ +# fsetpos.o \ +# ftell.o \ +# getchar.o \ +# gets.o \ +# gmtime.o \ +# locale.o \ +# localtime.o \ +# mktime.o \ +# perror.o \ +# pmemalign.o \ +# puts.o \ +# qsort.o \ +# realloc.o \ +# rewind.o \ +# sleep.o \ +# strftime.o \ +# strtok.o \ +# strtol.o \ +# strtoul.o \ +# strxfrm.o \ +# system.o \ +# timezone.o + +# From assembly source-files +S_OBJS = zerobss.o copydata.o +#_cwd.o \ + # _environ.o \ + # _fdesc.o \ + # _file.o \ + # _fopen.o \ + # _heap.o \ + # _heapadd.o \ + # _heapblocksize.o\ + # _heapmaxavail.o \ + # _heapmemavail.o \ + # _oserror.o \ + # _printf.o \ + # _seterrno.o \ + # _swap.o \ + # _sys.o \ + # abs.o \ + # atexit.o \ + # atoi.o \ + # calloc.o \ + # chdir.o \ + # copydata.o \ + # creat.o \ + # ctime.o \ + # divt.o \ + # errno.o \ + # fclose.o \ + # fmisc.o \ + # fopen.o \ + # fprintf.o \ + # fread.o \ + # free.o \ + # fscanf.o \ + # fwrite.o \ + # getcpu.o \ + # getcwd.o \ + # getenv.o \ + # interrupt.o \ + # isalnum.o \ + # isalpha.o \ + # isblank.o \ + # iscntrl.o \ + # isdigit.o \ + # isgraph.o \ + # islower.o \ + # isprint.o \ + # ispunct.o \ + # isspace.o \ + # isupper.o \ + # isxdigit.o \ + # itoa.o \ + # labs.o \ + # longjmp.o \ + # ltoa.o \ + # malloc.o \ + # maperrno.o \ + # memchr.o \ + # memcmp.o \ + # memcpy.o \ + # memmove.o \ + # memset.o \ + # mkdir.o \ + # modfree.o \ + # modload.o \ + # oserrcheck.o \ + # printf.o \ + # putchar.o \ + # putenv.o \ + # rand.o \ + # raise.o \ + # remove.o \ + # rename.o \ + # rmdir.o \ + # scanf.o \ + # searchenv.o \ + # setjmp.o \ + # signal.o \ + # sigtable.o \ + # snprintf.o \ + # sprintf.o \ + # sscanf.o \ + # strcat.o \ + # strchr.o \ + # strcmp.o \ + # strcoll.o \ + # strcpy.o \ + # strcspn.o \ + # strdup.o \ + # strerror.o \ + # stricmp.o \ + # strlen.o \ + # strlower.o \ + # strncat.o \ + # strncmp.o \ + # strncpy.o \ + # strnicmp.o \ + # stroserr.o \ + # strpbrk.o \ + # strrchr.o \ + # strspn.o \ + # strstr.o \ + # strtoimax.o \ + # strtoumax.o \ + # strupper.o \ + # time.o \ + # tolower.o \ + # toupper.o \ + # uname.o \ + # ungetc.o \ + # unlink.o \ + # utscopy.o \ + # vfprintf.o \ + # vfscanf.o \ + # vprintf.o \ + # vscanf.o \ + # vsnprintf.o \ + # vsprintf.o \ + # vsscanf.o \ + # zerobss.o + + +#-------------------------------------------------------------------------- +# Targets + +.PHONY: all clean zap + +all: $(C_OBJS) $(S_OBJS) + +clean: + @$(RM) *~ *.lst + @$(RM) $(C_OBJS:.o=.s) + @$(RM) $(C_OBJS) + @$(RM) $(S_OBJS) + +zap: clean + diff --git a/lib/common/copydata.s b/lib/common/copydata.s new file mode 100644 index 0000000..b0a9987 --- /dev/null +++ b/lib/common/copydata.s @@ -0,0 +1,49 @@ +; +; Ullrich von Bassewitz, 1998-12-07, 2004-12-01 +; +; Copy the data segment from the LOAD to the RUN location +; + + .export copydata + .import __DATA_LOAD__, __DATA_RUN__, __DATA_SIZE__ + .importzp ptr1, ptr2, tmp1 + + +copydata: + lda #<__DATA_LOAD__ ; Source pointer + sta ptr1 + lda #>__DATA_LOAD__ + sta ptr1+1 + + lda #<__DATA_RUN__ ; Target pointer + sta ptr2 + lda #>__DATA_RUN__ + sta ptr2+1 + + ldx #<~__DATA_SIZE__ + lda #>~__DATA_SIZE__ ; Use -(__DATASIZE__+1) + sta tmp1 + ldy #$00 + +; Copy loop + +@L1: inx + beq @L3 + +@L2: lda (ptr1),y + sta (ptr2),y + iny + bne @L1 + inc ptr1+1 + inc ptr2+1 ; Bump pointers + bne @L1 ; Branch always (hopefully) + +; Bump the high counter byte + +@L3: inc tmp1 + bne @L2 + +; Done + + rts + diff --git a/lib/common/zerobss.s b/lib/common/zerobss.s new file mode 100644 index 0000000..321424e --- /dev/null +++ b/lib/common/zerobss.s @@ -0,0 +1,46 @@ +; +; Ullrich von Bassewitz, 1998-09-17, 2005-02-26. +; +; Zero the bss segment. +; + + .export zerobss + .import __BSS_RUN__, __BSS_SIZE__ + .importzp ptr1 + + +.segment "INIT" + +zerobss: + lda #<__BSS_RUN__ + sta ptr1 + lda #>__BSS_RUN__ + sta ptr1+1 + lda #0 + tay + +; Clear full pages + +L1: ldx #>__BSS_SIZE__ + beq L3 +L2: sta (ptr1),y + iny + bne L2 + inc ptr1+1 + dex + bne L2 + +; Clear remaining page (y is zero on entry) + +L3: cpy #<__BSS_SIZE__ + beq L4 + sta (ptr1),y + iny + bne L3 + +; Done + +L4: rts + + + diff --git a/lib/rpc8e.cfg b/lib/rpc8e.cfg new file mode 100644 index 0000000..65e932a --- /dev/null +++ b/lib/rpc8e.cfg @@ -0,0 +1,40 @@ +MEMORY { + ZEROPAGE: start = $0006, size = $00FA; + STACK: start = $0100, size = $0100, define = yes; + RAM: start = $0500, size = $FAFF, define = yes; +} + +SEGMENTS { + ZEROPAGE: load = ZEROPAGE, type = zp, define = yes; + STARTUP: load = RAM, type = ro; + CODE: load = RAM, type = ro; + INIT: load = RAM, type = ro; + DATA: load = RAM, type = rw, define = yes, run = RAM; + RODATA: load = RAM, type = ro; + BSS: load = RAM, type = bss, define = yes; + HEAP: load = RAM, type = bss, optional = yes; + # VECTOR: load = RAM, type = ro, start = $C000; +} + +FEATURES { + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + # Define the stack size for the application + __STACKSIZE__: value = $0200, weak = yes; +} + +# 0x0000 Zero page +# 0x0100 P-stack +# 0x0200 R-stack +# 0x0300 bus output +# 0x0400 bus input (also Bootloader space) +# 0x0500 Ram (the bootloader loads the disk image here) \ No newline at end of file diff --git a/lib/rpc8e.lib b/lib/rpc8e.lib new file mode 100644 index 0000000..59d3d69 Binary files /dev/null and b/lib/rpc8e.lib differ diff --git a/lib/rpc8e/Makefile b/lib/rpc8e/Makefile new file mode 100644 index 0000000..c30a725 --- /dev/null +++ b/lib/rpc8e/Makefile @@ -0,0 +1,45 @@ +# +# makefile for CC65 runtime library +# + +.SUFFIXES: .o .s .c + +#-------------------------------------------------------------------------- +# Programs and flags + +SYS = none + +AS = ../../bin/ca65 +CC = ../../bin/cc65 +LD = ../../bin/ld65 + +AFLAGS = -t $(SYS) --forget-inc-paths -I../asminc --cpu $(CPU) +CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(CPU) + +#-------------------------------------------------------------------------- +# Rules + +.c.s: + @$(CC) $(CFLAGS) $< + +.s.o: + @$(AS) -g -o $@ $(AFLAGS) $< + +#-------------------------------------------------------------------------- +# Object files + +OBJS = crt0.o \ + redbus.o + +#-------------------------------------------------------------------------- +# Targets + +.PHONY: all clean zap + +all: $(OBJS) + +clean: + @$(RM) *~ $(COBJS:.o=.s) $(OBJS) + +zap: clean + diff --git a/lib/rpc8e/crt0.s b/lib/rpc8e/crt0.s new file mode 100644 index 0000000..0124f15 --- /dev/null +++ b/lib/rpc8e/crt0.s @@ -0,0 +1,95 @@ +; --------------------------------------------------------------------------- +; crt0.s +; --------------------------------------------------------------------------- +; +; Startup code for c65el02 + +.export _init, _exit +.import _main + +.export __STARTUP__ : absolute = 1 ; Mark as startup +.import __STACK_START__, __STACK_SIZE__ ; Linker generated + +.import copydata, zerobss, initlib, donelib + +.include "zeropage.inc" + +.macro MMU command + .byte $EF + .byte command +.endmacro + +.macro XCE + .byte $FB +.endmacro + +; --------------------------------------------------------------------------- +; Place the startup code in a special segment + +.segment "STARTUP" + +;.byte $DB + +; --------------------------------------------------------------------------- +; A little light 6502 housekeeping + +_init: LDX #$FF ; Initialize stack pointer to $01FF + TXS + CLD ; Clear decimal mode + +; --------------------------------------------------------------------------- +; Set cc65 argument stack pointer + + LDA #<(__STACK_START__ + __STACK_SIZE__ - 1) + STA sp + LDA #>(__STACK_START__ + __STACK_SIZE__ - 1) + STA sp+1 + +; --------------------------------------------------------------------------- +; Initialize memory storage + + JSR zerobss ; Clear BSS segment + JSR copydata ; Initialize DATA segment + JSR initlib ; Run constructors + +; --------------------------------------------------------------------------- +; Initialize redbus + +; from foth boot disk +;000500 18 CLC +;000501 FB XCE +;000502 C2 30 REP #$30 +;000504 A9 00 03 LDA #$0300 +;000507 EF 01 MMU $01 +;000509 EF 02 MMU $02 +;00050B A9 00 04 LDA #$0400 +;00050E EF 03 MMU $03 +;000510 EF 04 MMU $04 +;000512 A9 00 05 LDA #$0500 +;000515 EF 06 MMU $06 +;000517 4C 56 1D JMP $1D56 + +;LDA $01 ; Get the main console ID +;MMU $00 + +;LDA #$00 ; Select first line +;STA $0300 + +;LDA #$42 ; Seems to work +;STA $0310 + +;.byte $DB + + + + +; --------------------------------------------------------------------------- +; Call main() + + JSR _main + +; --------------------------------------------------------------------------- +; Back from main (this is also the _exit entry): force a software break + +_exit: JSR donelib ; Run destructors + BRK \ No newline at end of file diff --git a/lib/rpc8e/redbus.s b/lib/rpc8e/redbus.s new file mode 100644 index 0000000..4a6bc3a --- /dev/null +++ b/lib/rpc8e/redbus.s @@ -0,0 +1,55 @@ +.include "mmu.inc" + +.export _rb_enable, _rb_disable, _rb_map_device, _rb_set_window + + +.segment "CODE" + +;------------------------------------------ +; void __inline__ rb_enable(void); +;------------------------------------------ +_rb_enable: + mmu $02 + rts + + +;------------------------------------------ +; void __inline__ rb_disable(void); +;------------------------------------------ +_rb_disable: + mmu $82 + rts + + +;------------------------------------------ +; void __fastcall__ rb_set_window(void* address); +;------------------------------------------ +_rb_set_window: + ;switch to native 16bit + clc + .byte $FB ; XCE + .byte $C2, $30 ; REP #$30 + + ; init redstone window at $0300 + ;.byte $A9, $00, $03 ; LDA #$0300 + .byte $EB ; XBA + stx $55 + ora $55 + .byte $EB ; XBA + mmu $01 + + ;switch to emulated 8bit + .byte $E2, $30 ; SEP #$30 + sec + .byte $FB ; XCE + rts + + +;------------------------------------------ +; void __fastcall__ rb_map_device(unsigned char id); +;------------------------------------------ +_rb_map_device: + mmu $00 + rts + + diff --git a/lib/runtime/Makefile b/lib/runtime/Makefile new file mode 100644 index 0000000..8cadbd4 --- /dev/null +++ b/lib/runtime/Makefile @@ -0,0 +1,234 @@ +# +# makefile for CC65 runtime library +# + +.SUFFIXES: .o .s .c + +#-------------------------------------------------------------------------- +# Programs and flags + +SYS = none + +AS = ../../bin/ca65 +CC = ../../bin/cc65 +LD = ../../bin/ld65 + +AFLAGS = -t $(SYS) --forget-inc-paths -I../asminc --cpu $(CPU) +CFLAGS = -Osir -g -T -t $(SYS) --forget-inc-paths -I . -I ../../include --cpu $(CPU) + +#-------------------------------------------------------------------------- +# Rules + +.c.s: + @$(CC) $(CFLAGS) $< + +.s.o: + @$(AS) -g -o $@ $(AFLAGS) $< + +#-------------------------------------------------------------------------- +# Object files + +OBJS = add.o \ + addeqsp.o \ + addysp.o \ + along.o \ + and.o \ + aslax1.o \ + aslax2.o \ + aslax3.o \ + aslax4.o \ + asleax1.o \ + asleax2.o \ + asleax3.o \ + asleax4.o \ + asr.o \ + asrax1.o \ + asrax2.o \ + asrax3.o \ + asrax4.o \ + asreax1.o \ + asreax2.o \ + asreax3.o \ + asreax4.o \ + axlong.o \ + bneg.o \ + bpushbsp.o \ + call.o \ + callirq.o \ + callmain.o \ + compl.o \ + condes.o \ + decax1.o \ + decax2.o \ + decax3.o \ + decax4.o \ + decax5.o \ + decax6.o \ + decax7.o \ + decax8.o \ + decaxy.o \ + decsp1.o \ + decsp2.o \ + decsp3.o \ + decsp4.o \ + decsp5.o \ + decsp6.o \ + decsp7.o \ + decsp8.o \ + div.o \ + enter.o \ + eq.o \ + ge.o \ + gt.o \ + icmp.o \ + incax1.o \ + incax2.o \ + incax3.o \ + incax5.o \ + incax6.o \ + incax7.o \ + incax8.o \ + incaxy.o \ + incsp1.o \ + incsp2.o \ + incsp3.o \ + incsp4.o \ + incsp5.o \ + incsp6.o \ + incsp7.o \ + incsp8.o \ + jmpvec.o \ + ladd.o \ + laddeq.o \ + laddeqsp.o \ + land.o \ + lasr.o \ + lbneg.o \ + lcmp.o \ + lcompl.o \ + ldai.o \ + ldau0sp.o \ + ldaui.o \ + ldauisp.o \ + ldaxi.o \ + ldaxsp.o \ + ldeaxi.o \ + ldeaxysp.o \ + ldec.o \ + ldiv.o \ + le.o \ + leaaxsp.o \ + leave.o \ + leq.o \ + lge.o \ + lgt.o \ + linc.o \ + lle.o \ + llt.o \ + lmod.o \ + lmul.o \ + lne.o \ + lneg.o \ + lor.o \ + lpop.o \ + lpush.o \ + lrsub.o \ + lsave.o \ + lshelp.o \ + lshl.o \ + lshr.o \ + lsub.o \ + lsubeq.o \ + lsubeqsp.o \ + lt.o \ + ltest.o \ + ludiv.o \ + luge.o \ + lugt.o \ + lule.o \ + lult.o \ + lumod.o \ + lxor.o \ + makebool.o \ + mod.o \ + mul.o \ + mul8.o \ + mulax3.o \ + mulax5.o \ + mulax6.o \ + mulax7.o \ + mulax9.o \ + mulax10.o \ + ne.o \ + neg.o \ + or.o \ + popa.o \ + popsreg.o \ + push1.o \ + push2.o \ + push3.o \ + push4.o \ + push5.o \ + push6.o \ + push7.o \ + pusha.o \ + pushaff.o \ + pushax.o \ + pushb.o \ + pushbsp.o \ + pushc0.o \ + pushc1.o \ + pushc2.o \ + pushlysp.o \ + pushw.o \ + pushwsp.o \ + regswap.o \ + regswap1.o \ + regswap2.o \ + return0.o \ + return1.o \ + rsub.o \ + shelp.o \ + shl.o \ + shr.o \ + shrax1.o \ + shrax2.o \ + shrax3.o \ + shrax4.o \ + shreax1.o \ + shreax2.o \ + shreax3.o \ + shreax4.o \ + staspidx.o \ + staxsp.o \ + staxspi.o \ + steaxsp.o \ + steaxspi.o \ + stkchk.o \ + sub.o \ + subeqsp.o \ + subysp.o \ + swap.o \ + tosint.o \ + toslong.o \ + udiv.o \ + uge.o \ + ugt.o \ + ule.o \ + ult.o \ + umod.o \ + xor.o \ + zeropage.o + +#-------------------------------------------------------------------------- +# Targets + +.PHONY: all clean zap + +all: $(OBJS) + +clean: + @$(RM) *~ $(COBJS:.o=.s) $(OBJS) + +zap: clean + diff --git a/lib/runtime/add.s b/lib/runtime/add.s new file mode 100644 index 0000000..a4a058d --- /dev/null +++ b/lib/runtime/add.s @@ -0,0 +1,39 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: add ints +; + +; Make this as fast as possible, even if it needs more space since it's +; called a lot! + + .export tosadda0, tosaddax + .importzp sp + + .macpack cpu + +tosadda0: + ldx #0 +tosaddax: + clc +.if (.cpu .bitand CPU_ISET_65SC02) + adc (sp) ; 65SC02 version - saves 2 cycles + ldy #1 +.else + ldy #0 + adc (sp),y ; lo byte + iny +.endif + pha ; save it + txa + adc (sp),y ; hi byte + tax + clc + lda sp + adc #2 + sta sp + bcc L1 + inc sp+1 +L1: pla ; Restore low byte + rts + diff --git a/lib/runtime/addeqsp.s b/lib/runtime/addeqsp.s new file mode 100644 index 0000000..d667e36 --- /dev/null +++ b/lib/runtime/addeqsp.s @@ -0,0 +1,24 @@ +; +; Ullrich von Bassewitz, 08.10.1998 +; +; CC65 runtime: += operator for ints on the stack +; + + .export addeq0sp, addeqysp + .importzp sp + +addeq0sp: + ldy #0 +addeqysp: + clc + adc (sp),y + sta (sp),y + pha + iny + txa + adc (sp),y + sta (sp),y + tax + pla + rts + diff --git a/lib/runtime/addysp.s b/lib/runtime/addysp.s new file mode 100644 index 0000000..b5069f1 --- /dev/null +++ b/lib/runtime/addysp.s @@ -0,0 +1,21 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by value in y +; + + .export addysp1, addysp + .importzp sp + +addysp1: + iny +addysp: pha ; Save A + clc + tya ; Get the value + adc sp ; Add low byte + sta sp ; Put it back + bcc @L1 ; If no carry, we're done + inc sp+1 ; Inc high byte +@L1: pla ; Restore A + rts + diff --git a/lib/runtime/along.s b/lib/runtime/along.s new file mode 100644 index 0000000..e8707d8 --- /dev/null +++ b/lib/runtime/along.s @@ -0,0 +1,24 @@ +; +; Ullrich von Bassewitz, 23.11.2002 +; +; CC65 runtime: Convert char in ax into a long +; + + .export aulong, along + .importzp sreg + +; Convert A from char to long in EAX + +aulong: ldx #0 + stx sreg + stx sreg+1 + rts + +along: cmp #$80 ; Positive? + bcc aulong ; Yes, handle like unsigned type + ldx #$ff + stx sreg + stx sreg+1 + rts + + diff --git a/lib/runtime/and.s b/lib/runtime/and.s new file mode 100644 index 0000000..c38b47b --- /dev/null +++ b/lib/runtime/and.s @@ -0,0 +1,30 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: and on ints +; + + .export tosanda0, tosandax + .import addysp1 + .importzp sp, ptr4 + + .macpack cpu + +tosanda0: + ldx #$00 +tosandax: +.if (.cpu .bitand CPU_ISET_65SC02) + and (sp) ; 65SC02 version, saves 2 cycles and 1 byte + ldy #1 +.else + ldy #0 + and (sp),y + iny +.endif + pha + txa + and (sp),y + tax + pla + jmp addysp1 ; drop TOS, set condition codes + diff --git a/lib/runtime/aslax1.s b/lib/runtime/aslax1.s new file mode 100644 index 0000000..eddb527 --- /dev/null +++ b/lib/runtime/aslax1.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register +; + + .export aslax1, shlax1 + .importzp tmp1 + +aslax1: +shlax1: stx tmp1 + asl A + rol tmp1 + ldx tmp1 + rts + + diff --git a/lib/runtime/aslax2.s b/lib/runtime/aslax2.s new file mode 100644 index 0000000..e6e56b0 --- /dev/null +++ b/lib/runtime/aslax2.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register by 4 +; + + .export aslax2, shlax2 + .importzp tmp1 + +aslax2: +shlax2: stx tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + ldx tmp1 + rts + diff --git a/lib/runtime/aslax3.s b/lib/runtime/aslax3.s new file mode 100644 index 0000000..9c9bbb8 --- /dev/null +++ b/lib/runtime/aslax3.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register by 8 +; + + .export aslax3, shlax3 + .importzp tmp1 + +aslax3: +shlax3: stx tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + ldx tmp1 + rts + diff --git a/lib/runtime/aslax4.s b/lib/runtime/aslax4.s new file mode 100644 index 0000000..13c5273 --- /dev/null +++ b/lib/runtime/aslax4.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 25.07.2001 +; +; CC65 runtime: Scale the primary register by 16 +; + + .export aslax4, shlax4 + .importzp tmp1 + +aslax4: +shlax4: stx tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + asl a + rol tmp1 + ldx tmp1 + rts + diff --git a/lib/runtime/asleax1.s b/lib/runtime/asleax1.s new file mode 100644 index 0000000..8f30a18 --- /dev/null +++ b/lib/runtime/asleax1.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 2 +; + + .export asleax1, shleax1 + .importzp sreg, tmp1 + +asleax1: +shleax1: + stx tmp1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + ldx tmp1 + rts + diff --git a/lib/runtime/asleax2.s b/lib/runtime/asleax2.s new file mode 100644 index 0000000..772a37d --- /dev/null +++ b/lib/runtime/asleax2.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 4 +; + + .export asleax2, shleax2 + .importzp sreg, tmp1 + +asleax2: +shleax2: + stx tmp1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + ldx tmp1 + rts + diff --git a/lib/runtime/asleax3.s b/lib/runtime/asleax3.s new file mode 100644 index 0000000..1c45320 --- /dev/null +++ b/lib/runtime/asleax3.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 8 +; + + .export asleax3, shleax3 + .importzp sreg, tmp1 + +asleax3: +shleax3: + stx tmp1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + asl a + rol tmp1 + rol sreg + rol sreg+1 + ldx tmp1 + rts + diff --git a/lib/runtime/asleax4.s b/lib/runtime/asleax4.s new file mode 100644 index 0000000..b5f1721 --- /dev/null +++ b/lib/runtime/asleax4.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 25.07.2001 +; +; CC65 runtime: Scale the 32 bit primary register by 16 +; + + .export asleax4, shleax4 + .importzp sreg, tmp1 + +asleax4: +shleax4: + stx tmp1 + ldx #4 +@L1: asl a + rol tmp1 + rol sreg + rol sreg+1 + dex + bne @L1 + ldx tmp1 + rts + diff --git a/lib/runtime/asr.s b/lib/runtime/asr.s new file mode 100644 index 0000000..8a3565e --- /dev/null +++ b/lib/runtime/asr.s @@ -0,0 +1,60 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for ints +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosasrax + .import popax + .importzp tmp1 + +tosasrax: + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + + cpy #8 ; Shift count 8 or greater? + bcc L1 ; Jump if not + +; Shift count is greater 8. The carry is set when we enter here. + + tya + sbc #8 + tay ; Adjust shift count + txa + ldx #$00 ; Shift by 8 bits + cmp #$00 ; Test sign bit + bpl L1 + dex ; Make X the correct sign extended value + +; Save the high byte so we can shift it + +L1: stx tmp1 ; Save high byte + jmp L3 + +; Do the actual shift + +L2: cpx #$80 ; Copy bit 15 into the carry + ror tmp1 + ror a +L3: dey + bpl L2 + +; Done with shift + + ldx tmp1 +L9: rts + + + diff --git a/lib/runtime/asrax1.s b/lib/runtime/asrax1.s new file mode 100644 index 0000000..bf7646a --- /dev/null +++ b/lib/runtime/asrax1.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register +; + + .export asrax1 + .importzp tmp1 + +asrax1: stx tmp1 + cpx #$80 ; Put bit 7 into carry + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asrax2.s b/lib/runtime/asrax2.s new file mode 100644 index 0000000..b6cb3f7 --- /dev/null +++ b/lib/runtime/asrax2.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register by 4 +; + + .export asrax2 + .importzp tmp1 + +asrax2: stx tmp1 + cpx #$80 ; Put bit 7 into carry + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asrax3.s b/lib/runtime/asrax3.s new file mode 100644 index 0000000..ee3e9f0 --- /dev/null +++ b/lib/runtime/asrax3.s @@ -0,0 +1,23 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Scale the primary register by 8 +; + + .export asrax3 + .importzp tmp1 + +asrax3: stx tmp1 + cpx #$80 ; Put bit 7 into carry + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asrax4.s b/lib/runtime/asrax4.s new file mode 100644 index 0000000..61b6645 --- /dev/null +++ b/lib/runtime/asrax4.s @@ -0,0 +1,26 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Scale the primary register by 16 +; + + .export asrax4 + .importzp tmp1 + +asrax4: stx tmp1 + cpx #$80 ; Put bit 7 into carry + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + cpx #$80 + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asreax1.s b/lib/runtime/asreax1.s new file mode 100644 index 0000000..ab02ed9 --- /dev/null +++ b/lib/runtime/asreax1.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register +; + + .export asreax1 + .importzp sreg, tmp1 + +asreax1: + stx tmp1 + ldx sreg+1 + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asreax2.s b/lib/runtime/asreax2.s new file mode 100644 index 0000000..9006b12 --- /dev/null +++ b/lib/runtime/asreax2.s @@ -0,0 +1,25 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 4 +; + + .export asreax2 + .importzp sreg, tmp1 + +asreax2: + stx tmp1 + ldx sreg+1 + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asreax3.s b/lib/runtime/asreax3.s new file mode 100644 index 0000000..5f759b2 --- /dev/null +++ b/lib/runtime/asreax3.s @@ -0,0 +1,30 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 8 +; + + .export asreax3 + .importzp sreg, tmp1 + +asreax3: + stx tmp1 + ldx sreg+1 + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/asreax4.s b/lib/runtime/asreax4.s new file mode 100644 index 0000000..577d9ae --- /dev/null +++ b/lib/runtime/asreax4.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 25.07.2001 +; +; CC65 runtime: Scale the 32 bit primary register by 16 +; + + .export asreax4 + .importzp sreg, tmp1 + +asreax4: + stx tmp1 + ldx sreg+1 + ldy #4 +@L1: cpx #$80 ; Get bit 7 into carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + dey + bne @L1 + ldx tmp1 + rts + diff --git a/lib/runtime/axlong.s b/lib/runtime/axlong.s new file mode 100644 index 0000000..dd208bf --- /dev/null +++ b/lib/runtime/axlong.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Convert int in ax into a long +; + + .export axulong, axlong + .importzp sreg + +; Convert AX from int to long in EAX + +axulong: + ldy #0 + sty sreg + sty sreg+1 + rts + +axlong: cpx #$80 ; Positive? + bcc axulong ; Yes, handle like unsigned type + ldy #$ff + sty sreg + sty sreg+1 + rts + + + diff --git a/lib/runtime/bneg.s b/lib/runtime/bneg.s new file mode 100644 index 0000000..8f488f9 --- /dev/null +++ b/lib/runtime/bneg.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: boolean negation +; + + .export bnega, bnegax + .import return0, return1 + +bnegax: cpx #0 + bne L0 +bnega: tax + bne L0 +L1: lda #1 ; Zero already in X + rts + +L0: ldx #0 + txa + rts + diff --git a/lib/runtime/bpushbsp.s b/lib/runtime/bpushbsp.s new file mode 100644 index 0000000..f4d8d53 --- /dev/null +++ b/lib/runtime/bpushbsp.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load a from stack slot and push as byte +; + + .export bpushbsp, bpushbysp + .import pusha + .importzp sp + +bpushbsp: + ldy #0 +bpushbysp: + lda (sp),y + jmp pusha + + + diff --git a/lib/runtime/call.s b/lib/runtime/call.s new file mode 100644 index 0000000..0600177 --- /dev/null +++ b/lib/runtime/call.s @@ -0,0 +1,13 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: call function via pointer in ax +; + + .export callax + .importzp ptr1 + +callax: sta ptr1 + stx ptr1+1 + jmp (ptr1) ; jump there + diff --git a/lib/runtime/callirq.s b/lib/runtime/callirq.s new file mode 100644 index 0000000..5f2c2d6 --- /dev/null +++ b/lib/runtime/callirq.s @@ -0,0 +1,63 @@ +; +; Ullrich von Bassewitz, 2004-04-04 +; +; CC65 runtime: Support for calling special irq routines declared as condes +; type 2. +; +; There are two reasons, why this is a separate routine, and the generic +; condes routine in condes.s is not used: +; +; 1. Speed. Having several things hardcoded makes it faster. This is +; important if it is called in each interrupt. +; +; 2. Reentrancy. The condes routines must use self modyfiying code, which +; means it is not reentrant. An IRQ using condes, that interrupts +; another use of condes will cause unpredicatble behaviour. The current +; code avoids this by using locking mechanisms, but it's complex and +; has a size and performance penalty. +; +; 3. Special semantics: An interruptor called by callirq must tell by +; setting or resetting the carry flag if the interrupt has been handled +; (which means that the interrupt is no longer active at the interrupt +; source). callirq will call no other interruptors if this happens. To +; simplify code, all interrupt routines will be called with carry clear +; on entry. +; +; As the normal condes routine, this one has the limitation of 127 table +; entries. +; + + .export callirq + .export callirq_y ; Same but with Y preloaded + + .import __INTERRUPTOR_TABLE__, __INTERRUPTOR_COUNT__ + +.code + +; -------------------------------------------------------------------------- +; Call all IRQ routines. The function needs to use self modifying code and +; is thereforce placed in the data segment. It will return carry set if the +; interrupt was handled and carry clear if not. The caller may choose to +; ignore this at will. +; NOTE: The routine must not be called if the table is empty! + +.data + +callirq: + ldy #.lobyte(__INTERRUPTOR_COUNT__*2) +callirq_y: + clc ; Preset carry flag +loop: dey + lda __INTERRUPTOR_TABLE__,y + sta jmpvec+2 ; Modify code below + dey + lda __INTERRUPTOR_TABLE__,y + sta jmpvec+1 ; Modify code below + sty index+1 ; Modify code below +jmpvec: jsr $FFFF ; Patched at runtime + bcs done ; Bail out if interrupt handled +index: ldy #$FF ; Patched at runtime + bne loop +done: rts + + diff --git a/lib/runtime/callmain.s b/lib/runtime/callmain.s new file mode 100644 index 0000000..7e7b689 --- /dev/null +++ b/lib/runtime/callmain.s @@ -0,0 +1,40 @@ +; +; Ullrich von Bassewitz, 2003-03-07 +; +; Push arguments and call main() +; + + + .export callmain + .export __argc, __argv + + .import _main, pushax + +;--------------------------------------------------------------------------- +; Setup the stack for main(), then jump to it + +.proc callmain + + lda __argc + ldx __argc+1 + jsr pushax ; Push argc + + lda __argv + ldx __argv+1 + jsr pushax ; Push argv + + ldy #4 ; Argument size + jmp _main + +.endproc + +;--------------------------------------------------------------------------- +; Data + +.bss +__argc: .res 2 +__argv: .res 2 + + + + diff --git a/lib/runtime/compl.s b/lib/runtime/compl.s new file mode 100644 index 0000000..5e96263 --- /dev/null +++ b/lib/runtime/compl.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: integer complement +; + + .export complax + +complax: + eor #$FF ; Not A + pha + txa + eor #$FF ; Not X + tax + pla + rts + diff --git a/lib/runtime/condes.s b/lib/runtime/condes.s new file mode 100644 index 0000000..c94e412 --- /dev/null +++ b/lib/runtime/condes.s @@ -0,0 +1,84 @@ +; +; Ullrich von Bassewitz, 20.11.2000 +; +; CC65 runtime: Support for calling module constructors/destructors +; +; The condes routine must be called with the table address in a/x and the +; size of the table (which must not be zero!) in y. The current implementation +; limits the table size to 254 bytes (127 vectors) but this shouldn't be +; problem for now and may be changed later. +; +; libinit and libdone call condes with the predefined module constructor and +; destructor tables, they must be called from the platform specific startup +; code. + + + .export initlib, donelib, condes + + .import __CONSTRUCTOR_TABLE__, __CONSTRUCTOR_COUNT__ + .import __DESTRUCTOR_TABLE__, __DESTRUCTOR_COUNT__ + + .macpack cpu + +; -------------------------------------------------------------------------- +; Initialize library modules + +.segment "INIT" + +.proc initlib + + ldy #<(__CONSTRUCTOR_COUNT__*2) + beq exit + lda #<__CONSTRUCTOR_TABLE__ + ldx #>__CONSTRUCTOR_TABLE__ + jmp condes +exit: rts + +.endproc + + +; -------------------------------------------------------------------------- +; Cleanup library modules + +.code + +.proc donelib + + ldy #<(__DESTRUCTOR_COUNT__*2) + beq exit + lda #<__DESTRUCTOR_TABLE__ + ldx #>__DESTRUCTOR_TABLE__ + jmp condes +exit: rts + +.endproc + + +; -------------------------------------------------------------------------- +; Generic table call handler. The code uses self modifying code and goes +; into the data segment for this reason. +; NOTE: The routine must not be called if the table is empty! + +.data + +.proc condes + + sta fetch1+1 + stx fetch1+2 + sta fetch2+1 + stx fetch2+2 +loop: dey +fetch1: lda $FFFF,y ; Patched at runtime + sta jmpvec+2 + dey +fetch2: lda $FFFF,y ; Patched at runtime + sta jmpvec+1 + sty index+1 +jmpvec: jsr $FFFF ; Patched at runtime +index: ldy #$FF ; Patched at runtime + bne loop + rts + +.endproc + + diff --git a/lib/runtime/decax1.s b/lib/runtime/decax1.s new file mode 100644 index 0000000..7c6891a --- /dev/null +++ b/lib/runtime/decax1.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: Decrement ax by 1 +; + + .export decax1 + + .macpack generic + +.proc decax1 + + sub #1 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax2.s b/lib/runtime/decax2.s new file mode 100644 index 0000000..f117063 --- /dev/null +++ b/lib/runtime/decax2.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: Decrement ax by 2 +; + + .export decax2 + + .macpack generic + +.proc decax2 + + sub #2 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax3.s b/lib/runtime/decax3.s new file mode 100644 index 0000000..3a86d3f --- /dev/null +++ b/lib/runtime/decax3.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 3 +; + + .export decax3 + + .macpack generic + +.proc decax3 + + sub #3 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax4.s b/lib/runtime/decax4.s new file mode 100644 index 0000000..57e5c7c --- /dev/null +++ b/lib/runtime/decax4.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 4 +; + + .export decax4 + + .macpack generic + +.proc decax4 + + sub #4 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax5.s b/lib/runtime/decax5.s new file mode 100644 index 0000000..5b44bbb --- /dev/null +++ b/lib/runtime/decax5.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 5 +; + + .export decax5 + + .macpack generic + +.proc decax5 + + sub #5 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax6.s b/lib/runtime/decax6.s new file mode 100644 index 0000000..0ca4de6 --- /dev/null +++ b/lib/runtime/decax6.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 6 +; + + .export decax6 + + .macpack generic + +.proc decax6 + + sub #6 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax7.s b/lib/runtime/decax7.s new file mode 100644 index 0000000..17636b5 --- /dev/null +++ b/lib/runtime/decax7.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 7 +; + + .export decax7 + + .macpack generic + +.proc decax7 + + sub #7 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decax8.s b/lib/runtime/decax8.s new file mode 100644 index 0000000..abeb632 --- /dev/null +++ b/lib/runtime/decax8.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 26.03.2001 +; +; CC65 runtime: Decrement ax by 8 +; + + .export decax8 + + .macpack generic + +.proc decax8 + + sub #8 + bcs @L9 + dex +@L9: rts + +.endproc diff --git a/lib/runtime/decaxy.s b/lib/runtime/decaxy.s new file mode 100644 index 0000000..ec2b9c7 --- /dev/null +++ b/lib/runtime/decaxy.s @@ -0,0 +1,21 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: Decrement ax by value in Y +; + + .export decaxy + .importzp tmp1 + + .macpack generic + +.proc decaxy + + sty tmp1 + sub tmp1 + bcs @L9 + dex +@L9: rts + +.endproc + diff --git a/lib/runtime/decsp1.s b/lib/runtime/decsp1.s new file mode 100644 index 0000000..ab31a49 --- /dev/null +++ b/lib/runtime/decsp1.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 1 +; + + .export decsp1 + .importzp sp + +.proc decsp1 + + ldy sp + bne @L1 + dec sp+1 +@L1: dec sp + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp2.s b/lib/runtime/decsp2.s new file mode 100644 index 0000000..c92da4d --- /dev/null +++ b/lib/runtime/decsp2.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 2 +; + + .export decsp2 + .importzp sp + +.proc decsp2 + + lda sp + sec + sbc #2 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp3.s b/lib/runtime/decsp3.s new file mode 100644 index 0000000..9401c3d --- /dev/null +++ b/lib/runtime/decsp3.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 3 +; + + .export decsp3 + .importzp sp + +.proc decsp3 + + lda sp + sec + sbc #3 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp4.s b/lib/runtime/decsp4.s new file mode 100644 index 0000000..8513390 --- /dev/null +++ b/lib/runtime/decsp4.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 4 +; + + .export decsp4 + .importzp sp + +.proc decsp4 + + lda sp + sec + sbc #4 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp5.s b/lib/runtime/decsp5.s new file mode 100644 index 0000000..0519bf4 --- /dev/null +++ b/lib/runtime/decsp5.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 5 +; + + .export decsp5 + .importzp sp + +.proc decsp5 + + lda sp + sec + sbc #5 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp6.s b/lib/runtime/decsp6.s new file mode 100644 index 0000000..31d6ec9 --- /dev/null +++ b/lib/runtime/decsp6.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 6 +; + + .export decsp6 + .importzp sp + +.proc decsp6 + + lda sp + sec + sbc #6 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/decsp7.s b/lib/runtime/decsp7.s new file mode 100644 index 0000000..249b00b --- /dev/null +++ b/lib/runtime/decsp7.s @@ -0,0 +1,25 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 7 +; + + .export decsp7 + .importzp sp + +.proc decsp7 + + lda sp + sec + sbc #7 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + diff --git a/lib/runtime/decsp8.s b/lib/runtime/decsp8.s new file mode 100644 index 0000000..0c0c8fe --- /dev/null +++ b/lib/runtime/decsp8.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Decrement the stackpointer by 8 +; + + .export decsp8 + .importzp sp + +.proc decsp8 + + lda sp + sec + sbc #8 + sta sp + bcc @L1 + rts + +@L1: dec sp+1 + rts + +.endproc + + + + + diff --git a/lib/runtime/div.s b/lib/runtime/div.s new file mode 100644 index 0000000..e419ded --- /dev/null +++ b/lib/runtime/div.s @@ -0,0 +1,37 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: division for signed ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $8000, in which case the negate will fail. + + .export tosdiva0, tosdivax + .import popsargs, udiv16, negax + .importzp sreg, tmp1, tmp2 + +tosdiva0: + ldx #0 +tosdivax: + jsr popsargs ; Get arguments from stack, adjust sign + jsr udiv16 ; Do the division + ldx sreg+1 ; Load high byte of result + +; Adjust the sign of the result. tmp1 contains the high byte of the left +; operand, tmp2 contains the high byte of the right operand. + + lda tmp1 + eor tmp2 + bpl Pos ; Jump if sign of result positive + +; Result is negative + + lda sreg ; Load low byte of result + jmp negax ; Adjust the sign + +; Result is positive + +Pos: lda sreg + rts + diff --git a/lib/runtime/enter.s b/lib/runtime/enter.s new file mode 100644 index 0000000..a246d5e --- /dev/null +++ b/lib/runtime/enter.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: function prologue +; + + .export enter + .importzp sp + +enter: tya ; get arg size + ldy sp + bne L1 + dec sp+1 +L1: dec sp + ldy #0 + sta (sp),y ; Store the arg count + rts + diff --git a/lib/runtime/eq.s b/lib/runtime/eq.s new file mode 100644 index 0000000..28e5205 --- /dev/null +++ b/lib/runtime/eq.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare == for ints +; + + .export toseq00, toseqa0, toseqax + .import tosicmp, booleq + .importzp sp, tmp1 + +toseq00: + lda #$00 +toseqa0: + ldx #$00 +toseqax: + jsr tosicmp ; Set flags + jmp booleq ; Convert to boolean diff --git a/lib/runtime/ge.s b/lib/runtime/ge.s new file mode 100644 index 0000000..17d4bb9 --- /dev/null +++ b/lib/runtime/ge.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare >= for signed ints +; + + .export tosge00, tosgea0, tosgeax + .import tosicmp, boolge + + +tosge00: + lda #$00 +tosgea0: + ldx #$00 +tosgeax: + jsr tosicmp ; Set flags + jmp boolge ; Convert to boolean diff --git a/lib/runtime/gt.s b/lib/runtime/gt.s new file mode 100644 index 0000000..b6ba7b6 --- /dev/null +++ b/lib/runtime/gt.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare > for signed ints +; + + .export tosgt00, tosgta0, tosgtax + .import tosicmp, boolgt + + +tosgt00: + lda #$00 +tosgta0: + ldx #$00 +tosgtax: + jsr tosicmp ; Set the flags + jmp boolgt ; Convert to boolean + diff --git a/lib/runtime/icmp.s b/lib/runtime/icmp.s new file mode 100644 index 0000000..70bcb76 --- /dev/null +++ b/lib/runtime/icmp.s @@ -0,0 +1,47 @@ +; +; Piotr Fusik, 15.04.2002 +; originally by Ullrich von Bassewitz +; +; Integer compare function - used by the compare operators +; + + .export tosicmp, tosicmp0 + .importzp sp, sreg + + +tosicmp0: + ldx #$00 + +tosicmp: + sta sreg + stx sreg+1 ; Save ax + + ldy #$00 + lda (sp),y ; Get low byte + tax + inc sp ; 5 + bne @L1 ; 3 + inc sp+1 ; (5) +@L1: + lda (sp),y ; Get high byte + inc sp ; 5 + bne @L2 ; 3 + inc sp+1 ; (5) + +; Do the compare. + +@L2: sec + sbc sreg+1 ; Compare high byte + bne @L4 + cpx sreg ; Compare low byte + beq @L3 + adc #$FF ; If the C flag is set then clear the N flag + ora #$01 ; else set the N flag +@L3: rts + +@L4: bvc @L3 + eor #$FF ; Fix the N flag if overflow + ora #$01 ; Clear the Z flag + rts + + diff --git a/lib/runtime/incax1.s b/lib/runtime/incax1.s new file mode 100644 index 0000000..2d57b39 --- /dev/null +++ b/lib/runtime/incax1.s @@ -0,0 +1,24 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 1 +; + + .export incax1 + + .macpack generic + .macpack cpu + +.proc incax1 + +.if (.cpu .bitand ::CPU_ISET_65SC02) + ina ; 65C02 version + bne @L9 +.else + add #1 + bcc @L9 +.endif + inx +@L9: rts + +.endproc diff --git a/lib/runtime/incax2.s b/lib/runtime/incax2.s new file mode 100644 index 0000000..9525171 --- /dev/null +++ b/lib/runtime/incax2.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 2 +; + + .export incax2 + + .macpack generic + +.proc incax2 + + add #2 + bcc @L9 + inx +@L9: rts + +.endproc diff --git a/lib/runtime/incax3.s b/lib/runtime/incax3.s new file mode 100644 index 0000000..e06b913 --- /dev/null +++ b/lib/runtime/incax3.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 3 +; + + .export incax3 + .import incaxy + +.proc incax3 + + ldy #3 + jmp incaxy + +.endproc + diff --git a/lib/runtime/incax5.s b/lib/runtime/incax5.s new file mode 100644 index 0000000..ae9e063 --- /dev/null +++ b/lib/runtime/incax5.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 5 +; + + .export incax5 + .import incaxy + +.proc incax5 + + ldy #5 + jmp incaxy + +.endproc + diff --git a/lib/runtime/incax6.s b/lib/runtime/incax6.s new file mode 100644 index 0000000..5f80d36 --- /dev/null +++ b/lib/runtime/incax6.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 6 +; + + .export incax6 + .import incaxy + +.proc incax6 + + ldy #6 + jmp incaxy + +.endproc + diff --git a/lib/runtime/incax7.s b/lib/runtime/incax7.s new file mode 100644 index 0000000..ed883c3 --- /dev/null +++ b/lib/runtime/incax7.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 7 +; + + .export incax7 + .import incaxy + +.proc incax7 + + ldy #7 + jmp incaxy + +.endproc + diff --git a/lib/runtime/incax8.s b/lib/runtime/incax8.s new file mode 100644 index 0000000..ae1e526 --- /dev/null +++ b/lib/runtime/incax8.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by 8 +; + + .export incax8 + .import incaxy + +.proc incax8 + + ldy #8 + jmp incaxy + +.endproc + diff --git a/lib/runtime/incaxy.s b/lib/runtime/incaxy.s new file mode 100644 index 0000000..feed956 --- /dev/null +++ b/lib/runtime/incaxy.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: Increment ax by valie in y +; + + .export incaxy, incax4 + .importzp tmp1 + .macpack generic + +incax4: ldy #4 +incaxy: sty tmp1 + add tmp1 + bcc @L9 + inx +@L9: rts + diff --git a/lib/runtime/incsp1.s b/lib/runtime/incsp1.s new file mode 100644 index 0000000..a85092d --- /dev/null +++ b/lib/runtime/incsp1.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 1 +; + + .export incsp1 + .importzp sp + +.proc incsp1 + + inc sp + bne @L1 + inc sp+1 +@L1: rts + +.endproc + + + + + diff --git a/lib/runtime/incsp2.s b/lib/runtime/incsp2.s new file mode 100644 index 0000000..639f8a4 --- /dev/null +++ b/lib/runtime/incsp2.s @@ -0,0 +1,47 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 2. For performance reasons, +; this modules does also contain the popax function. + + .export popax, incsp2 + .importzp sp + + .macpack cpu + +; Pop a/x from stack. This function will run directly into incsp2 + +.proc popax + + ldy #1 + lda (sp),y ; get hi byte + tax ; into x +.if (.cpu .bitand ::CPU_ISET_65SC02) + lda (sp) ; get lo byte +.else + dey + lda (sp),y ; get lo byte +.endif + +.endproc + + + +.proc incsp2 + + inc sp ; 5 + beq @L1 ; 2 + inc sp ; 5 + beq @L2 ; 2 + rts + +@L1: inc sp ; 5 +@L2: inc sp+1 ; 5 + rts + +.endproc + + + + + diff --git a/lib/runtime/incsp3.s b/lib/runtime/incsp3.s new file mode 100644 index 0000000..90dca0b --- /dev/null +++ b/lib/runtime/incsp3.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 3 +; + + .export incsp3 + .import addysp + +.proc incsp3 + + ldy #3 + jmp addysp + +.endproc + + + + + diff --git a/lib/runtime/incsp4.s b/lib/runtime/incsp4.s new file mode 100644 index 0000000..125c533 --- /dev/null +++ b/lib/runtime/incsp4.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 4 +; + + .export incsp4 + .import addysp + +.proc incsp4 + + ldy #4 + jmp addysp + +.endproc + + + + + diff --git a/lib/runtime/incsp5.s b/lib/runtime/incsp5.s new file mode 100644 index 0000000..df239cf --- /dev/null +++ b/lib/runtime/incsp5.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 5 +; + + .export incsp5 + .import addysp + +.proc incsp5 + + ldy #5 + jmp addysp + +.endproc + + + + + diff --git a/lib/runtime/incsp6.s b/lib/runtime/incsp6.s new file mode 100644 index 0000000..a7ab932 --- /dev/null +++ b/lib/runtime/incsp6.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 6 +; + + .export incsp6 + .import addysp + +.proc incsp6 + + ldy #6 + jmp addysp + +.endproc + + + + + diff --git a/lib/runtime/incsp7.s b/lib/runtime/incsp7.s new file mode 100644 index 0000000..417700f --- /dev/null +++ b/lib/runtime/incsp7.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 7 +; + + .export incsp7 + .import addysp + +.proc incsp7 + + ldy #7 + jmp addysp + +.endproc + + + + + diff --git a/lib/runtime/incsp8.s b/lib/runtime/incsp8.s new file mode 100644 index 0000000..3ec1520 --- /dev/null +++ b/lib/runtime/incsp8.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Increment the stackpointer by 8 +; + + .export incsp8 + .import addysp + +.proc incsp8 + + ldy #8 + jmp addysp + +.endproc + + diff --git a/lib/runtime/jmpvec.s b/lib/runtime/jmpvec.s new file mode 100644 index 0000000..6ae8715 --- /dev/null +++ b/lib/runtime/jmpvec.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 2002-12-26 +; +; CC65 runtime: Jump vector that resides in the data segment so it's address +; may be patched at runtime. +; + + .export jmpvec + +.data + +jmpvec: jmp $FFFF + + diff --git a/lib/runtime/ladd.s b/lib/runtime/ladd.s new file mode 100644 index 0000000..4e864c7 --- /dev/null +++ b/lib/runtime/ladd.s @@ -0,0 +1,44 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: long add +; + + .export tosadd0ax, tosaddeax + .import addysp1 + .importzp sp, sreg, tmp1 + + .macpack cpu + +; EAX = TOS + EAX + +tosadd0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosaddeax: + clc +.if (.cpu .bitand CPU_ISET_65SC02) + adc (sp) ; 65SC02 version - saves 2 cycles + ldy #1 +.else + ldy #0 + adc (sp),y ; lo byte + iny +.endif + sta tmp1 ; use as temp storage + txa + adc (sp),y ; byte 1 + tax + iny + lda sreg + adc (sp),y ; byte 2 + sta sreg + iny + lda sreg+1 + adc (sp),y ; byte 3 + sta sreg+1 + lda tmp1 ; load byte 0 + jmp addysp1 ; drop TOS + diff --git a/lib/runtime/laddeq.s b/lib/runtime/laddeq.s new file mode 100644 index 0000000..6478017 --- /dev/null +++ b/lib/runtime/laddeq.s @@ -0,0 +1,53 @@ +; +; Ullrich von Bassewitz, 07.04.2000 +; +; CC65 runtime: += operator +; +; On entry, the low byte of the address of the variable to increment is +; in ptr1, the high byte is in Y, and the increment is in eax. +; + + .export laddeq1, laddeqa, laddeq + .importzp sreg, ptr1, tmp1 + + +laddeq1: + lda #$01 + +laddeqa: + ldx #$00 + stx sreg + stx sreg+1 + +laddeq: sty ptr1+1 ; Store high byte of address + ldy #$00 ; Address low byte + clc + + adc (ptr1),y + sta (ptr1),y + pha ; Save byte 0 of result for later + + iny ; Address byte 1 + txa + adc (ptr1),y ; Load byte 1 + sta (ptr1),y + tax + + iny ; Address byte 2 + lda sreg + adc (ptr1),y + sta (ptr1),y + sta sreg + + iny ; Address byte 3 + lda sreg+1 + adc (ptr1),y + sta (ptr1),y + sta sreg+1 + + pla ; Retrieve byte 0 of result + + rts ; Done + + + diff --git a/lib/runtime/laddeqsp.s b/lib/runtime/laddeqsp.s new file mode 100644 index 0000000..e5a1f04 --- /dev/null +++ b/lib/runtime/laddeqsp.s @@ -0,0 +1,34 @@ +; +; Ullrich von Bassewitz, 08.10.1998 +; +; CC65 runtime: += operator for longs on the stack +; + + .export laddeq0sp, laddeqysp + .importzp sp, sreg + +laddeq0sp: + ldy #0 +laddeqysp: + clc + adc (sp),y + sta (sp),y + pha + iny + txa + adc (sp),y + sta (sp),y + tax + iny + lda sreg + adc (sp),y + sta (sp),y + sta sreg + iny + lda sreg+1 + adc (sp),y + sta (sp),y + sta sreg+1 + pla + rts + diff --git a/lib/runtime/land.s b/lib/runtime/land.s new file mode 100644 index 0000000..1e66039 --- /dev/null +++ b/lib/runtime/land.s @@ -0,0 +1,36 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: and on longs +; + + .export tosand0ax, tosandeax + .import addysp1 + .importzp sp, sreg, tmp1 + + +tosand0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosandeax: + ldy #0 + and (sp),y ; byte 0 + sta tmp1 + iny + txa + and (sp),y ; byte 1 + tax + iny + lda sreg + and (sp),y ; byte 2 + sta sreg + iny + lda sreg+1 + and (sp),y ; byte 3 + sta sreg+1 + + lda tmp1 + jmp addysp1 + diff --git a/lib/runtime/lasr.s b/lib/runtime/lasr.s new file mode 100644 index 0000000..c96f1e1 --- /dev/null +++ b/lib/runtime/lasr.s @@ -0,0 +1,44 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for longs +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosasreax + .import popeax + .importzp sreg, tmp1 + + +tosasreax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popeax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 + ldx sreg+1 ; Load byte 3 + +; Do the actual shift. Faster solutions are possible but need a lot more code. + +L2: cpx #$80 ; Copy bit 31 into the carry + ror sreg+1 + ror sreg + ror tmp1 + ror a + dey + bne L2 + +; Shift done + + ldx tmp1 +L9: rts + diff --git a/lib/runtime/lbneg.s b/lib/runtime/lbneg.s new file mode 100644 index 0000000..ca737e4 --- /dev/null +++ b/lib/runtime/lbneg.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: boolean negation for longs +; + + .export bnegeax + .importzp sreg, tmp1 + +bnegeax: + stx tmp1 + ldx #0 ; High byte of result + ora tmp1 + ora sreg + ora sreg+1 + bne @L0 + lda #1 + rts + +@L0: txa ; X is zero + rts + diff --git a/lib/runtime/lcmp.s b/lib/runtime/lcmp.s new file mode 100644 index 0000000..4e50aa5 --- /dev/null +++ b/lib/runtime/lcmp.s @@ -0,0 +1,56 @@ +; +; Piotr Fusik, 15.04.2002 +; originally by Ullrich von Bassewitz +; +; Long int compare function - used by the compare operators +; + + .export toslcmp + .import incsp4 + .importzp sp, sreg, ptr1 + + +toslcmp: + sta ptr1 + stx ptr1+1 ; EAX now in sreg:ptr1 + + ldy #$03 + lda (sp),y + sec + sbc sreg+1 + bne L4 + + dey + lda (sp),y + cmp sreg + bne L1 + + dey + lda (sp),y + cmp ptr1+1 + bne L1 + + dey + lda (sp),y + cmp ptr1 + +L1: php ; Save flags + jsr incsp4 ; Drop TOS + plp ; Restore the flags + beq L2 + bcs L3 + lda #$FF ; Set the N flag +L2: rts + +L3: lda #$01 ; Clear the N flag + rts + +L4: bvc L5 + eor #$FF ; Fix the N flag if overflow + ora #$01 ; Clear the Z flag +L5: php ; Save flags + jsr incsp4 ; Drop TOS + plp ; Restore flags + rts + + diff --git a/lib/runtime/lcompl.s b/lib/runtime/lcompl.s new file mode 100644 index 0000000..fff31d9 --- /dev/null +++ b/lib/runtime/lcompl.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: long complement +; + + .export compleax + .importzp sreg + +; eax = ~eax + +compleax: + eor #$FF + pha + txa + eor #$FF + tax + lda sreg + eor #$FF + sta sreg + lda sreg+1 + eor #$FF + sta sreg+1 + pla + rts + diff --git a/lib/runtime/ldai.s b/lib/runtime/ldai.s new file mode 100644 index 0000000..ec3a996 --- /dev/null +++ b/lib/runtime/ldai.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load a indirect from address in ax +; + + .export ldaidx + .importzp ptr1 + +.proc ldaidx + sta ptr1 + stx ptr1+1 + ldx #$00 + lda (ptr1),y + bpl @L1 + dex +@L1: rts +.endproc + diff --git a/lib/runtime/ldau0sp.s b/lib/runtime/ldau0sp.s new file mode 100644 index 0000000..0be99d3 --- /dev/null +++ b/lib/runtime/ldau0sp.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 11.04.1999 +; +; CC65 runtime: Load an unsigned char indirect from pointer somewhere in stack +; + + .export ldau00sp, ldau0ysp + .importzp sp, ptr1 + + .macpack cpu + +ldau00sp: + ldy #1 +ldau0ysp: + lda (sp),y + sta ptr1+1 + dey + lda (sp),y + sta ptr1 + ldx #0 +.if (.cpu .bitand CPU_ISET_65SC02) + lda (ptr1) ; Save one cycle for the C02 +.else + lda (ptr1,x) +.endif + rts + diff --git a/lib/runtime/ldaui.s b/lib/runtime/ldaui.s new file mode 100644 index 0000000..b84783d --- /dev/null +++ b/lib/runtime/ldaui.s @@ -0,0 +1,16 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load a unsigned indirect from address in ax +; + + .export ldauidx + .importzp ptr1 + +.proc ldauidx + sta ptr1 + stx ptr1+1 + ldx #0 + lda (ptr1),y + rts +.endproc diff --git a/lib/runtime/ldauisp.s b/lib/runtime/ldauisp.s new file mode 100644 index 0000000..7e15329 --- /dev/null +++ b/lib/runtime/ldauisp.s @@ -0,0 +1,24 @@ +; +; Ullrich von Bassewitz, 11.04.1999 +; +; CC65 runtime: Load an unsigned char indirect from pointer somewhere in stack +; + + .export ldaui0sp, ldauiysp + .importzp sp, ptr1 + +ldaui0sp: + ldy #1 +ldauiysp: + lda (sp),y + sta ptr1+1 + dey + lda (sp),y + sta ptr1 + txa + tay + ldx #0 + lda (ptr1),y + rts + + diff --git a/lib/runtime/ldaxi.s b/lib/runtime/ldaxi.s new file mode 100644 index 0000000..a03c610 --- /dev/null +++ b/lib/runtime/ldaxi.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load ax indirect from address in ax +; + + .export ldaxi, ldaxidx + .importzp ptr1 + +ldaxi: ldy #1 +ldaxidx: + sta ptr1 + stx ptr1+1 + lda (ptr1),y + tax + dey + lda (ptr1),y + rts + diff --git a/lib/runtime/ldaxsp.s b/lib/runtime/ldaxsp.s new file mode 100644 index 0000000..0f1a2c8 --- /dev/null +++ b/lib/runtime/ldaxsp.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load ax from offset in stack +; + + .export ldax0sp, ldaxysp + .importzp sp + +; Beware: The optimizer knows about the value in Y after return! + +ldax0sp: + ldy #1 +ldaxysp: + lda (sp),y ; get high byte + tax ; and save it + dey ; point to lo byte + lda (sp),y ; load low byte + rts + diff --git a/lib/runtime/ldeaxi.s b/lib/runtime/ldeaxi.s new file mode 100644 index 0000000..a1f9e64 --- /dev/null +++ b/lib/runtime/ldeaxi.s @@ -0,0 +1,25 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load eax indirect from address in ax +; + + .export ldeaxidx, ldeaxi + .importzp sreg, ptr1 + +ldeaxi: ldy #3 +ldeaxidx: + sta ptr1 + stx ptr1+1 + lda (ptr1),y + dey + sta sreg+1 + lda (ptr1),y + dey + sta sreg + lda (ptr1),y + dey + tax + lda (ptr1),y + rts + diff --git a/lib/runtime/ldeaxysp.s b/lib/runtime/ldeaxysp.s new file mode 100644 index 0000000..cf15f3f --- /dev/null +++ b/lib/runtime/ldeaxysp.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 22.06.1998 +; +; CC65 runtime: Load a long from somewhere in the stack +; +; Beware: The optimizer knows about the register contents after calling +; this function! +; + + + .export ldeax0sp, ldeaxysp + .importzp sreg, sp + +ldeax0sp: + ldy #3 +ldeaxysp: + lda (sp),y + sta sreg+1 + dey + lda (sp),y + sta sreg + dey + lda (sp),y + tax + dey + lda (sp),y + rts + diff --git a/lib/runtime/ldec.s b/lib/runtime/ldec.s new file mode 100644 index 0000000..a87323e --- /dev/null +++ b/lib/runtime/ldec.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: Decrement eax by value in Y +; + + .export deceaxy + .importzp sreg, tmp1 + +deceaxy: + sty tmp1 + sec + sbc tmp1 + sta tmp1 + txa + sbc #0 + tax + lda sreg + sbc #0 + sta sreg + lda sreg+1 + sbc #0 + sta sreg+1 + lda tmp1 + rts + diff --git a/lib/runtime/ldiv.s b/lib/runtime/ldiv.s new file mode 100644 index 0000000..3d8dda0 --- /dev/null +++ b/lib/runtime/ldiv.s @@ -0,0 +1,40 @@ +; +; Ullrich von Bassewitz, 17.08.1998 +; +; CC65 runtime: division for signed long ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $80000000, in which case the negate will fail. + + .export tosdiv0ax, tosdiveax + .import poplsargs, udiv32, negeax + .importzp sreg, ptr1, tmp1, tmp2 + +tosdiv0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosdiveax: + jsr poplsargs ; Get arguments from stack, adjust sign + jsr udiv32 ; Do the division, result is in (ptr1:sreg) + ldx ptr1+1 ; Load byte 1 of result + +; Adjust the sign of the result + + lda tmp1 ; Get sign of left operand + eor tmp2 ; Calculate sign of result + bpl Pos ; Jump if result positive + +; Result is negative + + lda ptr1 ; Load byte 0 + jmp negeax ; Negate value + +; Result is positive + +Pos: lda ptr1 + rts + + diff --git a/lib/runtime/le.s b/lib/runtime/le.s new file mode 100644 index 0000000..a615b3f --- /dev/null +++ b/lib/runtime/le.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare <= for signed ints +; + + .export tosle00, toslea0, tosleax + .import tosicmp, boolle + +tosle00: + lda #$00 +toslea0: + ldx #$00 +tosleax: + jsr tosicmp ; Set flags + jmp boolle ; Convert to boolean + diff --git a/lib/runtime/leaaxsp.s b/lib/runtime/leaaxsp.s new file mode 100644 index 0000000..2a92cf0 --- /dev/null +++ b/lib/runtime/leaaxsp.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 2009-08-31 +; +; CC65 runtime: Load effective address with offset in A/X relative to SP +; + + .export leaaxsp, leaa0sp + .importzp sp + +leaa0sp: + ldx #$00 +leaaxsp: + clc + adc sp + pha + txa + adc sp+1 + tax + pla + rts + + + diff --git a/lib/runtime/leave.s b/lib/runtime/leave.s new file mode 100644 index 0000000..4846b9e --- /dev/null +++ b/lib/runtime/leave.s @@ -0,0 +1,37 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: function epilogue +; + +; exit a function. pop stack and rts. The function comes in different +; flavours that provide default values for the return val, or drop a local +; stack frame with size in y. + + .export leave00, leave0, leavey00, leavey0, leavey + .export leave + .import addysp + .importzp sp + +leave00: + lda #0 +leave0: ldx #0 + beq leave + +leavey00: + lda #0 ; "return 0" +leavey0: + ldx #0 ; return < 256 +leavey: + jsr addysp ; drop stack frame +leave: pha ; save A a sec + ldy #0 + lda (sp),y ; that's the pushed arg size + sec ; Count the byte, the count's stored in + adc sp + sta sp + bcc L1 + inc sp+1 +L1: pla ; Get return value back + rts + diff --git a/lib/runtime/leq.s b/lib/runtime/leq.s new file mode 100644 index 0000000..6349caf --- /dev/null +++ b/lib/runtime/leq.s @@ -0,0 +1,15 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: long equal +; + + .export toseqeax + .import toslcmp, booleq + +toseqeax: + jsr toslcmp ; Set flags + jmp booleq ; Convert to boolean + + + diff --git a/lib/runtime/lge.s b/lib/runtime/lge.s new file mode 100644 index 0000000..1e4df32 --- /dev/null +++ b/lib/runtime/lge.s @@ -0,0 +1,13 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: Compare >= for long ints +; + + .export tosgeeax + .import toslcmp, boolge + +tosgeeax: + jsr toslcmp ; Set the flags + jmp boolge ; Convert to boolean + diff --git a/lib/runtime/lgt.s b/lib/runtime/lgt.s new file mode 100644 index 0000000..aa71570 --- /dev/null +++ b/lib/runtime/lgt.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: Compare > for long ints +; + + .export tosgteax + .import toslcmp, boolgt + +tosgteax: + jsr toslcmp ; Set the flags + jmp boolgt ; Convert to boolean + + diff --git a/lib/runtime/linc.s b/lib/runtime/linc.s new file mode 100644 index 0000000..aff3758 --- /dev/null +++ b/lib/runtime/linc.s @@ -0,0 +1,24 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: Increment eax by value in Y +; + + .export inceaxy + .importzp ptr4, sreg + +.proc inceaxy + + sty ptr4 + clc + adc ptr4 + bcc @L9 + inx + bne @L9 + inc sreg + bne @L9 + inc sreg+1 +@L9: rts + +.endproc + diff --git a/lib/runtime/lle.s b/lib/runtime/lle.s new file mode 100644 index 0000000..6f11e03 --- /dev/null +++ b/lib/runtime/lle.s @@ -0,0 +1,13 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: Compare <= for long ints +; + + .export tosleeax + .import toslcmp, boolle + +tosleeax: + jsr toslcmp ; Set the flags + jmp boolle ; Convert to boolean + diff --git a/lib/runtime/llt.s b/lib/runtime/llt.s new file mode 100644 index 0000000..5d5290d --- /dev/null +++ b/lib/runtime/llt.s @@ -0,0 +1,12 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: Compare < for long ints +; + + .export toslteax + .import toslcmp, boollt + +toslteax: + jsr toslcmp ; Set the flags + jmp boollt ; Convert to boolean diff --git a/lib/runtime/lmod.s b/lib/runtime/lmod.s new file mode 100644 index 0000000..89826ba --- /dev/null +++ b/lib/runtime/lmod.s @@ -0,0 +1,44 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: modulo operation for long signed ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $8000, in which case the negate will fail. + + .export tosmod0ax, tosmodeax + .import poplsargs, udiv32, negeax + .importzp sreg, ptr1, ptr2, tmp1, tmp3, tmp4 + +tosmod0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosmodeax: + jsr poplsargs ; Get arguments from stack, adjust sign + jsr udiv32 ; Do the division, remainder is in (ptr2:tmp3:tmp4) + +; Load the result + + lda ptr2 + ldx ptr2+1 + ldy tmp3 + sty sreg + ldy tmp4 + sty sreg+1 + +; Check the sign of the result. It is the sign of the left operand. + + bit tmp1 ; Check sign of left operand + bpl Pos ; Jump if result is positive + +; Result is negative + + jmp negeax ; Negate result + +; Result is positive + +Pos: rts ; Done + diff --git a/lib/runtime/lmul.s b/lib/runtime/lmul.s new file mode 100644 index 0000000..44a46b5 --- /dev/null +++ b/lib/runtime/lmul.s @@ -0,0 +1,69 @@ +; +; Ullrich von Bassewitz, 13.08.1998 +; +; CC65 runtime: multiplication for long (unsigned) ints +; + + .export tosumul0ax, tosumuleax, tosmul0ax, tosmuleax + .import addysp1 + .importzp sp, sreg, tmp1, tmp2, tmp3, tmp4, ptr1, ptr3, ptr4 + +tosmul0ax: +tosumul0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosmuleax: +tosumuleax: +mul32: sta ptr1 + stx ptr1+1 ; op2 now in ptr1/sreg + ldy #0 + lda (sp),y + sta ptr3 + iny + lda (sp),y + sta ptr3+1 + iny + lda (sp),y + sta ptr4 + iny + lda (sp),y + sta ptr4+1 ; op1 in pre3/ptr4 + jsr addysp1 ; Drop TOS + +; Do (ptr1:sreg)*(ptr3:ptr4) --> EAX. + + lda #0 + sta tmp4 + sta tmp3 + sta tmp2 + ldy #32 +L0: lsr tmp4 + ror tmp3 + ror tmp2 + ror a + ror sreg+1 + ror sreg + ror ptr1+1 + ror ptr1 + bcc L1 + clc + adc ptr3 + pha + lda ptr3+1 + adc tmp2 + sta tmp2 + lda ptr4 + adc tmp3 + sta tmp3 + lda ptr4+1 + adc tmp4 + sta tmp4 + pla +L1: dey + bpl L0 + lda ptr1 ; Load the low result word + ldx ptr1+1 + rts + diff --git a/lib/runtime/lne.s b/lib/runtime/lne.s new file mode 100644 index 0000000..e0f0485 --- /dev/null +++ b/lib/runtime/lne.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: long not equal +; + + .export tosneeax + .import toslcmp, boolne + +tosneeax: + jsr toslcmp ; Set flags + jmp boolne ; Convert to boolean + + diff --git a/lib/runtime/lneg.s b/lib/runtime/lneg.s new file mode 100644 index 0000000..12b744b --- /dev/null +++ b/lib/runtime/lneg.s @@ -0,0 +1,31 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: negation on longs +; + +; +; eax = -eax +; + .export negeax + .importzp sreg + +negeax: clc + eor #$FF + adc #1 + pha + txa + eor #$FF + adc #0 + tax + lda sreg + eor #$FF + adc #0 + sta sreg + lda sreg+1 + eor #$FF + adc #0 + sta sreg+1 + pla + rts + diff --git a/lib/runtime/lor.s b/lib/runtime/lor.s new file mode 100644 index 0000000..841154b --- /dev/null +++ b/lib/runtime/lor.s @@ -0,0 +1,36 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: or on longs +; + + .export tosor0ax, tosoreax + .import addysp1 + .importzp sp, sreg, tmp1 + + +tosor0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosoreax: + ldy #0 + ora (sp),y ; byte 0 + sta tmp1 + iny + txa + ora (sp),y ; byte 1 + tax + iny + lda sreg + ora (sp),y ; byte 2 + sta sreg + iny + lda sreg+1 + ora (sp),y ; byte 3 + sta sreg+1 + + lda tmp1 + jmp addysp1 + diff --git a/lib/runtime/lpop.s b/lib/runtime/lpop.s new file mode 100644 index 0000000..ff0d59b --- /dev/null +++ b/lib/runtime/lpop.s @@ -0,0 +1,25 @@ +; +; Ullrich von Bassewitz, 29.12.1999 +; +; CC65 runtime: long pop +; + + .export popeax + .import incsp4 + .importzp sp, sreg + + +popeax: ldy #3 + lda (sp),y + sta sreg+1 + dey + lda (sp),y + sta sreg + dey + lda (sp),y + tax + dey + lda (sp),y + jmp incsp4 + + diff --git a/lib/runtime/lpush.s b/lib/runtime/lpush.s new file mode 100644 index 0000000..6b7312a --- /dev/null +++ b/lib/runtime/lpush.s @@ -0,0 +1,34 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: long push +; + +; +; push eax on stack +; + .export push0ax, pusheax + .import decsp4 + .importzp sp, sreg + +push0ax: + ldy #0 + sty sreg + sty sreg+1 +pusheax: + pha ; decsp will destroy A (but not X) + jsr decsp4 + ldy #3 + lda sreg+1 + sta (sp),y + dey + lda sreg + sta (sp),y + dey + txa + sta (sp),y + dey + pla + sta (sp),y + rts + diff --git a/lib/runtime/lrsub.s b/lib/runtime/lrsub.s new file mode 100644 index 0000000..7dfe43a --- /dev/null +++ b/lib/runtime/lrsub.s @@ -0,0 +1,38 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: long sub reversed +; + +; +; EAX = EAX - TOS +; + .export tosrsub0ax, tosrsubeax + .import addysp1 + .importzp sp, sreg, tmp1 + +tosrsub0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosrsubeax: + ldy #0 + sec + sbc (sp),y ; byte 0 + sta tmp1 ; use as temp storage + txa + iny + sbc (sp),y ; byte 1 + tax + iny + lda sreg + sbc (sp),y ; byte 2 + sta sreg + iny + lda sreg+1 + sbc (sp),y ; byte 3 + sta sreg+1 + lda tmp1 + jmp addysp1 ; drop TOS + diff --git a/lib/runtime/lsave.s b/lib/runtime/lsave.s new file mode 100644 index 0000000..e9ccfc3 --- /dev/null +++ b/lib/runtime/lsave.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 08.08.1998 +; +; CC65 runtime: save ax into temp storage/restore ax from temp storage +; + + .export saveeax, resteax + .importzp sreg, regsave + +saveeax: + sta regsave + stx regsave+1 + lda sreg + sta regsave+2 + lda sreg+1 + sta regsave+3 + lda regsave + rts + +resteax: + lda regsave+3 + sta sreg+1 + lda regsave+2 + sta sreg + ldx regsave+1 + lda regsave + rts + diff --git a/lib/runtime/lshelp.s b/lib/runtime/lshelp.s new file mode 100644 index 0000000..a17f12f --- /dev/null +++ b/lib/runtime/lshelp.s @@ -0,0 +1,65 @@ +; +; Ullrich von Bassewitz, 13.08.1998 +; +; CC65 runtime: helper stuff for mod/div/mul with long signed ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $80000000, in which case the negate will fail. + + .export poplsargs + .import getlop + .importzp sreg, tmp1, tmp2, ptr1, ptr3, ptr4 + +poplsargs: + jsr getlop ; Get the operands + +; Remember the signs of the operands (that is, the high bytes) in tmp1 and +; tmp2. Make both operands positive. + + lda sreg+1 ; Is the left operand negative? + sta tmp1 ; Remember the sign for later + bpl L1 ; Jump if not + + clc ; Make it positive + lda ptr1 + eor #$FF + adc #$01 + sta ptr1 + lda ptr1+1 + eor #$FF + adc #$00 + sta ptr1+1 + lda sreg + eor #$FF + adc #$00 + sta sreg + lda sreg+1 + eor #$FF + adc #$00 + sta sreg+1 + +L1: lda ptr4+1 ; Is the right operand nagative? + sta tmp2 ; Remember the sign for later + bpl L2 ; Jump if not + + clc ; Make it positive + lda ptr3 + eor #$FF + adc #$01 + sta ptr3 + lda ptr3+1 + eor #$FF + adc #$00 + sta ptr3+1 + lda ptr4 + eor #$FF + adc #$00 + sta ptr4 + lda ptr4+1 + eor #$FF + adc #$00 + sta ptr4+1 + +L2: rts + diff --git a/lib/runtime/lshl.s b/lib/runtime/lshl.s new file mode 100644 index 0000000..3c4e708 --- /dev/null +++ b/lib/runtime/lshl.s @@ -0,0 +1,44 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: left shift support for long and unsigned long +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosasleax, tosshleax + .import popeax + .importzp sreg, tmp1 + + +tosshleax: +tosasleax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popeax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 + +; Do the actual shift. Faster solutions are possible but need a lot more code. + +L2: asl a + rol tmp1 + rol sreg + rol sreg+1 + dey + bne L2 + +; Shift done + + ldx tmp1 +L9: rts + + diff --git a/lib/runtime/lshr.s b/lib/runtime/lshr.s new file mode 100644 index 0000000..9c2a6e3 --- /dev/null +++ b/lib/runtime/lshr.s @@ -0,0 +1,48 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for unsigned longs +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosshreax + .import popeax + .importzp sreg, tmp1 + + +tosshreax: + and #$1F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popeax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + stx tmp1 ; Save byte 1 + +; Do the actual shift. Faster solutions are possible but need a lot more code. + +L2: lsr sreg+1 + ror sreg + ror tmp1 + ror a + dey + bne L2 + +; Shift done + + ldx tmp1 +L9: rts + + + + + + + diff --git a/lib/runtime/lsub.s b/lib/runtime/lsub.s new file mode 100644 index 0000000..30ae49d --- /dev/null +++ b/lib/runtime/lsub.s @@ -0,0 +1,47 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: long sub +; + +; +; EAX = TOS - EAX +; + .export tossub0ax, tossubeax + .import addysp1 + .importzp sp, sreg + + .macpack cpu + +tossub0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tossubeax: + sec + eor #$FF +.if (.cpu .bitand CPU_ISET_65SC02) + adc (sp) ; 65SC02 version - saves 2 cycles + ldy #1 +.else + ldy #0 + adc (sp),y ; lo byte + iny +.endif + pha ; Save low byte + txa + eor #$FF + adc (sp),y ; byte 1 + tax + iny + lda (sp),y + sbc sreg ; byte 2 + sta sreg + iny + lda (sp),y + sbc sreg+1 ; byte 3 + sta sreg+1 + pla ; Restore byte 0 + jmp addysp1 ; Drop TOS + diff --git a/lib/runtime/lsubeq.s b/lib/runtime/lsubeq.s new file mode 100644 index 0000000..acc6a28 --- /dev/null +++ b/lib/runtime/lsubeq.s @@ -0,0 +1,56 @@ +; +; Ullrich von Bassewitz, 07.04.2000 +; +; CC65 runtime: -= operator +; +; On entry, the low byte of the address of the variable to decrement is +; in ptr1, the high byte is in Y, and the decrement is in eax. +; + + .export lsubeq1, lsubeqa, lsubeq + .importzp sreg, ptr1 + + +lsubeq1: + lda #$01 + +lsubeqa: + ldx #$00 + stx sreg + stx sreg+1 + +lsubeq: sty ptr1+1 ; Store high byte of address + ldy #$00 ; Address low byte + sec + + eor #$FF + adc (ptr1),y ; Subtract byte 0 + sta (ptr1),y + pha ; Save byte 0 of result for later + + iny ; Address byte 1 + txa + eor #$FF + adc (ptr1),y ; Subtract byte 1 + sta (ptr1),y + tax + + iny ; Address byte 2 + lda (ptr1),y + sbc sreg + sta (ptr1),y + sta sreg + + iny ; Address byte 3 + lda (ptr1),y + sbc sreg+1 + sta (ptr1),y + sta sreg+1 + + pla ; Retrieve byte 0 of result + + rts ; Done + + + + diff --git a/lib/runtime/lsubeqsp.s b/lib/runtime/lsubeqsp.s new file mode 100644 index 0000000..c679c88 --- /dev/null +++ b/lib/runtime/lsubeqsp.s @@ -0,0 +1,36 @@ +; +; Ullrich von Bassewitz, 08.10.1998 +; +; CC65 runtime: -= operator for longs on the stack +; + + .export lsubeq0sp, lsubeqysp + .importzp sp, sreg + +lsubeq0sp: + ldy #0 +lsubeqysp: + sec + eor #$FF + adc (sp),y + sta (sp),y + pha ; Save low byte + iny + txa + eor #$FF + adc (sp),y + sta (sp),y + tax + iny + lda (sp),y + sbc sreg + sta (sp),y + sta sreg + iny + lda (sp),y + sbc sreg+1 + sta (sp),y + sta sreg+1 + pla + rts + diff --git a/lib/runtime/lt.s b/lib/runtime/lt.s new file mode 100644 index 0000000..1b681f5 --- /dev/null +++ b/lib/runtime/lt.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare < for signed ints +; + + .export toslt00, toslta0, tosltax + .import tosicmp, boollt + +toslt00: + lda #$00 +toslta0: + ldx #$00 +tosltax: + jsr tosicmp ; Set flags + jmp boollt ; Convert to boolean + diff --git a/lib/runtime/ltest.s b/lib/runtime/ltest.s new file mode 100644 index 0000000..2c66300 --- /dev/null +++ b/lib/runtime/ltest.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: test long in eax +; + + .export utsteax, tsteax + .importzp sreg, tmp1 + +tsteax: +utsteax: + tay ; Save value + stx tmp1 + ora tmp1 + ora sreg + ora sreg+1 + beq L9 + tya + ldy #1 ; Force NE +L9: rts + + diff --git a/lib/runtime/ludiv.s b/lib/runtime/ludiv.s new file mode 100644 index 0000000..aa40a96 --- /dev/null +++ b/lib/runtime/ludiv.s @@ -0,0 +1,98 @@ +; +; Ullrich von Bassewitz, 17.08.1998 +; +; CC65 runtime: division for long unsigned ints +; + + .export tosudiv0ax, tosudiveax, getlop, udiv32 + .import addysp1 + .importzp sp, sreg, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4 + +tosudiv0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosudiveax: + jsr getlop ; Get the paramameters + jsr udiv32 ; Do the division + lda ptr1 ; Result is in ptr1:sreg + ldx ptr1+1 + rts + +; Pop the parameters for the long division and put it into the relevant +; memory cells. Called from the signed divisions also. + +getlop: sta ptr3 ; Put right operand in place + stx ptr3+1 + lda sreg + sta ptr4 + lda sreg+1 + sta ptr4+1 + + ldy #0 ; Put left operand in place + lda (sp),y + sta ptr1 + iny + lda (sp),y + sta ptr1+1 + iny + lda (sp),y + sta sreg + iny + lda (sp),y + sta sreg+1 + jmp addysp1 ; Drop parameters + +; Do (ptr1:sreg) / (ptr3:ptr4) --> (ptr1:sreg), remainder in (ptr2:tmp3:tmp4) +; This is also the entry point for the signed division + +udiv32: lda #0 + sta ptr2+1 + sta tmp3 + sta tmp4 +; sta ptr1+1 + ldy #32 +L0: asl ptr1 + rol ptr1+1 + rol sreg + rol sreg+1 + rol a + rol ptr2+1 + rol tmp3 + rol tmp4 + +; Do a subtraction. we do not have enough space to store the intermediate +; result, so we may have to do the subtraction twice. + + pha + cmp ptr3 + lda ptr2+1 + sbc ptr3+1 + lda tmp3 + sbc ptr4 + lda tmp4 + sbc ptr4+1 + bcc L1 + +; Overflow, do the subtraction again, this time store the result + + sta tmp4 ; We have the high byte already + pla + sbc ptr3 ; byte 0 + pha + lda ptr2+1 + sbc ptr3+1 + sta ptr2+1 ; byte 1 + lda tmp3 + sbc ptr4 + sta tmp3 ; byte 2 + inc ptr1 ; Set result bit + +L1: pla + dey + bne L0 + sta ptr2 + rts + + diff --git a/lib/runtime/luge.s b/lib/runtime/luge.s new file mode 100644 index 0000000..541ff48 --- /dev/null +++ b/lib/runtime/luge.s @@ -0,0 +1,13 @@ +; +; Ullrich von Bassewitz, 10.12.1998 +; +; CC65 runtime: Compare >= for long unsigneds +; + + .export tosugeeax + .import toslcmp, booluge + +tosugeeax: + jsr toslcmp ; Set the flags + jmp booluge ; Convert to boolean + diff --git a/lib/runtime/lugt.s b/lib/runtime/lugt.s new file mode 100644 index 0000000..19cbcc0 --- /dev/null +++ b/lib/runtime/lugt.s @@ -0,0 +1,14 @@ +; +; Ullrich von Bassewitz, 10.12.1998 +; +; CC65 runtime: Compare > for long unsigneds +; + + .export tosugteax + .import toslcmp, boolugt + +tosugteax: + jsr toslcmp ; Set the flags + jmp boolugt ; Convert to boolean + + diff --git a/lib/runtime/lule.s b/lib/runtime/lule.s new file mode 100644 index 0000000..d898979 --- /dev/null +++ b/lib/runtime/lule.s @@ -0,0 +1,13 @@ +; +; Ullrich von Bassewitz, 10.12.1998 +; +; CC65 runtime: Compare <= for long unsigneds +; + + .export tosuleeax + .import toslcmp, boolule + +tosuleeax: + jsr toslcmp ; Set the flags + jmp boolule ; Convert to boolean + diff --git a/lib/runtime/lult.s b/lib/runtime/lult.s new file mode 100644 index 0000000..f13735e --- /dev/null +++ b/lib/runtime/lult.s @@ -0,0 +1,12 @@ +; +; Ullrich von Bassewitz, 10.12.1998 +; +; CC65 runtime: Compare < for long unsigneds +; + + .export tosulteax + .import toslcmp, boolult + +tosulteax: + jsr toslcmp ; Set the flags + jmp boolult ; Convert to boolean diff --git a/lib/runtime/lumod.s b/lib/runtime/lumod.s new file mode 100644 index 0000000..3128bc0 --- /dev/null +++ b/lib/runtime/lumod.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 27.09.1998 +; +; CC65 runtime: modulo operation for long unsigned ints +; + + .export tosumod0ax, tosumodeax + .import getlop, udiv32 + .importzp sreg, tmp3, tmp4, ptr2 + +tosumod0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosumodeax: + jsr getlop ; Get the paramameters + jsr udiv32 ; Do the division + lda tmp3 ; Remainder is in ptr2:tmp3:tmp4 + sta sreg + lda tmp4 + sta sreg+1 + lda ptr2 + ldx ptr2+1 + rts + diff --git a/lib/runtime/lxor.s b/lib/runtime/lxor.s new file mode 100644 index 0000000..46086fb --- /dev/null +++ b/lib/runtime/lxor.s @@ -0,0 +1,37 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: xor on longs +; + + .export tosxor0ax, tosxoreax + .import addysp1 + .importzp sp, sreg, tmp1 + +tosxor0ax: + ldy #$00 + sty sreg + sty sreg+1 + +tosxoreax: + ldy #0 + eor (sp),y ; byte 0 + sta tmp1 + iny + txa + eor (sp),y ; byte 1 + tax + iny + lda sreg + eor (sp),y ; byte 2 + sta sreg + iny + lda sreg+1 + eor (sp),y ; byte 3 + sta sreg+1 + + lda tmp1 + jmp addysp1 + + + diff --git a/lib/runtime/makebool.s b/lib/runtime/makebool.s new file mode 100644 index 0000000..3429ff0 --- /dev/null +++ b/lib/runtime/makebool.s @@ -0,0 +1,60 @@ +; +; Ullrich von Bassewitz, 05.10.1998 +; +; CC65 runtime: Make boolean according to flags +; + + .export boolne, booleq, boollt, boolle, boolgt, boolge + .export boolult, boolule, boolugt, booluge + + +boolne: bne ret1 + ldx #$00 + txa + rts + + +booleq: beq ret1 + ldx #$00 + txa + rts + + +boolle: beq ret1 +boollt: bmi ret1 + ldx #$00 + txa + rts + + +boolgt: beq L0 +boolge: bpl ret1 +L0: ldx #$00 + txa + rts + + +boolule: + beq ret1 +boolult: + bcc ret1 + ldx #$00 + txa + rts + + +boolugt: + beq L1 +booluge: + bcs ret1 +L1: ldx #$00 + txa + rts + + +ret1: ldx #$00 + lda #$01 + rts + + + diff --git a/lib/runtime/mod.s b/lib/runtime/mod.s new file mode 100644 index 0000000..c5565a8 --- /dev/null +++ b/lib/runtime/mod.s @@ -0,0 +1,37 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: modulo operation for signed ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $8000, in which case the negate will fail. + + .export tosmoda0, tosmodax + .import popsargs, udiv16, negax + .importzp ptr1, tmp1 + +tosmoda0: + ldx #0 +tosmodax: + jsr popsargs ; Get arguments from stack, adjust sign + jsr udiv16 ; Do the division + lda ptr1 ; Load low byte of result + ldx ptr1+1 ; Load high byte of result + +; Adjust the sign of the result. tmp1 contains the high byte of the left +; operand, tmp2 contains the high byte of the right operand. The sign of +; the result of the modulo operation is the same as that of the left +; operand + + bit tmp1 + bpl Pos ; Jump if sign of result positive + +; Result is negative + + jmp negax ; Adjust the sign + +; Result is positive + +Pos: rts + diff --git a/lib/runtime/mul.s b/lib/runtime/mul.s new file mode 100644 index 0000000..eaf1fb9 --- /dev/null +++ b/lib/runtime/mul.s @@ -0,0 +1,69 @@ +; +; Ullrich von Bassewitz, 2009-08-17 +; +; CC65 runtime: multiplication for ints +; + + .export tosumulax, tosmulax + .import mul8x16, mul8x16a ; in mul8.s + .import popsreg + .importzp sreg, tmp1, ptr4 + + +;--------------------------------------------------------------------------- +; 16x16 multiplication routine + +tosmulax: +tosumulax: + sta ptr4 + txa ; High byte zero + beq @L3 ; Do 8x16 multiplication if high byte zero + stx ptr4+1 ; Save right operand + jsr popsreg ; Get left operand + +; Do ptr4:ptr4+1 * sreg:sreg+1 --> AX + + lda #0 + ldx sreg+1 ; Get high byte into register for speed + beq @L4 ; -> we can do 8x16 after swap + sta tmp1 + ldy #16 ; Number of bits + + lsr ptr4+1 + ror ptr4 ; Get first bit into carry +@L0: bcc @L1 + + clc + adc sreg + pha + txa ; hi byte of left op + adc tmp1 + sta tmp1 + pla + +@L1: ror tmp1 + ror a + ror ptr4+1 + ror ptr4 + dey + bne @L0 + + lda ptr4 ; Load the result + ldx ptr4+1 + rts ; Done + +; High byte of rhs is zero, jump to the 8x16 routine instead + +@L3: jmp mul8x16 + +; If the high byte of rhs is zero, swap the operands and use the 8x16 +; routine. On entry, A and X are zero + +@L4: ldy sreg ; Save right operand (8 bit) + ldx ptr4 ; Copy left 16 bit operand to right + stx sreg + ldx ptr4+1 ; Don't store, this is done later + sty ptr4 ; Copy low 8 bit of right op to left + ldy #8 + jmp mul8x16a + diff --git a/lib/runtime/mul8.s b/lib/runtime/mul8.s new file mode 100644 index 0000000..3287e21 --- /dev/null +++ b/lib/runtime/mul8.s @@ -0,0 +1,63 @@ +; +; Ullrich von Bassewitz, 2009-08-17 +; +; CC65 runtime: multiplication for ints. Short versions. +; + + .export tosumula0, tosmula0 + .export mul8x16, mul8x16a + .import popsreg + .importzp sreg, ptr4 + + +;--------------------------------------------------------------------------- +; 8x16 routine with external entry points used by the 16x16 routine in mul.s + +tosmula0: +tosumula0: + sta ptr4 +mul8x16:jsr popsreg ; Get left operand + + lda #0 ; Clear byte 1 + ldy #8 ; Number of bits + ldx sreg+1 ; Get into register for speed + beq mul8x8 ; Do 8x8 multiplication if high byte zero +mul8x16a: + sta ptr4+1 ; Clear byte 2 + + lsr ptr4 ; Get first bit into carry +@L0: bcc @L1 + + clc + adc sreg + pha + txa ; hi byte of left op + adc ptr4+1 + sta ptr4+1 + pla + +@L1: ror ptr4+1 + ror a + ror ptr4 + dey + bne @L0 + tax + lda ptr4 ; Load the result + rts + +;--------------------------------------------------------------------------- +; 8x8 multiplication routine + +mul8x8: + lsr ptr4 ; Get first bit into carry +@L0: bcc @L1 + clc + adc sreg +@L1: ror + ror ptr4 + dey + bne @L0 + tax + lda ptr4 ; Load the result + rts ; Done + diff --git a/lib/runtime/mulax10.s b/lib/runtime/mulax10.s new file mode 100644 index 0000000..3fe250c --- /dev/null +++ b/lib/runtime/mulax10.s @@ -0,0 +1,32 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Multiply the primary register by 10 +; + + .export mulax10 + .importzp ptr1 + +.proc mulax10 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 + asl a + rol ptr1+1 + clc + adc ptr1 + sta ptr1 + txa + adc ptr1+1 + asl ptr1 + rol a + tax + lda ptr1 + rts + +.endproc + + diff --git a/lib/runtime/mulax3.s b/lib/runtime/mulax3.s new file mode 100644 index 0000000..07625f8 --- /dev/null +++ b/lib/runtime/mulax3.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 04.10.2001 +; +; CC65 runtime: Multiply the primary register +; + + .export mulax3 + .importzp ptr1 + +.proc mulax3 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 + clc + adc ptr1 + pha + txa + adc ptr1+1 + tax + pla + rts + +.endproc + + diff --git a/lib/runtime/mulax5.s b/lib/runtime/mulax5.s new file mode 100644 index 0000000..dbfa9fc --- /dev/null +++ b/lib/runtime/mulax5.s @@ -0,0 +1,29 @@ +; +; Ullrich von Bassewitz, 04.10.2001 +; +; CC65 runtime: Multiply the primary register +; + + .export mulax5 + .importzp ptr1 + +.proc mulax5 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 + asl a + rol ptr1+1 + clc + adc ptr1 + pha + txa + adc ptr1+1 + tax + pla + rts + +.endproc + + diff --git a/lib/runtime/mulax6.s b/lib/runtime/mulax6.s new file mode 100644 index 0000000..78aa85b --- /dev/null +++ b/lib/runtime/mulax6.s @@ -0,0 +1,30 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Multiply the primary register by 6 +; + + .export mulax6 + .importzp ptr1 + +.proc mulax6 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 + clc + adc ptr1 + sta ptr1 + txa + adc ptr1+1 + asl ptr1 + rol a + tax + lda ptr1 + rts + +.endproc + + diff --git a/lib/runtime/mulax7.s b/lib/runtime/mulax7.s new file mode 100644 index 0000000..c9f7e47 --- /dev/null +++ b/lib/runtime/mulax7.s @@ -0,0 +1,33 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Multiply the primary register by 7 +; + + .export mulax7 + .importzp ptr1 + +.proc mulax7 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 ; * 2 + asl a + rol ptr1+1 ; * 4 + asl a + rol ptr1+1 ; * 8 + sec + sbc ptr1 + pha + txa + eor #$ff + adc ptr1+1 ; * (8 - 1) + tax + pla + rts + +.endproc + + diff --git a/lib/runtime/mulax9.s b/lib/runtime/mulax9.s new file mode 100644 index 0000000..67a07b4 --- /dev/null +++ b/lib/runtime/mulax9.s @@ -0,0 +1,32 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Multiply the primary register by 9 +; + + .export mulax9 + .importzp ptr1 + +.proc mulax9 + + sta ptr1 + stx ptr1+1 + asl a + rol ptr1+1 ; * 2 + asl a + rol ptr1+1 ; * 4 + asl a + rol ptr1+1 ; * 8 + clc + adc ptr1 ; * (8+1) + pha + txa + adc ptr1+1 + tax + pla + rts + +.endproc + + diff --git a/lib/runtime/ne.s b/lib/runtime/ne.s new file mode 100644 index 0000000..ce9b817 --- /dev/null +++ b/lib/runtime/ne.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare != for ints +; + + .export tosne00, tosnea0, tosneax + .import tosicmp, boolne + +tosne00: + lda #$00 +tosnea0: + ldx #$00 +tosneax: + jsr tosicmp ; Set flags + jmp boolne ; Convert to boolean + + diff --git a/lib/runtime/neg.s b/lib/runtime/neg.s new file mode 100644 index 0000000..62807c7 --- /dev/null +++ b/lib/runtime/neg.s @@ -0,0 +1,21 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: negation on ints +; + + .export negax + +negax: clc + eor #$FF + adc #1 + pha + txa + eor #$FF + adc #0 + tax + pla + rts + + + diff --git a/lib/runtime/or.s b/lib/runtime/or.s new file mode 100644 index 0000000..f953549 --- /dev/null +++ b/lib/runtime/or.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: or on ints +; + + .export tosora0, tosorax + .import addysp1 + .importzp sp, tmp1 + +tosora0: + ldx #$00 +tosorax: + ldy #0 + ora (sp),y + sta tmp1 + iny + txa + ora (sp),y + tax + lda tmp1 + jmp addysp1 ; drop TOS, set condition codes + diff --git a/lib/runtime/popa.s b/lib/runtime/popa.s new file mode 100644 index 0000000..0534b24 --- /dev/null +++ b/lib/runtime/popa.s @@ -0,0 +1,29 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Pop a from stack +; + + .export popa + .importzp sp + + .macpack cpu + +.proc popa + +.if (.cpu .bitand ::CPU_ISET_65SC02) + lda (sp) +.else + ldy #0 ; (2) + lda (sp),y ; (7) Read byte +.endif + inc sp ; (12) + beq @L1 ; (14) + rts ; (20) + +@L1: inc sp+1 + rts + +.endproc + + diff --git a/lib/runtime/popsreg.s b/lib/runtime/popsreg.s new file mode 100644 index 0000000..80e4843 --- /dev/null +++ b/lib/runtime/popsreg.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 1998-08-21, 2009-02-22 +; +; CC65 runtime: Pop TOS into sreg +; + + .export popsreg + .import incsp2 + .importzp sp, sreg + + .macpack cpu + +popsreg: + pha ; save A + ldy #1 + lda (sp),y ; get hi byte + sta sreg+1 ; store it +.if (.cpu .bitand ::CPU_ISET_65SC02) + lda (sp) ; get lo byte +.else + dey + lda (sp),y ; get lo byte +.endif + sta sreg ; store it + pla ; get A back + jmp incsp2 ; bump stack and return + diff --git a/lib/runtime/push1.s b/lib/runtime/push1.s new file mode 100644 index 0000000..d58509a --- /dev/null +++ b/lib/runtime/push1.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)1 onto the stack +; + + .export push1 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push1 + + lda #1 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push2.s b/lib/runtime/push2.s new file mode 100644 index 0000000..2bbf815 --- /dev/null +++ b/lib/runtime/push2.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)2 onto the stack +; + + .export push2 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push2 + + lda #2 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push3.s b/lib/runtime/push3.s new file mode 100644 index 0000000..d55d1e4 --- /dev/null +++ b/lib/runtime/push3.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)3 onto the stack +; + + .export push3 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push3 + + lda #3 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push4.s b/lib/runtime/push4.s new file mode 100644 index 0000000..0ceeeda --- /dev/null +++ b/lib/runtime/push4.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)4 onto the stack +; + + .export push4 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push4 + + lda #4 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push5.s b/lib/runtime/push5.s new file mode 100644 index 0000000..5834864 --- /dev/null +++ b/lib/runtime/push5.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)5 onto the stack +; + + .export push5 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push5 + + lda #5 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push6.s b/lib/runtime/push6.s new file mode 100644 index 0000000..7355aea --- /dev/null +++ b/lib/runtime/push6.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)6 onto the stack +; + + .export push6 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push6 + + lda #6 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/push7.s b/lib/runtime/push7.s new file mode 100644 index 0000000..2dfc994 --- /dev/null +++ b/lib/runtime/push7.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (int)7 onto the stack +; + + .export push7 + .import pusha0 + +; Beware: The optimizer knows about this function! + +.proc push7 + + lda #7 + jmp pusha0 + +.endproc + + diff --git a/lib/runtime/pusha.s b/lib/runtime/pusha.s new file mode 100644 index 0000000..c1f1e31 --- /dev/null +++ b/lib/runtime/pusha.s @@ -0,0 +1,33 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push value in a onto the stack +; + + .export pusha0sp, pushaysp, pusha + .importzp sp + + .macpack cpu + +; Beware: The optimizer knows about this function! + +pusha0sp: + ldy #$00 +pushaysp: + lda (sp),y +pusha: ldy sp ; (3) + beq @L1 ; (6) + dec sp ; (11) +.if (.cpu .bitand CPU_ISET_65SC02) + sta (sp) +.else + ldy #0 ; (13) + sta (sp),y ; (19) +.endif + rts ; (25) + +@L1: dec sp+1 ; (11) + dec sp ; (16) + sta (sp),y ; (22) + rts ; (28) + diff --git a/lib/runtime/pushaff.s b/lib/runtime/pushaff.s new file mode 100644 index 0000000..dd8dc87 --- /dev/null +++ b/lib/runtime/pushaff.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push a extended with FF onto the stack +; + + .export pushaFF + .import pushax + +; Beware: The optimizer knows about this function! + +.proc pushaFF + + ldx #$FF + jmp pushax + +.endproc + + + diff --git a/lib/runtime/pushax.s b/lib/runtime/pushax.s new file mode 100644 index 0000000..d9efe7c --- /dev/null +++ b/lib/runtime/pushax.s @@ -0,0 +1,35 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push value in a/x onto the stack +; + + .export push0, pusha0, pushax + .importzp sp + +push0: lda #0 +pusha0: ldx #0 + +; This function is used *a lot*, so don't call any subroutines here. +; Beware: The value in ax must not be changed by this function! +; Beware^2: The optimizer knows about the value of Y after the function +; returns! + +.proc pushax + + pha ; (3) + lda sp ; (6) + sec ; (8) + sbc #2 ; (10) + sta sp ; (13) + bcs @L1 ; (17) + dec sp+1 ; (+5) +@L1: ldy #1 ; (19) + txa ; (21) + sta (sp),y ; (27) + pla ; (31) + dey ; (33) + sta (sp),y ; (38) + rts ; (44) + +.endproc diff --git a/lib/runtime/pushb.s b/lib/runtime/pushb.s new file mode 100644 index 0000000..d32c1c9 --- /dev/null +++ b/lib/runtime/pushb.s @@ -0,0 +1,30 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Push word from stack +; + + .export pushb, pushbidx + .import pushax + .importzp ptr1 + + .macpack cpu + +pushbidx: + sty ptr1 + clc + adc ptr1 + bcc pushb + inx +pushb: sta ptr1 + stx ptr1+1 + ldx #0 ; Load index/high byte +.if (.cpu .bitand CPU_ISET_65SC02) + lda (ptr1) ; Save one cycle for the C02 +.else + lda (ptr1,x) +.endif + bpl L1 + dex ; Make high byte FF +L1: jmp pushax + diff --git a/lib/runtime/pushbsp.s b/lib/runtime/pushbsp.s new file mode 100644 index 0000000..2ae0625 --- /dev/null +++ b/lib/runtime/pushbsp.s @@ -0,0 +1,17 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Load a from stack slot and push as word +; + + .export pushbsp, pushbysp + .import pusha0 + .importzp sp + +pushbsp: + ldy #0 +pushbysp: + lda (sp),y ; get lo byte + jmp pusha0 ; promote to unsigned and push + + diff --git a/lib/runtime/pushc0.s b/lib/runtime/pushc0.s new file mode 100644 index 0000000..fd72064 --- /dev/null +++ b/lib/runtime/pushc0.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (char)0 onto the stack +; + + .export pushc0 + .import pusha + +; Beware: The optimizer knows about this function! + +.proc pushc0 + + lda #0 + jmp pusha + +.endproc + + diff --git a/lib/runtime/pushc1.s b/lib/runtime/pushc1.s new file mode 100644 index 0000000..9997b56 --- /dev/null +++ b/lib/runtime/pushc1.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (char)1 onto the stack +; + + .export pushc1 + .import pusha + +; Beware: The optimizer knows about this function! + +.proc pushc1 + + lda #1 + jmp pusha + +.endproc + + diff --git a/lib/runtime/pushc2.s b/lib/runtime/pushc2.s new file mode 100644 index 0000000..4539f30 --- /dev/null +++ b/lib/runtime/pushc2.s @@ -0,0 +1,19 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Push (char)2 onto the stack +; + + .export pushc2 + .import pusha + +; Beware: The optimizer knows about this function! + +.proc pushc2 + + lda #2 + jmp pusha + +.endproc + + diff --git a/lib/runtime/pushlysp.s b/lib/runtime/pushlysp.s new file mode 100644 index 0000000..a91b9f7 --- /dev/null +++ b/lib/runtime/pushlysp.s @@ -0,0 +1,31 @@ +; +; Ullrich von Bassewitz, 22.06.1998 +; +; CC65 runtime: Push a long from somewhere in the stack +; + + + .export pushlysp + .import pusheax + .importzp sreg, sp + +.proc pushlysp + + iny + iny + lda (sp),y + iny + sta sreg + lda (sp),y + sta sreg+1 + dey + dey + lda (sp),y + dey + tax + lda (sp),y + jmp pusheax + +.endproc + + diff --git a/lib/runtime/pushw.s b/lib/runtime/pushw.s new file mode 100644 index 0000000..a88ebc3 --- /dev/null +++ b/lib/runtime/pushw.s @@ -0,0 +1,21 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Fetch word indirect and push +; + + .export pushw, pushwidx + .import pushax + .importzp ptr1 + + +pushw: ldy #1 +pushwidx: + sta ptr1 + stx ptr1+1 + lda (ptr1),y + tax + dey + lda (ptr1),y + jmp pushax + diff --git a/lib/runtime/pushwsp.s b/lib/runtime/pushwsp.s new file mode 100644 index 0000000..6e97354 --- /dev/null +++ b/lib/runtime/pushwsp.s @@ -0,0 +1,31 @@ +; +; Ullrich von Bassewitz, 24.10.2001 +; +; CC65 runtime: Load word from stack slot and push +; + + .export pushwysp, pushw0sp + .importzp sp + + .macpack generic + +pushw0sp: + ldy #3 +pushwysp: + lda sp ; 3 + sub #2 ; 4 + sta sp ; 3 + bcs @L1 ; 3(+1) + dec sp+1 ; (5) +@L1: lda (sp),y ; 5 =16 + tax ; 2 + dey ; 2 + lda (sp),y ; 5 + ldy #$00 ; 2 + sta (sp),y ; 5 + iny ; 2 + txa ; 2 + sta (sp),y ; 5 + rts + + diff --git a/lib/runtime/regswap.s b/lib/runtime/regswap.s new file mode 100644 index 0000000..28e0441 --- /dev/null +++ b/lib/runtime/regswap.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 25.11.2002 +; +; CC65 runtime: Swap x bytes of register variable space +; + + .export regswap + .importzp sp, regbank, tmp1 + +.proc regswap + + sta tmp1 ; Store count +@L1: lda regbank,x ; Get old value + pha ; Save it + lda (sp),y ; Get stack loc + sta regbank,x ; Store new value + pla + sta (sp),y ; Store old value + inx + iny + dec tmp1 + bne @L1 + + rts + +.endproc + + diff --git a/lib/runtime/regswap1.s b/lib/runtime/regswap1.s new file mode 100644 index 0000000..e2410f9 --- /dev/null +++ b/lib/runtime/regswap1.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 25.11.2002 +; +; CC65 runtime: Swap 1 byte of register variable space +; + + .export regswap1 + .importzp sp, regbank + +.proc regswap1 + + lda regbank,x ; Get old value + pha ; Save it + lda (sp),y ; Get stack loc + sta regbank,x ; Store new value + pla + sta (sp),y ; Store old value + rts + +.endproc + + diff --git a/lib/runtime/regswap2.s b/lib/runtime/regswap2.s new file mode 100644 index 0000000..50eb6c2 --- /dev/null +++ b/lib/runtime/regswap2.s @@ -0,0 +1,35 @@ +; +; Ullrich von Bassewitz, 25.11.2002 +; +; CC65 runtime: Swap 2 bytes of register variable space +; + + .export regswap2 + .importzp sp, regbank + +.proc regswap2 + +; First byte + + lda regbank,x ; Get old value + pha ; Save it + lda (sp),y ; Get stack loc + sta regbank,x ; Store new value + pla + sta (sp),y ; Store old value + +; Second byte + + iny + lda regbank+1,x ; Get old value + pha ; Save it + lda (sp),y ; Get stack loc + sta regbank+1,x ; Store new value + pla + sta (sp),y ; Store old value + + rts + +.endproc + + diff --git a/lib/runtime/return0.s b/lib/runtime/return0.s new file mode 100644 index 0000000..37c2608 --- /dev/null +++ b/lib/runtime/return0.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Return 0 in a/x +; + + .export return0 + +.proc return0 + + lda #0 + tax + rts + +.endproc + + + + + diff --git a/lib/runtime/return1.s b/lib/runtime/return1.s new file mode 100644 index 0000000..2987de3 --- /dev/null +++ b/lib/runtime/return1.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Return 1 in a/x +; + + .export return1 + +.proc return1 + + ldx #0 + lda #1 + rts + +.endproc + + + + + diff --git a/lib/runtime/rsub.s b/lib/runtime/rsub.s new file mode 100644 index 0000000..2b722e0 --- /dev/null +++ b/lib/runtime/rsub.s @@ -0,0 +1,29 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: sub ints reversed +; + + .export tosrsuba0, tosrsubax + .import addysp1 + .importzp sp, tmp1 + +; +; AX = AX - TOS +; + +tosrsuba0: + ldx #0 +tosrsubax: + ldy #0 + sec + sbc (sp),y ; lo byte + sta tmp1 ; save lo byte + txa + iny + sbc (sp),y ; hi byte + tax + lda tmp1 + jmp addysp1 ; drop TOS, set condition codes + + diff --git a/lib/runtime/shelp.s b/lib/runtime/shelp.s new file mode 100644 index 0000000..d4f55b1 --- /dev/null +++ b/lib/runtime/shelp.s @@ -0,0 +1,30 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: helper stuff for mod/div/mul with signed ints +; + +; When negating values, we will ignore the possibility here, that one of the +; values if $8000, in which case the negate will fail. + + .export popsargs + .import negax, popax + .importzp sreg, tmp1, tmp2, ptr4 + +popsargs: + stx tmp2 ; Remember sign + cpx #0 + bpl L1 + jsr negax ; Negate accumulator +L1: sta ptr4 + stx ptr4+1 ; Save right operand + + jsr popax + stx tmp1 ; Remember sign + cpx #0 + bpl L2 + jsr negax +L2: sta sreg + stx sreg+1 + rts + diff --git a/lib/runtime/shl.s b/lib/runtime/shl.s new file mode 100644 index 0000000..1963abb --- /dev/null +++ b/lib/runtime/shl.s @@ -0,0 +1,58 @@ +; +; Ullrich von Bassewitz, 1998-08-05, 2004-06-25 +; +; CC65 runtime: left shift support for ints and unsigneds +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosaslax, tosshlax + .import popax + .importzp tmp1 + +tosshlax: +tosaslax: + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + + cpy #8 ; Shift count 8 or greater? + bcc L3 ; Jump if not + +; Shift count is greater 7. The carry is set when we enter here. + + tax + tya + sbc #8 + tay + txa + jmp L2 +L1: asl a +L2: dey + bpl L1 + tax + lda #$00 + rts + +; Shift count is less than 8. + +L3: stx tmp1 ; Save high byte of lhs +L4: asl a + rol tmp1 + dey + bne L4 + +; Done with shift + + ldx tmp1 +L9: rts + diff --git a/lib/runtime/shr.s b/lib/runtime/shr.s new file mode 100644 index 0000000..3b505e7 --- /dev/null +++ b/lib/runtime/shr.s @@ -0,0 +1,55 @@ +; +; Ullrich von Bassewitz, 2004-06-30 +; +; CC65 runtime: right shift support for unsigneds +; +; Note: The standard declares a shift count that is negative or >= the +; bitcount of the shifted type for undefined behaviour. +; +; Note^2: The compiler knowns about the register/zero page usage of this +; function, so you need to change the compiler source if you change it! +; + + + .export tosshrax + .import popax + .importzp tmp1 + +tosshrax: + and #$0F ; Bring the shift count into a valid range + sta tmp1 ; Save it + + jsr popax ; Get the left hand operand + + ldy tmp1 ; Get shift count + beq L9 ; Bail out if shift count zero + + cpy #8 ; Shift count 8 or greater? + bcc L3 ; Jump if not + +; Shift count is greater 7. The carry is set when we enter here. + + tya + sbc #8 + tay ; Adjust shift count + txa + ldx #$00 ; Shift by 8 bits + beq L2 ; Branch always +L1: lsr a +L2: dey + bpl L1 + rts + +; Shift count is less than 8. Do the actual shift. + +L3: stx tmp1 ; Save high byte of lhs +L4: lsr tmp1 + ror a + dey + bne L4 + +; Done with shift + + ldx tmp1 +L9: rts + diff --git a/lib/runtime/shrax1.s b/lib/runtime/shrax1.s new file mode 100644 index 0000000..f7b6b72 --- /dev/null +++ b/lib/runtime/shrax1.s @@ -0,0 +1,15 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register +; + + .export shrax1 + .importzp tmp1 + +shrax1: stx tmp1 + lsr tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/shrax2.s b/lib/runtime/shrax2.s new file mode 100644 index 0000000..074ab8e --- /dev/null +++ b/lib/runtime/shrax2.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register by 4 +; + + .export shrax2 + .importzp tmp1 + +shrax2: stx tmp1 + lsr tmp1 + ror a + lsr tmp1 + ror a + ldx tmp1 + rts + + diff --git a/lib/runtime/shrax3.s b/lib/runtime/shrax3.s new file mode 100644 index 0000000..07e1e1f --- /dev/null +++ b/lib/runtime/shrax3.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the primary register by 8 +; + + .export shrax3 + .importzp tmp1 + +shrax3: stx tmp1 + lsr tmp1 + ror a + lsr tmp1 + ror a + lsr tmp1 + ror a + ldx tmp1 + rts + + diff --git a/lib/runtime/shrax4.s b/lib/runtime/shrax4.s new file mode 100644 index 0000000..46589e2 --- /dev/null +++ b/lib/runtime/shrax4.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 25.07.2001 +; +; CC65 runtime: Scale the primary register by 16 +; + + .export shrax4 + .importzp tmp1 + +shrax4: stx tmp1 + lsr tmp1 + ror a + lsr tmp1 + ror a + lsr tmp1 + ror a + lsr tmp1 + ror a + ldx tmp1 + rts + + diff --git a/lib/runtime/shreax1.s b/lib/runtime/shreax1.s new file mode 100644 index 0000000..f4d808f --- /dev/null +++ b/lib/runtime/shreax1.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 2 +; + + .export shreax1 + .importzp sreg, tmp1 + +shreax1: + stx tmp1 + lsr sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/shreax2.s b/lib/runtime/shreax2.s new file mode 100644 index 0000000..1f2a23d --- /dev/null +++ b/lib/runtime/shreax2.s @@ -0,0 +1,22 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 4 +; + + .export shreax2 + .importzp sreg, tmp1 + +shreax2: + stx tmp1 + lsr sreg+1 + ror sreg + ror tmp1 + ror a + lsr sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/shreax3.s b/lib/runtime/shreax3.s new file mode 100644 index 0000000..8111253 --- /dev/null +++ b/lib/runtime/shreax3.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Scale the 32 bit primary register by 8 +; + + .export shreax3 + .importzp sreg, tmp1 + +shreax3: + stx tmp1 + lsr sreg+1 + ror sreg + ror tmp1 + ror a + lsr sreg+1 + ror sreg + ror tmp1 + ror a + lsr sreg+1 + ror sreg + ror tmp1 + ror a + ldx tmp1 + rts + diff --git a/lib/runtime/shreax4.s b/lib/runtime/shreax4.s new file mode 100644 index 0000000..8020592 --- /dev/null +++ b/lib/runtime/shreax4.s @@ -0,0 +1,21 @@ +; +; Ullrich von Bassewitz, 25.07.2001 +; +; CC65 runtime: Scale the 32 bit primary register by 16 +; + + .export shreax4 + .importzp sreg, tmp1 + +shreax4: + stx tmp1 + ldx #4 +@L1: lsr sreg+1 + ror sreg + ror tmp1 + ror a + dex + bne @L1 + ldx tmp1 + rts + diff --git a/lib/runtime/staspidx.s b/lib/runtime/staspidx.s new file mode 100644 index 0000000..c5e1440 --- /dev/null +++ b/lib/runtime/staspidx.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Store a indirect into address at top of stack with index +; + + .export staspidx + .import incsp2 + .importzp sp, tmp1, ptr1 + +.proc staspidx + + pha + sty tmp1 ; Save Index + ldy #1 + lda (sp),y + sta ptr1+1 + dey + lda (sp),y + sta ptr1 ; Pointer now in ptr1 + ldy tmp1 ; Restore offset + pla ; Restore value + sta (ptr1),y ; Store + jmp incsp2 ; Drop address + +.endproc + + diff --git a/lib/runtime/staxsp.s b/lib/runtime/staxsp.s new file mode 100644 index 0000000..07828e3 --- /dev/null +++ b/lib/runtime/staxsp.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Store ax at (sp),y +; + + .export staxysp, stax0sp + .importzp sp + +stax0sp: + ldy #0 +staxysp: + sta (sp),y + iny + pha + txa + sta (sp),y + pla + rts + diff --git a/lib/runtime/staxspi.s b/lib/runtime/staxspi.s new file mode 100644 index 0000000..1c4c011 --- /dev/null +++ b/lib/runtime/staxspi.s @@ -0,0 +1,32 @@ +; +; Ullrich von Bassewitz, 26.10.2000 +; +; CC65 runtime: Store a/x indirect into address at top of stack with index +; + + .export staxspidx + .import incsp2 + .importzp sp, tmp1, ptr1 + +.proc staxspidx + + sty tmp1 ; Save Y + pha ; Save A + ldy #1 + lda (sp),y + sta ptr1+1 + dey + lda (sp),y + sta ptr1 ; Address now in ptr1 + ldy tmp1 ; Restore Y + iny ; Address high byte + txa ; Get high byte + sta (ptr1),y ; Store high byte + dey ; Address low byte + pla ; Restore low byte into A + sta (ptr1),y ; Store low byte + jmp incsp2 ; Drop address + +.endproc + + diff --git a/lib/runtime/steaxsp.s b/lib/runtime/steaxsp.s new file mode 100644 index 0000000..de134e2 --- /dev/null +++ b/lib/runtime/steaxsp.s @@ -0,0 +1,27 @@ +; +; Ullrich von Bassewitz, 31.08.1998 +; +; CC65 runtime: Store eax at (sp),y +; + + .export steaxysp, steax0sp + .importzp sp, sreg + +steax0sp: + ldy #0 +steaxysp: + sta (sp),y + iny + pha + txa + sta (sp),y + iny + lda sreg + sta (sp),y + iny + lda sreg+1 + sta (sp),y + pla + rts + + diff --git a/lib/runtime/steaxspi.s b/lib/runtime/steaxspi.s new file mode 100644 index 0000000..ec1777e --- /dev/null +++ b/lib/runtime/steaxspi.s @@ -0,0 +1,39 @@ +; +; Ullrich von Bassewitz, 22.06.1998 +; +; CC65 runtime: Store eax at the address on top of stack with index +; + + + .export steaxspidx + .import popax + .importzp sreg, ptr1, tmp1, tmp2, tmp3 + + +.proc steaxspidx + + sta tmp1 + stx tmp2 + sty tmp3 + jsr popax ; get the pointer + sta ptr1 + stx ptr1+1 + ldy tmp3 + lda tmp1 + sta (ptr1),y + iny + lda tmp2 + sta (ptr1),y + iny + tax + lda sreg + sta (ptr1),y + iny + lda sreg+1 + sta (ptr1),y + lda tmp1 + rts + +.endproc + + diff --git a/lib/runtime/stkchk.s b/lib/runtime/stkchk.s new file mode 100644 index 0000000..ee0b714 --- /dev/null +++ b/lib/runtime/stkchk.s @@ -0,0 +1,114 @@ +; +; Ullrich von Bassewitz, 19.03.2001 +; +; Stack checking code. These are actually two routines, one to check the C +; stack, and the other one to check the 6502 hardware stack. +; For performance reasons (to avoid having to pass a parameter), the compiler +; calls the cstkchk routine *after* allocating space on the stack. So the +; stackpointer may already be invalid if this routine is called. In addition +; to that, pushs and pops that are needed for expression evaluation are not +; checked (this would be way too much overhead). As a consequence we will +; operate using a safety area at the stack bottom. Once the stack reaches this +; safety area, we consider it an overflow, even if the stack is still inside +; its' bounds. +; + + .export stkchk, cstkchk + .constructor initstkchk, 25 + .import __STACKSIZE__ ; Linker defined + .import pusha0, _exit + .importzp sp + + ; Use macros for better readability + .macpack generic + .macpack cpu + + +; ---------------------------------------------------------------------------- +; Initialization code. This is a constructor, so it is called on startup if +; the linker has detected references to this module. + +.segment "INIT" + +.proc initstkchk + + lda sp + sta initialsp + sub #<__STACKSIZE__ + sta lowwater + lda sp+1 + sta initialsp+1 + sbc #>__STACKSIZE__ +.if (.cpu .bitand ::CPU_ISET_65SC02) + ina ; Add 256 bytes safety area +.else + add #1 ; Add 256 bytes safety area +.endif + sta lowwater+1 + rts + +.endproc + +; ---------------------------------------------------------------------------- +; 6502 stack checking routine. Does not need to save any registers. +; Safety zone for the hardware stack is 12 bytes. + +.code + +stkchk: tsx + cpx #12 + bcc Fail ; Jump on stack overflow + rts ; Return if ok + +; ---------------------------------------------------------------------------- +; C stack checking routine. Does not need to save any registers. + +.code + +cstkchk: + +; Check the high byte of the software stack + +@L0: lda lowwater+1 + cmp sp+1 + bcs @L1 + rts + +; Check low byte + +@L1: bne CStackOverflow + lda lowwater + cmp sp + bcs CStackOverflow +Done: rts + +; We have a C stack overflow. Set the stack pointer to the initial value, so +; we can continue without worrying about stack issues. + +CStackOverflow: + lda initialsp + sta sp + lda initialsp+1 + sta sp+1 + +; Generic abort entry. We should output a diagnostic here, but this is +; difficult, since we're operating at a lower level here. + +Fail: lda #4 + ldx #0 + jmp _exit + +; ---------------------------------------------------------------------------- +; Data + +.bss + +; Initial stack pointer value. Stack is reset to this in case of overflows to +; allow program exit processing. +initialsp: .word 0 + +; Stack low water mark. +lowwater: .word 0 + + + diff --git a/lib/runtime/sub.s b/lib/runtime/sub.s new file mode 100644 index 0000000..c9d427e --- /dev/null +++ b/lib/runtime/sub.s @@ -0,0 +1,35 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: sub ints +; + + .export tossuba0, tossubax + .import addysp1 + .importzp sp + + .macpack cpu + +; AX = TOS - AX + +tossuba0: + ldx #0 +tossubax: + sec + eor #$FF +.if (.cpu .bitand CPU_ISET_65SC02) + adc (sp) + ldy #1 +.else + ldy #0 + adc (sp),y ; Subtract low byte + iny +.endif + pha ; Save high byte + txa + eor #$FF + adc (sp),y ; Subtract high byte + tax ; High byte into X + pla ; Restore low byte + jmp addysp1 ; drop TOS + diff --git a/lib/runtime/subeqsp.s b/lib/runtime/subeqsp.s new file mode 100644 index 0000000..8a2e3e3 --- /dev/null +++ b/lib/runtime/subeqsp.s @@ -0,0 +1,26 @@ +; +; Ullrich von Bassewitz, 08.10.1998 +; +; CC65 runtime: -= operator for ints on the stack +; + + .export subeq0sp, subeqysp + .importzp sp + +subeq0sp: + ldy #0 +subeqysp: + sec + eor #$FF + adc (sp),y + sta (sp),y + pha ; Save low byte + iny + txa + eor #$FF + adc (sp),y + sta (sp),y + tax + pla ; Restore low byte + rts + diff --git a/lib/runtime/subysp.s b/lib/runtime/subysp.s new file mode 100644 index 0000000..9d1a2c6 --- /dev/null +++ b/lib/runtime/subysp.s @@ -0,0 +1,24 @@ +; +; Piotr Fusik, 24.10.2003 +; originally by Ullrich von Bassewitz +; +; CC65 runtime: Decrement the stackpointer by value in y +; + + .export subysp + .importzp sp + +.proc subysp + + tya + eor #$ff + sec + adc sp + sta sp + bcs @L1 + dec sp+1 +@L1: rts + +.endproc + + diff --git a/lib/runtime/swap.s b/lib/runtime/swap.s new file mode 100644 index 0000000..e2f882f --- /dev/null +++ b/lib/runtime/swap.s @@ -0,0 +1,25 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: swap ax with TOS +; + + .export swapstk + .importzp sp, ptr4 + +swapstk: + sta ptr4 + stx ptr4+1 + ldy #1 ; index + lda (sp),y + tax + lda ptr4+1 + sta (sp),y + dey + lda (sp),y + pha + lda ptr4 + sta (sp),y + pla + rts ; whew! + diff --git a/lib/runtime/tosint.s b/lib/runtime/tosint.s new file mode 100644 index 0000000..d29fa2e --- /dev/null +++ b/lib/runtime/tosint.s @@ -0,0 +1,33 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Convert tos from long to int +; + + .export tosint + .import incsp2 + .importzp sp + + .macpack cpu + +; Convert TOS from long to int by cutting of the high 16bit + +.proc tosint + + pha +.if (.cpu .bitand ::CPU_ISET_65SC02) + lda (sp) +.else + ldy #0 + lda (sp),y ; sp+1 +.endif + ldy #2 + sta (sp),y + dey + lda (sp),y + ldy #3 + sta (sp),y + pla + jmp incsp2 ; Drop 16 bit + +.endproc diff --git a/lib/runtime/toslong.s b/lib/runtime/toslong.s new file mode 100644 index 0000000..9bf66a3 --- /dev/null +++ b/lib/runtime/toslong.s @@ -0,0 +1,60 @@ +; +; Ullrich von Bassewitz, 25.10.2000 +; +; CC65 runtime: Convert tos from int to long +; + + .export tosulong, toslong + .import decsp2 + .importzp sp + + .macpack cpu + +; Convert TOS from int to long + +tosulong: + pha + jsr decsp2 ; Make room + ldy #2 + lda (sp),y +.if (.cpu .bitand CPU_ISET_65SC02) + sta (sp) ; 65C02 version + iny ; Y = 3 +.else + ldy #0 + sta (sp),y + ldy #3 +.endif + lda (sp),y +toslong1: + ldy #1 + sta (sp),y + lda #0 ; Zero extend +toslong2: + iny + sta (sp),y + iny + sta (sp),y + pla + rts + +toslong: + pha + jsr decsp2 ; Make room + ldy #2 + lda (sp),y +.if (.cpu .bitand CPU_ISET_65SC02) + sta (sp) ; 65C02 version + iny ; Y = 3 +.else + ldy #0 + sta (sp),y + ldy #3 +.endif + lda (sp),y + bpl toslong1 ; Jump if positive, high word is zero + ldy #1 + sta (sp),y + lda #$FF + bne toslong2 ; Branch always + diff --git a/lib/runtime/udiv.s b/lib/runtime/udiv.s new file mode 100644 index 0000000..e667af0 --- /dev/null +++ b/lib/runtime/udiv.s @@ -0,0 +1,82 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: division for unsigned ints +; + + .export tosudiva0, tosudivax, udiv16 + .import popsreg + .importzp sreg, ptr1, ptr4 + + +tosudiva0: + ldx #$00 ; Clear high byte +tosudivax: + sta ptr4 + stx ptr4+1 ; Save right operand + jsr popsreg ; Get left operand + +; Do the division + + jsr udiv16 + +; Result is in sreg, remainder in ptr1 + + lda sreg + ldx sreg+1 + rts + +;--------------------------------------------------------------------------- +; 16by16 division. Divide sreg by ptr4. Result is in sreg, remainder in ptr1 +; (see mult-div.s from "The Fridge"). +; This is also the entry point for the signed division + +udiv16: lda #0 + sta ptr1+1 + ldy #16 + ldx ptr4+1 + beq udiv16by8a + +L0: asl sreg + rol sreg+1 + rol a + rol ptr1+1 + + pha + cmp ptr4 + lda ptr1+1 + sbc ptr4+1 + bcc L1 + + sta ptr1+1 + pla + sbc ptr4 + pha + inc sreg + +L1: pla + dey + bne L0 + sta ptr1 + rts + + +;--------------------------------------------------------------------------- +; 16by8 division + +udiv16by8a: +@L0: asl sreg + rol sreg+1 + rol a + bcs @L1 + + cmp ptr4 + bcc @L2 +@L1: sbc ptr4 + inc sreg + +@L2: dey + bne @L0 + sta ptr1 + rts + diff --git a/lib/runtime/uge.s b/lib/runtime/uge.s new file mode 100644 index 0000000..96e9497 --- /dev/null +++ b/lib/runtime/uge.s @@ -0,0 +1,20 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare >= for unsigned ints +; + + .export tosuge00, tosugea0, tosugeax + .import tosicmp, booluge + + +tosuge00: + lda #$00 +tosugea0: + ldx #$00 +tosugeax: + jsr tosicmp ; Set flags + jmp booluge ; Convert to boolean + + + diff --git a/lib/runtime/ugt.s b/lib/runtime/ugt.s new file mode 100644 index 0000000..a8befbf --- /dev/null +++ b/lib/runtime/ugt.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare > for unsigned ints +; + + .export tosugt00, tosugta0, tosugtax + .import tosicmp, boolugt + + +tosugt00: + lda #$00 +tosugta0: + ldx #$00 +tosugtax: + jsr tosicmp ; Set flags + jmp boolugt ; Convert to boolean + diff --git a/lib/runtime/ule.s b/lib/runtime/ule.s new file mode 100644 index 0000000..5e0817d --- /dev/null +++ b/lib/runtime/ule.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare <= for unsigned ints +; + + .export tosule00, tosulea0, tosuleax + .import tosicmp, boolule + +tosule00: + lda #$00 +tosulea0: + ldx #$00 +tosuleax: + jsr tosicmp ; Set flags + jmp boolule ; Convert to boolean + + diff --git a/lib/runtime/ult.s b/lib/runtime/ult.s new file mode 100644 index 0000000..d2895d0 --- /dev/null +++ b/lib/runtime/ult.s @@ -0,0 +1,18 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; +; CC65 runtime: Compare < for unsigned ints +; + + .export tosult00, tosulta0, tosultax + .import tosicmp, boolult, return0 + + +tosult00 = return0 ; This is always false + +tosulta0: + ldx #$00 +tosultax: + jsr tosicmp ; Set flags + jmp boolult ; Convert to boolean + diff --git a/lib/runtime/umod.s b/lib/runtime/umod.s new file mode 100644 index 0000000..b465d90 --- /dev/null +++ b/lib/runtime/umod.s @@ -0,0 +1,28 @@ +; +; Ullrich von Bassewitz, 07.08.1998 +; +; CC65 runtime: modulo operation for unsigned ints +; + + .export tosumoda0, tosumodax + .import popsreg, udiv16 + .importzp ptr1, ptr4 + +tosumoda0: + ldx #0 +tosumodax: + sta ptr4 + stx ptr4+1 ; Save right operand + jsr popsreg ; Get right operand + +; Do the division + + jsr udiv16 + +; Result is in sreg, remainder in ptr1 + + lda ptr1 + ldx ptr1+1 + rts + + diff --git a/lib/runtime/xor.s b/lib/runtime/xor.s new file mode 100644 index 0000000..9027cb1 --- /dev/null +++ b/lib/runtime/xor.s @@ -0,0 +1,23 @@ +; +; Ullrich von Bassewitz, 05.08.1998 +; +; CC65 runtime: xor on ints +; + + .export tosxora0, tosxorax + .import addysp1 + .importzp sp, tmp1 + +tosxora0: + ldx #$00 +tosxorax: + ldy #0 + eor (sp),y + sta tmp1 + iny + txa + eor (sp),y + tax + lda tmp1 + jmp addysp1 ; drop TOS, set condition codes + diff --git a/lib/runtime/zeropage.s b/lib/runtime/zeropage.s new file mode 100644 index 0000000..ab87901 --- /dev/null +++ b/lib/runtime/zeropage.s @@ -0,0 +1,34 @@ +; +; Ullrich von Bassewitz, 26.05.2002 +; +; CC65 runtime: zeropage usage +; + + .exportzp sp, sreg, regsave + .exportzp ptr1, ptr2, ptr3, ptr4 + .exportzp tmp1, tmp2, tmp3, tmp4 + .exportzp regbank + +; ------------------------------------------------------------------------ + +.zeropage + +sp: .res 2 ; Stack pointer +sreg: .res 2 ; Secondary register/high 16 bit for longs +regsave: .res 4 ; slot to save/restore (E)AX into +ptr1: .res 2 +ptr2: .res 2 +ptr3: .res 2 +ptr4: .res 2 +tmp1: .res 1 +tmp2: .res 1 +tmp3: .res 1 +tmp4: .res 1 +regbank: .res 6 ; 6 byte register bank + +; Add an empty EXTZP zeropage segment to avoid linker warnings that this +; segment does not exist (it does not exist in most builtin linker configs +; but is used when linking modules). + +.segment "EXTZP" : zeropage + diff --git a/script/disk b/script/disk new file mode 100644 index 0000000..e57a27f --- /dev/null +++ b/script/disk @@ -0,0 +1,4 @@ +#!/bin/bash + + +cp ./test/irc_client.img /Applications/MultiMC.app/Contents/Resources/instances/1.2.5\ ftb/minecraft/saves/cpu\ test/redpower/ \ No newline at end of file diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..a9a86c2 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,33 @@ +LD = ../bin/ld65 +AS = ../bin/ca65 +CC = ../bin/cc65 +AL = ../bin/align + +CINCLUDE = -I ../include +CFLAGS = -t none --cpu $(CPU) +LFLAGS = -C ../lib/rpc8e.cfg +LLIBS = ../lib/rpc8e.lib + +IMAGES = test_rb.img irc_client.img + +.PHONY: all +all: $(IMAGES) + +%.s: %.c + $(CC) $(CFLAGS) $(CINCLUDE) $< + +%.o: %.s + $(AS) $(CFLAGS) $< + +%.img: %.o + $(LD) $(LFLAGS) $< $(LLIBS) -o $@ + $(AL) $@ + + + + + +clean: + rm *.o + +.SUFFIXES: \ No newline at end of file diff --git a/test/irc_client.c b/test/irc_client.c new file mode 100644 index 0000000..e276cc0 --- /dev/null +++ b/test/irc_client.c @@ -0,0 +1,185 @@ +//irc_client.c + +#include +#include +#include + +#define RB 0x0300 + +Console* con; +Disk* dis; + +#define DSTAT 32 +#define DOUT 31 +#define DIN 30 + + +#define LPROMPT 49 +#define LSTAT 48 +#define LSTREAM 47 + +#define SCREEN_W 80 +#define SCREEN_H 50 + +#define map_con() rb_map_device(0x01); +#define map_dis() rb_map_device(0x02); + +void blit(char command, char x, char y, char xo, char yo, char w, char h) { + con->blit_start_x = x; + con->blit_start_y = y; + con->blit_offset_x = xo; + con->blit_offset_y = yo; + con->blit_width = w; + con->blit_height = h; + con->blit_mode = command; + while(con->blit_mode != 0) ; //WAI +} + +#define fill(b, x, y, w, h) blit(1, b, 0, x, y, w, h) +#define invert(x, y, w, h) blit(2, 0, 0, x, y, w, h) +#define scroll(x, y, ox, oy, w, h) blit(3, x, y, ox, oy, w, h) + +#define LF 13 + +void prepare_screen() { + map_con(); + fill(0x20,0,0,SCREEN_W,SCREEN_H); + invert(0,LSTAT,SCREEN_W,1); + con->cursor_x = 0; + con->cursor_y = LPROMPT; + con->cursor_mode = 2; +} + +char send = 0; +char recv = 0; +char outbuf[128]; +char inbuf[128]; + +#define CONTROL 0 +#define READPTR 1 +#define WRITEPTR 2 + +unsigned char flush() { + dis->command = WRITE; + while(dis->command != IDLE && dis->command != FAIL) ; + return dis->command; +} + +unsigned char wait() { + dis->command = READ; + while(dis->command != IDLE && dis->command != FAIL) ; + return dis->command; +} + +void prepare_disk() { + map_dis(); + dis->sector_num = DSTAT; + dis->sector[CONTROL] = 'N'; + flush(); +} + +unsigned char cursor = 0; + +void linefeed() { + scroll(0,1,0,0,SCREEN_W,SCREEN_H-3); + fill(0x20,0,LSTREAM,SCREEN_W,1); +} + +void print(char* buffer) { + unsigned char i = 0; + + if(buffer[0] == 0) return; + + con->line = LSTREAM; + + if(cursor == 0) linefeed(); + + while(buffer[i] != 0 && i < 128) { + if(buffer[i] == '\n' || cursor == 80) { + cursor = 0; + linefeed(); + } else { + con->display[cursor] = buffer[i]; + ++cursor; + } + ++i; + } + + if(i < 128) + cursor = 0; +} + +void read_keyboard() { + con->line = LPROMPT; + while(con->kb_pos != con->kb_start) { + outbuf[con->cursor_x] = con->kb_key; + if(con->kb_key == LF) { + outbuf[con->cursor_x+1] = 0; + fill(0x20,0,LPROMPT,SCREEN_W,1); + send = 1; + con->cursor_x = 0; + ++con->kb_start; + break; + } + con->display[con->cursor_x] = con->kb_key; + ++con->cursor_x; + ++con->kb_start; + } +} + +void perform_io() { + unsigned int i = 0; + + map_dis(); + + i = 0; + dis->sector_num = DIN; + wait(); + while(dis->sector[i] != 0 && i < 128) { + inbuf[i] = dis->sector[i]; + dis->sector[i] = 0; + ++i; + } + inbuf[i] = 0; + + flush(); + + i = 0; + + dis->sector_num = DOUT; + if(send == 1) { + while(outbuf[i] != 0 && i < 128) { + dis->sector[i] = outbuf[i]; + ++i; + } + //send = 0; + } else dis->sector[i] == 0; + if(!flush() && send == 1) send = 0; + + map_con(); +} + +void main() { + + rb_set_window((void*)RB); + con = (Console*)RB; + dis = (Disk*)RB; + rb_enable(); + + prepare_screen(); + + print("IRC for RPC8/e\nInitializing IO buffer space... "); + + prepare_disk(); + + map_con(); + + print("[DONE]\nStarting IO loop."); + + while(1) { + read_keyboard(); + perform_io(); + print(inbuf); + inbuf[0] = 0; + } +} \ No newline at end of file diff --git a/test/test_rb.c b/test/test_rb.c new file mode 100644 index 0000000..59ee58b --- /dev/null +++ b/test/test_rb.c @@ -0,0 +1,22 @@ +//test_rb.c + +#include +#include + +#define redbus 0x0300 +#define default_console_id 0x01 + +void main() { + Console* console; + + rb_set_window((void*)redbus); + rb_map_device(default_console_id); + rb_enable(); + + + console = (Console*)redbus; + + console->cursor_mode = 2; + console->display[0] = 'X'; + console->display[1] = inv('Y'); +} \ No newline at end of file diff --git a/test/test_rb.s b/test/test_rb.s new file mode 100644 index 0000000..c0063b2 --- /dev/null +++ b/test/test_rb.s @@ -0,0 +1,64 @@ +; +; File generated by cc65 v 2.13.3 +; + .fopt compiler,"cc65 v 2.13.3" + .setcpu "65C02" + .smart on + .autoimport on + .case on + .debuginfo off + .importzp sp, sreg, regsave, regbank, tmp1, ptr1, ptr2 + .macpack longbranch + .forceimport __STARTUP__ + .import _rb_enable + .import _rb_set_window + .import _rb_map_device + .export _main + +; --------------------------------------------------------------- +; void __near__ main (void) +; --------------------------------------------------------------- + +.segment "CODE" + +.proc _main: near + +.segment "CODE" + + jsr decsp2 + ldx #$03 + lda #$00 + jsr _rb_set_window + lda #$01 + jsr _rb_map_device + jsr _rb_enable + ldx #$03 + lda #$00 + ldy #$00 + jsr staxysp + ldy #$01 + jsr ldaxysp + jsr pushax + ldx #$00 + lda #$02 + ldy #$03 + jsr staspidx + ldy #$01 + jsr ldaxysp + jsr pushax + ldx #$00 + lda #$58 + ldy #$10 + jsr staspidx + ldy #$01 + jsr ldaxysp + jsr pushax + ldx #$00 + lda #$D9 + ldy #$11 + jsr staspidx + jsr incsp2 + rts + +.endproc +