This commit was generated by cvs2svn to compensate for changes in r2,

which included commits to RCS files with non-trunk default branches.


git-svn-id: svn://svn.cc65.org/cc65/trunk@3 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2000-05-28 13:40:48 +00:00
parent 579491e8a4
commit 53dd513176
847 changed files with 91345 additions and 0 deletions

11
doc/BUGS Normal file
View File

@@ -0,0 +1,11 @@
List of known bugs that will not get fixed in the near future:
* The compiler does not detect if part of an expression evaluated
with && or || is constant. Since the expression evaluation is also
used for the preprocessor, this defeats the use of
#if defined(x) && defined(y)
* Initialization of local variables with compound data types is not
possible.

62
doc/CREDITS Normal file
View File

@@ -0,0 +1,62 @@
Many special thanks go to the guy who started it all:
John R.Dunning.
Without his great work, there would not be a single freeware C crosscompiler
for the 6502 out there. He built the grounds for this cc65 and some other cc65
implementations and a lot of his code is still in the current compiler.
More special thanks to:
* Keith W. Gerdes <kwg@freebird.ghofn.org>
Without his outstanding help, the assembler/compiler wouldn't be, what it
is now. He helped with suggestions, bug reports and even kicked me here
and then, when I started to get too lazy:-)
* Tennessee Carmel-Veilleux <veilleux@ameth.org>
Tennessee worked on the NES port.
* Kevin Ruland <kevin@rodin.wustl.edu>
Kevin did the Apple 2 port and found at least one serious error in the
C library while doing so.
* Christian Groessler <cpg@aladdin.de>
Christian sent me several fixes for 64 bit machines.
* Sidney Cadot <sidney@ch.twi.tudelft.nl>
Sidney rewrote the random number generator.
* Maciej Witkowiak <ytm@friko.onet.pl>
Maciej is responsible for the GEOS support.
Thanks to
Mark Nasgowitz <MNasgowitz@NAZdesign.com>
da Blondie <db@tvnet.hu>
Jari Tuominen <jer64@kolumbus.fi>
MagerValp <magervalp@cling.gu.se>
Ingo Korb <unseen@gmx.net>
Robert R. Wal <rrw@reptile.eu.org>
Jesse Beach <agmorion@erols.com>
Chris Ward <chris.ward@freenet.co.uk>
Eric Au <eric_au@hotmail.com>
Tim Vanderhoek <hoek@FreeBSD.org>
Bill Craig <craigw@gusun.georgetown.edu>
for bug reports and suggestions.
This list is probably incomplete. So, if you think you should be mentioned
here, but cannot find yourself, please drop me a mail.

152
doc/ar65.txt Normal file
View File

@@ -0,0 +1,152 @@
ar65
An Archiver for Object Files Generated by ca65
(C) Copyright 1998-1999 Ullrich von Bassewitz
(uz@musoftware.de)
Contents
--------
1. Overview
2. Usage
3. Bugs/Feedback
4. Copyright
1. Overview
-----------
ar65 is a replacement for the libr65 archiver that was part of the cc65 C
compiler suite developed by John R. Dunning. libr65 had some problems and
the copyright does not permit some things which I wanted to be possible,
so I decided to write a completely new assembler/linker/archiver suite
for the cc65 compiler. ar65 is part of this suite.
2. Usage
--------
The archiver is called as follows:
Usage: ar65 <operation> lib file|module ...
Operation is one of:
a Add modules
d Delete modules
l List library contents
x Extract modules
X Print the archiver version
You may add modules to a library using the `a' command. If the library
does not exist, it is created (and a warning message is printed which you
may ignore if creation of the library was your intention). You may
specify any number of modules on the command line following the library.
If a module with the same name exists in the library, it is replaced by
the new one. The archiver prints a warning, if the module in the library
has a newer timestamp than the one to add.
Here's an example:
ar65 a mysubs.lib sub1.o sub2.o
This will add two modules to the library `mysubs.lib' creating the
library if necessary. If the library contains modules named sub1.o or
sub2.o, they are replaced by the new ones.
Modules names in the library are stored without the path, so, using
ar65 a mysubs.lib ofiles/sub1.o ofiles/sub2.o
will add two modules named `sub1.o' and `sub2.o' to the library.
Deleting modules from a library is done with the `d' command. You may not
give a path when naming the modules.
Example:
ar65 d mysubs.lib sub1.o
This will delete the module named `sub1.o' from the library, printing an
error if the library does not contain that module.
The `l' command prints a list of all modules in the library. Any module
names on the command line are ignored.
Example:
ar65 l mysubs.lib
Using the `x' command, you may extract modules from the library. The
modules named on the command line are extracted from the library and put
into the current directory.
Note: Because of the indexing done by the archiver, the modules may have
a changed binary layout, that is, a binary compare with the old module
(before importing it into the library) may yield differences. The
extracted modules are accepted by the linker and archiver, however, so
this is not a problem.
Example for extracting a module from the library:
ar65 x mysubs.lib sub1.o
The `V' command prints the version number of the assembler. If you send
any suggestions or bugfixes, please include your version number.
In addition to these operations, the archiver will check for, and warn
about duplicate external symbols in the library, every time when an
operation does update the library. This is only a warning, the linker
will ignore one of the duplicate symbols (which one is unspecified).
3. Bugs/Feedback
----------------
If you have problems using the archiver, if you find any bugs, or if
you're doing something interesting with it, I would be glad to hear from
you. Feel free to contact me by email (uz@musoftware.de).
4. Copyright
------------
ar65 (and all cc65 binutils) are (C) Copyright 1998 Ullrich von Bassewitz.
For usage of the binaries and/or sources the following conditions do
apply:
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.

1903
doc/ca65.txt Normal file

File diff suppressed because it is too large Load Diff

600
doc/cc65.txt Normal file
View File

@@ -0,0 +1,600 @@
cc65
A C Compiler for 6502 Systems
(C) Copyright 1989 John R. Dunning
(C) Copyright 1998-2000 Ullrich von Bassewitz
(uz@musoftware.de)
Contents
--------
1. Overview
2. Usage
3. Input and output
4. Differences to the ISO standard
5. Extensions
6. Predefined macros
7. #pragmas
8. Bugs/Feedback
9. Copyright
1. Overview
-----------
cc65 was originally a C compiler for the Atari 8-bit machines written by
John R. Dunning. In prior releases I've described the compiler by listing
up the changes made by me. I have made many more changes in the meantime
(and rewritten major parts of the compiler), so I will no longer do that,
since the list would be too large and of no use to anyone. Instead I will
describe the compiler in respect to the ANSI/ISO C standard. In fact, I'm
planning a complete rewrite (that is, a complete new compiler) for the
next release, since there are too many limitations in the current code,
and removing these limitations would mean a rewrite of many more parts of
the compiler.
There is a separate document named "library.txt" that covers the library
available for the compiler. If you know C and are interested in doing
actual programming, the library documentation is probably of much more use
than this document.
If you need some hints for getting the best code out of the compiler, you
may have a look at "coding.txt" which covers some code generation issues.
2. Usage
--------
The compiler translates C files into files containing assembler code that
may be translated by the ca65 macroassembler (for more information about
the assembler, have a look at ca65.txt).
The compiler may be called as follows:
Usage: cc65 [options] file
-d Debug mode
-g Add debug info to object files
-h Print this help
-j Default characters are signed
-o name Name the output file
-s Print some statistics
-tx Set target system x
-v Verbose mode
-A Strict ANSI mode
-Cl Make local variables static
-Dsym[=defn] Define a symbol
-I path Set include directory
-O Optimize code
-Oi Optimize code, inline more code
-Or Enable register variables
-Os Inline some known functions
-T Include source as comment
-V Print version number
-W Suppress warnings
The -A option disables any compiler exensions. Have a look at section 5
for a discussion of compiler extensions. In addition, the macro
__STRICT_ANSI__
is defined, when compiling with -A.
-d enables debug mode, something that should not be needed for mere
mortals:-)
-g will cause the compiler to insert a .DEBUGINFO command into the
generated assembler code. This will cause the assembler to include all
symbols in a special section in the object file.
-h and -s print some statistics, nothing spectacular.
Using -j you can make the default characters signed. Since the 6502 has
no provisions for sign extending characters (which is needed on almost
any load operation), this will make the code larger and slower. A better
way is to declare characters explicitly as "signed" if needed. You can
also use "#pragma signedchars" for better control of this option (see
section 7).
The -t option is used to set the target system. The target system
determines things like the character set that is used for strings and
character constants. The following target systems are supported:
none
c64
c128
ace (no library support)
plus4
cbm610
pet (all CBM PET systems except the 2001)
nes (Nintendo Entertainment System)
apple2
geos
Using -v, the compiler will be somewhat more verbose if errors or warnings
are encountered.
-Cl will use static storage for local variables instead of storage on the
stack. Since the stack is emulated in software, this gives shorter and
usually faster code, but the code is no longer reentrant. The difference
between -Cl and declaring local variables as static yourself is, that
initializer code is executed each time, the function is entered. So when
using
void f (void)
{
unsigned a = 1;
...
}
the variable a will always have the value 1 when entering the function and
using -Cl, while in
void f (void)
{
static unsigned a = 1;
....
}
the variable a will have the value 1 only the first time, the function is
entered, and will keep the old value from one call of the function to the
next.
You may also use #pragma staticlocals to change this setting in your
sources (see section 7).
-I sets the directory where the compiler searches for include files. You
may use -I multiple times to add more than one directory to the search
list.
-O will enable an optimizer run over the produced code. Using -Oi, the
code generator will inline some code where otherwise a runtime functions
would have been called, even if the generated code is larger. This will
not only remove the overhead for a function call, but will make the code
visible for the optimizer.
-Or will make the compiler honor the "register" keyword. Local variables
may be placed in registers (which are actually zero page locations).
There is some overhead involved with register variables, since the old
contents of the registers must be saved and restored. In addition, the
current implementation does not make good use of register variables, so
using -Or may make your program even slower and larger. Use with care!
Using -Os will force the compiler to inline some known functions from the
C library like strlen. Note: This has two consequences:
* You may not use names of standard C functions in your own code. If
you do that, your program is not standard compliant anyway, but
using -Os will actually break things.
* The inlined string and memory functions will not handle strings or
memory areas larger than 255 bytes. Similar, the inlined is..()
functions will not work with values outside char range.
It is possible to concatenate the modifiers for -O. For example, to
enable register variables and inlining of known functions, you may use
-Ors.
-T will include the source code as comments in the generated code. This is
normally not needed.
-V prints the version number of the compiler. When submitting a bug
report, please include the operating system you're using, and the compiler
version.
The -W switch suppresses any warnings generated by the compiler. Since any
source file may be written in a manner that it will not produce compiler
warnings, using this option is usually not a good idea.
3. Input and output
-------------------
The compiler will accept one C file per invocation and create a file with
the same base name, but with the extension replaced by ".s". The output
file contains assembler code suitable for the use with the ca65 macro
assembler.
In addition to the paths named in the -I option on the command line, the
directory named in the environment variable CC65_INC is added to the
search path for include files on startup.
4. Differences to the ISO standard
----------------------------------
Here is a list of differences between the language, the compiler accepts,
and the one defined by the ISO standard:
* The compiler allows single line comments that start with //. This
feature is disabled in strict ANSI mode.
* The compiler allows unnamed parameters in parameter lists. The
compiler will not issue warnings about unused parameters that don't
have a name. This feature is disabled in strict ANSI mode.
* The compiler has some additional keywords:
asm, __asm__, fastcall, __fastcall__, __AX__, __EAX__, __func__
The keywords without the underlines are disabled in strict ANSI mode.
* The "const" modifier is available, but has no effect.
* The datatypes "float" and "double" are not available.
* The compiler does not support bit fields.
* Initialization of local variables is only possible for scalar data
types (that is, not for arrays and structs).
* Because of the "wrong" order of the parameters on the stack, there is
an additional macro needed to access parameters in a variable
parameter list in a C function.
* The compiler has only one symbol table. Because of that, it's not
possible to use the name of a local variable in a nested block in the
same function (global and local names are distinct, however).
+ The preprocessor does not understand the "defined" keyword in
expressions evaluated in #if statements.
* Functions may not return structs, struct assignment is not possible.
* The size of any struct referenced via a pointer may not exceed 256
bytes (this is because the Y register is used as index).
* In a function, the size of the parameters plus the size of all local
variables may not exceed 256 bytes (in fact, the limit may be even less
depeding on the complexity of your expressions).
* Part of the C library is available only with fastcall calling
conventions (see below). This means, that you may not mix pointers to
those functions with pointers to user written functions.
There may be some more minor differences, I'm currently not aware off. The
biggest problems are the missing const and float data types. With both
these things in mind, you should be able to write fairly portable code.
5. Extensions
-------------
This cc65 version has some extensions to the ISO C standard.
* The compiler allows // comments (like in C++ and in the proposed C9x
standard). This feature is disabled by -A.
* The compiler allows to insert assembler statements into the output
file. The syntax is
asm (<string literal>) ;
or
__asm__ (<string literal>) ;
The first form is in the user namespace and is disabled if the -A
switch is given.
The given string is inserted literally into the output file, and a
newline is appended. The statements in this string are not checked by
the compiler, so be careful!
The asm statement may be used inside a function and on global file
level.
* There is a special calling convention named "fastcall". This calling
convention is currently only usable for functions written in
assembler. The syntax for a function declaration using fastcall is
<return type> fastcall <function name> (<parameter list>)
or
<return type> __fastcall__ <function name> (<parameter list>)
An example would be
void __fastcall__ f (unsigned char c)
The first form of the fastcall keyword is in the user namespace and is
therefore disabled in strict ANSI mode.
For functions declared as fastcall, the rightmost parameter is not
pushed on the stack but left in the primary register when the function
is called. This will reduce the cost when calling assembler functions
significantly, especially when the function itself is rather small.
BEWARE: You must not declare C functions as fastcall! This will not
work for now and is not checked by the assembler, so you will get
wrong code.
* There are two pseudo variables named __AX__ and __EAX__. Both refer to
the primary register that is used by the compiler to evaluate
expressions or return function results. __AX__ is of type unsigned int
and __EAX__ of type long unsigned int respectively. The pseudo
variables may be used as lvalue and rvalue as every other variable.
They are most useful together with short sequences of assembler code.
For example, the macro
#define hi(x) (__AX__=(x),asm("\ttxa\n\tldx\t#$00",__AX__)
will give the high byte of any unsigned value.
* Inside a function, the identifier __func__ gives the name of the
current function as a string. Outside of functions, __func__ is
undefined.
Example:
#define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s);
The macro will print the name of the current function plus a given
string.
6. Predefined macros
--------------------
The compiler defines several macros at startup:
__CC65__ This macro is always defined. Its value is the version
number of the compiler in hex. Version 2.0.1 of the
compiler will have this macro defined as 0x0201.
__CBM__ This macro is defined if the target system is one of the
CBM targets.
__C64__ This macro is defined if the target is the c64 (-t c64).
__C128__ This macro is defined if the target is the c128 (-t c128).
__PLUS4__ This macro is defined if the target is the plus/4
(-t plus4).
__CBM610__ This macro is defined if the target is one of the CBM
600/700 family of computers (called B series in the US).
__PET__ This macro is defined if the target is the PET family of
computers (-t pet).
__NES__ This macro is defined if the target is the Nintendo
Entertainment System (-t nes).
__ATARI__ This macro is defined if the target is one of the Atari
computers (400/800/130XL/800XL). Note that there is no
runtime and C library support for atari systems.
__ACE__ This macro is defined if the target is Bruce Craigs ACE
operating system. Note that there is no longer runtime
and library support for ACE.
__APPLE2__ This macro is defined if the target is the Apple ][
(-t apple2).
__GEOS__ This macro is defined if you are compiling for the GEOS
system (-t geos).
__FILE__ This macro expands to a string containing the name of
the C source file.
__LINE__ This macro expands to the current line number.
__STRICT_ANSI__ This macro is defined to 1 if the -A compiler option was
given, and undefined otherwise.
__OPT__ Is defined if the compiler was called with the -O command
line option.
__OPT_i__ Is defined if the compiler was called with the -Oi command
line option.
__OPT_r__ Is defined if the compiler was called with the -Or command
line option.
__OPT_s__ Is defined if the compiler was called with the -Os command
line option.
7. #pragmas
-----------
The compiler understands some pragmas that may be used to change code
generation and other stuff.
#pragma bssseg (<name>)
This pragma changes the name used for the BSS segment (the BSS segment
is used to store uninitialized data). The argument is a string enclosed
in double quotes.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
Beware: The startup code will zero only the default BSS segment. If you
use another BSS segment, you have to do that yourself, otherwise
uninitialized variables do not have the value zero.
Example:
#pragma bssseg ("MyBSS")
#pragma codeseg (<name>)
This pragma changes the name used for the CODE segment (the CODE segment
is used to store executable code). The argument is a string enclosed in
double quotes.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
Example:
#pragma bssseg ("MyCODE")
#pragma dataseg (<name>)
This pragma changes the name used for the DATA segment (the DATA segment
is used to store initialized data). The argument is a string enclosed in
double quotes.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
Example:
#pragma bssseg ("MyDATA")
#pragma rodataseg (<name>)
This pragma changes the name used for the RODATA segment (the RODATA
segment is used to store readonly data). The argument is a string
enclosed in double quotes.
Note: The default linker configuration file does only map the standard
segments. If you use other segments, you have to create a new linker
configuration file.
Example:
#pragma bssseg ("MyRODATA")
#pragma regvaraddr (<const int>)
The compiler does not allow to take the address of register variables.
The regvaraddr pragma changes this. Taking the address of a register
variable is allowed after using this pragma, if the argument is not
zero. Using an argument of zero changes back to the default behaviour.
Beware: The C standard does not allow taking the address of a variable
declared as register. So your programs become non-portable if you use
this pragma. In addition, your program may not work. This is usually the
case if a subroutine is called with the address of a register variable,
and this subroutine (or a subroutine called from there) uses itself
register variables. So be careful with this #pragma.
Example:
#pragma regvaraddr(1) /* Allow taking the address
* of register variables
*/
#pragma signedchars (<const int>)
Changed the signedness of the default character type. If the argument
is not zero, default characters are signed, otherwise characters are
unsigned. The compiler default is to make characters unsigned since this
creates a lot better code.
#pragma staticlocals (<const int>)
Use variables in the bss segment instead of variables on the stack. This
pragma changes the default set by the compiler option -Cl. If the argument
is not zero, local variables are allocated in the BSS segment, leading to
shorter and in most cases faster, but non-reentrant code.
#pragma zpsym (<name>)
Tell the compiler that the - previously as external declared - symbol with
the given name is a zero page symbol (usually from an assembler file).
The compiler will create a matching import declaration for the assembler.
Example:
extern int foo;
#pragma zpsym ("foo"); /* foo is in the zeropage */
8. Bugs/Feedback
----------------
If you have problems using the compiler, if you find any bugs, or if
you're doing something interesting with the compiler, I would be glad to
hear from you. Feel free to contact me by email (uz@musoftware.de).
9. Copyright
------------
This is the original compiler copyright:
--------------------------------------------------------------------------
-*- Mode: Text -*-
This is the copyright notice for RA65, LINK65, LIBR65, and other
Atari 8-bit programs. Said programs are Copyright 1989, by John R.
Dunning. All rights reserved, with the following exceptions:
Anyone may copy or redistribute these programs, provided that:
1: You don't charge anything for the copy. It is permissable to
charge a nominal fee for media, etc.
2: All source code and documentation for the programs is made
available as part of the distribution.
3: This copyright notice is preserved verbatim, and included in
the distribution.
You are allowed to modify these programs, and redistribute the
modified versions, provided that the modifications are clearly noted.
There is NO WARRANTY with this software, it comes as is, and is
distributed in the hope that it may be useful.
This copyright notice applies to any program which contains
this text, or the refers to this file.
This copyright notice is based on the one published by the Free
Software Foundation, sometimes known as the GNU project. The idea
is the same as theirs, ie the software is free, and is intended to
stay that way. Everybody has the right to copy, modify, and re-
distribute this software. Nobody has the right to prevent anyone
else from copying, modifying or redistributing it.
--------------------------------------------------------------------------
In acknowledgment of this copyright, I will place my own changes to the
compiler under the same copyright. Please note however, that the library
and all binutils are covered by another copyright, and that I'm planning
to do a complete rewrite of the compiler, after which the compiler
copyright will also change.
For the list of changes requested by this copyright see newvers.txt.

183
doc/cl65.txt Normal file
View File

@@ -0,0 +1,183 @@
cl65
Compile and link utility for cc65
(C) Copyright 1999 Ullrich von Bassewitz
(uz@musoftware.de)
Contents
--------
1. Overview
2. Basic Usage
3. More usage
4. Examples
5. Bugs/Feedback
6. Copyright
1. Overview
-----------
cl65 is a frontend for cc65, ca65 and ld65. While you may not use the full
power of the tools when calling them through cl65, most features are
available, and the use of cl65 is much simpler.
2. Usage
--------
The cl65 compile and link utility may be used to compile, assemble and
link files. While the separate tools do just one step, cl65 knows how to
build object files from C files (by calling the compiler, then the
assembler) and other things.
Usage: cl65 [options] file
Options:
-A Strict ANSI mode
-C name Use linker config file
-D sym[=defn] Define a preprocessor symbol
-I path Set an include directory path
-Ln name Create a VICE label file
-O Optimize code
-Oi Optimize code, inline functions
-Or Optimize code, honour the register keyword
-Os Optimize code, inline known C funtions
-S Compile but don't assemble and link
-V Print the version number
-W Suppress warnings
-c Compiler and assemble but don't link
-d Debug mode
-g Add debug info
-h Help (this text)
-m name Create a map file
-o name Name the output file
-t system Set the target system
-v Verbose mode
-vm Verbose map file
Most of the options have the same meaning than the corresponding compiler,
assembler or linker option. If an option is available for more than one
of the tools, it is set for all tools, where it is available. One example
for this is -v: The compiler, the assembler and the linker are all called
with the -v switch.
There are a few remaining options that control the behaviour of cl65:
The -S option forces cl65 to stop after the assembly step. This means that
C files are translated into assembler files, but nothing more is done.
Assembler files, object files and libraries given on the command line are
ignored.
The -c options forces cl65 to stop after the assembly step. This means
that C and assembler files given on the command line are translated into
object files, but there is no link step, and object files and libraries
given on the command line are ignored.
The -o option is used for the target name in the final step. This causes
problems, if the linker will not be called, and there are several input
files on the command line. In this case, the name given with -o will be
used for all of them, which makes the option pretty useless. You shouldn't
use -o when more than one output file is created.
The default for the -t option is different from the compiler and linker in
the case that the option is missing: While the compiler and linker will
use the "none" system settings by default, cl65 will use the C64 as a
target system by default. This was choosen since most people seem to use
cc65 to develop for the C64.
3. More usage
-------------
Since cl65 was created to simplify the use of the cc65 development
package, it tries to be smart about several things.
- If you don't give a target system on the command line, cl65
defaults to the C64.
- When linking, cl65 will supply the names of the startup file and
library for the target system to the linker, so you don't have to do
that.
- If the final step is the linker, and the name of the output file was
not explicitly given, cl65 will use the name of the first input file
without the extension, provided that the name of this file has an
extension. So you don't need to name the executable name in most
cases, just give the name of your "main" file as first input file.
4. Examples
-----------
The morse trainer software, which consists of one C file (morse.c) and one
assembler file (irq.s) will need the following separate steps to compile
into an executable named morse:
cc65 -g -Oi -t c64 morse.c
ca65 -g morse.s
ca65 -g irq.s
ld65 -t c64 -o morse c64.o morse.o irq.o c64.lib
When using cl65, this is simplified to
cl65 -g -Oi morse.c irq.s
As a general rule, you may use cl65 instead of cc65 at most times,
especially in makefiles to build object files directly from C files. Use
.c.o:
cl65 -g -Oi $<
to do this.
5. Bugs/Feedback
----------------
If you have problems using the utility, if you find any bugs, or if you're
doing something interesting with it, I would be glad to hear from you.
Feel free to contact me by email (uz@musoftware.de).
6. Copyright
------------
cl65 is (C) Copyright 1998 Ullrich von Bassewitz. For usage of the
binaries and/or sources the following conditions do apply:
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.

340
doc/coding.txt Normal file
View File

@@ -0,0 +1,340 @@
How to generate the most effective code with cc65.
1. Use prototypes.
This will not only help to find errors between separate modules, it will
also generate better code, since the compiler must not assume that a
variable sized parameter list is in place and must not pass the argument
count to the called function. This will lead to shorter and faster code.
2. Don't declare auto variables in nested function blocks.
Variable declarations in nested blocks are usually a good thing. But with
cc65, there are several drawbacks:
a. The compiler has only one symbol table (there's no true nesting).
This means that your variables must not have the same names as
variables in the enclosing block.
b. Since the compiler generates code in one pass, it must create the
the variables on the stack each time the block is entered and destroy
them when the block is left. This causes a speed penalty and larger
code.
3. Remember that the compiler does not optimize.
The compiler needs hints from you about the code to generate. When
accessing indexed data structures, get a pointer to the element and
use this pointer instead of calculating the index again and again.
If you want to have your loops unrolled, or loop invariant code moved
outside the loop, you have to do that yourself.
4. Longs are slow!
While long support is necessary for some things, it's really, really slow
on the 6502. Remember that any long variable will use 4 bytes of memory,
and any operation works on double the data compared to an int.
5. Use unsigned types wherever possible.
The CPU has no opcodes to handle signed values greater than 8 bit. So
sign extension, test of signedness etc. has to be done by hand. The
code to handle signed operations is usually a bit slower than the same
code for unsigned types.
6. Use chars instead of ints if possible.
While in arithmetic operations, chars are immidiately promoted to ints,
they are passed as chars in parameter lists and are accessed as chars
in variables. The code generated is usually not much smaller, but it
is faster, since accessing chars is faster. For several operations, the
generated code may be better if intermediate results that are known not
to be larger than 8 bit are casted to chars.
When doing
unsigned char a;
...
if ((a & 0x0F) == 0)
the result of the & operator is an int because of the int promotion
rules of the language. So the compare is also done with 16 bits. When
using
unsigned char a;
...
if ((unsigned char)(a & 0x0F) == 0)
the generated code is much shorter, since the operation is done with
8 bits instead of 16.
7. Make the size of your array elements one of 1, 2, 4, 8.
When indexing into an array, the compiler has to calculate the byte
offset into the array, which is the index multiplied by the size of
one element. When doing the multiplication, the compiler will do a
strength reduction, that is, replace the multiplication by a shift
if possible. For the values 2, 4 and 8, there are even more specialized
subroutines available. So, array access is fastest when using one of
these sizes.
8. Expressions are evaluated from left to right.
Since cc65 is not building an explicit expression tree when parsing an
expression, constant subexpressions may not be detected and optimized
properly if you don't help. Look at this example:
#define OFFS 4
int i;
i = i + OFFS + 3;
The expression is parsed from left to right, that means, the compiler sees
'i', and puts it contents into the secondary register. Next is OFFS, which
is constant. The compiler emits code to add a constant to the secondary
register. Same thing again for the constant 3. So the code produced
contains a fetch of 'i', two additions of constants, and a store (into
'i'). Unfortunately, the compiler does not see, that "OFFS + 3" is a
constant for itself, since it does it's evaluation from left to right.
There are some ways to help the compiler to recognize expression like
this:
a. Write "i = OFFS + 3 + i;". Since the first and second operand are
constant, the compiler will evaluate them at compile time reducing the
code to a fetch, one addition (secondary + constant) and one store.
b. Write "i = i + (OFFS + 3)". When seeing the opening parenthesis, the
compiler will start a new expression evaluation for the stuff in the
braces, and since all operands in the subexpression are constant, it
will detect this and reduce the code to one fetch, one addition and
one store.
9. Case labels in a switch statments are checked in source order.
Labels that appear first in a switch statement are tested first. So,
if your switch statement contains labels that are selected most of
the time, put them first in your source code. This will speed up the
code.
10. Use the preincrement and predecrement operators.
The compiler is currently not smart enough to figure out, if the rvalue of
an increment is used or not. So it has to save and restore that value when
producing code for the postincrement and postdecrement operators, even if
this value is never used. To avoid the additional overhead, use the
preincrement and predecrement operators if you don't need the resulting
value. That means, use
...
++i;
...
instead of
...
i++;
...
11. Use constants to access absolute memory locations.
The compiler produces optimized code, if the value of a pointer is a
constant. So, to access direct memory locations, use
#define VDC_DATA 0xD601
*(char*)VDC_STATUS = 0x01;
That will be translated to
lda #$01
sta $D600
The constant value detection works also for struct pointers and arrays,
if the subscript is a constant. So
#define VDC ((unsigned char*)0xD600)
#define STATUS 0x01
VDC [STATUS] = 0x01;
will also work.
If you first load the constant into a variable and use that variable to
access an absolute memory location, the generated code will be much
slower, since the compiler does not know anything about the contents of
the variable.
12. Use initialized local variables - but use it with care.
Initialization of local variables when declaring them gives shorter
and faster code. So, use
int i = 1;
instead of
int i;
i = 1;
But beware: To maximize your savings, don't mix uninitialized and
initialized variables. Create one block of initialized variables and
one of uniniitalized ones. The reason for this is, that the compiler
will sum up the space needed for uninitialized variables as long as
possible, and then allocate the space once for all these variables.
If you mix uninitialized and initialized variables, you force the
compiler to allocate space for the uninitialized variables each time,
it parses an initialized one. So do this:
int i, j;
int a = 3;
int b = 0;
instead of
int i;
int a = 3;
int j;
int b = 0;
The latter will work, but will create larger and slower code.
13. When using the ?: operator, cast values that are not ints.
The result type of the ?: operator is a long, if one of the second or
third operands is a long. If the second operand has been evaluated and
it was of type int, and the compiler detects that the third operand is
a long, it has to add an additional int->long conversion for the
second operand. However, since the code for the second operand has
already been emitted, this gives much worse code.
Look at this:
long f (long a)
{
return (a != 0)? 1 : a;
}
When the compiler sees the literal "1", it does not know, that the
result type of the ?: operator is a long, so it will emit code to load
a integer constant 1. After parsing "a", which is a long, a int->long
conversion has to be applied to the second operand. This creates one
additional jump, and an additional code for the conversion.
A better way would have been to write:
long f (long a)
{
return (a != 0)? 1L : a;
}
By forcing the literal "1" to be of type long, the correct code is
created in the first place, and no additional conversion code is
needed.
14. Use the array operator [] even for pointers.
When addressing an array via a pointer, don't use the plus and
dereference operators, but the array operator. This will generate
better code in some common cases.
Don't use
char* a;
char b, c;
char b = *(a + c);
Use
char* a;
char b, c;
char b = a[c];
instead.
15. Use register variables with care.
Register variables may give faster and shorter code, but they do also
have an overhead. Register variables are actually zero page
locations, so using them saves roughly one cycle per access. Since
the old values have to be saved and restored, there is an overhead of
about 70 cycles per 2 byte variable. It is easy to see, that - apart
from the additional code that is needed to save and restore the
values - you need to make heavy use of a variable to justify the
overhead.
An exception are pointers, especially char pointers. The optimizer
has code to detect and transform the most common pointer operations
if the pointer variable is a register variable. Declaring heavily
used character pointers as register may give significant gains in
speed and size.
And remember: Register variables must be enabled with -Or.
16. Decimal constants greater than 0x7FFF are actually long ints
The language rules for constant numeric values specify that decimal
constants without a type suffix that are not in integer range must be
of type long int or unsigned long int. This means that a simple
constant like 40000 is of type long int, and may cause an expression
to be evaluated with 32 bits.
An example is:
unsigned val;
...
if (val < 65535) {
...
}
Here, the compare is evaluated using 32 bit precision. This makes the
code larger and a lot slower.
Using
unsigned val;
...
if (val < 0xFFFF) {
...
}
or
unsigned val;
...
if (val < 65535U) {
...
}
instead will give shorter and faster code.

159
doc/compile.txt Normal file
View File

@@ -0,0 +1,159 @@
Instructions for compiling cc65 and the ca65 binutils:
Linux (and probably most other Unices)
--------------------------------------
You need the GNU C compiler. Do a
make -f make/gcc.mak
twice(!) in each of the directories
cc65
binutils
After that, you need to compile the libraries. Do
cd lib
make clean c64lib
make clean c128lib
make clean plus4lib
make clean cbm610lib
make clean petlib
make clean apple2lib
Be sure to say "clean" each time, since some of the sources have a
"#ifdef <target_system>".
DOS using the DJGPP compiler
----------------------------
Most information in this section was provided by Keith W. Gerdes
(kwg@freebird.ghofn.org). Thanks a lot!
The tmpfile() function in DJGPP has a bug and will not open the scratch
file in binary mode. If you have problems with the archiver (which uses
the tmpfile() function), you have two choices:
1. Get a fix from http://www.cartsys.com/eldredge/djgpp-patches.html
and apply it. This will solve the problem once and forever.
2. For a temporary solution, in the file binutils/ar65/main.c, add the
following lines:
At top:
#include <fcntl.h>
At start of main:
_fmode = O_BINARY;
This will switch the default mode to binary and will work around the
bug.
Keith sent me the following notes how to build the tools on a DOS system
using DJGPP (add your system type to CFLAGS if needed):
-------------------------------------------------------------------------
Here's my current batch file:
cd cc65
if exist .depend goto ahead1
make -f make\gcc.mak
:ahead1
make -f make\gcc.mak
move *.exe ..\binutils
cd ..\cl65
if exist .depend goto ahead2
make -f make\gcc.mak
:ahead2
make -f make\gcc.mak
move *.exe ..\binutils
cd ..\binutils\common
if exist .depend goto ahead3
make -f make\gcc.mak
:ahead3
make -f make\gcc.mak
cd ..\ca65
if exist .depend goto ahead4
make -f make\gcc.mak
:ahead4
make -f make\gcc.mak
move *.exe ..
cd ..\ld65
if exist .depend goto ahead5
make -f make\gcc.mak
:ahead5
make -f make\gcc.mak
move *.exe ..
cd ..\ar65
if exist .depend goto ahead6
make -f make\gcc.mak
:ahead6
make -f make\gcc.mak
move *.exe ..
cd ..\..\lib\common
make 'CFLAGS=-Oi -I../../include/'
ar65 a common.lib *.o
move common.lib ..
cd ..\runtime
make 'CFLAGS=-Oi -I../../include/'
ar65 a runtime.lib *.o
move runtime.lib ..
--
In djgpp.env I use:
+LFN=Y
for the .depend file.
--
And in autoexec.bat I have:
set CC65_INC=E:\djgpp_v2\cc65\include
set CC65_LIB=E:\djgpp_v2\cc65\lib
PATH=E:\djgpp_v2\cc65\binutils;%PATH%
-------------------------------------------------------------------------
DOS, Windows, OS/2 using the Watcom Compiler
--------------------------------------------
This is what I'm using. You need the Borland make in addition to the
Watcom tools, or you have to change the makefile.
1. Copy %WATCOM%\src\startup\wildargv.c from your Watcom directory into
binutils\common.
2. Enter
make -f make\watcom.mak
in each of the directories
cc65
binutils
3. Use Linux to build the libraries:-) If you don't have Linux, get it
now! More serious: There is no makefile to build the libraries. Use a
batch file similar to the one above, or rewrite the makefile.

151
doc/debugging.txt Normal file
View File

@@ -0,0 +1,151 @@
Debugging your code using VICE
Ullrich von Bassewitz, March 1999
Contents
--------
1. Overview
2. What is VICE?
3. How to prepare your sources
4. How to use the label file
5. Problems and workarounds
1. Overview
-----------
This document describes how to debug your programs using the cc65
development tools and the VICE CBM emulator.
2. What is VICE?
----------------
VICE is an emulator for many of the CBM machines. It runs on Unix, DOS and
Windows 95. It emulates the Commodore 64, 128, VIC20, PET and the 600/700
machines. For more information see the VICE home page:
http://www.cs.cmu.edu/~dsladic/vice/vice.html
VICE has a builtin machine language monitor that may be used for debugging
your programs. Using an emulator for debugging has some advantages:
- Since you're using a crossassembler/-compiler anyway, you don't need
to transfer the program to the real machine until it is done.
- An emulator allows many things that are almost impossible one of the
original machines. You may set watchpoints (detect read or write
access to arbitary addresses), debug interrupt handlers and even debug
routines that run inside the 1541 floppy.
- You may use the label file generated by the linker to make much more
use from the monitor.
Please note that you need at least VICE version 0.16 for the label file
feature to work. This version has still some problems (see section 5 for
descriptions and some workarounds), but older versions had even more
problems and do NOT work correctly.
3. How to prepare your programs
-------------------------------
VICE support is mostly done via a label file that is generated by the
linker and that may be read by the VICE monitor, so it knows about your
program. Source level debugging is *not* available, you have to debug your
programs in the assembler view.
The first step is to generate object files that contain information about
ALL labels in your sources, not just the exported ones. This can be done
by several means:
- Use the -g switch on the assembler command line.
- Use the
.debuginfo +
command in your source.
- Use the -g switch when invoking the compiler. The compiler will then
put the .debuginfo command into the generated assembler source.
So, if you have just C code, all you need is to invoke the compiler with
-g. If you're using assembler code, you have to use -g for the assembler,
or add ".debuginfo +" to your source files. Since the generated debug info
is not appended to the generated executables, it is a good idea to always
use -g. It makes the object files and libraries slightly larger (~30%),
but this is usually not a problem.
The second step is to tell the linker that it should generate a VICE label
file. This is done by the -L switch followed by the name of the label file
(I'm usually using a .lbl extension for these files). An example for a
linker command line would be:
ld65 -t c64 -L hello.lbl -m hello.map -o hello crt0 hello.o c64.lib
This will generate a file named hello.lbl that contains all symbols used
in your program.
Note: The runtime libraries and startup files were generated with debug
info, so you don't have to care about this.
4. How to use the label file
----------------------------
Load your program, then enter the monitor and use the "pb" command to load
your label file like this:
pb "hello.lbl"
You will get lots of warnings and even a few errors. You may ignore safely
all these warnings and errors as long as they reference any problems VICE
thinks it has with the labels.
After loading the labels, they are used by VICE in the disassembler
listing, and you may use them whereever you need to specify an address.
Try
d ._main
as an example (note that VICE needs a leading dot before all labels, and
that the compiler prepends an underline under most named labels).
5. Problems and workarounds
---------------------------
Unfortunately, the VICE monitor has several problems with labels. However,
it is still tremendously useful, and I think that most problems are gone
in the next version. So, here is a list of the problems known to me as of
version 0.16.1:
* The "ll" command does not work. Worse, it seems that internal memory
gets corrupted when using this command, so VICE will crash after use.
Be sure to use the "pb" command to load the label file.
* VICE will crash if you use a label that is undefined. This is probably
the worst problem of all, since it needs just one typo to kill VICE.
So, watch your steps:-)
* Cheap labels, that is, labels starting with '@' or '?' are not
accepted.
* The disassembly output is somewhat suboptimal. However, most things are
just cosmetical, e.g. labels appended to the right side of the
disassembled code.

185
doc/internal.doc Normal file
View File

@@ -0,0 +1,185 @@
Internals doc for CC65
Stacks:
-------
The program stack used by programs compiled with CC65 is located in high
memory. The stack starts there and grows down. Arguments to functions, local
data etc are allocated on this stack, and deallocated when functions exit.
The program code and data is located in low memory. The heap is located
between the program code and the stack. The default size for the parameter
stack is 2K, you may change this by declaring an externally visible variable
named named _stksize that holds the new stack size:
unsigned _stksize = 4*1024; /* Use 4K stack */
Note: The size of the stack is only needed if you use the heap, or if you
call the stack checking routine (_stkcheck) from somewhere in your program.
When calling other functions, the return address goes on the normal 6502
stack, *not* on the parameter stack.
Registers:
----------
Since CC65 is a member of the Small-C family of compilers, it uses the notion
of a 'primary register'. In the CC65 implementation, I used the AX register
pair as the primary register. Just about everything interesting that the
library code does is done by somehow getting a value into AX, and then calling
some routine or other. In places where Small-C would use a secondary
register, top-of-stack is used, so for instance two argument function like
integer-multiply work by loading AX, pushing it on the stack, loading the
second value, and calling the internal function. The stack is popped, and the
result comes back in AX.
Calling sequences:
------------------
C functions are called by pushing their args on the stack, and JSR'ing to the
entry point. (See ex 1, below) If the function returns a value, it comes back
in AX. NOTE!!! A potentially significant difference between the CC65
environment and other C environments is that the CALLEE pops arguments, not
the CALLER. (This is done so as to generate more compact code) In normal use,
this doesn't cause any problems, as the normal function entry/exit conventions
take care of popping the right number of things off the stack, but you may
have to worry about it when doing things like writing hand-coded assembly
language routines that take variable numbers of arguments. More about that
later.
Ex 1: Function call: Assuming 'i' declared int and 'c' declared
char, the following C code
i = baz(i, c);
in absence of a prototype generates this assembler code. I've added
the comments.
lda _i ; get 'i', low byte
ldx _i+1 ; get 'i', hi byte
jsr pushax ; push it
lda _c ; get 'c'
ldx #0 ; fill hi byte with 0
jsr pushax ; push it
ldy #4 ; arg size
jsr _baz ; call the function
sta _i ; store the result
stx _i+1
In presence of a prototype, the picture changes slightly, since the
compiler is able to do some optimizations:
lda _i ; get 'i', low byte
ldx _i+1 ; get 'i', hi byte
jsr pushax ; push it
lda _c ; get 'c'
jsr pusha ; push it
jsr _baz ; call the function
sta _i ; store the result
stx _i+1
Note that the two words of arguments to baz were popped before it exitted.
The way baz could tell how much to pop was by the argument count in Y at call
time. Thus, even if baz had been called with 3 args instead of the 2 it was
expecting, that would not cause stack corruption.
There's another tricky part about all this, though. Note that the args to baz
are pushed in FORWARD order, ie the order they appear in the C statement.
That means that if you call a function with a different number of args than it
was expecting, they wont end up in the right places, ie if you call baz, as
above, with 3 args, it'll operate on the LAST two, not the first two.
Symbols:
--------
CC65 does the usual trick of prepending an underbar ('_') to symbol names when
compiling them into assembler. Therefore if you have a C function named
'bar', CC65 will define and refer to it as '_bar'.
Systems:
--------
Supported systems at this time are: C64, C128, Plus/4, CBM 600/700, the newer
PET machines (not 2001), and the Apple ][ (thanks to Kevin Ruland, who did the
port).
C64: The program runs in a memory configuration, where only the kernal ROM
is enabled. The text screen is expected at the usual place ($400), so
54K of memory are available to the program.
C128: The startup code will reprogram the MMU, so that only the kernal ROM
is enabled. This means, there are 41K of memory available to the
program.
Plus/4: Unfortunately, the Plus/4 is not able to disable only part of it's
ROM, it's an all or nothing approach. So, on the Plus/4, the program
has only 28K available (16K machines are detected and the amount of
free memory is reduced to 12K).
CBM 600/700:
The C program runs in a separate segment and has almost full 64K of
memory available.
PET: The startup code will adjust the upper memory limit to the installed
memory. However, only linear memory is used, this limits the top to
$8000, so on a 8032 or similar machine, 31K of memory are available to
the program.
APPLE2: The program starts at $800, and of RAM is $8E00, so 33.5K of memory
(including stack) are available.
Note: The above numbers do not mean that the remaining memory is unusable.
However, it is not linear memory and must be accessed by other, nonportable
methods. I'm thinking about a library extension that allows access to the
additional memory as a far heap, but these routines do not exist until now.
Inline Assembly:
----------------
CC65 allows inline assembly by a special keyword named "asm". Inline assembly
looks like a function call. The string in parenthesis is output in the
assembler file.
Example, insert a break instruction into the code:
asm ("\t.byte\t$00")
Note: The \t in the string is replaced by the tab character, as in all other
strings.
Pseudo variables:
-----------------
There are two special variables available named __AX__ and __EAX__. These
variables must never be declared (this gives an error), but may be used as any
other variable. However, accessing these variables will access the primary
register that is used by the compiler to evaluate expressions, return
functions results and pass parameters.
This feature is useful with inline assembly and macros. For example, a macro
that reads a CRTC register may be written like this:
#define wr(idx) (__AX__=(idx),asm("\tsta\t$2000\n\tlda\t$2000\n\tldx\t#$00"),__AX__)
An obvious problem here is that macro definitions may not use more than one
line.

206
doc/intro.txt Normal file
View File

@@ -0,0 +1,206 @@
How to use the cc65 C compiler
Ullrich von Bassewitz, 1998/1999
Contents
--------
1. Overview
2. The compiler
3. The assembler
4. The linker
5. The easy way (using the cl65 utility)
1. Overview
-----------
This is a short intro, how to use the compiler and the binutils. It
contains a step-by-step example, how to build a complete application from
one C and one assembler module. This file does *NOT* contain a complete
reference for the tools used in the process. There are separate files
describing these tools in detail.
Note: There is a much simpler way to compile this example using the cl65
compiler and link utility. However, it makes sense to understand how the
separate steps work. How to do the example with the cl65 utility is
described in section 5.
To explain the development flow, I will use the following example modules:
hello.c:
#include <stdio.h>
#include <stdlib.h>
extern const char text[]; /* In text.s */
int main (void)
{
printf ("%s\n", text);
return EXIT_SUCCESS;
}
text.s:
.export _text
_text: .asciiz "Hello world!"
We assume that the target file should be named "hello", and the target
system is the C64.
+---------+
| hello.c |
+---------+
|
cc65
\/
+---------+ +---------+
| hello.s | | text.s |
+---------+ +---------+
| |
ca65 ca65
\/ \/
+---------+ +---------+ +----------+ +---------+
| hello.o | | text.o | | c64.o | | c64.lib |
+---------+ +---------+ +----------+ +---------+
| \ / |
| \ / |
| \ / |
+----------------------->ld65<-------------------------+
\/
hello
c64.o (the startup code) and c64.lib (the c64 version of the runtime and C
library) are provided in binary form in the cc65 package.
2. The compiler
---------------
The compiler translates one C source into one assembler source for each
invocation. It does *NOT* create object files directly, and it is *NOT*
able to translate more than one file per run.
In the example above, we would use the following command line, to
translate hello.c into hello.s:
cc65 -O -I ../include -t c64 hello.c
The -O switch tells the compiler to do an additional optimizer run, which
is usually a good idea, since it makes the code smaller. If you don't care
about the size, but want to have slightly faster code, use -Oi to inline
some runtime functions.
The -I switch gives a search path for the include files. You may also set
the environment variable CC65_INC to the search path.
The -t switch is followed by the target system.
If the compiler does not complain about errors in our hello world, we will
have a file named "hello.s" in our directory that contains the assembler
source for the hello module.
For more information about the compiler see cc65.txt.
3. The assembler
----------------
The assembler translates one assembler source into an object file for each
invocation. The assembler is *NOT* able to translate more than one source
file per run.
Let's translate the hello.s and text.s files from our example:
ca65 hello.s
ca65 text.s
If the assembler does not complain, we should now have two object files
(named hello.o and text.o) in the current directory.
For more information about the assembler see ca65.txt.
4. The linker
-------------
The linker combines several object and library file into one output file.
ld65 is very configurable, but fortunately has a builtin configuration for
the C64, so we don't need to mess with configuration files here.
The compiler uses small functions to do things that cannot be done inline
without big impact on code size. These runtime functions, together with
the C library are in an object file archive named after the system, in
this case "c64.lib". We have to specify this file on the command line so
that the linker can resolve these functions.
A second file (this time an object file) needed, is the startup code that
prepares the grounds for the C program to run. The startup file must be
executed first, so it must be the first file on the linker command line.
Let's link our files to get the final executable:
ld65 -t c64 -o hello c64.o hello.o text.o c64.lib
The argument after -o specifies the name of the output file, the argument
after -t gives the target system. As discussed, the startup file must be the
first file on the command line (you may have to add a path here, if c64.o is
not in your current directory). Since the library resolves imports in hello.o
and text.o, it must be specified *after* these files.
After a successful linker run, we have a file named "hello", ready for our
C64!
For more information about the linker see ld65.txt.
5. The easy way (using the cl65 utility)
----------------------------------------
The cl65 utility is able to do all of the steps described above in just
one call, and it has defaults for some options that are very well suited
for our example.
To compile both files into one executable enter
cl65 -O -I ../include hello.c test.s
(The -I switch is not needed if you are working under Linux with the
include files in the default path, or the CC65_INC environment variable is
set correctly).
The cl65 utility knows, how to translate C files into object files (it
will call the compiler and then the assembler). It does also know how to
create object files from assembler files (it will call the assember for
that). It knows how to build an executable (it will pass all object files
to the linker). And, finally, it has the C64 as a default target and will
supply the correct startup file and runtime library names to the linker,
so you don't have to care about that.
The one-liner above should give you a C64 executable named "hello" in the
current directory.
For more information about the compile & link utility see cl65.txt.

655
doc/ld65.txt Normal file
View File

@@ -0,0 +1,655 @@
ld65
A Linker for ca65 Object modules
(C) Copyright 1998-1999 Ullrich von Bassewitz
(uz@musoftware.de)
Contents
--------
1. Overview
2. Usage
3. Detailed workings
4. Output configuration files
4.1 Introduction
4.2 Reference
4.3 Builtin configurations
5. Bugs/Feedback
6. Copyright
1. Overview
-----------
ld65 is a replacement for the link65 linker that was part of the cc65 C
compiler suite developed by John R. Dunning. link65 had some problems and
the copyright does not permit some things which I wanted to be possible,
so I decided to write a completely new assembler/linker/archiver suite
for the cc65 compiler. ld65 is part of this suite.
The ld65 linker combines several object modules, producing an executable
file. The object modules may be read from a library created by the ar65
archiver (this is somewhat faster and more convenient). The linker was
designed to be as flexible as possible. It complements the features that
are built into the ca65 macroassembler:
* Accept any number of segments to form an executable module.
* Resolve arbitrary expressions stored in the object files.
* In case of errors, use the meta information stored in the object
files to produce helpful error messages. In case of undefined
symbols, expression range errors, or symbol type mismatches, ld65 is
able to tell you the exact location in the source, where the symbol
was referenced.
* Flexible output. The output of ld65 is highly configurable by a
config file. More common platforms are supported by builtin
configurations that may be activated by naming the target system.
The output generation was designed with different output formats in
mind, so adding other formats shouldn't be a great problem.
2. Usage
--------
The linker is called as follows:
Usage: ld65 [options] module ...
Options are:
-m name Create a map file
-o name Name the default output file
-t type Type of target system
-v Verbose mode
-vm Verbose map file
-C name Use linker config file
-Ln name Create a VICE label file
-Lp Mark write protected segments as such (VICE)
-S addr Set the default start address
-V Print linker version
The -m switch (which needs an argument that will used as a filename for
the generated map file) will cause the linker to generate a map file. The
map file does contain a detailed overview over the modules used, the
sizes for the different segments, and a table containing exported
symbols.
The -o switch is used to give the name of the default output file.
Depending on your output configuration, this name may NOT be used as name
for the output file. However, for the builtin configurations, this name
is used for the output file name.
The argument for the -t switch is the name of the target system. Since
this switch will activate a builtin configuration, it may not be used
together with the -C option.
The following target systems are defined (* = currently unsupported):
none
atari
c64
c128
ace
plus4
cbm610
pet
nes
apple2
See section 4.3 for more information about the builtin configurations.
Using the -v option, you may enable more output that may help you to
locate problems. If an undefined symbol is encountered, -v causes the
linker to print a detailed list of the references (that is, source file
and line) for this symbol.
-C gives the name of an output config file to use. See section 4 for more
information about config files. -C may not be used together with -t.
-L allows you to create a file that contains all global labels and may be
loaded into VICE emulator using the pb (playback) command. You may use
this to debug your code with VICE. Note: The label feature is very new in
VICE and has some bugs. If you have problems, please get the latest VICE
version.
Using -S you may define the default starting address. If and how this
address is used depends on the config file in use. For the builtin
configurations, only the "none" system honors an explicit start address,
all other builtin config provide their own.
-V prints the version number of the linker. If you send any suggestions or
bugfixes, please include this number.
If one of the modules is not found in the current directory, and the
module name does not have a path component, the value of the environment
variable CC65_LIB is prepended to the name, and the linker tries to open
the module with this new name.
3. Detailed workings
--------------------
The linker does several things when combining object modules:
First, the command line is parsed from left to right. For each object file
encountered (object files are recognized by a magic word in the header, so
the linker does not care about the name), imported and exported
identifiers are read from the file and inserted in a table. If a library
name is given (libraries are also recognized by a magic word, there are no
special naming conventions), all modules in the library are checked if an
export from this module would satisfy an import from other modules. All
modules where this is the case are marked. If duplicate identifiers are
found, the linker issues a warning.
This procedure (parsing and reading from left to right) does mean, that a
library may only satisfy references for object modules (given directly or
from a library) named BEFORE that library. With the command line
ld65 crt0.o clib.lib test.o
the module test.o may not contain references to modules in the library
clib.lib. If this is the case, you have to change the order of the modules
on the command line:
ld65 crt0.o test.o clib.lib
Step two is, to read the configuration file, and assign start addresses
for the segments and define any linker symbols (see section 4).
After that, the linker is ready to produce an output file. Before doing
that, it checks it's data for consistency. That is, it checks for
unresolved externals (if the output format is not relocatable) and for
symbol type mismatches (for example a zero page symbol is imported by a
module as absolute symbol).
Step four is, to write the actual target files. In this step, the linker
will resolve any expressions contained in the segment data. Circular
references are also detected in this step (a symbol may have a circular
reference that goes unnoticed if the symbol is not used).
Step five is to output a map file with a detailed list of all modules,
segments and symbols encountered.
And, last step, if you give the -v switch twice, you get a dump of the
segment data. However, this may be quite unreadable if you're not a
developer:-)
4. Output configuration files
-----------------------------
Configuration files are used to describe the layout of the output file(s).
Two major topics are covered in a config file: The memory layout of the
target architecture, and the assignment of segments to memory areas. In
addition, several other attributes may be specified.
Case is ignored for keywords, that is, section or attribute names, but it
is NOT ignored for names and strings.
4.1 Introduction
----------------
Memory areas are specified in a "MEMORY" section. Lets have a look at an
example (this one describes the usable memory layout of the C64):
MEMORY {
RAM1: start = $0800, size = $9800;
ROM1: start = $A000, size = $2000;
RAM2: start = $C000, size = $1000;
ROM2: start = $E000, size = $2000;
}
As you can see, there are two ram areas and two rom areas. The names
(before the colon) are arbitrary names that must start with a letter, with
the remaining characters being letters or digits. The names of the memory
areas are used when assigning segments. As mentioned above, case is
significant for these names.
The syntax above is used in all sections of the config file. The name
("ROM1" etc.) is said to be an identifier, the remaining tokens up to the
semicolon specify attributes for this identifier. You may use the equal
sign to assign values to attributes, and you may use a comma to separate
attributes, you may also leave both out. But you MUST use a semicolon to
mark the end of the attributes for one identifier. The section above may
also have looked like this:
# Start of memory section
MEMORY
{
RAM1:
start $0800
size $9800;
ROM1:
start $A000
size $2000;
RAM2:
start $C000
size $1000;
ROM2:
start $E000
size $2000;
}
There are of course more attributes for a memory section than just start
and size. Start and size are mandatory attributes, that means, each memory
area defined MUST have these attributes given (the linker will check
that). I will cover other attributes later. As you may have noticed, I've
used a comment in the example above. Comments start with a hash mark
(`#'), the remainder of the line is ignored if this character is found.
Let's assume you have written a program for your trusty old C64, and you
would like to run it. For testing purposes, it should run in the RAM area.
So we will start to assign segments to memory sections in the SEGMENTS
section:
SEGMENTS {
CODE: load = RAM1, type = ro;
RODATA: load = RAM1, type = ro;
DATA: load = RAM1, type = rw;
BSS: load = RAM1, type = bss, define = yes;
}
What we are doing here is telling the linker, that all segments go into
the RAM1 memory area in the order specified in the SEGMENTS section. So
the linker will first write the CODE segment, then the RODATA segment,
then the DATA segment - but it will not write the BSS segment. Why? Enter
the segment type: For each segment specified, you may also specify a
segment attribute. There are five possible segment attributes:
ro means readonly
wprot same as ro but will be marked as write protected in
the VICE label file if -Lp is given
rw means read/write
bss means that this is an uninitialized segment
empty will not go in any output file
So, because we specified that the segment with the name BSS is of type
bss, the linker knows that this is uninitialized data, and will not write
it to an output file. This is an important point: For the assembler, the
BSS segment has no special meaning. You specify, which segments have the
bss attribute when linking. This approach is much more flexible than
having one fixed bss segment, and is a result of the design decision to
supporting an arbitrary segment count.
If you specify "type = bss" for a segment, the linker will make sure that
this segment does only contain uninitialized data (that is, zeroes), and
issue a warning if this is not the case.
For a bss type segment to be useful, it must be cleared somehow by your
program (this happens usually in the startup code - for example the
startup code for cc65 generated programs takes care about that). But how
does your code know, where the segment starts, and how big it is? The
linker is able to give that information, but you must request it. This is,
what we're doing with the "define = yes" attribute in the BSS definitions.
For each segment, where this attribute is true, the linker will export
three symbols.
__NAME_LOAD__ This is set to the address where the segment is
loaded.
__NAME_RUN__ This is set to the run address of the segment.
We will cover run addresses later.
__NAME_SIZE__ This is set to the segment size.
Replace "NAME" by the name of the segment, in the example above, this
would be "BSS". These symbols may be accessed by your code.
Now, as we've configured the linker to write the first three segments and
create symbols for the last one, there's only one question left: Where
does the linker put the data? It would be very convenient to have the data
in a file, wouldn't it?
We don't have any files specified above, and indeed, this is not needed in
a simple configuration like the one above. There is an additional
attribute "file" that may be specified for a memory area, that gives a
file name to write the area data into. If there is no file name given, the
linker will assign the default file name. This is "a.out" or the one given
with the -o option on the command line. Since the default behaviour is ok
for our purposes, I did not use the attribute in the example above. Let's
have a look at it now.
The "file" attribute (the keyword may also be written as "FILE" if you
like that better) takes a string enclosed in double quotes (`"') that
specifies the file, where the data is written. You may specifiy the same
file several times, in that case the data for all memory areas having this
file name is written into this file, in the order of the memory areas
defined in the MEMORY section. Let's specify some file names in the MEMORY
section used above:
MEMORY {
RAM1: start = $0800, size = $9800, file = %O;
ROM1: start = $A000, size = $2000, file = "rom1.bin";
RAM2: start = $C000, size = $1000, file = %O;
ROM2: start = $E000, size = $2000, file = "rom2.bin";
}
The %O used here is a way to specify the default behaviour explicitly: %O
is replaced by a string (including the quotes) that contains the default
output name, that is, "a.out" or the name specified with the -o option on
the command line. Into this file, the linker will first write any segments
that go into RAM1, and will append then the segments for RAM2, because the
memory areas are given in this order. So, for the RAM areas, nothing has
really changed.
We've not used the ROM areas, but we will do that below, so we give the
file names here. Segments that go into ROM1 will be written to a file
named "rom1.bin", and segments that go into ROM2 will be written to a file
named "rom2.bin". The name given on the command line is ignored in both
cases.
Let us look now at a more complex example. Say, you've successfully tested
your new "Super Operating System" (SOS for short) for the C64, and you
will now go and replace the ROMs by your own code. When doing that, you
face a new problem: If the code runs in RAM, we need not to care about
read/write data. But now, if the code is in ROM, we must care about it.
Remember the default segments (you may of course specify your own):
CODE read only code
RODATA read only data
DATA read/write data
BSS uninitialized data, read/write
Since the BSS is not initialized, we must not care about it now, but what
about DATA? DATA contains initialized data, that is, data that was
explicitly assigned a value. And your program will rely on these values on
startup. Since there's no other way to remember the contents of the data
segment, than storing it into one of the ROMs, we have to put it there.
But unfortunately, ROM is not writeable, so we have to copy it into RAM
before running the actual code.
The linker cannot help you copying the data from ROM into RAM (this must
be done by the startup code of your program), but it has some features
that will help you in this process.
First, you may not only specify a "load" attribute for a segment, but also
a "run" attribute. The "load" attribute is mandatory, and, if you don't
specify a "run" attribute, the linker assumes that load area and run area
are the same. We will use this feature for our data area:
SEGMENTS {
CODE: load = ROM1, type = ro;
RODATA: load = ROM2, type = ro;
DATA: load = ROM2, run = RAM2, type = rw, define = yes;
BSS: load = RAM2, type = bss, define = yes;
}
Let's have a closer look at this SEGMENTS section. We specify that the
CODE segment goes into ROM1 (the one at $A000). The readonly data goes
into ROM2. Read/write data will be loaded into ROM2 but is run in RAM2.
That means that all references to labels in the DATA segment are relocated
to be in RAM2, but the segment is written to ROM2. All your startup code
has to do is, to copy the data from it's location in ROM2 to the final
location in RAM2.
So, how do you know, where the data is located? This is the second point,
where you get help from the linker. Remember the "define" attribute? Since
we have set this attribute to true, the linker will define three external
symbols for the data segment that may be accessed from your code:
__DATA_LOAD__ This is set to the address where the segment is
loaded, in this case, it is an address in ROM2.
__DATA_RUN__ This is set to the run address of the segment, in
this case, it is an address in RAM2.
__DATA_SIZE__ This is set to the segment size.
So, what your startup code must do, is to copy __DATA_SIZE__ bytes from
__DATA_LOAD__ to __DATA_RUN__ before any other routines are called. All
references to labels in the DATA segment are relocated to RAM2 by the
linker, so things will work properly.
There are some other attributes not covered above. Before starting the
reference section, I will discuss the remaining things here.
You may request symbols definitions also for memory areas. This may be
useful for things like a software stack, or an i/o area.
MEMORY {
STACK: start = $C000, size = $1000, define = yes;
}
This will define three external symbols that may be used in your code:
__STACK_START__ This is set to the start of the memory
area, $C000 in this example.
__STACK_SIZE__ The size of the area, here $1000.
__STACK_LAST__ This is NOT the same as START+SIZE.
Instead, it it defined as the first
address that is not used by data. If we
don't define any segments for this area,
the value will be the same as START.
A memory section may also have a type. Valid types are
ro for readonly memory
and rw for read/write memory.
The linker will assure, that no segment marked as read/write or bss is put
into a memory area that is marked as readonly.
Unused memory in a memory area may be filled. Use the "fill = yes"
attribute to request this. The default value to fill unused space is zero.
If you don't like this, you may specify a byte value that is used to fill
these areas with the "fillval" attribute. This value is also used to fill
unfilled areas generated by the assemblers .ALIGN and .RES directives.
Segments may be aligned to some memory boundary. Specify "align = num" to
request this feature. Num must be a power of two. To align all segments on
a page boundary, use
SEGMENTS {
CODE: load = ROM1, type = ro, align = $100;
RODATA: load = ROM2, type = ro, align = $100;
DATA: load = ROM2, run = RAM2, type = rw, define = yes,
align = $100;
BSS: load = RAM2, type = bss, define = yes, align = $100;
}
If an alignment is requested, the linker will add enough space to the
output file, so that the new segment starts at an address that is
divideable by the given number without a remainder. All addresses are
adjusted accordingly. To fill the unused space, bytes of zero are used,
or, if the memory area has a "fillval" attribute, that value. Alignment is
always needed, if you have the used the .ALIGN command in the assembler.
The alignment of a segment must be equal or greater than the alignment
used in the .ALIGN command. The linker will check that, and issue a
warning, if the alignment of a segment is lower than the alignment
requested in a .ALIGN command of one of the modules making up this
segment.
For a given segment you may also specify a fixed offset into a memory area or
a fixed start address. Use this if you want the code to run at a specific
address (a prominent case is the interrupt vector table which must go at
address $FFFA). Only one of ALIGN or OFFSET or START may be specified. If the
directive creates empty space, it will be filled with zero, of with the value
specified with the "fillval" attribute if one is given. The linker will warn
you if it is not possible to put the code at the specified offset (this may
happen if other segments in this area are too large). Here's an example:
SEGMENTS {
VECTORS: load = ROM2, type = ro, start = $FFFA;
}
or (for the segment definitions from above)
SEGMENTS {
VECTORS: load = ROM2, type = ro, offset = $1FFA;
}
File names may be empty, data from segments assigned to a memory area with
an empty file name is discarded. This is useful, if the a memory area has
segments assigned that are empty (for example because they are of type
bss). In that case, the linker will create an empty output file. This may
be suppressed by assigning an empty file name to that memory area.
The symbol %S may be used to access the default start address (that is,
$200 or the value given on the command line with the -S option).
4.2 Reference
-------------
4.3 Builtin configurations
--------------------------
Here is a list of the builin configurations for the different target
types:
none:
MEMORY {
RAM: start = %S, size = $10000, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = rw;
RODATA: load = RAM, type = rw;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
atari:
(non-existent)
c64:
MEMORY {
RAM: start = $7FF, size = $c801, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
c128:
MEMORY {
RAM: start = $1bff, size = $a401, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
ace:
(non-existent)
plus4:
MEMORY {
RAM: start = $0fff, size = $7001, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
cbm610:
MEMORY {
RAM: start = $0001, size = $FFF0, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
pet:
MEMORY {
RAM: start = $03FF, size = $7BFF, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
nes:
MEMORY {
RAM: start = $0200, size = $0600, file = "";
ROM: start = $8000, size = $8000, file = %O;
}
SEGMENTS {
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
DATA: load = ROM, run = RAM, type = rw, define = yes;
BSS: load = RAM, type = bss, define = yes;
VECTORS: load = ROM, type = ro, start = $FFFA;
}
apple2:
MEMORY {
RAM: start = $800, size = $8E00, file = %O;
}
SEGMENTS {
CODE: load = RAM, type = ro;
RODATA: load = RAM, type = ro;
DATA: load = RAM, type = rw;
BSS: load = RAM, type = bss, define = yes;
}
The "start" attribute for the RAM memory area of the CBM systems is two
less than the actual start of the basic RAM to account for the two bytes
load address that is needed on disk and supplied by the startup code.
5. Bugs/Feedback
----------------
If you have problems using the linker, if you find any bugs, or if you're
doing something interesting with it, I would be glad to hear from you.
Feel free to contact me by email (uz@musoftware.de).
6. Copyright
------------
ld65 (and all cc65 binutils) are (C) Copyright 1998 Ullrich von Bassewitz.
For usage of the binaries and/or sources the following conditions do
apply:
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.

235
doc/library.txt Normal file
View File

@@ -0,0 +1,235 @@
Description of the C library for the cc65 C compiler
(C) Copyright 1998-1999 Ullrich von Bassewitz
(uz@musoftware.de)
Contents
--------
1. Overview
2. ISO C compatible library
3. CPU specific stuff - 6502.h
4. System specific stuff
5. Direct console I/O - conio.h
6. Using the joystick - joystick.h
7. Bugs/Feedback
8. Copyright
1. Overview
-----------
This file contains a description of the library routines available for the
cc65 C compiler. It is not complete in some areas, so if you miss
something, have a look into the header files. All functions, that are not
defined by the ISO C standard have a short comment in the headers,
explaining their use.
2. ISO C compatible library
---------------------------
The C library contains a large subset of the ISO C library. Functions are
usually missing in areas, where there is no support on typical 6502
systems. Wide character sets are an example for this.
I will not go into detail about the ISO functions. If a function is not
mentioned here explicitly, expect it to be available and to behave as
defined in the C standard.
Functions that are NOT available:
* ftell/fseek/fgetpos/fsetpos
* tmpfile/tmpnam
* The scanf family of functions
* time/asctime/ctime/difftime/asctime/gmtime/localtime/mktime/strftime
* system
* All functions that handle floating point numbers in some manner.
* The div and ldiv functions (because cc65 is not able to return
structs).
* All functions handling wide character strings.
* Signals and all related functions (having SIGSEGV would be cool:-)
* rename/remove/rewind
* setbuf/setvbuf/ungetc
Functions that are limited in any way:
* fopen/fread/fwrite/fclose/fputs/fgets/fscanf....
These functions are built on open/read/write/close. Neither of these
low level functions is currently available for the supported systems,
and so, fopen and friends do not work. However, the functions exist
and are tested to some degree under the ACE operating systems (which
is no longer supported).
* The va_... family of macros
The macros do not work completely as defined by the standard. Since cc65
has the wrong calling order, the (non-standard) va_fix macro must be used
to access fixed parameters in functions with a variable parameter size.
See newvers.txt for a discussion of the problem.
* The character classification functions (is...)
These functions have unexpected results when called with arguments that
are not really chars (are outside the 0..255 range).
* The strerror function
The function will return "error #n" where n is the error number.
* strcspn/strpbrk/strspn
These functions have a length limitation of 256 for the second string
argument. Since this string gives a character set, and there are only 256
distinct characters, this shouldn't be a problem.
* Since there is no such thing as an environment on all supported
systems, the getenv function will always return a NULL pointer.
* There is no other locale than the "C" locale. The native locale is
identical to the "C" locale.
3. CPU specific stuff - 6502.h
------------------------------
The header file 6502.h contains some functions that make only sense with
the 6502 CPU. Examples are macros to insert more or less useful
instructions into your C code, or a function to call arbitrary machine
language subroutines, passing registers in and out.
4. System specific stuff
------------------------
For each supported system there's a header file that contains calls or
defines specific for this system. So, when programming for the C64,
include c64.h, for the C128, include c128.h and so on. To make the task
for the Commodore systems easier, there is also a header file named cbm.h
that will define stuff common for all CBM systems, and include the header
file for the specific target system.
The header files contain
* Defines for special keys (like function keys)
* Defines for special characters (like the graphics characters)
* Variables with a fixed address in memory that may be used to access
special hardware. For the C64 and C128 there is a variable struct
named "sid". Writing to the fields of this struct will write to the
SID device instead. Using these variables will make your program more
readable and more portable. Don't fear ineffective code when using
these variables, the compiler will translate reads and writes to these
structs into direct memory accesses.
* Other routines that make only sense for a specific system. One example
are routines to write memory locations in the system bank for the CBM
600/700 family (called B128/B256 in the US).
5. Direct console I/O - conio.h
-------------------------------
The conio header file contains a large set of functions that do screen and
keyboard I/O. The functions will write directly to the screen or poll the
keyboard directly with no more help from the operating system than needed.
This has some disadvantages, but on the other side it's fast and
reasonably portable. conio implementations exist for the following
targets:
c64
c128
plus/4
cbm610 (that is, the complete 600/700 series)
pet (all PETs except the 2001)
apple 2
The conio.h header file does also include the system specific header files
which define constants for special characters and keys.
6. Using the joystick - joystick.h
----------------------------------
For systems that have a joystick, joystick.h will define a subroutine to
read the current value, including constants to evaluate the result of this
function. To help in writing portable code, the header file will define
the symbol __JOYSTICK__ on systems that have a joystick.
7. Bugs/Feedback
----------------
If you have problems using the library, if you find any bugs, or if you've
written some extensions or otherwise interesting programs, I would be glad
to hear from you. Feel free to contact me by email (uz@musoftware.de).
8. Copyright
------------
This C runtime library implementation for the cc65 compiler is (C)
Copyright 1998-1999 Ullrich von Bassewitz. For usage of the binaries
and/or sources the following conditions do apply:
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.

511
doc/newvers.txt Normal file
View File

@@ -0,0 +1,511 @@
This document is slightly outdated! See cc65.txt and library.txt for a more
up-to-date discussion.
Discussion of some of the features/non features of the current cc65 version
---------------------------------------------------------------------------
1. Copyright
2. Differences to the original version
3. Known bugs and limitations
4. Library
5. Bugs
1. Copyright
-----------
This is the original compiler copyright:
--------------------------------------------------------------------------
-*- Mode: Text -*-
This is the copyright notice for RA65, LINK65, LIBR65, and other
Atari 8-bit programs. Said programs are Copyright 1989, by John R.
Dunning. All rights reserved, with the following exceptions:
Anyone may copy or redistribute these programs, provided that:
1: You don't charge anything for the copy. It is permissable to
charge a nominal fee for media, etc.
2: All source code and documentation for the programs is made
available as part of the distribution.
3: This copyright notice is preserved verbatim, and included in
the distribution.
You are allowed to modify these programs, and redistribute the
modified versions, provided that the modifications are clearly noted.
There is NO WARRANTY with this software, it comes as is, and is
distributed in the hope that it may be useful.
This copyright notice applies to any program which contains
this text, or the refers to this file.
This copyright notice is based on the one published by the Free
Software Foundation, sometimes known as the GNU project. The idea
is the same as theirs, ie the software is free, and is intended to
stay that way. Everybody has the right to copy, modify, and re-
distribute this software. Nobody has the right to prevent anyone
else from copying, modifying or redistributing it.
--------------------------------------------------------------------------
In acknowledgment of this copyright, I will place my own changes to the
compiler under the same copyright.
However, since the library and all binutils (assembler, archiver, linker)
are a complete rewrite, they are covered by another copyright:
--------------------------------------------------------------------------
CC65 C Library and Binutils
(C) Copyright 1998 Ullrich von Bassewitz
COPYING CONDITIONS
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
--------------------------------------------------------------------------
I will try to contact John, maybe he is also willing to place his sources
under a less restrictive copyright, after all these years:-)
2. Differences to the original version
--------------------------------------
This is a list of changes against the cc65 archives. I got the originals
from:
http://www.umich.edu/~archive/atari/8bit/Languages/Cc65/
* Removed all assembler code from the compiler. It was unportable because
it made assumptions about the character set (ATASCII) and made the
sources hard to read and to debug.
* All programs do return an error code, so they may be used by make. All
programs try to remove the target file, if there were errors.
* The assembler now checks several error conditions (others still go
undetected - see "known bugs").
* Removed many bugs from the compiler. One error was invalid code
produced by the compiler that went through the assembler since the
assembler did not check for ranges itself.
* Removed many non-portable constructs from the compiler. Code cleanups,
rewrite of the function headers and more.
* New style function prototypes supported instead of the old K&R syntax.
The new syntax is a must, that is, the old style syntax is no longer
understood. As an extension, unnamed parameters may be used to avoid
warnings about unused parameters.
* New void type. May also be used as a function return type.
* Changed the memory management in the compiler. Use malloc/free instead
of the old homebrew (and unportable) stuff.
* Default character type is unsigned. This is much more what you want in
small systems environments, since a char is often used to represent a
small numerical value, and the integer promotion does the wrong thing
in those cases. Look at the follwing piece of code:
char c = read_char ();
switch (c) {
case 0x80: printf ("c is 0x80\n"); break;
default: printf ("c is something else\n"); break;
}
With signed chars, the code above, will *always* run into the default
selector. c is promoted to int, and since it is signed, 0x80 will get
promoted to 0xFF80 - which will select the default label. With unsigned
chars, the code works as intended (but note: the code works for cc65
but it is non portable anyway, since many other compilers have signed
chars by default, so be careful! Having unsigned chars is just a
convenience thing).
* Shorter code when using the builtin operators and the lhs of an expr
is a constant (e.g. expressions like "c == 0x80" are encoded two
bytes shorter).
* Some optimizations when pushing constants.
* Character set translation by the compiler. A new -t option was added
to set the target system type. Use
-t0 For no spefic target system (default)
-t1 For the atari (does not work completely, since I did not
have an ATASCII translation table).
-t2 Target system is C64.
-t3 Target system is C128.
-t4 Target system is ACE.
-t5 Target system is Plus/5.
* Dito for the linker: Allow an option to set the target system and add
code to the linker to produce different headers and set the correct
start address.
* Complete rewrite of the C library. See extra chapter.
* Many changes in the runtime library. Splitted it into more than one
file to allow for smaller executables if not all of the code is needed.
* Allow longer names. Now the first 12 characters are sigificant at the
expense of some more memory used at runtime.
* String constants are now concatenated in all places. This allows
things like:
fputs ("Options:\n"
" -b bomb computer\n"
" -f format hard disk\n"
" -k kill init\n",
stderr);
saving code for more than one call to the function.
* Several new macros are defined:
M6502 This one is old - don't use!
__CC65__ Use this instead. Defined when compiling with cc65.
__ATARI__ Defined when the target system is atari.
__CBM__ Defined when compiling for a CBM system as target.
__C64__ Defined when the C64 is the target system.
__C128__ Defined when compiling for the 128.
__ACE__ Defined when compiling for ACE.
__PLUS4__ Defined when compiling for the Plus/4.
The __CC65__ macro has the compiler version as its value, version
1.0 of the compiler will define this macro as 0x100.
* The -a option is gone.
* The compiler will generate external references (via .globl) only if a
function is defined as extern in a module, or not defined but called
from a module. The old behaviour was to generate a reference for every
function prototype ever seen, which meant that using a header file like
stdio.h got most of the C library linked in, even if it was never used.
* Many new warnings added (about unused parameters, unused variables,
compares of unsigneds against zero, function call without prototype
and much more).
* Added a new compiler option (-W) to suppress all warnings.
* New internal variable __fixargs__ that gives the size of fixed
arguments, a function takes. This allows to work (somehow) around the
problem, that cc65 has the "wrong" (that is, pascal) calling order. See
below ("Known problems") for a discussion.
* The "empty" preprocessor directive ("#" on a line) is now ignored.
* Added a "#error" directive to force user errors.
* Optimization of the code generation. Constant parts of expressions are
now detected in many places where the old compiler evaluated the
constants at runtime.
* Allow local static variables (there was code in the original compiler for
that, but it did not work). Allow also initialization in this case (no
code for that in the original). Local static variables in the top level
function block have no penalty, for static variables in nested blocks, the
compiler generates a jump around the variable space. To eliminate this,
an assembler/linker with support for segments is needed.
* You cannot return a value from a void function, and must return a value
in a non-void function. Violations are flagged as an error.
* Typedefs added.
* The nonstandard evaluation of the NOARGC and FIXARGC macros has been
replaced by a smart algorithm that does the same thing automagically
and without user help (provided there are function prototypes).
* Function pointers may now be used to call a function without
dereferencing. Given a function
void f1 (void (*f2) ())
the following was valid before:
(*f2) ();
The ANSI standard allows a second form (because there's no ambiguity)
which is now also allowed:
f2 ();
* Pointer subtraction was completely messed up and did not work (that is,
subtraction of a pointer from a pointer produced wrong results).
* Local struct definitions are allowed.
* Check types in assignments, parameters for function calls and more.
* A new long type (32 bit) is available. The integer promotion rules
are applied if needed. This includes much more type checking and a
better handling of chars (they are handled as chars, not as ints, in
all places where this is possible).
* Integer constants now have an associated type, 'U' and 'L' modifers
may be used.
* The old #asm statement is gone. Instead, there's now a asm ("xxx")
statement that has the syntax that is defined by the C++ standard
(the C standard does not define an ASM statement). The string literal
in parenthesis is inserted in the assembler output. You may also
use __asm__ instead of asm (see below).
* Allow // comments.
* New compiler option -A (ANSI) that disables several extensions (asm
directive, // comments, unnamed function parameters) and also defines
a macro named __STRICT_ANSI__. The header files will exclude some
non-ANSI functions if __STRICT_ANSI__ is defined (that is, -A is given
on the command line).
-A will not disable the __asm__ directive (identifiers starting with
__ are in the namespace of the implementation).
* Create optimized code if the address of a variable is a constant. This
may be achieved by constructs like "*(char*)0x200 = 0x01" and is used
to access absolute memory locations. The compiler detects this case
also if structs or arrays are involved and generates direct stores and
fetches.
3. Known problems
-----------------
* No floats.
* Only simple automatic variables may be initialized (no arrays).
* "Wrong" order of arguments on the stack. The arguments are pushed in
the order, the arguments are parsed. That means that the va_xxx macros
in stdarg.h are ok (they work as expected), but the fixed parameters of
a function with a variable argument list do not match and must be
determined with the (non-standard) va_fix macro.
Using the __fixargs__ kludge, it is possible to write standard conform
va_xxx macros to work with variable sized argument lists. However, the
fixed parameters in the function itself usually have the wrong values,
because the order of the arguments on the stack is reversed compared to
a stock C compiler. Pushing the args the other way round requires much
work and a more elaborated intermediate code than cc65 has.
To understand the problem, have a look at this (non working!) sprintf
function:
int sprintf (char* buf, char* format, ...)
/* Non working version */
{
int count;
va_list ap;
va_start (ap, format);
count = vsprintf (buf, format, ap);
va_end (ap);
return count;
}
The problem here is in the "format" and "buf" parameters. They do (in
most cases) not contain, what the caller gave us as arguments. To
access the "real" arguments, use the va_fix macro. It is only valid
before the first call to va_arg, and takes the va_list and the number
of the fixed argument as parameters. So the right way would be
int sprintf (char* buf, char* format, ...)
/* Working version */
{
int count;
va_list ap;
va_start (ap, format);
count = vsprintf (va_fix (ap, 1), va_fix (ap, 2), ap);
va_end (ap);
return count;
}
The fixed parameter are obtained by using the va_fix macro with the
number of the parameter given as second argument. Beware: Since the
fixed arguments declared are usually one of the additional parameters,
the following code, which tries to be somewhat portable, does *not*
work. The assignment will overwrite the other parameters instead,
causing unexpected results:
int sprintf (char* buf, char* format, ...)
/* Non working version */
{
int count;
va_list ap;
va_start (ap, format);
#ifdef __CC65__
buf = va_fix (ap, 1);
format = va_fix (ap, 2);
#endif
count = vsprintf (buf, format, ap);
va_end (ap);
return count;
}
To write a portable version of sprintf, use code like this instead:
int sprintf (char* buf, char* format, ...)
/* Working version */
{
int count;
va_list ap;
va_start (ap, format);
#ifdef __CC65__
count = vsprintf (va_fix (ap, 1), va_fix (ap, 2), ap);
#else
count = vsprintf (buf, format, ap);
#endif
va_end (ap);
return count;
}
I know, va_fix is a kludge, but at least it *is* possible to write
functions with variable sized argument lists in a comfortable manner.
* The assembler still accepts lots of illegal stuff without an error (and
creates wrong code). Be careful!
* When starting a compiled program twice on the C64 (or 128), you may get
other results or the program may even crash. This is because static
variables do not have their startup values, they were changed in the
first run.
* There's only *one* symbol table level. It is - via a flag - used for both,
locals and global symbols. However, if you have variables in nested
blocks, the names may collide with the ones in the upper block. I will
probably add real symbol tables some time to remove this problem.
* Variables in nested blocks are handled inefficiently, especially in loops.
The frame on the stack is allocated and deallocated for each loop
iteration. There's no way around this, since the compiler has not enough
memory to hold a complete function body in memory (it would be able to
backpatch the frame generating code on function entry).
4. Library
----------
The C library is a complete rewrite and has nothing in common with the old
Atari stuff. When rewriting the library, I was guided by the following
rules:
* Use standard conform functions as far as possible. In addition, if
there's a ANSI-C compatible function, it should act as defined in the
ANSI standard. If if does not act as defined, this is an error.
* Do not use non-standard functions if the functionality of those
functions is covered by a standard function. Use exceptions only, if
there is a non-ANSI function that is very popular (example: itoa).
* Use new style prototpyes and header files.
* Make the library portable. For example, the complete stdio stuff is
based on only four system dependent functions:
open, read, write, close
So, if you rewrite these functions for a new system, all others
(printf, fprintf, fgets, fputc ...) will work, too.
* Do not expect a common character set. Unfortunately, I was not able to
be completely consequent in this respect. C sources are no problem
since the compiler does character translation, but the assembler
sources make assumptions about the following characters:
0 --> code $30
+ --> code $2B
- --> code $2D
All other functions (especially the isxxx ones) are table driven, so
only the classification table is system dependent.
The first port was for the ACE operating system. The current version has also
support for the C64, the C128 and the Plus/4 in native mode. The ACE port has
disk support but no conio module, all others don't have disk support but
direct console I/O.
Currently the following limitations the are known:
* getwd (ace) does not work. I get an error (carry flag) with an error
code of zero (aceErrStopped). Maybe my code is wrong...
* The error codes are currently system error codes. They should be
translated to something system independent. The ace codes are a good
starting point. However, I don't like the idea, that zero is a valid
error code, and some other codes are missing ("invalid parameter" and
more). As soon as this is done, it is also possible to write a
strerror() function to give more descriptive error messages to the
user.
* Many functions not very good tested.
* The printf and heap functions are way too big. Rewritting _printf
and malloc/free in assembler will probably squeeze 2K out of the
code.
* The isxxx functions do not handle EOF correctly. This is probably
a permanent restriction, even if it is non-standard. It would require
extra code in each of the isxxx functions, since EOF is defined as -1
and cannot be handled effectively with the table approach and 8 bit
index registers.
* The strcspn, strpbrk and strspn functions have a string length limitation
of 256 for the second argument. This is usually not a problem since the
second argument gives a character set, and a character set cannot be
larger than 256 chars for all known 6502 systems.
5. Bugs
-------
Please note that the compiler and the libraries are beta! Send bug reports to
uz@musoftware.de.

34
doc/readme.1st Normal file
View File

@@ -0,0 +1,34 @@
If you have got the source package, see
doc/compile.txt
for instructions how to compile the stuff for the different systems.
If you have a binary package: Have a look in the doc directory for
information on how to use the tools. If you are new to cc65, the file
intro.txt may be of interest to you.
To avoid having to mess with paths, you may want to set the environment
variables
CC65_LIB
and CC65_INC
to the directory containing the libraries and the system include files
respectively. If you have installed cc65 in C:\cc65 (assuming a DOS or
Windows system), you should use
set CC65_LIB=c:\cc65\lib
and set CC65_INC=c:\cc65\include
Unix people probably know, how to translate these lines into the
appropriate Unix commands:-)
Have fun!
Uz

31
doc/readme.txt Normal file
View File

@@ -0,0 +1,31 @@
Documentation overview:
ar65.txt - Describes the ar65 archiver.
debugging.txt - Debug programs using the VICE emulator.
ca65.txt - Describes the ca65 macro assembler.
cc65.txt - Describes the cc65 C compiler.
cl65.txt - Describes the cl65 compile & link utility.
coding.txt - Containes hints on creating the most effective code
with cc65.
intro.txt - Describes the use of the tools by a short "hello world"
example.
ld65.txt - Describes the ld65 linker.
library.txt - Describes the cc65 runtime and C libraries.
newvers.txt - Somewhat outdated. Lists the differences between the
current cc65 release and the original atari version
created by J.R Dunning.
readme.txt - This file.