Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.apple2 > #22557
| From | D Finnigan <dog_cow@macgui.com> |
|---|---|
| Newsgroups | comp.sys.apple2, comp.sys.apple2.programmer |
| Subject | Re: Some cc65 optimizations... |
| Followup-To | comp.sys.apple2.programmer |
| Date | 2014-11-22 12:54 -0600 |
| Organization | A noiseless patient Spider |
| Message-ID | <m4qm46$24a$1@dont-email.me> (permalink) |
| References | <e499d43f-d51b-4afe-a71a-397e416b2c30@googlegroups.com> |
Cross-posted to 2 groups.
Followups directed to: comp.sys.apple2.programmer
Here is his text file:
------------------------------
Optimizing_cc65_Code-1.00.txt
Optimizing cc65 Code:
What the Author Didn't Tell You
By Joseph Rose,
a.k.a. Harry Potter
-------------------------------
[Intro]
Welcome to my cc65 C optimization documentation! Here, you will find
some tricks and techniques to produce the best C code under cc65. Most
of the
techniques here will work for other 6502 targets, other C compilers and even
other compilers and interpreters. I'm not yet an advanced programmer, but I
believe these optimizations to be useful.
Some of these techniques may be obvious to some, but you may still find
something useful.
This document is organized into sections, where each describes one
technique. The individual techniques follow:
[Middleman]
If your code needs to call the same function or group of functions in
order with some of the same parameters, you can use a "middleman," where the
middleman will accept the call and call the base function or functions
for the
callee and supply the constant parameters. This will require some
parameters
to be passed only once in your code, making for smaller code. An example
follows:
Instead of:
-----------
extern int i[10];
int func2 (int ramcount,
enum machine m,
char* language)
{
...
}
void func (void) {
{
i[0]=func2 (64, machC64, "c");
i[1]=func2 (64, machC64, "BASIC");
i[2]=func2 (64, machC64, "assembler");
i[3]=func2 (64, machC64, "FORTH");
i[4]=func2 (64, machC64, "Pascal");
}
------------
Try:
------------
extern int i[10];
int func2 (int ramcount,
enum machine m,
char* language)
{
...
}
int func2a (char* language)
{ return func2(64, machC64, language);}
void func (void) {
{
i[0]=func2 ("c");
i[1]=func2 ("BASIC");
i[2]=func2 ("assembler");
i[3]=func2 ("FORTH");
i[4]=func2 ("Pascal");
}
---------------------
[Caching Variables]
If you need a particular element in, for example, a multi-subscript
array of structs many times in your code, it is a good idea to read it once,
store the value in a local variable and access that, instead. If you
need to
access different members of the struct, assign the struct's address to a
local
pointer and use that to access the struct. This is made even better if
you use
a zeropage variable.
[Minimize Function Usage]
Don't use functions you don't need. If you don't need the services of
printf(), don't use it. Examples follow:
* My CBMSIMPIO library simplifies displaying text and numbers on
the screen. If you don't need the services of the standard
screen output library and CBMSIMPIO can do the job, use
CBMSIMPIO instead. This can save 2-3k in your program.
* If you need to copy memory from one location to another and the
two never overlap, don't use memmove(). memmove() requires
more overhead, and memcpy() can do the job.
[System-Specific Functions]
If you're writing code for a specific target, use functions made for
that target. This requires less overhead for conversion and otherwise makes
for better code in general. An example is if you use file access with a CBM
model, using the CBM OS functions access the OS directly.
[CBM Control Codes]
The good thing about CBM screen output is that output can contain
control codes to perform functions such as change color or clear screen. If
you need to, for example, clear the screen before writing some text,
including
a clear screen code in the text can save from an explicit clrscr() call and
shave 4 bytes from your code.
[Assembler]
Most programs can be created solely in C. However, some programs may
require at least some assembler. When deciding to use assembler in your
code
and where, keep the following in mind:
* C is a medium-level and is good for calculations and program
flow.
* Assembler is a low-level language and is good for data-
crunching, hardware-manipulation and OS calls.
* If C can do the job immediately, you should use C.
* If C needs to do a work-around to do the job, you may want to
use assembler.
* If you want or need full control over hardware or the computer,
you should use assembler.
Don't be afraid to use assembler. It can be beneficial if used
properly.
[Assuming Parameters]
This is simlar to the Middleman optimization. If a function only needs
one value for a particular parameter, remove the parameter and replace
it with
the value. Then, remove the parameter in the declaration, definition
and calls
to the function.
[Tokenizing Calculations]
If you need to use the same calculataions over and over, store the
calculation(s) in one function each and call the function(s) as needed.
[Optimizing Longs]
On an 8-bit computer, longs are very slow and require alot of code.
Fortunately, using pointers to longs instead seems to produce tighter
code. I
think this is because it allows your program to handle words, while the
compiler provides the routines to handle the longs referenced. This,
however,
should slow down your code even more.
[Calculate Once]
If you need the result of a particular calculation several times,
perform it once.
[Use Switches]
Switches are good for many possibilities. Switches load the value once
and perform several comparisons on it, saving from the extra loads necessary
with ifs. The exception to this rule is a true/false case which works
better
on ifs.
[Incremental Switch Returns]
When you use a switch to return an incremetal value where each
condition returns one more (or less) than the previous, reorganize the
code by
putting the highest (or lowest if less than the previous), using an
increment/
decrement instead and remove the breaks on all except the last if necessary.
An example follows:
Instead of:
-------------------------------
char c=0, d;
switch (c) {
case 1: d=1; break;
case 3: d=2; break;
case 2: d=3; break;
case 4: d=4; break;
}
-------------------------------
Try:
-------------------------------
char c=0, d=0;
switch (c) {
case 4: ++d;
case 2: ++d;
case 3: ++d;
case 1: ++d; break;
}
-------------------------------
[Toggling Bools]
If you know that, for example, b is a bool and either 1 or 0, toggling
b using b^1 is shorter and probably also faster than !b.
[Ifs Without Elses]
If you have a series of ifs, all of which are mutually
exclusive (i.e. only one will work anyway), exclude the elses. In
this way, you avoid the extra jump over the next elses.
[Assigning]
Assinging a value when it's first used can save an explicit load. Ex:
Instead of:
------------
c=a*2-1; f00(c);
------------
Try:
------------
f00 (c=a*2-1);
------------
[Ints are shorter and faster than strings]
If you need to compare a string to a list of other strings several
times in your code, do the compare once and set an enum to the string's
number
and substitute the number compare. This also allows you to use switch() to
delegate the different tasks instead of a series of !strcmp()'s.
[Avoid Unnecessary Error-Checking]
If a
[Footnote]
I am glad you looked at this document. Please, tell me what you
think! If you find this document to be helpful, e-mail me. If you have any
suggestions, complaints or comments, e-mail me. If you have any additions,
post them on the cc65 contribs site. My e-mail address is
rose.joseph12@yahoo.com.
-----------------
Back to comp.sys.apple2 | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
Some cc65 optimizations... Harry Potter <rose.joseph12@yahoo.com> - 2014-11-22 06:05 -0800
Re: Some cc65 optimizations... D Finnigan <dog_cow@macgui.com> - 2014-11-22 12:54 -0600
Re: Some cc65 optimizations... Antoine Vignau <antoine.vignau@laposte.net> - 2014-11-22 13:14 -0800
Re: Some cc65 optimizations... Harry Potter <rose.joseph12@yahoo.com> - 2014-11-22 13:51 -0800
Re: Some cc65 optimizations... qkumba <peter.ferrie@gmail.com> - 2014-11-22 21:37 -0800
Re: Some cc65 optimizations... Harry Potter <rose.joseph12@yahoo.com> - 2014-11-23 04:56 -0800
Re: Some cc65 optimizations... "Bill Buckels" <bbuckels@mts.net> - 2014-11-23 12:55 -0600
Re: Some cc65 optimizations... Harry Potter <rose.joseph12@yahoo.com> - 2014-11-23 13:53 -0800
Re: Some cc65 optimizations... "Bill Buckels" <bbuckels@mts.net> - 2014-11-23 17:47 -0600
Re: Some cc65 optimizations... opengeek@gmail.com - 2014-11-24 09:55 -0800
Re: Some cc65 optimizations... Harry Potter <rose.joseph12@yahoo.com> - 2014-11-24 16:07 -0800
Re: Some cc65 optimizations... D Finnigan <dog_cow@macgui.com> - 2014-11-24 14:22 -0600
csiph-web