ds390) unless explicitly casted and --std-c89 and --std-c99 command line option are not deﬁned. But we also sometimes introduce some incompatibilities with older versions. library and documentation ﬁles are stored is now in /usr/local/share. The debugger currently uses ucSim. linkers etc. without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. it used to be equivalent to char (8 bits) which is not ANSI compliant. old programs may be compiled using the --short-is-8bits commandline option (see 3. a. The latest SDCC version can be downloaded from http://sdcc. either version 2. Boston. • the default directory for gcc-builds where include.net/snap. USA. mcs51. we will use the following convention. • option --noregparms has been removed. MA 02111-1307. will push a as two ints if --std-c89 or --std-c99 command line option is deﬁned. • short is now equivalent to int (16 bits). you are welcome to use. • char type parameters to vararg functions are casted to int unless explicitly casted and --std-c89 and --std-c99 command line option are not deﬁned. • option --stack-after-data has been removed.Suite 330. if not.
1 Obviously
this has pros and cons
7
.g. In other words. a free open source simulator for 8051 and other micro-controllers. (char)a).2
Open Source
All packages used in this compiler system are free open source. you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation.2 for ANSI-Compliance). Not just for the fun of it.3
Typographic conventions
Throughout this manual. This program is distributed in the hope that it will be useful. • pointer type parameters to vararg functions are casted to generic pointers on harvard architectures (e. efﬁcient and ANSI compliant (see section 8. Commands you have to type in are printed in "sans serif". Help stamp out software-hoarding!
1. share and improve this program.2.sourceforge.
1. To maintain compatibility. Code samples are printed in typewriter font. See the GNU General Public License for more details.1.2. share and improve what you give them.g. This program is free software. assemblers. or (at your option) any later version.: char a=3. INTRODUCTION
SDCC also comes with a companion source level debugger SDCDB. OPEN SOURCE
CHAPTER 1.9 on page 31). source code for all the sub-packages (pre-processor. 59 Temple Place . e. This documentation is maintained using a free open source word processor (LYX). • option --regextend has been removed. printf ("%d %c\n".) is distributed with the package. write to the Free Software Foundation.php. Please note: the compiler will probably always be some steps ahead of this documentation1 . Interesting items and new terms are printed in italic. You should have received a copy of the GNU General Public License along with this program. but to make the compiler more stable.
1. will push a as an int and as a char resp if --std-c89 and --std-c99 command line options are not deﬁned. You are forbidden to forbid anyone else to use. but WITHOUT ANY WARRANTY.4
Compatibility with previous versions
Newer versions have usually numerous bug ﬁxes compared with the previous version.

See section 3. • in versions older then 2. which is not conforming with ISO/IEC 9899:1999 standard (see section Section 6. b = ~b.5: struct { int a : 2. • targets for xa51 and avr are disabled by default in version 3.7. such as one-line (//) comments • in versions older than 2. The as2gbmap utility can be used to convert sdld map format to rrgb and no$gmb ﬁle formats.b = 2 */ • libraries. and can cause compilation failures on code built with --std-c89 but using c99 preprocessor features.2 ANSI-Compliance. For Windows some pre-compiled binary distributions are available for your convenience. char : 2. "%hb" and "%lb"). • in sdcc version 3.a = 1. /* equivalent to b=1 instead of toggling b */ b = !b. • special sdcc keywords which are not preceded by a double underscore are deprecated in version 3. • in sdcc version 3.8. /* toggles b */ In previous versions. See section 8.c and recompiling the library.b = 3 */ New behavior: struct { int a : 2. 2}. are in ar format in sdcc version 2. You should have some experience with command line tools and compiler use.0 and higher. • in older versions. s. the preprocessor was always called with --std-c99 regardless of the --std-xxx setting.g. before version 2.a = 1. 3}. It can be enabled by deﬁning BINARY_SPECIFIER macro in ﬁles device/lib/pic16/libc/stdio/vfprintf. /* s. included in sdcc packages.5.8.c and device/lib/pic16/libc/stdio/printf_tiny. The ’b’ speciﬁer is now disabled by default. This is no longer true.0 and higher sdldgb and sdldz80 don’t support generation of GameBoy binary image format. The most common incompatibility resulting from this change is related to bit toggling idioms.0 and higher sdldgb and sdldz80 don’t support generation of rrgb (GameBoy simulator) map ﬁle and no$gmb symbol ﬁle formats. } s = {1. clause 9) Old behavior.8 Initialization. e.6. The makebin utility can be used to convert Intel Hex format to GameBoy binary image format. 2.0 and higher.5 the unnamed bitﬁeld structure members participated in initialization.4 the pic16 *printf() and printf_tiny() library functions supported undocumented and not standard compliant ’b’ binary format speciﬁer ("%b". } s = {1. and a desire to compute.1.1.: bit b. int b : 2.
1. s.
8
. SYSTEM REQUIREMENTS
CHAPTER 1.5
System Requirements
What do you need before you start installation of SDCC? A computer.8. both forms would have toggled the bit. The preferred method of installation is to compile SDCC from source using GNU gcc and make. char : 2.9. /* s. INTRODUCTION
• bit and sbit types now consistently behave like the C99 _Bool type with respect to type conversion.0 and higher. int b : 2.

2 about ﬁling feature requests. Web links to other SDCC related sites can also be found here.
1.6
Other Resources
The SDCC home page at http://sdcc.pdf. OTHER RESOURCES
CHAPTER 1. INTRODUCTION
1.6.
9
.sourceforge. You can also ﬁnd links to the user mailing lists that offer help or discuss SDCC with other SDCC users. please see the section 7.svn.net/svnroot/sdcc/trunk/sdcc.1.sourceforge. This document can be found in the DOC directory of the source package as a text or HTML ﬁle.7
Wishes for the future
There are (and always will be) some things that could be done. Here are some I can think of: char KernelFunction3(char p) at 0x340. A pdf version of this document is available at http://sdcc. the complete source package is available directly from Subversion on https://sdcc.net/ doc/sdccman. better code banking support for mcs51 If you can think of some more. If you want the latest unreleased software. Some of the other tools (simulator and assembler) included with SDCC contain their own documentation and can be found in the source distribution.net/ is a great place to ﬁnd distribution sets.sourceforge.

a gcc compiler and last but not least 3. the binaries can be built by cross compiling on SDCC Distributed Compile Farm./configure . The other Win32 builds using VC or whatever don’t use ’conﬁgure’. open source. Lower runtime footprint. because it’s 1. This is needed for full relocatability of a binary package and to complete search paths (see section search paths below): Variable (computed) BIN2DATA_DIR PREFIX2BIN_DIR PREFIX2DATA_DIR Examples: . The names of the standard libraries STD_LIB. Please see ‘conﬁgure --help’ and the man/info pages of ‘conﬁgure’ for details. SDCC_INCLUDE_NAME. CFLAGS.../configure --disable-avr-port --disable-xa51-port 11 default . These defaults are: Variable PREFIX EXEC_PREFIX BINDIR DATADIR DATAROOTDIR DOCDIR INCLUDE_DIR_SUFFIX LIB_DIR_SUFFIX default /usr/local $PREFIX $EXEC_PREFIX/bin $DATAROOTDIR $PREFIX/share $DATAROOTDIR/sdcc/doc sdcc/include sdcc/lib Win32 builds \sdcc $PREFIX $EXEC_PREFIX\bin $DATAROOTDIR $PREFIX $DATAROOTDIR\doc include lib The
’conﬁgure’ also computes relative paths. These conﬁgure options are compiled into the binaries..h built by ’conﬁgure’ for Win32. The conﬁgure options are written in italics to distinguish them from run time environment variables (see section search paths).1. INSTALLING SDCC
Furthermore the environment variables CC.h is the same as sdccconf. The settings for ”Win32 builds” are used by the SDCC team to build the ofﬁcial Win32 binaries. STD_FP_LIB../share bin share/sdcc Win32 builds . At the moment it’s not possible to change the default settings (it was simply never required). STD_XA51_LIB and the environment variables SDCC_DIR_NAME. STD_INT_LIB.2. STD_LONG_LIB. CONFIGURE OPTIONS --disable-device-lib Disables automatically building device libraries --disable-packihx Disables building packihx --enable-doc Build pdf. See the examples. STD_DS390_LIB. SDCC_LIB_NAME are deﬁned by ‘conﬁgure’ too. html and txt ﬁles from the lyx sources --enable-libgc Use the Bohem memory allocator. bin
. how to pass the Win32 settings to ’conﬁgure’. 2. --without-ccache Do not use ccache even if available
CHAPTER 2. and can only be changed by rerunning ’conﬁgure’ and recompiling SDCC. the tools and their arguments can be inﬂuenced./configure --prefix=”/usr/bin” --datarootdir=”/usr/share” . SDCC team uses Mingw32 to build the ofﬁcial Windows binaries. but a header ﬁle sdcc_vc_in. .

On Mac OS X 10. 5.sdk -arch i386 -arch ppc" \ CXXFLAGS = "-O2 -isysroot /Developer/SDKs/MacOSX10.com http://www.4. 6. All of the source packages will compile.4.2
Building SDCC on Mac OS X
Follow the instruction for Linux. BUILDING SDCC 2.9. such as xterm.4u.4
Building SDCC using Cygwin and Mingw32
For building and installing a Cygwin executable follow the instructions for Linux./conﬁgure". Type ". Fortunately there’s also gcc 2.2.3
Cross compiling SDCC on Linux for Windows
With the Mingw32 gcc cross compiler it’s easy to compile SDCC for Win32./configure CC=gcc2 CXX=g++2 Universal (ppc and i386) binaries can be produced on Mac OS X 10. the libraries and the documentation to the install directories.-syslibroot.
2. Type "make". this will create a sub-directory called sdcc with all of the sources.
2.x is ﬁne.7. for example type: "cd sdcc". In order to install Cygwin on Windows download setup.4.bz2”. This compiler can be selected by running ’conﬁgure’ with: .cygwin. For the necessary ’conﬁgure’ options see section ’conﬁgure options’ or the script ’sdcc/support/scripts/sdcc_cygwin_mingw32’./configure \ LDFLAGS="-Wl. com/. 7. which makes life much easier under windoze (see below) • man .4u. This copies the binary executables. 4. but you’ll miss it sooner or later 14
. Never deselect these packages! • ﬂex • bison • gcc . which will not need the Cygwin-DLL. INSTALLING SDCC
3. not really needed for building SDCC. selected with gcc • make • rxvt ./Developer/SDKs/MacOSX10. Type "make install" as root. version 3.x it was reported.1 20020420 (prerelease)) fails to compile SDCC. Run it. a nice console.sdk -arch i386 -arch ppc"
2.x installed.4. which works ﬁne. Change directory into the main SDCC directory. Some packages are selected by default.9x • binutils . Proceed with section 2.x with Xcode.tar. set the ”default text ﬁle type” to ”unix” and download/install at least the following packages.cygwin. but you’ll miss it sooner or later • less .
CHAPTER 2. this can take a while.4u.4. not really needed for building SDCC. no need to use the old 2. See section ’Conﬁgure Options’.sdk -arch i386 -arch ppc" \ CFLAGS = "-O2 -isysroot /Developer/SDKs/MacOSX10. Bring up a command line terminal. Unpack the ﬁle using a command like: "tar -xvjf sdcc-src-yyyymmdd-rrrr. Run ’conﬁgure’ with: .exe from www. This conﬁgures the package for compilation on your system. On Cygwin a ”native” Win32-binary can be built. that the default gcc (version 3. others will be automatically selected because of dependencies with the manually selected packages. the include ﬁles.2.

Replace in your cygwin. Doug Hawkins reported in the sdcc-user list that this works: C:\Programming\SDCC> unix2dos sdcc.dsw C:\Programming\SDCC> for /R %I in (*.0/NET (except for SDCDB and ucSim). Make sure not to commit ﬁles with windows line endings. One good place to get them is here http://unxutils.zip. and ﬁles you need to build it using Visual C++ 6. BUILDING SDCC • svn . don’t use autoconf-stable! rxvt is a nice console with history. not the 0x0a Unix style line endings. Using // invokes a network lookup which is very slow. If however you are getting a message such as "This makeﬁle was not generated by Developer Studio etc. all the executables are created in a folder called sdcc\bin_vc.4.5
Building SDCC Using Microsoft Visual C++ 6.2. the gnu debugger. The other good tip is to make sure you have no //c/-style paths anywhere. for the regression tests • gdb .dsp) do @unix2dos "%I" In order to build SDCC with MSVC you need win32 executables of bison.bz2. SDCC is distributed with all the projects.sourceforge.dsw’. it will be named something like sdcc-src-yyyymmddrrrr. workspaces.dsp projects. pasting works with shift-insert. mount -s -u -c /mnt SDCC sources use the unix line ending LF. if you store the source tree on a drive which is mounted in binary mode. 0x0a DOS style line endings. WARNING: Visual studio is very picky with line terminations.bat the line bash --login -i with (one line): rxvt -sl 1000 -fn "Lucida Console-12" -sr -cr red -bg black -fg white -geometry 100x65 -e bash --login Text selected with the mouse is automatically copied to the clipboard.0/NET (MSVC)
Download the source package either from the SDCC Subversion repository or from the snapshot builds http://sdcc.” when opening the sdcc. Although a tabulator spacing of 8 is a sensible choice for programmers (it’s a power of 2 and allows to display 8/16 bit signed variables without loosing columns) the plan is to move towards using only spaces in the source. together with the nice GUI ”insight” • openssh . When using the Subversion repository it’s easiest to conﬁgure the svn client to convert automatically for you.4.net Download the ﬁle UnxUtils. use /cygdrive/c/ instead.php. if you want to ﬁght with ’conﬁgure’.sourceforge. only if you use Subversion access If you want to develop something you’ll need: • python .net/snap. Life is much easier. Once built you need to copy the executables from sdcc\bin_vc to sdcc\bin before running SDCC. Now you have to install the utilities and setup MSVC so it can locate the required programs. Please note that as it is now. And use an editor which can handle LF-only line endings. it expects the 0x0d.dsw workspace or any of the *.g.tar. then you need to convert the Unix style line endings to DOS style line endings. To do so you can use the ”unix2dos” utility freely available on the internet. etc.exe.exe. and gawk. Here there are two alternatives (choose one!):
15
. If you think ”cygdrive” is too long.
2. to access the CF or commit changes
CHAPTER 2. INSTALLING SDCC
• autoconf and autoconf-devel . you can change it with e.exe. The tabulator spacing used in the project is 8. The workspace name is ’sdcc. ﬂex.

exe’.
2. Open ’sdcc. ’ﬂex.exe to ’_bison. you get a bunch of Unix utilities that could be useful. BUILDING SDCC 1.exe’. e) In the Visual C++ IDE click Tools.hairy’. and in the directories window add a new path: ’C:\user\local\wbin’.2. (As a side effect.exe to such directory WITHOUT preserving the original paths. ’/usr/local/share/’ I think.
2. otherwise bison won’t work.
16
.simple’. This should unpack to a group of sub-directories. Options.dsw’ in Visual Studio. The easy way:
CHAPTER 2. but requires some extra work: a) Create a directory were to put the tools needed. click ’build all’.net/snap. and in the directories window add a new path: ’c:\util’.7
Windows Install Using the Setup Program
Download the setup program sdcc-x. ’bison. and gawk.4.zip to your C:\ hard disk PRESERVING the original paths. such as diff and patch. etc). (If you are using WinZip make certain that ’Use folder names’ is selected) b) In the Visual C++ IDE click Tools.hairy’ reside in some weird Unix directory. ’bison.net/snap. select the Directory tab. 2. So you don’t have to execute step ’e’ :) That is it. when it ﬁnishes copy the executables from sdcc\bin_vc to sdcc\bin.simple set BISON_HAIRY=C:\util\bison.6
Windows Install Using a ZIP Package
1. even the path where the Visual C++ tools are. c:\sdcc\include and c:\sdcc\lib for the include and libraries.exe’. click ok. in ’Show directories for:’ select ’Executable ﬁles’. A more compact way: This one avoids extracting a bunch of ﬁles you may not use.php?group_id=599 or a setup program for one of the snapshots sdcc-yyyymmdd-xxxx-setup. click ok. and you can compile using SDCC.sf.simple’ and ’bison. Download the binary zip package from http://sdcc. d) Create a batch ﬁle ’bison. That is the function of the environment variables BISON_SIMPLE and BISON_HAIRY.net/project/showfiles. b) Extract ’bison. Note that you can use any other path instead of ’c:\util’.) 2.exe from http://sdcc.php and unpack it using your favorite unpacking tool (gunzip. A windows typical installer will guide you through the installation process. An example directory structure after unpacking the mingw32 package is: c:\sdcc\bin for the executables. (If you are using WinZip make certain that ’Use folder names’ is not selected) c) Rename bison. probably: ’C:\Program Files\Microsoft Visual Studio\Common\Tools’. Adjust your environment variable PATH to include the location of the bin directory or start sdcc using the full path. select the Directory tab. So it is necessary to tell bison where those ﬁles are located if they are not in such directory.exe for an ofﬁcial release from http://sf. in ’Show directories for:’ select ’Executable ﬁles’.bat’ in ’C:\util\’ and add these lines: set BISON_SIMPLE=C:\util\bison.sf.php and execute it.4. or use a directory already present. Options.4.y. INSTALLING SDCC
a) Extract UnxUtils.hairy _bison %1 %2 %3 %4 %5 %6 %7 %8 %9 Steps ’c’ and ’d’ are needed because bison requires by default that the ﬁles ’bison.z-setup. WinZip. Say for example ’C:\util’.

enter ‘make clean’.sf. restrictions and warnings than to the solution. e. This document currently matches SDCC for mcs51 and DS390 best and does give too few information about f.org as editor is straightforward. Another possibility is to change to the doc directory and to type ”make” there. make will do the rest for you!
2..tar. • There are still lots of typos and there are more different writing styles than pictures.php.net/doc/sdccman.
2.opencores.bz2 # extract source to directory sdcc mkdir sdcc.net/ projects/fpgac ”have you ever heard of an open source compiler that compiles a subset of C for an FPGA?” we expect you to have a quick look there and come back. If you read this you are on the right track. INSTALLING SDCC
2. top_srcdir and top_buildir for each directory.build . You’ll ﬁnd the pdf version at http://sdcc.5. You’re invited to make changes and additions to this manual (sdcc/doc/sdccman.build # put output in sdcc. when cross compiling.lyx). Prebuilt documentation in html and pdf format is available from http://sdcc. as for unknown reason the hyperlinks are working there whereas in the html version they are not1 . PIC14.g.e. Simply copy it to the build directory.4. dvips and makeindex) to get the job done.html. BUILDING THE DOCUMENTATION
CHAPTER 2. LTEX.build. while the source ﬁles stay in ~/sdcc. PIC16 and HC08. After running make the generated ﬁles will be in ~/sdcc. If there f. pdﬂatex. • There are many references pointing away from this documentation.8
VPATH feature
SDCC supports the VPATH feature provided by conﬁgure and make. edit it.org together with a statement ”some processors which are targetted by SDCC can be implemented in a f ield programmable gate array” or http://sf. was a reference like http://www. You will A A need several tools (LYX.html/index. A html version should be online at http://sdcc. This is not only usefull for building different binaries. It allows to separate the source and build trees.net/snap.2. LTEX2HTML.build. • Some sections attribute more space to problems.net/doc/sdccman./sdcc/configure # configure is doing all the magic! make That’s it! conﬁgure will create the directory tree will all the necessary Makeﬁles in ~/sdcc. It automagically computes the variables srcdir. dvipdf.
1 If
you should know why please drop us a note
17
. Here’s an example: cd ~ # cd $HOME tar -xjf sdcc-src-yyyymmdd-rrrr.5
Building the Documentation
Add --enable-doc to the conﬁgure arguments to build the documentation together with all the other stuff.build cd sdcc. This documentation is in some aspects different from a commercial documentation: • It tries to document SDCC for several processor architectures in one document (commercially these probably would be separate documents/products).sf.lyx.dep’ and ‘make’. Don’t let this distract you.sf. Using LYX http://www. It also gives you a much better overview in the source tree when all the generated ﬁles are not scattered between the source ﬁles. Z80.pdf. • The installation section and the section about the debugger is intimidating.e.6
Reading the Documentation
Currently reading the document in pdf format is recommended. ‘rm Makeﬁle. And the best thing is: if you want to change a ﬁle you can leave the original ﬁle untouched in the source directory.

then the problem is that SDCC cannot ﬁnd the /usr/local/share/sdcc/include directory (see the section 2.8
2. This should generate a test. the compiler will generate a test. and it should give no warnings such as not ﬁnding the string. then the problem is most likely that SDCC cannot ﬁnd the /usr/local/share/sdcc/lib directory (see section 2. If it cannot ﬁnd the string. or gives a message about not ﬁnding sdcc program.c and change it to the following: #include <string. just to keep things simple for this step. Make sure that the sdcc program is in the bin folder. and the program should run and output its version like: SDCC : mcs51/z80/avr/ds390/pic16/pic14/ds400/hc08 2. Type in the following test.8 Install trouble-shooting for suggestions).c". If this step fails (no test./conﬁgure 2>&1 | tee conﬁgure.log and build it like:
18
.ihx output ﬁle.ihx. The ﬁnal test is to ensure SDCC can use the standard header ﬁles and libraries.asm and test.c program using your favorite ASCII editor: char test.rel ﬁle. Type "sdcc --version" at the prompt. } Compile this using the following command: "sdcc -c test. Congratulations. Type in "sdcc test. Conﬁgure it like: . Use option --print-search-dirs to ﬁnd exactly where SDCC is looking for the include and lib ﬁles. "testing"). void main(void) { strcpy(str1.7. Make sure that the sdcc bin directory is in your executable search path deﬁned by the PATH environment setting (see section 2.h ﬁle. if not perhaps something did not install correctly. and the linker generates warnings).5.1
Install Trouble-shooting
If SDCC does not build correctly
A thing to try is starting from scratch by unpacking the .
2.2. We used the -c option to tell SDCC not to link the generated code. } Compile this by typing "sdcc test. INSTALLING SDCC
2.8 Install trouble-shooting for suggestions). you’ve just compiled your ﬁrst program with SDCC. The next step is to try it with the linker.c". then you need to check over your installation.7
Testing the SDCC Compiler
The ﬁrst thing you should do after installing your SDCC compiler is to see if it runs. If all goes well the compiler will link with the libraries and produce a test.c".h> char str1[10].8 Install trouble-shooting section for suggestions). Make sure the compiler works on a very simple example.6 #4169 (May 8 2006) (UNIX) If it doesn’t run.ihx output ﬁle.8. SDCC is commonly installed as described in section ”Install and search paths”. If all goes well.tgz source package again in an empty directory. Edit test. TESTING THE SDCC COMPILER
CHAPTER 2. void main(void) { test=0.h ﬁle.

9.The C preprocessor. • sdld6808 .The Z80 and GameBoy Z80 linkers.8./conﬁgure” command is a script that analyzes your system and performs some conﬁguration to ensure the source package compiles on your system. 2.The ucSim 8051 simulator. Or a relevant part of this can be attached to an email that could be helpful when requesting help from the mailing list.
This will install the compiler.
2.2. and will compile a few tests to determine what compiler features are installed.
2. • sdasz80. • sdcpp .9
Components of SDCC
SDCC is not just a compiler. COMPONENTS OF SDCC make 2>&1 | tee make.4
What the ”make install” command does.The 6808 linker. • s51 . You might want to look at the ﬁles which are installed in <installdir>. we ﬁnd the following programs for gcc-builds: In <installdir>/bin: • sdcc . which automatically compiles all the source packages into the ﬁnal installed binary executables.The source debugger.3
What the ”make” does
This runs the GNU make tool. As SDCC grows to include support for other processors. These include linkers./conﬁgure” does
The ”.The assembler for 8051 type processors.A tool to convert Intel Hex ﬁle to a binary and GameBoy binary image ﬁle format. INSTALLING SDCC
If anything goes wrong. other packages from various developers are included and may have their own sets of documentation. • sdcdb . simulators and other components. • sdas6808 . • sdld -The linker for 8051 type processors. sdldgb . Note that the included simulator and assembler have separate documentation which you can ﬁnd in the source package in their respective directories. In <installdir>/share/sdcc/include
19
. but a collection of tools by various developers. you can review the log ﬁles to locate the problem.A tool to pack (compress) Intel hex ﬁles. Here is a summary of some of the components. See sections 2.2
What the ”.The Z80 and GameBoy Z80 assemblers.The 6808 assembler.8. • packihx . On most systems you will need super-user privileges to do this.3 about install and search paths.
2. It will take a few minutes to run. • sdas8051 .2. • makebin . other executables libraries and include ﬁles into the appropriate directories. assemblers.8. sdasgb .The compiler.log
CHAPTER 2.
2. At the time of this writing. • sdldz80.

2.
20
. but can be easily changed to use other simulators.3
sdas. etc.1
sdcc .
2. so a reunion could be possible.9. The C preprocessor is used to pull in #include sources.iit. More about SDCDB in section 5. large.The Simulator
S51 is a free open source simulator developed by Daniel Drotos.The C-Preprocessor
The preprocessor is a modiﬁed version of the GNU cpp preprocessor http://gcc.9.0 which unfortunately is not compatible with the more advanced (f.0 available under the GPL licence (GPLv3 or later).uni-miskolc. In <installdir>/share/sdcc/doc • the documentation As development for other processors proceeds.The Compiler
This is the actual compiler.9. The simulator is built as part of the build process. John Hartman created the version for 8051. it in turn uses the c-preprocessor and invokes the assembler and linkage editor. PIC.kent.hu/~drdani/ embedded/s51. SDCC uses an about 1998 branch of asxxxx version 2.5
sdcdb . It currently supports the core mcs51. The current version of the debugger uses Daniel’s Simulator S51.
2. which was developed by Alan Baldwin.The Assemblers and Linkage Editors
This is a set of retargettable assemblers and linkage editors. For more information visit Daniel’s web site at: http://mazsola. the Dallas DS80C390 and the Phillips XA51 family.gnu.9. gbz80 and ds390 with the precompiled relocatables.9. In 2009 Alan made his ASxxxx Cross Assemblers versin 5.org/. more targets) ASxxxx Cross Assemblers nowadays available from Alan Baldwin http: //shop-pdp. #deﬁnes and so on.edu/.4
s51 .2
sdcpp . this list will expand to include executables to support processors like AVR.Source Level Debugger
SDCDB is the companion source level debugger.
2. and I (Sandeep) have made some enhancements and bug ﬁxes for it to work properly with SDCC.
2. macros. INSTALLING SDCC
• the subdirs src and small.9. z80.1.e. sdld . process #ifdef statements. Thanks Alan!
2. COMPONENTS OF SDCC • the include ﬁles In <installdir>/share/sdcc/lib
CHAPTER 2.

hex
21
.pdf • sourceﬁle. • sourceﬁle.rel .rst .symbol listing for the sourceﬁle. input to Linkage editor • sourceﬁle.2.1 ”Anatomy of the compiler”).ihx .c".1.An optional ﬁle (with --debug) containing debug information.1
3.A ﬁle with a summary of the memory usage • sourceﬁle.The load module in Intel hex format (you can select the Motorola S19 format with --out-fmts19. The (Intel) absolute object module f ormat is a subformat of the OMF51 format and is commonly used by third party tools (debuggers. If your toolchain or a bootloader does not like this you can use the tool packihx which is part of the SDCC distribution: packihx sourceﬁle. created by the Linker • sourceﬁle.see also section 3.Assembler listing ﬁle updated with linkedit information.2
Postprocessing the Intel Hex ﬁle
In most cases this won’t be needed but the Intel Hex ﬁle which is generated by SDCC might include lines of varying length and the addresses within the ﬁle are not guaranteed to be strictly ascending.cdb ﬁle (with -debug) • sourceﬁle.Dump ﬁle to debug the compiler it self (generated with option --dumpall) (see section 3.An intermediate ﬁle containing debug information needed to create the .The memory map for the load module.10 and section 9.(no extension) An optional AOMF or AOMF51 ﬁle containing debug information (generated with option --debug).Chapter 3
Using SDCC
3. Both formats are documented in the documentation of srecord • sourceﬁle. emulators).Object ﬁle created by the assembler.map .1. created by linkage editor • sourceﬁle. If you need another format you might want to use objdump or srecord . simulators. Compile your programs with the following command "sdcc sourceﬁle.cdb .ihx >sourceﬁle.mem .Assembler listing ﬁle created by the Assembler • sourceﬁle.sym . This will compile. assemble and link your source ﬁle.2).1
Compiling
Single Source File Projects
For single source ﬁle 8051 projects the process is very simple.1. Output ﬁles are as follows: • sourceﬁle. created by the assembler • sourceﬁle.lst . .dump* . The format is documented in cdbﬁleformat.Assembler source ﬁle created by the compiler • sourceﬁle.
3.adb .asm .

rel foo1. Libraries created in this manner can be included in the command line.lib in the directory mylib (if that is not the same as your current project): sdcc foomain. . The lib ﬁle
1 the command backﬁlls unused memory with 0x12 and the overall 16 bit sum of the complete 64 kByte block is zero.c (contains some functions) foo2. If the program counter on an mcs51 runs wild the backﬁll pattern 0x12 will be interpreted as an lcall to address 0x1212 (where an emergency routine could sit).1.c (contains some more functions) foomain. since the linkage editor processes ﬁle in the order they are presented to it. split.ihx -intel -o sourceﬁle.c (contains more functions and the function main) The ﬁrst two ﬁles will need to be compiled separately with the commands: sdcc -c foo1.c Then compile the source ﬁle containing the main() function and link the ﬁles together with the following command: sdcc foomain.3
Projects with Multiple Source Files
SDCC can compile only ONE ﬁle at a time.lib library ﬁle. Here is an example.c sdcc foomain.lib -L mylib Note here that mylib must be an absolute path name. You can view this ﬁle to troubleshoot linking problems such as those arising from missing libraries. USING SDCC
The separately available srecord package additionally allows to set undeﬁned locations to a predeﬁned value.c can be separately compiled as well: sdcc -c foomain.. xor) and to perform other manipulations (convert.rel foo2.
22
.1. Make sure you include the -L <library-path> option to tell the linker where to look for these ﬁles if they are not in the current directory.net/projects/srecord .c foo1. offset. crop.hex -intel -ﬁll 0x12 0x0000 0xfffe -little-endian-checksum-negative 0xfffe 0x02 0x02 -o source-
The srecord package is available at http://sf.hex -intel An example for a more complex command line1 could look like:
srec_cat sourceﬁle. add. Let us for example assume that you have a project containing the following ﬁles: foo1. COMPILING
CHAPTER 3. The linker is invoked from SDCC using a script ﬁle with extension . The most efﬁcient way to use libraries is to keep separate modules in separate source ﬁles.
3. srec_cat sourceﬁle.lnk.
3.c and a library foolib.rel The ﬁle containing the main() function MUST be the FIRST ﬁle speciﬁed in the command line. see the documentation for the assembler and linkage editor (which are in <installdir>/share/sdcc/doc) for how to create a .c foolib.c sdcc -c foo2.). to insert checksums of various ﬂavours (crc.4
Projects with Additional Libraries
Some reusable routines may be compiled into a library..1. assuming you have the source ﬁle foomain.ihx -intel ﬁle. foomain.3.rel Alternatively.rel foo2.

start by compiling all the required modules.lib _divsint. and _mulint.rel Or.rel _mulint. To display a list of options supported by sdcclib type: sdcclib -? To create a new library ﬁle.lib myliblist.c sdcc -c _divuint. For an example see the standard library ﬁle libsdcc.rel _modsint. if the ﬁle ’myliblist.lib _divuint.1.rel _divuint. For example: set SDCCLIB_CC=sdcc -c sdcclib -l libint. _divuint. For example. If a list of . it will be replaced.rel ﬁle for each entry on the library ﬁle as described in the preceding section. options -s and -m are available.txt To see what modules and symbols are included in the library.rel _mulint.c This will create ﬁles _divsint.lib _mulint.rel.lib myliblist.lib _divsint. This results in a larger library ﬁle.rel sdcclib libint.rel _modsint.1.3.rel.rel ﬁles.rel sdcclib libint. USING SDCC
now should name all the modules.lib _moduint. For example: sdcc -c _divsint. if you preffer: sdcclib libint. _moduint. COMPILING
CHAPTER 3. the packed library ﬁle contains an index of all include modules and symbols that signiﬁcantly speeds up the linking process.rel: 23
.rel ﬁles to the library ﬁle: sdcclib libint.lib in the directory <installdir>/share/lib/small.rel sdcclib libint.lib _modsint. you can instruct sdcclib to compiles the ﬁles before adding them to the library.rel If the ﬁle already exists in the library. sdcclib can be used to embed all the modules belonging to such library in the library ﬁle itself.rel ﬁles is available.c sdcc -c _moduint.c sdcc -c _mulint.rel. For example: sdcclib -s libint.txt’ contains _divsint.rel.rel Use sdcclib -l libint.5
Using sdcclib to Create and Manage Libraries
Alternatively. This is achieved using the environment variables SDCCLIB_CC and/or SDCCLIB_AS. The next step is to add the .rel _moduint.rel sdcclib libint. instead of having a .
3.txt Additionally. _modsint. but it greatly reduces the number of disk ﬁles accessed by the linker.c sdcc -c _modsint.lib _divsint. you can tell sdcclib to add those ﬁles to a library.rel _divuint. Additionally.rel.rel _moduint.

Mac OS X.cygwin. Library ﬁles created using sdcclib are used as described in the preceding sections.rel ﬁles> asranlib <library name>.org/.1.3. since all the information required for linking is embedded in the library ﬁle itself.2. which produces the ar symbol lookup table.2
3.9. several unix ﬂavors) so it is not included in the sdcc package.
3. Once a . For Windows platform you can ﬁnd ar utility in GNU binutils package included in several projects: Cygwin at http://www.rel: __moduint_a_1_1 __moduint_PARM_2 __moduint_count_1_1 __moduint _mulint.mingw.2.lib
3. COMMAND LINE OPTIONS __divsint_a_1_1 __divsint_PARM_2 __divsint _divuint.lib <list of . Generate code for the Dallas DS80C400 processor.rel: __mulint_PARM_2 __mulint
CHAPTER 3. called asranlib.rel: __modsint_a_1_1 __modsint_PARM_2 __modsint _moduint. USING SDCC
If the source ﬁles are compiled using --debug. This is the default processor target. MinGW at http://www. Generate code for the Dallas DS80C390 processor. The library ﬁles created with sdcclib are plain text ﬁles. Ar is a standard archive managing utility on unices (Linux.0.com/. Ar doesn’t understand the sdas object ﬁle format. the corresponding debug information ﬁle .adb ﬁle) is added to a library using sdcclib. It is not recommended to modify a library ﬁle created with sdcclib using a text editor. 24
-mmcs51 -mds390 -mds400
. Both the GNU and BSD ar format variants are suppurated by sdld linkers. so they can be viewed with a text editor. it can be safely deleted. so there is a special version of ranlib distributed with sdcc.1
Command Line Options
Processor Selection Options
Generate code for the Intel MCS51 family of processors. To create a library containing sdas object ﬁles.adb will be include in the library ﬁle as well. as there are ﬁle indexes numbers located across the ﬁle used by the linker to quickly locate the required module to link.rel: __divuint_a_1_1 __divuint_PARM_2 __divuint_reste_1_1 __divuint_count_1_1 __divuint _modsint. you should use the following sequence: ar -Sq <library name>.rel ﬁle (as well as a .6
Using ar to Create and Manage Libraries
Support for ar format libraries was introduced in sdcc 2.

‘-M’ implies ‘-E’. not complete). Generate code for the Atmel AVR processor (Not maintained. 25
. USING SDCC
Generate code for the GameBoy Z80 processor (Not actively maintained).h” ﬁles. Tell the preprocessor to output only a list of the macro deﬁnitions that are in effect at the end of preprocessing.
-D<macro[=value]> Command line deﬁnition of macros. not complete). Passed to the preprocessor. The list of rules is printed on standard output instead of the preprocessed C program. COMMAND LINE OPTIONS -mhc08 -mz80 -mgbz80 -mavr Generate code for the Freescale/Motorola HC08 family of processors.. which is based on the gcc compiler. Used with the ‘-E’ option. -Umacro -dM -dD -dN Undeﬁne macro macro.
3. z80-sdcc) or by calling SDCC from a suitable link. For each source ﬁle. in their proper sequence in the rest of the output. Like ‘-dD’ except that the macro arguments and contents are omitted.gnu.net/index. avrfreaks.
SDCC inspects the program name it was called with so the processor family can also be selected by renaming the sdcc binary (to f.
CHAPTER 3. AVR users should have a look at winavr http://sourceforge. Tell the preprocessor not to discard comments. Generate code for the Microchip PIC 14-bit processors (p16f84 and variants. but before any ‘-include’ and ‘-imacros’ options. Generate code for the Zilog Z80 family of processors. Generate code for the Microchip PIC 16-bit processors (p18f452 and variants. Tell the preprocessor to pass all macro deﬁnitions into the output. not complete).
-mpic14
-mpic16
-mtlcs900h Generate code for the Toshiba TLCS-900H processor (Not maintained. -M Tell the preprocessor to output a rule suitable for make describing the dependencies of each object ﬁle.
-C -MM
-Aquestion(answer) Assert the answer answer for question. org/).2. Option -m has higher priority than setting from program name.h> or “.e.3. -mxa51 Generate code for the Phillips XA51 processor (Not maintained. This rule may be a single line or may be continued with ‘\’-newline if it is long. If you need more dedicated options than those listed below please refer to the GCC CPP Manual at http://www.2. -I<path> The additional location where the preprocessor will look for <. ‘-A-’ disables the standard assertions that normally describe the target machine.2
Preprocessor Options
SDCC uses an adapted version of the GNU Compiler Collection preprocessor cpp (gcc http://gcc.php?name=PNphpBB2&file=index. not complete). Only ‘#deﬁne name’ is included in the output. not complete). ‘-U’ options are evaluated after all ‘-D’ options.gnu. the preprocessor outputs one make-rule whose target is the object ﬁle name for that source ﬁle and whose dependencies are all the ﬁles ‘#include’d in it. In development.org/software/gcc/onlinedocs/. In development. Used with the ‘-E’ option.net/projects/winavr or http://www.. System header ﬁles included with ‘#include <ﬁle>’ are omitted. Like ‘-M’ but the output mentions only the user header ﬁles included with ‘#include “ﬁle"’. in case it is tested with a preprocessor conditional such as ‘#if #question(answer)’.

The format itself is documented in the documentation of srecord. --xstack-loc 0x8000 or --stack-loc 32768. --data-loc <Value> The start location of the internal ram data segment. Pass the linkOption to the linker. e. --out-fmt-s19 The linker output (ﬁnal object code) is in Motorola S19 format.. The value entered can be in Hexadecimal or Decimal format.linkOption].g. The format itself is documented in the documentation of srecord. the data segment will be set. This is the default option. --stack-loc 0x20 or --stack-loc 32. default value is 0. --xstack-loc <Value> By default the external stack is placed after the pdata segment. if --data-loc is not used.19 .: --code-loc 0x8000 or --code-loc 32768. (By default. -Wl-bCSEG=0x1000). File sdcc/as/doc/asxhtm.preprocessorOption].3. Either use the double quotes around this option or use no space (e. (Currently only supported for the HC08 processors) -Wl linkOption[.. --code-loc <Value> The start location of the code segment. If a bootloader is used an option like ”-Wl bCSEG=0x1000” would be typical to set the start of the code segment. --idata-loc 0x88 or --idata-loc 136. Using this option the xstack can be placed anywhere in the external memory space of the 8051.2. to location 0x10. e. The value entered can be in Hexadecimal or Decimal format. eg. --out-fmt-ihx The linker output (ﬁnal object code) is in Intel Hex format. the initial sp will be set to one byte prior the provided value. taking into account the used register banks and the bit segment at address 0x20. default value is 0x80. e. --out-fmt-elf The linker output (ﬁnal object code) is in ELF format.
26
.3
Linker Options
-L --lib-path <absolute path to additional libraries> This option is passed to the linkage editor’s additional libraries search path. Instead an option can be passed directly to the linker: -Wl -bBSEG=<Value>. Since the sp register is incremented before a push or call. The provided value should not overlap any other memory areas such as used register banks or the data segment and with enough space for the current application. The provided value should not overlap any other memory areas such as the pdata or xdata segment and with enough space for the current application. --stack-loc <Value> By default the stack is placed after the data segment. The value entered can be in Hexadecimal or Decimal format. The value entered can be in Hexadecimal or Decimal format. For example if register banks 0 and 1 are used without bit variables. Note when this option is used the interrupt vector table is also relocated to the given address. Additional library ﬁles may be speciﬁed in the command line.19 Note: this functionality is not in conformance with C99 standard! -Wp preprocessorOption[.g.. COMMAND LINE OPTIONS
CHAPTER 3.: --xram-loc 0x8000 or --xram-loc 32768. --bit-loc <Value> The start location of the bit addressable internal ram of the 8051. The value entered can be in Hexadecimal or Decimal format. This is not implemented yet. default value 0.html has more on linker options. See also #pragma pedantic_parse_number on page 56 in section3. Pass the preprocessorOption to the preprocessor sdcpp.
3.. e. --data-loc 0x20 or --data-loc 32.) --idata-loc <Value> The start location of the indirectly addressable internal ram of the 8051. The value entered can be in Hexadecimal or Decimal format.g. USING SDCC
-pedantic-parse-number Pedantic parse numbers so that situations like 0xfe-LO_B(3) are parsed properly and the macro LO_B(3) gets expanded.g. --xram-loc <Value> The start location of the external ram.2. The --pack-iram option (which is now a default setting) will override this setting. Using this option the stack can be placed anywhere in the internal memory space of the 8051. so you should also specify the --no-pack-iram option if you need to manually place the stack. See also #pragma constseg and #pragma codeseg in section 3. The path name must be absolute. eg. the start location of the internal ram data segment is set as low as possible in memory. See section Compiling programs for more details.g.

--xram-size <Value> Causes the linker to check if the external ram usage is within limits of the given value.1.2. This is the one and only that the ds390 code generator supports right now and is default when using -mds390. --stack-size <Value> Causes the linker to check if there is at minimum <Value> bytes for stack. See section Memory Models for more details. If this option is used all source ﬁles in the project have to be compiled with this option. see section Memory Models for more details. --no-pack-iram Causes the linker to use old style for allocating memory areas. This means that only the lower 256 bytes of the potential 1K stack space will actually be used. see section Memory Models for more details.2. idata and stack together. See section 3. --stack-probe insert call to function __stack_probe at each function prologue.5
DS390 / DS400 Options
--model-ﬂat24 Generate 24-bit ﬂat mode code. It is important to ensure that the processor is in this mode before calling any re-entrant functions compiled with this option. However. --xstack Uses a pseudo stack in the pdata area (usually the ﬁrst 256 bytes in the external ram) for allocating variables and passing parameters. It is incompatible with the --xstack option. --model-medium Generate code for Medium model programs. Note that the support is incomplete. --stack-10bit Generate code for the 10 bit stack mode of the Dallas DS80C390 part. --tini-libid <nnnn> LibraryID used in -mTININative.4
MCS51 Options
--model-small Generate code for Small Model programs. the stack is located in the lower 1K of the internal RAM. --model-large Generate code for Large model programs.. This is the default now. It also only makes sense if the processor is in 24 bit contiguous addressing mode (see the --model-ﬂat24 option).2 External Stack for more details. --protect-sp-update disable interrupts during ESP:SP updates. It must also be used when invoking the linker.
--iram-size <Value> Causes the linker to check if the internal ram usage is within limits of the given value. This is the default model. You may need to use this option for some 8051 derivatives which lack the lcall/ljmp instructions. --code-size <Value> Causes the linker to check if the code memory usage is within limits of the given value. but that has not been tested.
3. --acall-ajmp Replaces the three byte instructions lcall/ljmp with the two byte instructions acall/ajmp.18.3. If this option is used all source ﬁles in the project have to be compiled with this option. --pack-iram Causes the linker to use unused register banks for data variables and pack data. The compiler will not generate any code to put the processor into 10 bit stack mode. which is mapped to 0x400000. see section Memory Models for more details. COMMAND LINE OPTIONS
CHAPTER 3. this does allow you to reclaim the precious 256 bytes of low RAM for use for the DATA and IDATA segments. In this mode. this should work with the --stack-auto option. It must also be used when invoking the linker.2.
27
. --use-accelerator generate code for DS390 Arithmetic Accelerator. USING SDCC
3. In principle. This is the one and only that the ds390 code generator supports right now and is default when using -mds390. since it still uses a single byte as the stack pointer. Only use this option if your code is in the same 2k block of memory.

rel object ﬁle. USING SDCC
3. --constseg <Value> Use <Value> for the const segment name. It is recommended that this option NOT be used. It is recommended that this option is NOT used.6
Z80 Options
--callee-saves-bc Force a called function to always save BC.7 Switch Statements for more details.2. #pragma nojtbound can be used to turn off boundary checking for jump tables for a given function only. #pragma noinduction can be used to turn off induction optimizations for a given function only.3. sdasz80. COMMAND LINE OPTIONS
CHAPTER 3. see section strength reduction for more details.
3. --nolabelopt Will not optimize labels (makes the dumpﬁles more readable). --noloopreverse Will not do loop reversal optimization. --codeseg <Value> Use <Value> for the code segment name. --constseg <Value> Use <Value> for the const segment name. --asm=<Value> Deﬁne assembler name (<Value> is rgbds.4.2. A warning message will be generated when this happens and the compiler will indicate the number of extra bytes it allocated. You must provide your own crt0. skip the standard crt0. --no-xinit-opt Will not memcpy initialized data from code space into xdata space. It is recommended that this option NOT be used. this option may be used when the compiler creates undesirably large stack/data spaces to store compiler temporaries (spill locations. sloc).7
GBZ80 Options
--callee-saves-bc Force a called function to always save BC.2.1. #pragma noinvariant can be used to turn off invariant optimizations for a given function only. skip the standard crt0. You must provide your own crt0.8
--nogcse
Optimization Options
Will not do global subexpression elimination.
--noinvariant Will not do loop invariant optimizations. isas or z80asm).rel for your system when linking. --nojtbound Will not generate boundary condition check when switch statements are implemented using jumptables.rel for your system when linking. This saves a few bytes in code space if you don’t have initialized data. -ba <Num> Use data bank <Num>. See section 8.
28
.
3. this may be turned off for reasons explained for the previous option. --portmode=<Value> Determinate PORT I/O mode (<Value> is z80 or z180).rel object ﬁle. --codeseg <Value> Use <Value> for the code segment name. -bo <Num> Use code bank <Num>. --no-std-crt0 When linking. It is recommended that this option is NOT used. --noinduction Will not do loop induction optimizations.2. #pragma nogcse can be used to turn off global subexpression elimination for a given function only. For more details of loop optimizations performed see Loop Invariants in section 8.1. --no-std-crt0 When linking.

If this option is used all source ﬁles in the project should be compiled with this option. --peep-ﬁle <ﬁlename> This option can be used to use additional rules to be used by the peep hole optimizer. The ﬁle name for the assembler output must be speciﬁed using the -o option. Run only the C preprocessor. the parameters and local variables will be allocated on the stack. Note for Windows users: if the path contains spaces. Preprocess all the C source ﬁles speciﬁed and output the results to standard output. The compiler will not save registers when calling these functions. COMMAND LINE OPTIONS
CHAPTER 3..2..
29
. This option can be used to switch the register saving convention for the function names speciﬁed. no extra code will be generated at the entry and exit (function prologue and epilogue) for these functions to save and restore the registers used by these functions. it must have a trailing slash (or backslash for the Windows binaries) to be recognized as a path. if this option is used for a library function the appropriate library function needs to be recompiled with the same option. The path using slashes for directory delimiters can be used too. If the project consists of multiple source ﬁles then all the source ﬁle should be compiled with the same --callee-saves option string. The trailing backslash should be doubled in order to prevent escaping the ﬁnal quote. possibly at the expense of code speed.
3. i.13 Peep Hole optimizations for details on how to write these rules. --opt-code-size The compiler will optimize code generation towards compact code. See section 8.. --opt-code-speed The compiler will optimize code generation towards fast code. In the future the compiler (with inter procedural analysis) will be able to determine the appropriate scheme to use for each function call.. It automatically implies --int-long-reent and --ﬂoat-reent. This can cause unexpected changes to inline assembler code. --callee-saves function1[. it should be surrounded by quotes.3. USING SDCC
--nooverlay The compiler will not overlay parameters and local variables of any function.
-o <path/ﬁle> The output path where everything will be placed or the ﬁle name used for all generated output ﬁles.function2][. --c1mode -E reads the preprocessed source from standard input and compiles it. Also see #pragma callee_saves on page 55. but will not call the linkage editor. -c --compile-only will compile and assemble the source. --peep-asm Pass the inline assembler code through the peep hole optimizer. for example: -o ”F:/Projects/test3/output 1/”.2. possibly at the expense of code size. for example: -o ”F:\Projects\test3\output 1\\” or put after the ﬁnal quote. If the parameter is a path.function3]. --no-peep Disable peep-hole optimization with built-in rules. See section 3.def’ before using this option.. however this can cause unnecessary register pushing and popping when calling small functions from larger functions. for example: -o ”F:\Projects\test3\output 1”\. please go through the peephole optimizer rules deﬁned in the source ﬁle tree ’<target>/peeph. this can SUBSTANTIALLY reduce code and improve run time performance of the generated code. --stack-auto All functions in the source ﬁle will be compiled as reentrant. The compiler by default uses a caller saves convention for register saving across function calls..e.1. --all-callee-saves Function of --callee-saves will be applied to all functions by default. DO NOT use this option for built-in functions such as _mulint.7 Parameters and Local Variables for more details. see section Parameters and local variables for more details.9
Other Options
-v --version displays the sdcc version.

Stop after the stage of compilation proper. --verbose -V Shows the various actions the compiler is performing. --disable-warning <nnnn> Disable speciﬁc warning with number <nnnn>. The message contains some important information about the function. --nostdinc This will prevent the compiler from passing on the default include path to the preprocessor. In some embedded environments the default signedness of char is unsigned. --ﬂoat-reent Floating point library is compiled as reentrant. Sounds like noise but is most helpful for debugging the compiler itself. integration into most programming editors should be straightforward. generate a ’sjmp . --main-return This option can be used if the code generated is called by a monitor program or if the main routine includes an endless loop. --Werror Treat all warnings as errors. For more details. and most importantly the cyclomatic complexity see section on Cyclomatic Complexity for more details. The number of edges and nodes the compiler detected in the control ﬂow graph of the function.
-S
--int-long-reent Integer (16 bit) and long (32 bit) libraries have been compiled as reentrant. -Wa asmOption[. --less-pedantic Disable some of the more pedantic warnings. See section Installation for more details. With SDCC both offering a GCC-like (the default) and a MSVC-like output style.cd 30
.. see the less_pedantic pragma on page 55.asmOption]. Note by default these libraries are compiled as non-reentrant.3. All other types are unaffected. To set the signess for characters to unsigned.
--no-c-code-in-asm Hides your ugly and inefﬁcient c-code from the asm ﬁle. Shows the actual commands the compiler is executing.
--use-stdout Send errors and warnings to stdout instead of stderr. a char will be signed. Pass the asmOption to the assembler. See section Installation for more details. See ﬁle sdcc/as/doc/asxhtm. The return from the ’main’ function will return to the function calling main.2. This option results in slightly smaller code and saves two bytes of stack space.’.
--print-search-dirs Display the directories in the compiler’s search path --vc Display errors and warnings using MSVC style. The output is an assembler code ﬁle for the input ﬁle speciﬁed. The debug information collected in a ﬁle with . For more information see documentation for SDCDB. COMMAND LINE OPTIONS --debug
CHAPTER 3. use the option -funsigned-char.e. --funsigned-char The default signedness for every type is signed.. If this option is set and no signedness keyword (unsigned/signed) is given. --nostdlib This will prevent the compiler from passing on the default library path to the linker. so you can always blame the compiler :) --fverbose-asm Include code generator and peep-hole comments in the generated asm ﬁles.cdb extension can be used with the SDCDB. --cyclomatic This option will cause the compiler to generate an information message for each function in the source ﬁle. --i-code-in-asm Include i-codes in the asm ﬁle. The default setting is to lock up i.html for assembler options. --no-peep-comments Don’t include peep-hole comments in the generated asm ﬁles even if --fverbose-asm option is speciﬁed. Another ﬁle with no extension contains debug information in AOMF or AOMF51 format which is commonly used by third party tools. USING SDCC
When this option is used the compiler will generate debug information. do not assemble. so you can use SDCC with the visual studio IDE.

--dumprange Will create a dump of iCodes. into a ﬁle named <source ﬁlename>. but allow SDCC features that conﬂict with the standard (incomplete support). into a ﬁle named <source ﬁlename>.dumprange. USING SDCC
--std-sdcc89 Generally follow the C89 standard.org/manual/ and it’s capabilities go beyond pure syntax checking.dumprassgn. into a ﬁle named <source ﬁlename>. --more-pedantic Actually this is not a SDCC compiler option but if you want more warnings you can use a separate tool dedicated to syntax checking like splint http://www.org.e. default CONST. --dumpdeadcode Will create a dump of iCodes. The basic blocks at this stage ordered in the depth ﬁrst number. --dumpregassign Will create a dump of iCodes.3. --std-c99 Follow the C99 standard and disable SDCC features that conﬂict with the standard (incomplete support). 31
.dumploop.
--std-sdcc99 Generally follow the C99 standard. before any optimizations are done. after register assignment.4)
3. This is useful if you need to tell the compiler to put the const data in a special segment so you can later on tell the linker to put this segment in a special place in memory.2. --fdollars-in-identiﬁers Permit ’$’ as an identiﬁer character.2. --std-c89 Follow the C89 standard and disable SDCC features that conﬂict with the standard. You’ll need to tell splint the location of SDCC’s include ﬁles so a typical command line could look like this: splint -I /usr/local/share/sdcc/include/mcs51/ myprogram. --dumpraw This option will cause the compiler to dump the intermediate code into a ﬁle of named <source ﬁlename>. COMMAND LINE OPTIONS
CHAPTER 3.splint.1 ”The anatomy of the compiler”. To make your source ﬁles parseable by splint you will have to include lint.dumpraw just after the intermediate code has been generated for a function. This is useful if you need to tell the compiler to put the code in a special segment so you can later on tell the linker to put this segment in a special place in memory. --dumploop Will create a dump of iCodes. Splint has an excellent on line manual at http://www.c --short-is-8bits Treat short as 8-bit (for backward compatibility with older versions of compiler .10
Intermediate Dump Options
The following options are provided for the purpose of retargetting and debugging the compiler. but allow SDCC features that conﬂict with the standard (default).
--codeseg <Name> The name to be used for the code segment.see section 1. i.h in your source ﬁle and add brackets around extended keywords (like ”__at (0xab)” and ”__interrupt (2)”). after deadcode elimination. --constseg <Name> The name to be used for the const segment. --dumlrange Will dump the life ranges for all symbols.splint. after live range analysis. --dumpgcse Will create a dump of iCodes. after global subexpression elimination. They provide a means to dump the intermediate code (iCode) generated by the compiler in human readable form at various stages of the compilation process. into a ﬁle named <source ﬁlename>. Can be used for instance when using bank switching to put the const data in a bank. so they may not be in sequence of execution.dumpdeadcode. after loop optimizations. More on iCodes see chapter 9. into a ﬁle named <source ﬁlename>.dumpgcse. Can be used for instance when using bank switching to put the code in a bank. default CSEG.

USING SDCC
3. and there’s no need to set them.1
Storage Class Language Extensions
MCS51/DS390 Storage Class Language Extensions
In addition to the ANSI storage classes SDCC allows the following MCS51 speciﬁc storage classes: 3. To force all messages to ”standard output” use --use-stdout. SDCC_LIB Path.#0x01
you are curious search in SDCC’s sources for ”getenv”
32
. In a standard *nix environment these variables are not set. Writing 0x01 to this variable generates the assembly code: 75*00 01
2 if
mov
_test_data..2. see section 2. if you happen to have visual studio installed in your windows machine. There are some more environment variables recognized by SDCC. SDCC_INCLUDE Path.2 ” Install Paths”.1 data / near
This is the default storage class for the Small Memory model (data and near or the more ANSI-C compliant forms __data and __near can be used synonymously).g. TMP.exe --vc --model-large -c $(InputPath)
3. e.3 ”Search Paths”. SDCC_HOME Path.: __data unsigned char test_data.4. TEMP. If this environment variable is set. you can use it to compile your sources using a custom build and the SDCC --vc option. see section 2. They can change or disappear very quickly. ENVIRONMENT VARIABLES --dumplrange Will create a dump of the live ranges of iTemp’s --dumpall Will cause all the above mentioned dumps to be created. see section 2. but these are mainly used for debugging purposes.1.3 ”Search Paths”. SDCC won’t install the signal handler in order to be able to debug SDCC.
CHAPTER 3. The order of the variables is the search order.4. Something like this should work: c:\sdcc\bin\sdcc. Variables declared with this storage class will be allocated in the directly addressable portion of the internal RAM of a 8051. TMPDIR Path. Additionally.
3. where temporary ﬁles will be created.3
Environment variables
SDCC recognizes the following environment variables: SDCC_LEAVE_SIGNALS SDCC installs a signal handler to be able to delete temporary ﬁles after an user break (^C) or an exception.3. On Windows it’s recommended to set one of them.3. and will never be documented2 .11
Redirecting output on Windows Shells
By default SDCC writes its error messages to ”standard error”.4
3.

2 xdata / far
CHAPTER 3. pdata access physically accesses xdata memory.’e’. The high byte of the address is determined by port P2 (or in case of some 8051 variants by a separate Special Function Register.#0x01 movx @r0.4.1). the ﬁrst 128 byte of idata physically access the same RAM as the data memory.’a’.#_test_array movc a.#0x01
Please note. e.’h’.#_test_idata @r0. 3.g.g.#_test_code clr a movc a._index mov dptr. Read access to this variable generates the assembly code: 90s00r6F E4 93 mov dptr.: __xdata unsigned char test_xdata. Writing 0x01 to this variable generates the assembly code: 78r00 76 01 mov mov r0.4. The original 8051 had 128 byte idata memory.a
If the --xstack option is used the pdata memory area is followed by the xstack memory area and the sum of their sizes is limited to 256 bytes.#_test_xdata mov a. The stack is located in idata memory. This is the default storage class for the Large Memory model.: __idata unsigned char test_idata.1. It is typically located at the start of xdata and has a maximum size of 256 bytes.1.#_test_pdata mov a.5 code
’Variables’ declared with this storage class will be placed in the code memory: __code unsigned char test_code.3 idata mov dptr. USING SDCC
Variables declared with this storage class will be placed in the external RAM.3. see section 4. Read access to this array using an 8-bit unsigned index generates the assembly code: E5*00 90s00r41 93 mov a. 3. Writing 0x01 to this variable generates the assembly code: 78r00 74 01 F2 mov r0.4.a
Variables declared with this storage class will be allocated into the indirectly addressable portion of the internal ram of a 8051.4.1. nowadays most devices have 256 byte idata memory. The following example writes 0x01 to the pdata variable. e.: __pdata unsigned char test_pdata.1. Writing 0x01 to this variable generates the assembly code: 90s00r00 74 01 F0 3. e.#0x01 movx @dptr.g. Please note.@a+dptr 33
. STORAGE CLASS LANGUAGE EXTENSIONS 3.’p’}.@a+dptr
char indexed arrays of characters in code memory can be accessed efﬁciently: __code char test_array[] = {’c’. This is the default storage class for the Medium Memory model.4.4 pdata
Paged xdata access is just as straightforward as using the other addressing modes of a 8051.

USING SDCC
This is a data-type and a storage class speciﬁer. they are used to describe the special f unction registers and special bit variables of a 8051. e.h and sup-
34
. but nevertheless showing what bitﬁelds are about: port/regression/tests/bitﬁelds. In accordance with ISO/IEC 9899 bits and bitﬁelds without an explicit signed modiﬁer are implemented as unsigned.1). /* pointer physically in external ram pointing to object in internal ram */ __data unsigned char * __xdata p. 3. Please note. it is allocated into the bit addressable memory of 8051.4. In addition to the explicit pointers. Apart from this 8051 speciﬁc storage class most architectures support ANSI-C bitﬁelds3 . if you use a header ﬁle which was written for another compiler then the sfr / sfr16 / sfr32 / sbit Storage Class extensions will most likely be not compatible. this is not guaranteed.4.6 bit
CHAPTER 3.1. an sbit addresses a speciﬁc bit within these sfr. is compiled without warning by SDCC to an assignment of 0x80 to a variable called P0 . __sbit __at (0xd7) CY. 0x80 */ /* special function register P0 at location
/* 16 bit special function register combination for timer 0 with the high byte at location 0x8C and the low byte at location 0x8A */ __sfr16 __at (0x8C8A) TMR0.h it is possible to write header ﬁles which can be shared among different compilers (see section 6.1.8 Pointers to MCS51/DS390 speciﬁc memory spaces
SDCC allows (via language extensions) pointers to explicitly point to any of the memory spaces of the 8051. sfr / sfr16 / sfr32 / sbit signify both a data-type and storage class.g.7 sfr / sfr16 / sfr32 / sbit
Like the bit keyword. Pointer declaration examples: /* pointer physically in internal ram pointing to object in external ram */ __xdata unsigned char * __data p. Speciﬁcally the syntax sfr P0 = 0x80. /* CY (Carry Flag) */
Special function registers which are located on an address dividable by 8 are bit-addressable. Nevertheless with the ﬁle ! compiler. 16 Bit and 32 bit special function register combinations which require a certain access order are better not declared using sfr16 or sfr32.4.3. the compiler uses (by default) generic pointers which can be used to point to any of the memory spaces.: __bit test_bit.4. When a variable is declared as a bit.
3 Not really meant as examples. STORAGE CLASS LANGUAGE EXTENSIONS 3. 3.1. eg: __sfr __at (0x80) P0. Writing 1 to this variable generates the assembly code: D2*00 setb _test_bit
The bit addressable memory consists of 128 bits which are located from 0x20 to 0x2f in data memory. Allthough SDCC usually accesses them Least Signiﬁcant Byte (LSB) ﬁrst.c
device/include/mc68hc908qy.

16 bytes to hold 128 bit variables and. /* generic pointer physically located in default memory space */ unsigned char * p.3. Additionally some members of the MCS51 family may have up to 128 bytes of additional. then you can adjust it. This implies that as the stack grows. don’t specify any options and see if the resulting memory layout is appropriate. but it is possible to specify that other banks of registers (keyword using ) should be used for example in interrupt routines. Option --stack-loc allows you to specify the start of the stack. Same goes for the code memory. /* generic pointer physically located in xdata space */ unsigned char * __xdata p. data variables will be placed starting from address 0x10 to 0x20 and continue at address 0x22. Well you get the idea. By default the 8051 linker will place the stack after the last byte of (i)data variables. it will position the base of the internal stack at address 20 (0x14). the data variables will be placed in unused register banks and after the byte holding the last bit variable.1. Sometimes this built in xdata memory has to be activated before using it (you can probably ﬁnd this information on the datasheet of the microcontroller your are using. STORAGE CLASS LANGUAGE EXTENSIONS
CHAPTER 3.9 Notes on MCS51 memory layout
The 8051 family of microcontrollers have a minimum of 128 bytes of internal RAM memory which is structured as follows: . internal RAM memory (idata).Bytes 30-7F . If in doubt. it will use up the remaining register banks. All unqualiﬁed pointers are treated as 3-byte (4-byte for the ds390) generic pointers. and the 16 bytes used by the 128 bit variables. if the ﬁrst 2 banks of registers are used. /* the following is a function pointer physically located in data space */ char (* __data fp)(void).4.80 bytes for general purpose use. if register banks 0 and 1 are used. If your microcontroller has additional indirectly addressable internal RAM (idata) you can place the stack on it. For example. you could start it after any data in the general purpose area. USING SDCC
/* pointer physically in code rom pointing to data in xdata space */ __xdata unsigned char * __code p. The highest order byte of the generic pointers contains the data space information. 3. directly addressable RAM memory (data). i.32 bytes to hold up to 4 banks of the registers R0 to R7.Bytes 20-2F . some chips may have some built in external memory (xdata) which should not be confused with the internal. . . Explicitly specifying the pointer type will generate the most efﬁcient code. 35
. and there are 9 bit variables (two bytes used). using --code-loc and --code-size. see also section 3. You can also use --dataloc to specify the start address of the data and --iram-size to specify the size of the total internal RAM (data+idata). For example.e. and only four bytes are used for data variables. Assembler support routines are called whenever data is stored or retrieved using generic pointers. /* pointer physically in code space pointing to data in code space */ __code unsigned char * __code p. and 80 bytes for general purpose use.4. If any bit variables are used. indirectly addressable. By default.Bytes 00-1F . These are useful for developing reusable library routines. the compiler will place the stack after the last byte of allocated memory for variables.12 Startup-Code). Normally SDCC will only use the ﬁrst bank of registers (register bank 0). Furthermore. You may also need to use --xdata-loc to set the start address of the external RAM (xdata) and --xram-size to specify its size.

The ﬁrst. This feature is only enabled when the compiler is invoked using –std-sdccxx. IoPort */ /* define a var in I/O space at 78h called
Writing 0x01 to this variable generates the assembly code: 3E 01 D3 78 3.
3. The HC08 is most efﬁcient at accessing variables (especially pointers) stored here.mem ﬁles to ﬁnd out what the problem is.4. This is the default if no storage class is speciﬁed. OTHER SDCC LANGUAGE EXTENSIONS
CHAPTER 3. The second with extension .g.3. there is not enough memory.#0x01 out (c).5
3.4.h this will be set automatically. e. If you get any linking warnings and/or errors related to stack or segments allocation.a
banked sfr (in/out to 16-bit addresses)
The keyword banked is used to support 16 bit addresses in I/O memory e.4. or there is not enough space for stack. with extension .
3. Writing 0x01 to this variable generates the assembly code: 01 23 01 3E 01 ED 79 3.a
sfr (in0/out0 to 8 bit addresses on Z180/HD64180)
The compiler option --portmode=180 (80) and a compiler #pragma portmode z180 (z80) is used to turn on (off) the Z180/HD64180 port addressing instructions in0/out0 instead of in/out.1
HC08 Storage Class Language Extensions
data
The data storage class declares a variable that resides in the ﬁrst 256 bytes of memory (the direct page). USING SDCC
The linker generates two ﬁles with memory allocation information.map shows all the variables and segments.2.mem ﬁle may even suggest a solution to the problem. take a look at either the .4. The .mem shows the ﬁnal memory layout.4.5. If you include the ﬁle z180.2 xdata
The xdata storage class declares a variable that can reside anywhere in memory.4.1
Other SDCC language extensions
Binary constants
SDCC supports the use of binary constants.
36
.4.2
3.5.3
3.: __sfr __at 0x78 IoPort.
3. I/O memory is accessed with special instructions.2 ld a. such as 0b01100010. The linker will complain either if memory segments overlap.map or . 3.: __sfr __banked __at 0x123 IoPort.2.3 ld bc.2.g.#_IoPort ld a.3.3.1
Z80/Z180 Storage Class Language Extensions
sfr (in/out to 8-bit addresses)
The Z80 family has separate address spaces for memory and input/output memory.#0x01 out (_IoPort).

bit 1 */ /* I/O port 0. polarity of data and bit order */ unsigned char spi_io(unsigned char out_byte) { unsigned char i=8. One possible use would be to write hardware portable code. someplace in the code for the ﬁrst hardware you would use __bit __at (0x80) MOSI. /* I/O port 0. The assembler listing ﬁle (.rst) and (. For some architectures (mcs51) array accesses are more efﬁcient if an (xdata/far) array starts at a block (256 byte) boundary (section 3. } while(--i). There is no real advantage to assigning absolute addresses to variables in this manner.13. out_byte <<= 1.6. /* master out. e. USING SDCC
3. If however you provide an initializer actual memory allocation will take place and overlaps will be detected by the linker. __bit __at (0x81) MISO. return out_byte. The above example will allocate the variable at offset 0x02 in the bit-addressable space. ! Thus it is left to the programmer to make sure there are no overlaps with other variables that are declared without the absolute address. do { MOSI = out_byte & 0x80. extern volatile __bit MISO. } Then.lst) and the linker output ﬁles (. in addition to a storage class.g. Absolute addresses can be speciﬁed for variables in all storage classes. E. If needed adapt polarity of clock. */ /* for slow peripherals */ if(MISO) out_byte += 1.g.1 has an example). ABSOLUTE ADDRESSING
CHAPTER 3. extern volatile __bit MCLK. e. slave in */ /* master in. slave out */ /* master clock */
/* Input and Output of a byte on a 3-wire serial bus. bit 2 */ 37
. In the above example the variable Id will be located from 0x7ff0 to 0x7ff4 in code memory. MCLK = 0. In case of memory mapped I/O devices the keyword volatile has to be used to tell the compiler that accesses might not be removed: volatile __xdata __at (0x8000) unsigned char PORTA_8255.:
In the above example the variable chksum will be located at 0x7ffe and 0x7fff of the external ram.: __code __at (0x7ff0) char Id[5] = ”SDCC”. and such pins are different for two different hardwares. bit 0 */ /* I/O port 0.3. MCLK = 1. unless you want strict control over all the variables allocated.: __bit __at (0x02) bvar.
Data items can be assigned an absolute address with the at <address> keyword. if you have a routine that uses one or more of the microcontroller I/O pins. The compiler does not reserve any space for variables declared in this way (they are implemented with an equate in the assembler). For example. /* __asm nop __endasm. you can declare the I/O pins in your routine using: extern volatile __bit MOSI.g.6
Absolute Addressing
__xdata __at (0x7ffe) unsigned int chksum. __bit __at (0x82) MCLK.map) are good places to look for such overlaps.

. bit 1 */ /* I/O port 1. Parameters and local variables of a function will be allocated to an overlayable segment if the function has no other function calls and the function is non-reentrant and the memory model is small. ! Also note that the compiler does not do any processing of inline assembler code. so the compiler might incorrectly assign local variables and parameters of a function into the overlay segment if the inline assembler code calls other c-functions that might use the overlay. . When compiled with --stack-auto or when a function is declared as reentrant this should only be done for static variables.: unsigned char foo(char i) __reentrant { . } Since stack space on 8051 is limited. bvar in bit addressable space and j in internal ram. the reentrant keyword or the --stack-auto option should be used sparingly. __bit __at (0x92) MCLK. The default action of the compiler is to place these variables in the internal RAM (for small model) or external RAM (for medium or large model). e. but only one absolute address has to be speciﬁed in the whole project.g.7. __data __at (0x31) unsigned char j. e. They can be placed on the stack by using the --stack-auto option. It is however allowed to use bit parameters in reentrant functions and also non-static local bit variables are supported.: 38
. } In the above example the parameter parm and the variable i will be allocated in the external ram.
3. bit 2 */
CHAPTER 3. Local variables can be assigned storage classes and absolute addresses.. This is somehow similar to sbit.
3. __bit __at (0x91) MISO. by using #pragma stackauto or by using the reentrant keyword in the function declaration. __bit bvar. it does not mean that the function is register bank independent. as for example in a library. If an explicit storage class is speciﬁed for a local variable.. PARAMETERS & LOCAL VARIABLES Similarly.g. Efﬁcient use is limited to 8 semi-bitregisters in bit space. /* I/O port 0. e. for the second hardware you would use __bit __at (0x83) MOSI.7
Parameters & Local Variables
Automatic (local) variables and parameters to functions can either be placed on the stack or in data-space.g.: unsigned char foo(__xdata int parm) { __xdata unsigned char i. In that case the #pragma nooverlay should be used. Parameters and local variables of functions that contain 16 or 32 bit multiplication or division will NOT be overlaid since these are implemented using external functions. USING SDCC
and you can use the same hardware dependent routine without changes.3. This in fact makes them similar to static so by default functions are non-reentrant.. Functions that are called from an interrupt service routine should be preceded by a #pragma nooverlay if they are not reentrant.8
Overlaying
For non-reentrant functions SDCC will try to reduce internal ram space usage by overlaying parameters and local variables of a function (if possible). it will NOT be overlaid. Note that the reentrant keyword just means that the parameters & local variables will be allocated to the stack. They are pushed and popped to stack as a single byte just like the normal registers. bit 3 */ /* I/O port 1. Note that the compiler (not the linkage editor) makes the decision for overlaying the data items.

the processor needs more than one instruction for the access and could be interrupted while accessing the variable) the interrupt must be disabled during the access to avoid inconsistent data. ..
39
.2 Common interrupt pitfall: non-atomic access
If the access to these variables is not atomic (i. INTERRUPT SERVICE ROUTINES #pragma save #pragma nooverlay void set_error(unsigned char errcd) { P3 = errcd.. We need an example here: f. ”counter += 8.. } #pragma restore void some_isr () __interrupt (2) { .9. Bugs like these are hard to reproduce and can cause a lot of trouble. but a prototype of the isr MUST be present or included in the ﬁle that contains the function main. If you have multiple source ﬁles in your project. The #pragma nooverlay ensures that the parameters and local variables for the function are NOT overlaid. the compiler will insert a call to this routine in the interrupt vector table for the interrupt number speciﬁed.” is not atomic on the 8051 even if counter is located in data memory. Setting ”flags |= 0x40. When present.9.9.1 Common interrupt pitfall: variable not declared volatile
If an interrupt service routine changes variables which are accessed by other functions these variables have to be declared volatile. USING SDCC
In the above example the parameter errcd for the function set_error would be assigned to the overlayable segment if the #pragma nooverlay was not present. on the 8051 the harmless looking ”flags |= 0x80.3.. }
CHAPTER 3.. You’re not automatically on the safe side if you use 8 bit variables though.
The optional number following the interrupt keyword is the interrupt number this routine will service.1
Interrupt Service Routines
General Information
void timer_isr (void) __interrupt (1) __using (1) { . set_error(10).org/wiki/Volatile_variable . Access to 16 or 32 bit variables is obviously not atomic on 8 bit CPUs and should be protected by disabling interrupts. Interrupt service routines open the door for some very interesting bugs: 3.e. with some extended keywords. interrupt service routines can be present in any of them.” is not atomic if flags resides in xdata.wikipedia. 3.1.1. }
SDCC allows interrupt service routines to be coded in C.9
3.9.e. The optional (8051 speciﬁc) keyword using can be used to tell the compiler to use the speciﬁed register bank when generating code for this function. See http://en.
3.. this could cause unpredictable runtime behavior when called from an interrupt service routine.” from within an interrupt routine might get lost if the interrupt occurs at the wrong time.

USING SDCC
The return address and the registers used in the interrupt service routine are saved on the stack so there must be sufﬁcient stack space.1. However.3
HC08 Interrupt Service Routines
Since the number of interrupts available is chip speciﬁc and the interrupt vector table always ends at the last byte of memory. if such an interrupt service routine calls another function (using another register bank) then the entire register bank of the called function will be saved on the stack. multiplication & modulus and ﬂoating-point operations are implemented using external support routines. This stack overﬂow is most likely to happen if the interrupt occurs during the ”deepest” subroutine when the stack is already in use for f. the type promotion required by ANSI C can cause 16 bit routines to be used without the programmer being ! aware of it.. dptr & psw are saved and restored. Furthermore nonreentrant functions should not be called from the main program while the interrupt service routine might be active. instead see section 3. If the interrupt service routine is deﬁned to be using a speciﬁc register bank then only a.8 about Overlaying and section 3. n Description External 0 Timer 0 External 1 Timer 1 Serial Timer 2 (8052) Vector Address 0x0003 0x000b 0x0013 0x001b 0x0023 0x002b . See f. This scheme is recommended for larger interrupt service routines. the compiler will save the registers used by itself on the stack upon entry and restore them at exit. INTERRUPT SERVICE ROUTINES 3. many return addresses. SDCC will automatically adjust the to the maximum interrupt number speciﬁed.3 Common interrupt pitfall: stack overﬂow
CHAPTER 3.
3. Also see section 3.9.1. interrupt 2 will use the interrupt vector at 0xfffa.3. b. You could use semaphores or make the function critical if all parameters are passed in registers. If there isn’t variables or registers (or even the return address itself) will be corrupted. the cast (unsigned char)(tail-1) within the if clause in section 3. They also must not be called from low priority interrupt service routines while a high priority interrupt service routine might be active. If an interrupt service routine needs to do any of these operations then the support routines (as mentioned in a following section) will have to be recompiled using the --stack-auto option and the source ﬁle will need to be compiled using the --int-long-reent compiler option. int (16 bit) and long (32 bit) integer division.2
MCS51/DS390 Interrupt Service Routines
Interrupt numbers and the corresponding address & descriptions for the Standard 8051/8052 are listed below.e.11 about Functions using private register banks. and so on.9. however if such an interrupt service routine calls another function then the entire register bank will be saved on the stack. Note.
3.4 Common interrupt pitfall: use of non-reentrant functions
A special note here. the interrupt numbers corresponds to the interrupt vectors in reverse order of address.9. interrupt 1 will use the interrupt vector at 0xfffc. interrupt 0 (the reset vector at 0xfffe) is not redeﬁnable in this way. Calling other functions from an interrupt service routine is not recommended.e. 0x0003 + 8*n
If the interrupt service routine is deﬁned without using a register bank or with register bank 0 (using 0). avoid it if possible.12 for details on customizing startup. This scheme may be advantageous for small interrupt service routines which have low register usage.9.. Note that when some function is called from an interrupt service routine it should be preceded by a #pragma nooverlay if it is not reentrant.13..1. Interrupt # 0 1 2 3 4 5 .9.
40
. For example. 3..

3. To write an interrupt handler for the non-maskable interrupt. EA = 0..1
Enabling and Disabling Interrupts
Critical Functions and Critical Statements
A special keyword may be associated with a block or a function declaring it as critical. Note: it is sometimes sufﬁcient to disable only a speciﬁc interrupt source like f. The keyword critical may also be used to disable interrupts more locally: __critical{ i++. SDCC will generate code to disable all interrupts upon entry to a critical function and restore the interrupt enable to the previous state before returning. EA = 1.e. } The critical attribute maybe used with other attributes like reentrant. which uses a RETI instruction to return from the interrupt. __endasm. Usually the time during which interrupts are disabled should be kept as short as possible...
On other architectures which have separate opcodes for enabling and disabling interrupts you might want to make use of deﬁnes with inline assembly (HC08): #define CLI __asm #define SEI __asm .. By default. . .10. USING SDCC
3.10.
. SDCC generates code for a maskable interrupt. . a timer or serial interrupt by manipulating an interrupt mask register. EA = EA_SAVE.2
Enabling and Disabling Interrupts directly
or: EA_SAVE = EA. int foo () __critical { .3. add the critical keyword: void nmi_isr (void) critical interrupt { . To distinguish between this and an nmi_isr you must provide an interrupt number.
Interrupts can also be disabled and enabled directly (8051): EA = 0. This minimizes both interrupt latency (the time between the occurrence of the interrupt and the execution of the ﬁrst code in the interrupt 41 cli sei __endasm. which needs a RETN instruction instead. Therefore...4
Z80 Interrupt Service Routines
The Z80 uses several different methods for determining the correct interrupt vector depending on the hardware implementation..10
3. SDCC ignores the optional interrupt number and does not attempt to generate an interrupt vector table.
3.. } However if you need to create a non-interruptable interrupt service routine you would also require the critical keyword. ENABLING AND DISABLING INTERRUPTS
CHAPTER 3.10. } More than one statement could have been included in the block... Nesting critical functions will need one additional byte on the stack for each call.9...

} Note. With the atomic bit test and clear instruction interrupts don’t have to be disabled for the locking operation. These really are something different. since this would prevent the ISR from having to save bank zero to the stack on entry and switch to bank zero before calling the function
42
. USING SDCC
routine) and interrupt jitter (the difference between the shortest and the longest interrupt latency).) An interrupt function using a non-zero bank will assume that it can trash that register bank. if (resource_is_free) { resource_is_free=0. This is probably most easily done by having all high priority ISRs use one bank and all low priority ISRs use another. For instance. f.. whereas a much smaller jitter will be very audible.
3.3
Semaphore locking (mcs51/ds390)
Some architectures (mcs51/ds390) have an atomic bit test and clear instruction. whereas it does not care about jitter. On a loudspeaker driven via a digital to analog converter which is fed by an interrupt a latency of a few milliseconds might be tolerable. resource_is_free=1. nowadays the using attribute has an effect on the generated code for a non-interrupt function. It is very inefﬁcient to call a function using a different. you’re on your own: I suggest using the default bank zero and taking the small performance hit. It is most efﬁcient if your ISR calls no other functions.. it can be declared with the same ’using’ attribute as the calling ’interrupt’ functions. SDCC supports this feature with the using attribute (which tells the compiler to use a register bank other than the default bank zero). If your ISR must call other functions. (pending: Note. non-zero bank from an ISR. if you have several ISRs using bank one. You can reenable interrupts within an interrupt routine and on some architectures you can make use of two (or more) levels of interrupt priorities. and all of them call memcpy(). To prevent this. This will in most circumstances make the generated ISR code more efﬁcient since it will not have to save registers on the stack. . Since high-priority interrupts can interrupt low-priority ones on the 8051 and friends. and will not save it. The using attribute will have no effect on the generated code for a non-interrupt function (but may occasionally be useful anyway4 ). SDCC generates this instruction if the source follows this pattern: volatile bit resource_is_free.e.
3. the next best is if the called functions use bank zero.11. If you have an ISR which can change priority at runtime. where a routine f. Check there is sufﬁcient space on the stack and don’t add complexity unless you have to. terrible and bad things can happen. On some architectures which don’t support interrupt priorities these can be implemented by manipulating the interrupt mask and reenabling interrupts within the interrupt routine. mcs51 and ds390 support only an atomic bit test and clear instruction (as opposed to atomic bit test and set).3.
4 possible exception: if a function is called ONLY from ’interrupt’ functions using a particular bank.11
Functions using private register banks (mcs51/ds390)
Some architectures have support for quickly changing register sets. These type of instructions are typically used in preemptive multitasking systems. claims the use of a data structure (’acquires a lock on it’). a serial interrupt has to be served before its buffer overruns so it cares for the maximum interrupt latency.10.e. it might make sense to create a specialized version of memcpy() ’using 1’. makes some modiﬁcations and then releases the lock when the data structure is consistent again. no single register bank should be used by both a high priority and a low priority ISR. The instruction may also be used if interrupt and non-interrupt code have to compete for a resource. FUNCTIONS USING PRIVATE REGISTER BANKS (MCS51/DS390)
CHAPTER 3. this means that if a highpriority ISR using a particular bank occurs while processing a low-priority ISR using the same bank. It should only be applied to interrupt functions (see footnote below). it is most efﬁcient if those functions use the same bank as the ISR (see note 1 below).

3
Z80 Startup Code
On the Z80 the startup code is inserted by linking with crt0. The startup code clears all internal data memory. and for C99 compatibility.asm and when linking your project explicitly specify crtstart. adapt it there.2
HC08 Startup Code
The HC08 startup code follows the same scheme as the MCS51 startup code. the double-underscore form (__asm and __endasm) has to be used.12. that the single underscore form (_asm and _endasm) are not C99 compatible.sourceforge.9. /* if interrupts are involved see section 3.
3. The latter is also used in the library functions.rel which is generated from sdcc/device/lib/z80/crt0.e. The recommended way would be to copy crtstart. we have something to start with. See also the compiler options --no-xinit-opt.svn.c) is compiled with SDCC then a corresponding buffer. Then add ”__asm” and ”__endasm.13. INLINE ASSEMBLER CODE
CHAPTER 3.3. --main-return and section 4. USING SDCC
_sdcc_external_startup() routine to your program to override the default if you need to setup hardware or perform some other critical operation prior to static & global variable initialization.12.asm (f.rel. As a bonus a listing of the relocated object ﬁle crtstart.asm should not be checked (or _sdcc_external_startup() should not be called at all).net/viewvc/sdcc/trunk/sdcc/device/ lib/mcs51/Makefile. from http://sdcc. /* access to a 256 byte aligned array */ }
!
If the code snippet (assume it is saved in buffer. access variables.”6 to the beginning and the end of the function body:
/* With a cut and paste from the . On some mcs51 variants xdata memory has to be explicitly enabled before it can be accessed or if the watchdog needs to be disabled. The example uses an MCS51 here but is easily adapted for other architectures.s.asm) into the source directory.rst is generated. The function is not yet OK! (registers aren’t saved) */ void to_buffer_asm( unsigned char c ) are the assembler options used in http://sdcc. then assemble it with asx8051 -plosgff 5 crtstart.1. but from 0 to n-1 if --iram-sizen is used.asm ﬁle is generated.net/viewvc/*checkout*/sdcc/trunk/sdcc/ device/lib/mcs51/crtstart. We deﬁne a new function to_buffer_asm() in ﬁle buffer.1 about MCS51-variants. 256 bytes by default. unsigned char head.c in which we cut and paste the generated code.
5 ”-plosgff”
45
.13.asm file.sourceforge.svn.rel. a function parameter and an array in xdata memory. (recommended for Chipcon CC1010). tail.
3. This is a buffer routine which should be optimized:
unsigned char __far __at(0x7f00) buf[0x100]. removing unwanted comments and some ’:’.in?view=markup 6 Note.1 about volatile */ void to_buffer( unsigned char c ) { if( head != (unsigned char)(tail-1) ) /* cast needed to avoid promotion to integer */ buf[ head++ ] = c.13
3. While these initialization modules are meant as generic startup code there might be the need for customization.
3.1
Inline Assembler Code
A Step by Step Introduction
Starting from a small snippet of c-code this example shows for the MCS51 how to use inline assembly. this is the place to do it. Let’s assume the return value of _sdcc_external_startup() in crtstart. If you need a different startup code you can use the compiler option --no-std-crt0 and provide your own crt0.

} For an 8051 target. The compiler does not do any validation of the code within the __asm . it might cause some unexpected changes in the inline assembler code. generating the return instruction at the end. The assembler does not like some characters like ’:’ or ”’ in comments. Speciﬁcally it will not know which registers are used and thus register pushing/popping has to be done manually.sourceforge.
3. This means that the user is entirely responsible for such things as saving any registers that may need to be preserved. net/viewvc/*checkout*/sdcc/trunk/sdcc/as/doc/asxhtm. INLINE ASSEMBLER CODE
CHAPTER 3. restore used registers here _endasm. no need to save psw reti . which can have a large (and often unnecessary) prologue/epilogue. The _naked function modiﬁer attribute prevents the compiler from generating prologue and epilogue code for that function.svn. does not change flags..13.def before using this option. this means that the contents of the function must be written in inline assembler. It is recommended that each assembly instruction (including labels) be placed in a separate line (as the example shows). etc.13.html . This is particularly useful for interrupt functions. this is an outdated example. When the --peep-asm command line option is used.a inc _head . For example.#0x0f here to use a smaller buffer (see above) t_b_end$: . we could do an ANL _head. You’ll ﬁnd an 100+ pages assembler manual in sdcc/as/doc/asxhtm.. void simpleInterrupt(void) __interrupt (1) { counter++.3. } void nakedInterrupt(void) __interrupt (2) __naked { __asm inc _counter . this includes any assembler directives and comment lines. There are only a few (if any) cases where this option makes sense. the generated simpleInterrupt looks like: Note. USING SDCC
movx @dptr.#0x00 47
. keyword pair. selecting the proper register bank. Please go through the peephole optimizer rules deﬁned in ﬁle SDCCpeeph. recent versions of SDCC generate the same code for simpleInterrupt() and nakedInterrupt()! _simpleInterrupt: push acc push b push dpl push dph push psw mov psw.html or online at http://sdcc. __endasm. compare the code generated by these two functions: volatile data unsigned char counter. __endasm. the inline assembler code will be passed through the peephole optimizer.2
Naked Functions
A special keyword may be associated with a function declaring it as _naked. MUST explicitly include ret or reti in _naked function. } #endif
The inline assembler code can contain any valid code understood by the assembler. Practically.

the C-label clabel is translated by the compiler into a local label. USING SDCC
whereas nakedInterrupt looks like: _nakedInterrupt: inc _counter . Please refer to the assemblers documentation for further details. and places always a standard label at the beginning of a function.3. labels deﬁnes in inline assembly can not be accessed by C statements. locality of which is conﬁned within two labels of the standard form. no need to save psw reti . thus limiting the locality of labels within the scope of the function. an improperly placed non-local label in the assembler would break up the reference space for labels created by the compiler for the C-code. e.13. any valid integer will do. INLINE ASSEMBLER CODE inc pop pop pop pop pop reti _counter psw dph dpl b acc
CHAPTER 3. The numeric part of local labels does not need to have 5 digits (although this is the form of labels output by the compiler). The same goes the other way. leading to an assembling error. So.e.
48
. if the inline assembler part would be embedded into C-code. some assembler code ljmp 0003$ __endasm. does not change flags.3
Use of Labels within Inline Assembler
SDCC allows the use of in-line assembler with a few restrictions regarding labels. /* some more c code */ } In other words inline assembly code can access labels deﬁned in inline assembly within the scope of the function. however it can reference labels deﬁned by the inline assembler.g. and it is recommended that you stick to inline assembler.
7 This is a slightly more stringent rule than absolutely necessary.13.
3. MUST explicitly include ret or reti in _naked function The related directive #pragma exclude allows a more ﬁne grained control over pushing & popping the registers.#10 b. i.00001$
Inline assembler code cannot reference any C-labels. 8 Here. so the locality of labels within the function is not broken. All labels deﬁned within inline assembler code have to be of the form nnnnn$ where nnnnn is a number less than 100 (which implies a limit of utmost 100 inline assembler labels per function).label (can be referenced by inline assembler only) __endasm . The compiler uses the same form for labels within a function (but starting from nnnnn=00100). Labels in the form of nnnnn$ are local labels in the assembler. /* some more c code */ clabel: /* inline assembler cannot reference this label */ 8 __asm 0003$: . there are many ways to shoot yourself in the foot doing this. While there is nothing preventing you from writing C code inside a _naked function.: foo() { /* some c code */ __asm . b.7 __asm mov 00001$: djnz __endasm . but stays always on the safe side.

3. the caller will save the registers (R0-R7) around the call. and four byte values in DPH.14. according to the following scheme: one byte return value in DPL. DPL.2
Registers usage
Unless the called function is declared as _naked. } int main() { return c_func(10. USING SDCC
3.1
Interfacing with Assembler Code
Global Registers used for Parameter Passing
The compiler always uses the global registers DPL. B and ACC to pass the ﬁrst (non-bit) parameter to a function.globl _asm_func_PARM_2 .a mov dph. two byte value in DPL (LSB) and DPH (MSB).14. Bit parameters are passed in a virtual register called ’bits’ in bit-addressable space for reentrant functions or allocated directly in bit memory otherwise. and also to pass the return value of function. Functions (with two or more parameters or bit parameters) that are called through function pointers must therefor be reentrant so the compiler knows how to pass the parameters.area OSEG _asm_func_PARM_2: . 0x40 – idata/near – . where n is the parameter number starting from 1.3. INTERFACING WITH ASSEMBLER CODE
CHAPTER 3. B and ACC observing that they are used for parameter/return value passing. DPL. so the called function can destroy they content freely. extern int asm_func(unsigned char. The ﬁrst parameter is passed in DPH. B and ACC according to the 49
. The second parameter onwards is either allocated on the stack (for reentrant routines or if --stack-auto is used) or in data/xdata memory (depending on the memory model). } The corresponding assembler function is: . B and ACC.j).14.14.dpl add a.globl _asm_func . DPL and B.area CSEG _asm_func: mov a. 0x80 – code.14
3. 0x60 – pdata.
3.3
Assembler Routine (non-reentrant)
In the following example the function c_func calls an assembler routine asm_func.ds 1 . if caller and callee use different register banks (having them deﬁned by the _using modiﬁer). or the --callee-saves/--all-callee-saves command line option or the corresponding callee_saves pragma are used. If the called function is not declared as _naked.9). unsigned char j) { return asm_func(i. int c_func (unsigned char i. which takes two parameters. DPH. DPH. three byte values (generic pointers) in DPH.#0x00 ret The parameter naming convention is _<function_name>_PARM_<n>. unsigned char). the caller will swap register banks around the call. The called function can also use DPL. and counting from the left._asm_func_PARM_2 mov dpl. Generic pointers contain type of accessed memory in B: 0x00 – xdata/far.

INTERFACING WITH ASSEMBLER CODE
CHAPTER 3.r2 .9.return value goes into dptr (cast into int) mov dph.stack contains: _bp. } int main() { return c_func(10.#0x00 mov sp.c asmfunc.calculate pointer to the second parameter mov r0.
50
.#0xfd .k). third parameter mov r2.3._bp pop _bp ret The compiling and linking procedure remains the same._bp add a.calculate the result (= sum of all three parameters) mov dpl.@r0 add a. The variable name for the second parameter will be _<function_name>_PARM_2.a mov a.8).#0xfc .globl _asm_func _asm_func: push _bp mov _bp.dpl mov a. USING SDCC
description above.14.asm Then compile and link the assembler routine to the C source ﬁle with the following command: sdcc cfunc. however note the extra entry & exit linkage required for the assembler code. Here is an example: extern int asm_func(unsigned char. unsigned char j. before the call the second leftmost parameter will be on the top of the stack (the leftmost parameter is passed in registers). unsigned char) reentrant. } The corresponding (unoptimized) assembler routine is: .j. unsigned char k) reentrant { return asm_func(i. the parameters are pushed from right to left i.4
Assembler Routine (reentrant)
In this case the second parameter onwards will be passed on the stack. return address.14. second parameter.rel
3.@r1 add a.sp .e. _bp is the stack frame pointer and is used to compute the offset into the stack for parameters and local variables. Assemble the assembler routine with the following command: asx8051 -losg asmfunc. int c_func (unsigned char i.a mov a.calculate pointer to the rightmost parameter mov r1._bp add a.a . unsigned char.

3.c _fs2ulong.c _divulong.c and consist of the following routines: Function _fsadd.c _uchar2fs.c _fs2char. Notice that you don’t have to call these routines directly. after which the source program will have to be compiled with --int-long-reent option. INT (16 BIT) AND LONG (32 BIT) SUPPORT
CHAPTER 3.
9 These
ﬂoating point routines (not sinf().c _uint2fs. all of them can be found in <installdir>/share/sdcc/lib.16
Floating Point Support
SDCC supports IEEE (single precision 4 bytes) ﬂoating point numbers.c _fssub. The ﬂoating point support routines are derived from gcc’s ﬂoatlib.) for the mcs51 are implemented in assembler.3.c Description 16 bit multiplication signed 16 bit division (calls _divuint) unsigned 16 bit division signed 16 bit modulus (calls _moduint) unsigned 16 bit modulus 32 bit multiplication signed 32 division (calls _divulong) unsigned 32 division signed 32 bit modulus (calls _modulong) unsigned 32 bit modulus
Since they are compiled as non-reentrant.c _fs2uchar.c _fsmul. cosf().c _modsint.c _ulong2fs.c _int2fs. The compiler will use them automatically every time a ﬂoating point operation is required.
51
.c _fs2long. If this is unavoidable then the above routines will need to be compiled with the --stack-auto option. .c _fs2int.c _mullong. USING SDCC
3.c _fsdiv.c _long2fs.c _fs2uint.c _divuint. Note if all these routines are used simultaneously the data space might overﬂow.. interrupt service routines should not do any of the above operations. The following ﬁles contain the described routines.c Description add ﬂoating point numbers subtract ﬂoating point numbers divide ﬂoating point numbers multiply ﬂoating point numbers convert ﬂoating point to unsigned char convert ﬂoating point to signed char convert ﬂoating point to unsigned int convert ﬂoating point to signed int convert ﬂoating point to unsigned long convert ﬂoating point to signed long convert unsigned char to ﬂoating point convert char to ﬂoating point number convert unsigned int to ﬂoating point convert int to ﬂoating point numbers convert unsigned long to ﬂoating point number convert long to ﬂoating point number
These support routines are developed in ANSI-C so there is room for space and speed improvement9 . multiplication and modulus operations are implemented by support routines.c _char2fs.c _divsint. The compiler will use them automatically every time an integer operation is required. division.c _modulong..c _modslong. Also notice that you don’t have to call this routines directly.c _divslong. These support routines are all developed in ANSI-C to facilitate porting to other MCUs.c _moduint.15. although some model speciﬁc assembler optimizations are used. Function _mulint. For serious ﬂoating point usage the large model might be needed.15
int (16 bit) and long (32 bit) Support
For signed & unsigned int (16 bit) and long (32 bit) variables.

7k / 2.)
<stdio.9k 1.) Stdclib functions (puts.2k / 1.17.c does not support ﬂoat (except on ds390).6k / 1.1
Compiler support routines (_gptrget. _mulint etc.4294967040.9k / 1. keyboard or other device. see 4. LCD.26k / 0.26k
cdiopsux x b x
cdﬁopsux x b %f x
cdsux x x
cdfsux x %f10 x
cdsux -
10 Range
limited to +/.47k (+ _ltoa) cdosx x -
1.c
printf_fast_f
printf_fast_f. in sdcc/device/lib.8k 0.c
1.8. Be sure to use only one of these printf options within a project.45k / 0. putchar() As usual on embedded systems you have to provide your own getchar() and putchar() routines.8k / 3.2. For the mcs51 there additionally are assembly versions printf_tiny() (subset of printf using less than 270 bytes) and printf_fast() and printf_fast_f() (ﬂoating-point aware version of printf_fast) which should ﬁt the requirements of many embedded systems (printf_fast() can be customized by unsetting #deﬁnes to not support long variables and ﬁeld widths).3k / 1. since this uses a lot of memory. precision limited to 8 digits past decimal
52
.17. Use --model-large for the mcs51 port. To enable ﬂoating point output.6k
0.4k / 2. SBUF = c. recompile it with the option -DUSE_FLOATS=1 on the command line. You’ll ﬁnd examples for serial routines f.c
printf
USE_FLOATS=1 printf_large.4k 1. TI = 0.0k
4.44k / 0.17.3k / 5.c
printf_small
printﬂ.17
Library Routines
<pending: this is messy and incomplete .44k 0.a little more information is in sdcc/doc/libdoc. And whether a lf to crlf conversion within putchar() is intended.1 3.e. LIBRARY ROUTINES
CHAPTER 3. If you’re short on code memory you might want to use printf_small() instead of printf(). } printf() The default printf() implementation in printf_large. printf.3k 1.
mcs51
ﬁlename ”Hello World” size small / large code size small / large formats long (32 bit) support byte arguments on stack ﬂoat format ﬂoat formats %e %g ﬁeld width
printf
printf_large. USING SDCC
3.txt >
3.c
printf_fast
printf_fast.2
3.h>
getchar().2k
1.6.7k
1. To enable ﬂoat support for the pic16 targets. Feature matrix of different printf options on mcs51.6k 2.17.c
printf_tiny
printf_tiny. strcat etc.3.2k / 1. For the mcs51 this minimalistic polling putchar() routine might be a start: void putchar (char c) { while (!TI) /* assumes UART is initialized */ . SDCC does not know whether the system connects to a serial line with or without handshake. only <NO FLOAT> will be printed instead of the value.

However.18. When the small model is used variables without storage class are allocated in the internal ram. variables will by default be placed into the XDATA segment.1). When the medium or large model is used all variables declared without a storage class will be allocated into the external ram. When --xstack option is used to compile the program.dalsemi. this includes all parameters and local variables (for non-reentrant functions).
3. the -r ﬂag must be passed to the linker to generate the proper segment relocations. Judicious usage of the processor speciﬁc storage classes and the ’reentrant’ function type will yield much more efﬁcient code. The compiler outputs the higher order address byte of the external ram segment into port P2 (see also section 4. See 54
. In this mode. When used with the --stack-auto option.19
Pragmas
Pragmas are used to turn on and/or off certain compiler options. Modules compiled with different memory models should never be combined together or the results would be unpredictable.3. See the data sheets at www. Medium and Large
SDCC allows three memory models for MCS51 code.will restore saved options from the last save. this port may not be used by the application program. the boot loader or similar code must ensure that the processor is in 24 bit contiguous addressing mode before calling the SDCC startup code. The -r ﬂag can be passed to the linker by using the option -Wl-r on the SDCC command line. This generates code for the 24 bit contiguous addressing mode of the Dallas DS80C390 part.18. Like the --model-large option. medium and large.2 External Stack
The external stack (--xstack option) is located in pdata memory (usually at the start of the external ram segment) and uses all unused space in pdata (max.2 on page 24).this will save most current options to the save/restore stack. SDCC uses a save/restore stack: save pushes current options to the stack. currently the linker can not handle code segments > 64k. See #pragma restore. saves & restores can be nested. the parameters and local variables of all reentrant functions are allocated in this area. all parameters and local variables are allocated on the external stack (note: support libraries will need to be recompiled with the same options.1
Memory Models
MCS51 Memory Models
Small. Several optimizations are disabled when the program is compiled using the large model. USING SDCC
3. 3. medium and large. therefore when using the External Stack option. restore pulls current options from the stack. • restore .1.
3. There is a predeﬁned target in the library makeﬁle).1
3. Note that the compiler does not generate any code to place the processor into 24 bitmode (although tinibios in the ds390 libraries will do that for you). If you don’t use tinibios. and the Intel HEX output format must be used. it is therefore recommended that the small model be used unless absolutely required. up to four meg of external RAM or code space can be directly addressed. This option is provided for programs with large stack space requirements. Note that if any segments are located above 64K.18
3.18. SDCC supports the following #pragma directives: • save . than using the large model. Some of them are closely related to corresponding command-line options (see section 3. Pragmas should be placed before and/or after a function.2
DS390 Memory Model
The only model supported is Flat 24.18. medium and large so that you can link to the appropriate set.18. Segments may be placed anywhere in the 4 meg address space using the usual --*-loc options.1. The compiled library modules are contained in separate directories as small.com for further information on this part. placing pragmas inside a function body could have unpredictable results. small. MEMORY MODELS
CHAPTER 3. The library routines supplied with the compiler are compiled as small. 256 bytes).

[the (in)famous] conditional ﬂow changed by optimizer: so said EVELYN the modiﬁed DOG (110).19. PRAGMAS #pragma save. USING SDCC
• callee_saves function1[. out of range (81). Furthermore. More elegantly this can be achieved by omitting the optional interrupt number after the interrupt keyword. namely: constant value ’[]’.the compiler will not overlay the parameters and local variables of a function.The compiler by default uses a caller saves convention for register saving across function calls.1. Currently this has little effect. • noinvariant . • opt_code_size . cyclomatic complexity [number] (121).-( . # nodes [number] . This option can be used to switch off the register saving convention for the function names speciﬁed. The directive should be placed immediately before the ISR function deﬁnition and it affects ALL ISR functions following it. In the future the compiler (with inter procedural analysis) may be able to determine the appropriate scheme to use for each function call.
CHAPTER 3..the compiler will not warn you anymore for obvious mistakes.g. see section 3.Do not generate interrupt vector table entries for all ISR functions deﬁned after the pragma. for the autovector feature of the Cypress EZ-USB FX2). This is useful in cases where the interrupt vector table must be deﬁned manually. overﬂow in implicit constant conversion (158). For more details see section 8. • nojtbound . extra code need to be manually inserted at the entry and exit for these functions to save and restore the registers used by these functions.Will not do loop reversal optimization • nooverlay . the following warnings will be disabled: comparison is always [true/false] due to limited range of data type (94). • exclude none | {acc[.]] .function3. See also the related keyword _naked.The exclude pragma disables the generation of pairs of push/pop instructions in Interrupt Service Routines. • noloopreverse . # edges [number] .b[. • disable_warning <nnnn> . • less_pedantic . For more details see Loop Invariants in section8. function ’[function name]’. comparison of ’signed char’ with ’unsigned char’ requires promotion to int (185). unreachable code (126). [left/right] shifting more than size of object changed to zero (116). Currently this has little effect. when switch statements are turned into jump-tables (dangerous).7 Parameters and Local Variables.9 about interrupts. possibly at the expense of code speed.will stop loop induction optimizations.dpl[. or when there is a secondary.The compiler will optimize code generation towards compact code. 55
.function2[. integer overﬂow in expression (165). possibly at the expense of code size.dph]]] . function ’[function name]’ must return value (59).the compiler will not warn you anymore about warning number <nnnn>.. • nogcse .3. the function names speciﬁed in #pragma callee_saves is appended to the list of functions speciﬁed in the command line. • noiv . • noinduction . • opt_code_speed . The compiler will not save registers when calling these functions. To enable the normal register saving for ISR functions use #pragma exclude none. manually deﬁned interrupt vector table (e. extended stack by [number] bytes for compiler temp(s) :in function ’[function name]’: [] (114). this can SUBSTANTIALLY reduce code and improve run time performance of the generated code. warnings of less importance (of PEDANTIC and INFO warning level) are disabled.will not do loop invariant optimizations. • stackauto. however this can cause unnecessary register pushing and popping when calling small functions from larger functions. See also the command line option --less-pedantic on page 30. If --callee-saves command line option is used (see page on page 29). you’re on your own now .See option --stack-auto and section 3.1. More speciﬁcally. unmatched #pragma save and #pragma restore (170). ISO C90 does not support ﬂexible array members (187).4. too.7.The compiler will optimize code generation towards fast code.will stop global common subexpression elimination.will not generate code for boundary value checking.

3.19. PRAGMAS

CHAPTER 3. USING SDCC

• opt_code_balanced - The compiler will attempt to generate code that is both compact and fast, as long as meeting one goal is not a detriment to the other (this is the default). • std_sdcc89 - Generally follow the C89 standard, but allow SDCC features that conﬂict with the standard (default). • std_c89 - Follow the C89 standard and disable SDCC features that conﬂict with the standard. • std_sdcc99 - Generally follow the C99 standard, but allow SDCC features that conﬂict with the standard (incomplete support). • std_c99 - Follow the C99 standard and disable SDCC features that conﬂict with the standard (incomplete support). • codeseg <name>- Use this name (max. 8 characters) for the code segment. See option --codeseg. • constseg <name>- Use this name (max. 8 characters) for the const segment. See option --constseg. The preprocessor SDCPP supports the following #pragma directives: • pedantic_parse_number (+ | -) - Pedantic parse numbers so that situations like 0xfe-LO_B(3) are parsed properly and the macro LO_B(3) gets expanded. Default is off. See also the --pedantic-parse-number command line option on page 26. Below is an example on how to use this pragma. Note: this functionality is not in conformance with standard! #pragma pedantic_parse_number + #define LO_B(x) ((x) & 0xff) unsigned char foo(void) { unsigned char c=0xfe-LO_B(3); return c; } • preproc_asm (+ | -) - switch the __asm __endasm block preprocessing on / off. Default is on. Below is an example on how to use this pragma. #pragma preproc_asm /* this is a c code nop */ #define NOP ; void foo (void) { ... while (--i) NOP ... __asm ; this is an assembler nop instruction ; it is not preprocessed to ’;’ since the asm preprocessing is disabled NOP __endasm; ... } The pragma preproc_asm should not be used to deﬁne multilines of assembly code (even if it supports it), since this behavior is only a side effect of sdcpp __asm __endasm implementation in combination with pragma preproc_asm and is not in conformance with the C standard. This behavior 56

3.19. PRAGMAS

CHAPTER 3. USING SDCC

might be changed in the future sdcpp versions. To deﬁne multilines of assembly code you have to include each assembly line into it’s own __asm __endasm block. Below is an example for multiline assembly deﬁnes. #define Nop __asm \ nop \ __endasm #define ThreeNops Nop; \ Nop; \ Nop void foo (void) { ... ThreeNops; ... } • sdcc_hash (+ | -) - Allow "naked" hash in macro deﬁnition, for example: #define DIR_LO(x) #(x & 0xff) Default is off. Below is an example on how to use this pragma. #pragma preproc_asm + #pragma sdcc_hash + #define ROMCALL(x) \ mov R6_B3, #(x & 0xff) \ mov R7_B3, #((x >> 8) & 0xff) \ lcall __romcall ... __asm ROMCALL(72) __endasm; ... Some of the pragmas are intended to be used to turn-on or off certain optimizations which might cause the compiler to generate extra stack and/or data space to store compiler generated temporary variables. This usually happens in large functions. Pragma directives should be used as shown in the following example, they are used to control options and optimizations for a given function. #pragma save /* save the current settings */ #pragma nogcse /* turnoff global subexpression elimination */ #pragma noinduction /* turn off induction optimizations */ int foo () { ... /* large code */ ... } #pragma restore /* turn the optimizations back on */ The compiler will generate a warning message when extra space is allocated. It is strongly recommended that the save and restore pragmas be used when changing options for a function.

57

3.20. DEFINES CREATED BY THE COMPILER

CHAPTER 3. USING SDCC

3.20

Deﬁnes Created by the Compiler
Description Always deﬁned. Since version 2.5.6 the version number as an int (ex. 256) depending on the model used (e.g.: -mds390) depending on the model used (e.g. -mz80) when --stack-auto option is used when --model-small is used when --model-medium is used when --model-large is used when --xstack option is used when --funsigned-char option is used when -mds390 is used when -mds390 is used Always deﬁned. SDCC svn revision number when --parms-in-bank1 is used when --ﬂoat-reent is used when --int-long-reent is used

4. EMI0CN */ __sfr __at (0xaa) _XPAGE.a.k. __sfr __at (0x85) _XPAGE. you should deﬁne an sfr with the name _XPAGE at the appropriate location if the default.12 for other possibilities. Some examples are: MPAGE */ __sfr __at (0x92) _XPAGE. is not used for this. 16x16 Multiply. While they might differ considerably in respect to Special Function Registers the core MCS51 is usually not modiﬁed or is kept compatible.3
Bankswitching
Bankswitching (a.1. code banking) is a technique to increase the code space above the 64k limit of the 8051. MPAGE */ __sfr __at (0x91) _XPAGE.a. /* Infineon (Siemens) C500 family a. Switching the high byte for pdata access which was formerly done by port P2 is then achieved by a Special Function Register.1.k.k. So that the startup code can correctly initialize xdata variables. XPAGE */ __sfr __at (0xaf) _XPAGE.
4.k.a. multiple DPTR.k. /* Cypress EZ-USB family.
4. decrementing DPTR. If you absolutely need them you can fall back to inline assembly or submit a patch to SDCC.a.1. 4.Chapter 4
Notes on supported Processors
4.a.k. EMI0CN */ For more exotic implementations further customizations may be needed. /* some Silicon Labs (Cygnal) chips a.2
Other Features available by SFR
Some MCS51 variants offer features like Double DPTR. port P2. In well-established MCS51 tradition the address of this sfr is where the chip designers decided to put it.a. Texas Instruments (Chipcon) a. /* Ramtron VRS51 family a.3. See section 3. Needless to say that they didn’t agree on a common name either.1
pdata access by SFR
With the upcome of devices with internal xdata and ﬂash memory devices using port P2 as dedicated I/O port is becoming more popular.1. These are currently not used for the MCS51 port. /* some Silicon Labs (Cygnal) chips a.1 Hardware
8000-FFFF bank1 bank2 bank3 0000-7FFF common SiLabs C8051F120 example
59
.1 MCS51 variants
MCS51 processors are available from many vendors and come in many different ﬂavours.

3. When the banked function returns it jumps to __sdcc_banked_ret which restores the previous bank and returns to the caller. When linking your objects you need to tell the linker where to put your segments. DS400 PORT
CHAPTER 4.c. You also need to take over a bit of work from the linker.3). The caller must see this in the prototype of the callee and the callee needs it for a proper return. Library headers (currently in beta status) and other ﬁles are provided at ftp://ftp. so ﬂoating point support. This is your responsibility! Normally all functions you write end up in the segment CSEG.19) at the top of the C source ﬁle. The selected bank usually becomes active immediately upon assignment to this sfr and when running inside a bank it will switch out this code it is currently running. It sets the banknumber to 0x01 and maps the bank to 0x8000 and up.2
DS400 port
The DS80C400 microcontroller has a rich set of peripherals. Called functions within the same bank as the caller do not need the banked keyword nor do functions in the common area. Return values for the Z80 port are stored in L (one byte). To do this you either use --codeseg BANK1 (See 3. the code is the authoritative reference . The stack frame is similar to that generated by the IAR Z80 compiler. The gbz80 port use the same set of registers for the return values. and BC and DE are available for holding variables. See mailing lists and forums about interrupt routines. again this is your responsibility. The Z80 port is passed through the same regressions tests (see section 7.3
The Z80 and gbz80 port
SDCC can target both the Zilog Z80 and the Nintendo GameBoy’s Z80-like gbz80.c and z80/gen. To do this you use the following command line option to SDCC: -Wl-b BANK1=0x18000 (See 3. When calling a banked function SDCC will put the LSB of the functions address in register R0. BANK1).see z80/ralloc.dalsemi. but in a different order of signiﬁcance: E (one byte). The segment name always applies to the whole source ﬁle and generated object so functions for different banks need to be deﬁned in different source ﬁles. HL (two bytes). The current selected bank is saved on the stack.asm and you may need to change it to your 8051 derivative or schematic.8) as the MCS51 and DS390 ports. or DEHL (four bytes). This sets the virtual start address of this segment.9) on the command line when compiling or #pragma codeseg BANK1 (See 3.2.com/pub/tini/ds80c400/c_libraries/sdcc/
index. Beware: SDCC does not know or check if functions are in the same bank. If you want a function explicitly to reside in the common area put it in segment HOME. DE (two bytes).html. The presented code is written for the C8051F120. or HLDE (four bytes).g. This applies for instance to interrupt service routines as they should not be banked. the MSB in R1 and the bank in R2 and then call this trampoline __sdcc_banked_call. The linker will not check for overﬂows. The name can be mostly anything up to eight characters (e. For SDCC an example trampoline is in crtbank.
4. 4.1. support for long variables and bitﬁeld support is ﬁne.
4.4. As always. the new bank is selected and an indirect jump is made.
60
. HL and IY are used as a temporary registers. To create a function that can be called from another bank it requires the keyword banked.2. IX is used as the base pointer. among them is a TCP stack with IP4 and IP6 support. Therefor you cannot jump or call directly from one bank to another and need to use a so-called trampoline in the common area. Functions that need to be in a switched bank must be put in a named segment. In its built-in ROM library it includes functions to access some of the features. NOTES ON SUPPORTED PROCESSORS
Usually the hardware uses some sfr (an output port or an internal sfr) to select a bank and put it in the banked area of the memory map.2.2 Software
When writing banked software using SDCC you need to use some special keywords and options.

630. 675. This way the linker can put the code for each ﬁle into different code pages and there will be less page selection overhead. NOTES ON SUPPORTED PROCESSORS
4. 3. Each device is described in two ﬁles: pic16f*. 72. 77 16F: 616. 690 16F: 716. 871. 433 16C: 554.5. 914. 73. This ﬁle also contains further instructions on how to proceed. as non static functions require code page selection overhead. 765. 622a.4
The HC08 port
The port to the Freescale/Motorola HC08 family has been added in October 2003. 785 An up-to-date list of currently supported devices can be obtained via sdcc -mpic14 -phelp foo. Due to the way sdcc handles functions.h and pic16f*.inc ﬁles using the perl script support/scripts/inc2h. 887 16F: 913. It will put all the code section of a single . 73b. 872. and is still undergoing some basic development. 77. 76.c must exist. 819. For devices that have multiple code pages it is more efﬁcient to use the same number of ﬁles as pages: Use up to 4 separate . 870. 770. 636.
4. 877.5. Some of the SDCC’s standard C library functions have embedded non-HC08 inline assembly and so are not yet usable.c. 771. 747. 710. 87. 63a.8). 627.
4. 773. 877a. 876a.). 84. 72. 886. 688. 717.c (foo. 873. 2. 683 16C: 432. These ﬁles primarily deﬁne SFRs. The compiler assigns all static functions of a single . 628a. 84a. 687. 777. separate asm ﬁles must be used.. but the register allocation is still quite unoptimized. Both ﬁles can be generated from gputils’ . 715. 639. 620. 628. However.4.asm ﬁle into a single code page. This port is not yet mature and still lacks many features. Create a new device description. 648a. The HC08 port passes the regression test suite (see section 7. It does not have intimate knowledge of the code ﬂow. THE HC08 PORT
CHAPTER 4.pl. 874a.
4. 73. 711. 74. 61
.5
The PIC14 port
The PIC14 port adds support for MicrochipTM PICTM MCUs with 14 bit wide instructions. 558 16C: 62. 76. believing that the called function is externally deﬁned. 689. but only 2 ﬁles for the 16F874. 557. 873a. 676. 88.. 685. 785 16F: 818. 916. 620a. 621. 622. 737. The code generator is complete. follow these guidelines: 1. 781. 74. structs to access their bits. 621a. Make local functions static. 782 16C: 925. 774. 876. 946 26HV: 626.4. 926 16CR: 620a. 745. 917. And as for any 8 bit micro (especially for PIC14 as they have a very simple instruction set). and symbolic conﬁguration options. 627a. place called functions prior to calling functions in the ﬁle wherever possible: Otherwise sdcc will insert unnecessary pagesel directives around the call. 65b 16C: 71. 74b.1
PIC Code Pages and Memory Banks
The linker organizes allocation for the code page and RAM banks.c ﬁle into the same code page.c ﬁles for the 16F877. it can work for simple code.2
Adding New Devices to the Port
Adding support for a new 14 bit PIC MCU requires the following steps: 1. In order to make use of multiple code pages. use ‘unsigned char’ wherever possible instead of ‘int’. 648. Currently supported devices include: 12F: 629. 635. 767. 874. 684. To get the best results.

4.5. THE PIC14 PORT

CHAPTER 4. NOTES ON SUPPORTED PROCESSORS

2. Copy the .h ﬁle into SDCC’s include path and either add the .c ﬁle to your project or copy it to device/lib/pic/libdev. Afterwards, rebuild and install the libraries. 3. Edit pic14devices.txt in SDCC’s include path (device/include/pic/ in the source tree or /usr/local/share/sdcc/include/pic after installation). You need to add a device speciﬁcation here to make the memory layout (code banks, RAM, aliased memory regions, ...) known to the compiler. Probably you can copy and modify an existing entry. The ﬁle format is documented at the top of the ﬁle.

4.5.3

Interrupt Code

For the interrupt function, use the keyword ‘__interrupt’ with level number of 0 (PIC14 only has 1 interrupt so this number is only there to avoid a syntax error - it ought to be ﬁxed). E.g.: void Intr(void) __interrupt 0 { T0IF = 0; /* Clear timer interrupt */ }

4.5.4

Linking and Assembling

For assembling you can use either GPUTILS’ gpasm.exe or MPLAB’s mpasmwin.exe. GPUTILS are available from http://sourceforge.net/projects/gputils. For linking you can use either GPUTILS’ gplink or MPLAB’s mplink.exe. If you use MPLAB and an interrupt function then the linker script ﬁle vectors section will need to be enlarged to link with mplink. Here is a Makefile using GPUTILS: .c.o: sdcc -V -mpic14 -p16f877 -c $< $(PRJ).hex: $(OBJS) gplink -m -s $(PRJ).lkr -o $(PRJ).hex $(OBJS) libsdcc.lib Here is a Makefile using MPLAB: .c.o: sdcc -S -V -mpic14 -p16f877 $< mpasmwin /q /o $*.asm $(PRJ).hex: $(OBJS) mplink /v $(PRJ).lkr /m $(PRJ).map /o $(PRJ).hex $(OBJS) libsdcc.lib Please note that indentations within a Makefile have to be done with a tabulator character.

4.5.5

Command-Line Options

Besides the switches common to all SDCC backends, the PIC14 port accepts the following options (for an updated list see sdcc --help): --debug-xtra emit debug info in assembly output --no-pcode-opt disable (slightly faulty) optimization on pCode --stack-loc sets the lowest address of the argument passing stack (defaults to a suitably large shared databank to reduce BANKSEL overhead) --stack-size sets the size if the argument passing stack (default: 16, minimum: 4)

62

4.5. THE PIC14 PORT

CHAPTER 4. NOTES ON SUPPORTED PROCESSORS

4.5.6

Environment Variables

The PIC14 port recognizes the following environment variables: SDCC_PIC14_SPLIT_LOCALS If set and not empty, sdcc will allocate each temporary register (the ones called r0xNNNN) in a section of its own. By default (if this variable is unset), sdcc tries to cluster registers in sections in order to reduce the BANKSEL overhead when accessing them.

4.5.7

The Library

The PIC14 library currently only contains support routines required by the compiler to implement multiplication, division, and ﬂoating point support. No libc-like replacement is available at the moment, though many of the common sdcc library sources (in device/lib) should also compile with the PIC14 port. 4.5.7.1 error: missing deﬁnition for symbol “__gptrget1”

The PIC14 port uses library routines to provide more complex operations like multiplication, division/modulus and (generic) pointer dereferencing. In order to add these routines to your project, you must link with PIC14’s libsdcc.lib. For single source ﬁle projects this is done automatically, more complex projects must add libsdcc.lib to the linker’s arguments. Make sure you also add an include path for the library (using the -I switch to the linker)! 4.5.7.2 Processor mismatch in ﬁle “XXX”.

This warning can usually be ignored due to the very good compatibility amongst 14 bit PIC devices. You might also consider recompiling the library for your speciﬁc device by changing the ARCH=p16f877 (default target) entry in device/lib/pic/Makefile.in and device/lib/pic/Makefile to reﬂect your device. This might even improve performance for smaller devices as unnecessary BANKSELs might be removed.

4.5.8
4.5.8.1

Known Bugs
Function arguments

Functions with variable argument lists (like printf) are not yet supported. Similarly, taking the address of the ﬁrst argument passed into a function does not work: It is currently passed in WREG and has no address... 4.5.8.2 Regression tests fail

Though the small subset of regression tests in src/regression passes, SDCC regression test suite does not, indicating that there are still major bugs in the port. However, many smaller projects have successfully used SDCC in the past...

PIC16 port supports the standard command line arguments as supposed, with the exception of certain cases that will be mentioned in the following list: --callee-saves See --all-callee-saves --fomit-frame-pointer Frame pointer will be omitted when the function uses no local variables.

no optimization checks previous used register and if it is the same then does not emit BANKSEL, accounts only for labels.

64

--no-crt Don’t link the default run-time modules 4. reading of structure bitﬁelds is optimized by directly loading FSR0 with the address of the bitﬁeld structure. NO_REG_OPT Do not perform pCode registers optimization. --calltree Dump call tree in . NOTES ON SUPPORTED PROCESSORS
tries to check the location of (even different) symbols and removes BANKSELs if they are in the same bank. "udata_shr".5 Debugging Options
Debugging options enable extra debugging information in the output ﬁles. --optimize-df Analyze the dataﬂow of the generated code and improve it.4. --use-crt= Use a custom run-time module instead of the defaults. (i.2. --optimize-cmp Try to optimize some compares.d ﬁle with debugging information. --gstack Trace push/pops for stack pointer overﬂow.
4. <source> is the name of the ﬁle being compiled. --no-optimize-goto Do not use (conditional) BRA instead of GOTO. --ivt-loc=n Place the interrupt vector table at address n. Currently there is only two such variables available: OPTIMIZE_BITFIELD_POINTER_GET When this variable exists.calltree ﬁle.6. 65
. these variables are primarily for debugging purposes so they can be enabled/disabled at will. Valid keywords are: "udata_acs". Useful for bootloaders. 4.2. 4. --debug-xtra Similar to --debug. --nodefaultlibs Do not link default libraries when linking. 80 bytes of code space are saved when compiling malloc.6. --mplab-comp MPLAB compatibility option. --debug-ralloc Force register allocator to dump <source>. This step saves data ram and code space for functions that make heavy use of bitﬁelds.6. --preplace-udata-with=[kword] Replaces the default udata keyword for allocating unitialized data variables with [kword]. Normally SDCC will cast the bitﬁeld structure to a bitﬁeld pointer and then load FSR0.6.2. "udata_ovr".e.6.. Important: There might be problems if the linker script has data sections across bank borders!
--denable-peeps Force the usage of peepholes. THE PIC16 PORT 2
CHAPTER 4.4 Linking Options
--link= Sets the full path and name of an external linker to call. users can beneﬁt from temporarily disabling the optimizer until the bug is ﬁxed. Currently only suppresses special gpasm directives.3
Environment Variables
There is a number of environmental variables that can be used when running SDCC to enable certain optimizations or force a speciﬁc program behaviour. This should be used for debugging purposes.c with this option). If bugs in the pcode optimizer are found. --pcode-verbose Enable pcode debugging information in translation. Use with care. but dumps more information.3 Assembling Options
--asm= Sets the full path and name of an external assembler to call.

6
Pragmas
The PIC16 port currently supports the following pragmas: stack This forces the code generator to initialize the stack & frame pointers at a speciﬁc address. The stack pointer initially will point at address
Example: /* initializes stack of 100 bytes at RAM address 0x200 */ #pragma stack 0x200 100 If the stack_size ﬁeld is omitted then a stack is created with the default size of 64.6. 452.5
Directories
PIC16 port uses the following directories for searching header ﬁles and libraries.
66
. This is an ad hoc solution for cases where no STACK directive is available in the linker script or gplink is not instructed to create a stack section. Directory PREFIX/sdcc/include/pic16 PREFIX/sdcc/lib/pic16 Description PIC16 speciﬁc headers PIC16 speciﬁc libraries Target Compiler Linker Command preﬁx -I -L
4. 6620. THE PIC16 PORT
CHAPTER 4. The stack pragma should be used only once in a project. xxxx is the microcontrol identiﬁcation number. Example: /* place function test_func at 0x4000 */ #pragma code test_func 0x4000
1 The old format (ie. Multiple pragmas may result in indeterminate behaviour of the program. etc MCU Identiﬁcation (same as above) nnn = SMALL or LARGE respectively according to the stack model used
In addition the following macros are deﬁned when calling assembler: Macro __18Fxxxx SDCC_MODEL_nnn STACK_MODEL_nnn Description MCU Identiﬁcation. code Force a function to a static FLASH address.4. but its not enough for operations with deep function nesting or excessive stack usage.6. i. xxxx is the microcontrol identiﬁcation number. etc nnn = SMALL or LARGE respectively according to the memory model used for SDCC nnn = SMALL or LARGE respectively according to the stack model used
4.6.1 The format is as follows:
#pragma stack bottom_address [stack_size] bottom_address is the lower bound of the stack section.e. 452. Macro SDCC_pic16 __pic16 pic18fxxxx __18Fxxxx STACK_MODEL_nnn Description Port identiﬁcation Port identiﬁcation (same as above) MCU Identiﬁcation.6. This size might be enough for most programs.e.4
Preprocessor Macros
PIC16 port deﬁnes the following preprocessor macros while translating a source. #pragma stack 0x5ff) is deprecated and will cause the stack pointer to cross page boundaries (or even exceed the available data RAM) and crash the program. (bottom_address+stack_size-1). 6620. NOTES ON SUPPORTED PROCESSORS
4. i. Make sure that stack does not cross page boundaries when using the SMALL stack model.

Example: /* places variable foo at bank2 */ #pragma udata bank2 foo char foo. This feature allows for linking with speciﬁc libraries without having to explicit name them in the command line.e. i.4.lkr script. In order for this pragma to work extra SECTION directives should be added in the . CODEPAGE NAME=vectors START=0x0 CODEPAGE NAME=page START=0x2A CODEPAGE NAME=idlocs START=0x200000 CODEPAGE NAME=config START=0x300000 CODEPAGE NAME=devid START=0x3FFFFE CODEPAGE NAME=eedata START=0xF00000 ACCESSBANK NAME=accessram START=0x0 DATABANK NAME=gpr0 START=0x80 DATABANK NAME=gpr1 START=0x100 DATABANK NAME=gpr2 START=0x200 DATABANK NAME=gpr3 START=0x300 DATABANK NAME=gpr4 START=0x400 DATABANK NAME=gpr5 START=0x500 ACCESSBANK NAME=accesssfr START=0xF80 SECTION NAME=CONFIG ROM=config SECTION NAME=bank0 RAM=gpr0 SECTION NAME=bank1 RAM=gpr1 SECTION NAME=bank2 RAM=gpr2 SECTION NAME=bank3 RAM=gpr3 SECTION NAME=bank4 RAM=gpr4 SECTION NAME=bank5 RAM=gpr5 processor END=0x29 END=0x7FFF END=0x200007 END=0x30000D END=0x3FFFFF END=0xF000FF END=0x7F END=0xFF END=0x1FF END=0x2FF END=0x3FF END=0x4FF END=0x5FF END=0xFFF # # # # PROTECTED PROTECTED PROTECTED PROTECTED PROTECTED
PROTECTED
these SECTION directives should be added to link section name ’bank?’ with a specific DATABANK name
The linker will recognise the section name set in the pragma statement and will position the variable at the memory bank set with the RAM ﬁeld at the SECTION line in the linker script ﬁle. In the following example a sample .lib debug link the debug library libdebug. Note that there are four reserved keywords which have special meaning. 452 for PIC18F452 MCU.lib io link the I/O library libio18f*. NOTES ON SUPPORTED PROCESSORS
module_name can be any library or object ﬁle (including its path).lib math link the Math libarary libm18f. These are: Keyword Description Module to link ignore ignore all library pragmas (none) c link the C library libc18f.
67
. THE PIC16 PORT library instructs the linker to use a library module. Usage: #pragma library module_name
CHAPTER 4. Note that the IGNORE keyword will reject all modules speciﬁed by the library pragma.6.lib * is the device number.lkr ﬁle is shown: // Sample linker script for the PIC18F452 LIBPATH . udata The pragma udata instructs the compiler to emit code so that linker will place a variable at a speciﬁc memory bank.

6.lib. The speciﬁc library is selected automatically by the compiler at link stage according to the selected device. mv picDEVICE.c manually with -DUSE_FLOATS=1 should also work./configure.g.6. To change this.g. where xxxx is the microcontroller identiﬁcation number.c /path/to/sdcc/device/lib/pic16/libdev
68
. only <NO FLOAT> will appear instead of the value.
4. It can be included by adding the following line in the beginning of the ﬁle: #include <pic18fregs. That ﬁle is the pic18fregs. make model-pic16 su -c ’make install’ cd . these are the steps required to do so under Linux or Mac OS X (cygwin might work as well.7
Header Files
There is one main header ﬁle that can be included to the source ﬁles using the pic16 port. mv picDEVICE. in order to enable output of ﬂoat values via printf().h.8
Libraries
The libraries that PIC16 port depends on are the microcontroller device libraries which contain the symbol deﬁnitions for the microcontroller special function registers./configure.inc using perl /path/to/sdcc/support/scripts/inc2h-pic16. Building the libraries Before using SDCC/pic16 there are some libraries that need to be compiled.c is actually recompiled. e.pl \ /path/to/gputils/header/pDEVICE.. The more common appraoch of compiling vfprintf.c and picDEVICE./.. so it is necessary if the source accesses them. see below).. by touching it after the configure run or deleting its .
# install the libraries./configure. Should you require to rebuild the pic16 libraries manually (e. THE PIC16 PORT
CHAPTER 4. This process is done automatically if gputils are found at SDCC’s compile time.gnu. do: cd device/include su -c ’make install’ Output of ﬂoat values via printf() The library is normally built without support for displaying ﬂoat values.h /path/to/sdcc/device/include/pic16 3.h from pDEVICE. so the same source can be used with a variety of devices.gnu cd .h automatically.9
Adding New Devices to the Port
Adding support for a new 16 bit PIC MCU requires the following steps: 1. but is untested): cd device/lib/pic16 . If you need to install the headers too.net/projects/ gputils.6. rebuild the library as stated above. you need the root password
# install the headers. Also make sure that at least libc/stdio/vfprintf.gnu --enable-floats instead of just . These libraries have the format pic18fxxxx.o ﬁle.6.inc 2.4. NOTES ON SUPPORTED PROCESSORS
4. This header ﬁle contains the deﬁnitions for the processor special registers. but call .h> The speciﬁc microcontroller is selected within the pic18fregs. but is untested. you need the root password
4. Libraries are created with gplib which is part of the gputils package http://sourceforge. Create picDEVICE.

6.10
Memory Models
The following memory models are supported by the PIC16 port: • small model • large model Memory model affects the default size of pointers within the source. please). Update libdev/Makefile.usart}. Add DEVICE to /path/to/sdcc/device/lib/pic16/pics. Edit /path/to/sdcc/device/include/pic16devices.i2c.am Copy the record from the 18f2220 and adjust the device name. THE PIC16 PORT
CHAPTER 4. 7. Either (a) add the new device to /path/to/sdcc/device/lib/pic16/libio/*. I2 C.7) contain no reference to pointers.. Add the device to /path/to/sdcc/device/lib/pic16/libdev/Makefile.pl to assign I/O styles. just add #elif defined(picDEVICE) # include <picDEVICE. If one wants to override the default memory model.txt Copy and modify an existing entry or create a new one and insert it at the correct place (keep the ﬁle sorted.all Note: No 18f preﬁx here! 5. 11. The sizes are shown in the next table: Pointer sizes according to memory model code pointers data pointers small model 16-bits 16-bits large model 24-bits 16-bits
It is advisable that all sources within a project are compiled with the same memory model.ignore ﬁles are only used when auto-generating Makefile./libio/mkmk.in using .6.i2c.
fact. Far selects large memory model’s pointers.
2 In
69
.h> at the right place (keep the ﬁle sorted. Add the device to /path/to/sdcc/device/lib/pic16/libio/Makefile.4.c. or usart/*. replace your existing pic18fam.8. Recompile the pic16 libraries as described in 4.pl script to generate pic18fam. NOTES ON SUPPORTED PROCESSORS
4. Edit /path/to/sdcc/device/include/pic16/pic18fregs.am Copy an existing entry and adjust the device name.sh in /path/to/sdcc/device/lib/pic16. you must not include the adc/.sh script.h and /path/to/sdcc/device/lib/pic16/libio/*/*. The standard device libraries (see 4.usart}..gen.ignore. while near selects small memory model’s pointers. to actually suppress building the I/O library.h with the generated ﬁle.6./bootstrap.6. the . so they can be used with both memory models. remove the lines with references to adc/*.h The ﬁle format is self-explanatory. i2c/*. and (if required) implement new I/O styles in /path/to/sdcc/device/include/pic16/{adc. i2c/ and usart/ sources in the Makefile.6. 10. respectively. 8. run the pic18fam-h-gen.c. or if you added the new device to . this can be done by declaring a pointer as far or near.c. and/or (E)USART functionality as assumed by the library./libio/{adc.ignore to suppress building any of the I/O libraries for the new device2 .am from steps 8f using the ..am in step 9.in and libio/Makefile.h.. 9. please). or (b) add the device (family) to /path/to/sdcc/support/scripts/pic18fam-h-gen.
4. If the new device does not offer ADC.

12
Functions
In addition to the standard SDCC function keywords.e.11
Stack
The stack implementation for the PIC16 port uses two indirect registers. So its use is not advised.4. STATUS and BSR registers.. void isr_shadow(void) shadowregs interrupt 1 { . it is possible to take advantage of the PIC18F hardware shadow registers which hold the values of WREG.. so no more than 256 bytes of stack can be used. Usage: void func_wparam(int a) wparam { /* WREG hold the lower part of a */ /* the high part of a is stored in FSR2+2 (or +3 for large stack model) */ . The following table shows the stack/frame pointers sizes according to stack model and the maximum space they can address: Stack & Frame pointer sizes according to stack model Stack pointer FSR1 Frame pointer FSR2 small 8-bits 8-bits large 16-bits 16-bits
L ARGE stack model is currently not working properly throughout the code generator. FSR1 is assigned as stack pointer FSR2 is assigned as frame pointer The following stack models are supported by the PIC16 port • SMALL model • LARGE model S MALL model means that only the FSRxL byte is used to access stack and frame. This improves speed but you may not use this for functions with arguments that are called via function pointers. } shadowregs instructs the code generator not to store/restore WREG. This can be done by adding the keyword shadowregs before the interrupt keyword in the function’s header. Also there are some other points that need special care:
1. while LARGE uses both FSRxL and FSRxH registers. THE PIC16 PORT
CHAPTER 4. PIC16 port makes available two more: wparam Use the WREG to pass one byte of the ﬁrst function argument.. otherwise the ﬁrst byte of the ﬁrst parameter will get lost. Stack sections should no cross physical bank limits (i.
70
. STATUS..6. BSR when entering/exiting the ISR.
4.6.6. } shadowregs When entering/exiting an ISR. NOTES ON SUPPORTED PROCESSORS
4. Do not create stack sections with size more than one physical bank (that is 256 bytes) 2. FSR1 and FSR2. This problem will disappear after LARGE model is fully implemented. #pragma stack 0x50 0x100) These limitations are caused by the fact that only FSRxL is modiﬁed when using SMALL stack model.

void isr(void) interrupt n { . This single GOTO instruction is part of an automatically generated interrupt entry point function. The actuall ISR code is placed as normally would in the code space.6. When declaring interrupt functions as _naked this GOTO instruction is not generated. The following table shows these registers: size 8 bits 16 bits 24 bits 32 bits >32 bits destination register WREG PRODL:WREG PRODH:PRODL:WREG FSR0L:PRODH:PRODL:WREG on stack. 2.6. } n is the interrupt number.14
Interrupts
An interrupt service routine (ISR) is declared using the interrupt keyword. the GOTO instruction is executed which jumps to the ISR code. This way a function is generated similar to an ISR. This is not a problem for the LOW priority interrupts. NOTES ON SUPPORTED PROCESSORS
4. THE PIC16 PORT
CHAPTER 4.3 n may be omitted. then NO registers are stored or restored..
4 NOTE
that when the _naked attribute is speciﬁed for an interrupt routine. this is a HIGH interrupt ISR and LOW interrupts are disabled or not used.4
3 This
is not a problem when
1. When entering an interrupt.13
Function return values
Return values from functions are placed to the appropriate registers following a modiﬁed Microchip policy optimized for SDCC. which for PIC18F devices can be: n 0 1 2 Interrupt Vector RESET vector HIGH priority interrupts LOW priority interrupts Interrupt Vector Address 0x000000 0x000008 0x000018
When generating assembly code for ISR the code generator places a GOTO instruction at the Interrupt Vector Address which points at the generated ISR.4.6. The whole interrupt functions is therefore placed at the Interrupt Vector Address of the speciﬁc interrupt.. but it is not assigned to any interrupt. but it is a problem for the RESET and the HIGH priority interrupts because code may be written at the next interrupt’s vector address and cause indeterminate program behaviour if that interrupt is raised. FSR0 points to the beginning
4. currently the PIC16 port automatically saves the following registers: • WREG • STATUS • BSR • PROD (PRODL and PRODH) • FSR0 (FSR0L and FSR0H) These registers are restored upon return from the interrupt routine. when the ISR is small enough not to reach the next interrupt’s vector address. Upon interrupt request.
71
.

h as having its parameter in WREG (it has the wparam keyword).6. THE PIC16 PORT
CHAPTER 4. 2. In order to increase performance putchar is declared in stdio. In the libc library there exist the functions that are used to write to each of the above streams. This new type has the format: pointer type stream <7:6> 00 <5> 1 <4> 0 <3:0> nnnn rest of the pointer uuuuuuuu uuuuuuuu descrption upper byte high nubble is 0x2n.6.h: extern FILE * stdin.h exists the macro PUTCHAR(arg) that deﬁnes the putchar function in a user-friendly way.15
Generic Pointers
Generic pointers are implemented in PIC16 port as 3-byte (24-bit) types. There are 3 types of generic pointers currently implemented data.6. the rest are zeroes
Currently implemented there are 3 types of streams deﬁned: stream type STREAM_USART STREAM_MSSP STREAM_USER value 0x200000UL 0x210000UL 0x2f0000UL module USART MSSP (none) description Writes/Reads characters via the USART peripheral Writes/Reads characters via the MSSP peripheral Writes/Reads characters via used deﬁned functions
The stream identiﬁers are declared as macros in the stdio. 4 bytes. extern FILE * stdout. the stream pointer.h> PUTCHAR( c ) { PORTA = c.16
4.h header.4.
/* dump character c to PORTA */ 72
.h the type FILE is deﬁned as: typedef char * FILE.
4.h> #include <stdio. This writes a character to a user speciﬁed manner. 3.16. This type is the stream type implemented I/O in the PIC18F devices. code and eeprom pointers. These are __stream_usart_putchar writes a character at the USART stream __stream_mssp_putchar writes a character at the MSSP stream putchar dummy function. NOTES ON SUPPORTED PROCESSORS
4. The FILE type is actually a generic pointer which deﬁnes one more type of generic pointers. Also the standard input and output streams are declared in stdio.1
PIC16 C Libraries
Standard I/O Streams
In the stdio.6. arg is the name of the variable that holds the character to print. They are differentiated by the value of the 7th and 6th bits of the upper byte: pointer type data code eeprom (unimplemented) 7th bit 1 0 0 1 6th bit 0 0 1 1 rest of the pointer uuuuxxxx xxxxxxxx xxxxxxxx xxxxxxxx uuuuuuxx xxxxxxxx xxxxxxxx xxxxxxxx description a 12-bit data pointer in data RAM memory a 21-bit code pointer in FLASH memory a 10-bit eeprom pointer in EEPROM memory unimplemented pointer type
uuuuuu uxxxxx uuuuuu xxxxxx
Generic pointer are read and written with a set of library functions which read/write 1. In stdio. An example follows: #include <pic18fregs.

One must take care that when there are many levels of function nesting.4.
4. 4. 18f4455.18. If you encounter problems like not being able to print integers.) at the end of the DEF_* and END_DEF macros. or there is excessive usage of stack.18. Other ways to reduce stack usage may exist.6.h> #include <signal. Using command line arguments like --fomit-frame-pointer might reduce stack usage by not creating unnecessery stack frames.6.6.1
Known Bugs
Extended Instruction Set
The PIC16 port emits code which is incompatible with the extended instruction set available with many newer devices.1 Stack size
The default stack size (that is 64 bytes) probably is enough for many programs. _bcol_handler) END_DEF SIGHANDLER(_tmr0_handler) { /* action to be taken when timer 0 overflows */ } SIGHANDLERNAKED(_bcol_handler) { __asm /* action to be taken when bus collision occurs */ retfie __endasm.17
PIC16 Port – Tips
Here you can ﬁnd some general tips for compiling programs with SDCC/pic16.h>
CHAPTER 4. and 18f4550) use _ENHCPU_OFF_4L instead of _XINST_OFF_4L. Make sure to always explicitly disable it. THE PIC16 PORT #include <pic18fregs. The following diagram shows what happens when calling printf to print an integer: printf () --> ltoa () --> ultoa () --> divschar () It is should be understood that stack is easily consumed when calling complicated functions. 18f2550. its size should be extended.17.8).
4.6. 4. usually using static __code char __at(__CONFIG4L) conf4l = /* more flags & */ _XINST_OFF_4L. thus no automatic regression tests are currently performed for the PIC16 target.6. • when declaring SIGHANDLERNAKED handler never forget to use retﬁe for proper returning. 74
. An example of such a case is the printf/sprintf family of functions. then you need to set the stack size around the maximum (256 for small stack model).6. } NOTES: Special care should be taken when using the above scheme: • do not place a colon (. _tmr0_handler) DEF_HANDLER(SIG_BCOL. Some devices (namely 18f2455.18
4.2 Regression Tests
The PIC16 port currently passes most but not all of the tests in SDCC’s regression test suite (see section 7. NOTES ON SUPPORTED PROCESSORS
DEF_INTHIGH(high_int) DEF_HANDLER(SIG_TMR0.

You’ll probably want some level shifting device typically involving a MAX232 or similar IC. If the hardware serial port of the MCU is not available search for ’Software UART’ in your favourite search machine.2.1. have strategic points within your code where all variables are consistent.2. Most commercial compiler vendors will offer an evaluation version so you can test compile your code or snippets of your code.e.9) on how to handle syntax extensions like __xdata. In this context a monitor is a small program which usually accepts commands via a serial line and allows to set program counter.) to the devices the ICE can emulate... Debugging on a simulator: • there is a separate section about SDCDB (section 5. monitor 2 push-pull driven pins by connecting one via a 10 kΩ resistor and the other one by a 5 kΩ resistor to the oscilloscope probe (check output drive capability of the pins you want to monitor). If you need to monitor many more pins a logic analyzer will be handy.1) below. .. A digital oscilloscope with deep trace memory is really helpful especially if you have to debug a realtime application. Debugging On-target: • use a MCU port pin to serially output debug data to the RS232 port of your host. __at().Chapter 5
Debugging
There are several approaches to debugging your code. • use an on-target monitor. For the 8051 good examples of monitors are paulmon and cmon51 (see section 6. put conceptually similar variables into structs.5).. Usually very expensive. • use another C-compiler to compile code for your target. If you seriously consider walking this path you should at least occasionally check portability of your code. • use an ICE (in circuit emulator). use structured code.9) over the code.e. • or (8051 speciﬁc) use a free open source/commercial simulator which interfaces to the AOMF ﬁle (see 3. • for the high level code use a C-compiler (like f. Always an option but not recommended:) And not very likely to help you..
75
. . • toggle MCU port pins at strategic points within your code and use an oscilloscope. If you need to monitor more pins than your oscilloscope provides you can sometimes get away with a small R-2R network.) • run a syntax-checking tool like splint (see --more-pedantic 3. On a single channel oscilloscope you could f. This chapter is meant to show your options and to give detail on some of them: When writing your code: • write your code with debugging in mind (avoid duplicating code. And usually locks you (for years. See (see --more-pedantic 3. GCC) to compile run and debug the code on your host. And very nice to have too..1) optionally generated by SDCC. to single step through a program and read/write memory locations.

• foo.adb ﬁle.cdb ﬁle from the individual . DEBUGGING
• use a remote debugger. atomic.1. • foo. For the mcs51 most hardware debuggers use the AOMF ﬁle (see 3.cdb ﬁle from the .
5.the Intel hex format object ﬁle. The conﬁguration and build process is part of the standard compiler installation. Then the linker creates the .1.net/ is an effort to connect directly to the hardware. Last not least: • if you are not familiar with any of the following terms you’re likely to run into problems rather sooner than later: volatile.2
How the Debugger Works
When the --debug option is speciﬁed the compiler generates extra symbol information some of which are put into the assembler source and some are put into the .1
Compiling for Debugging
The --debug option must be speciﬁed for all ﬁles for which debug information is to be generated.adb ﬁles with the address information for the symbols. The debugger allows you debug BOTH at the C source and at the ASM source level.
5. overlay. The linker creates the .adb ﬁle for each of these ﬁles.sf.
5. As ’failure to communicate’ is probably one of the job-induced deformations of an embedded programmer this is highly encouraged. ’gdb stub’ or ’inferior debugger’. (Assume the ﬁle you are debugging has the ﬁle name foo).1.1. The debugger uses a command line interface. DEBUGGING WITH SDCDB
CHAPTER 5. Terms to enter into your favourite search engine could be ’remote debugging’.1
Debugging with SDCDB
SDCC is distributed with a source level debugger. Therefore usually a debugger on the host system connects to an on-target debugging stub which accepts only primitive commands.cdb is used by the debugger. The compiler generates a . This facility doesn’t require additional code to run on the target and usually doesn’t affect runtime behaviour until a breakpoint is hit. memory map.adb ﬁles and the address information. In most 8-bit systems the symbol information is not available on the target. • foo. and a complete debugger is too bulky for the target system. the program execution is controlled by the debugger. which also builds and installs the debugger in the target directory speciﬁed during conﬁguration. (Currently SDCDM only connects to the simulator but newcdb at http://ec2drv. 76
. Some of the more modern MCUs include hardware support for setting break points and monitoring/changing variables by using dedicated hardware pins.cdb .c .5. sdcdb foo The debugger will look for the following ﬁles. As an embedded programmer you have to know them so why not look them up before you have problems?) • tell someone else about your problem (actually this is a surprisingly effective means to hunt down the bug even if the listener is not familiar with your environment). It uses the SIMULATOR (Daniel’s S51) to execute the program. it translates it into appropriate commands for the simulator.the debugger symbol information ﬁle.1.3
Starting the Debugger SDCDB
The debugger can be started using the following command line.)
5. This . When a command is issued for the debugger.ihx . the command repertoire of the debugger has been kept as close to gdb (the GNU debugger) as possible. (is there one?) • use an on target hardware debugger.1) as input ﬁle.the source ﬁle. The debugger reads the symbolic information generated by the compiler & the address information generated by the linker.

after breakpoint. DEBUGGING WITH SDCDB
CHAPTER 5.used by GUI front ends.this argument is passed to the simulator please see the simulator docs for details.out> passed to simulator see the simulator docs for details. xxgdb or xemacs) existing for the GNU debugger.c:funcfoo continue Continue program being debugged. The debugger will look into the directory list speciﬁed for source. • -S <serial in. delete [n] Delete breakpoint number ’n’.1. if the source ﬁles can be in the directories /home/src1 and /home/src2. break [line | ﬁle:line | function | ﬁle:function] Set breakpoint at speciﬁed line or function: sdcdb>break 100 sdcdb>break foo. If you use a graphical user interface for the debugger you can skip this section.
77
.4
SDCDB Command Line Options
• --directory=<source ﬁle directory> this option can used to specify the directory search list.c:100 sdcdb>break funcfoo sdcdb>break foo. • -X <Clock frequency > this options is passed to the simulator please see the simulator docs for details. If used without any option clear ALL user deﬁned break points.1.g.
5.c:funcfoo clear [line | ﬁle:line | function | ﬁle:function ] Clear breakpoint at speciﬁed line or function: sdcdb>clear 100 sdcdb>clear foo. e.1. cdb & ihx ﬁles. the --directory option should be --directory=/home/src1:/home/src2. • -fullname . Note there can be no spaces in the option. • -s <serial port ﬁle> passed to simulator see the simulator docs for details. • -k <port number> passed to simulator see the simulator docs for details.5. This will help the integration with existing graphical user interfaces (like ddd. as possible.change to the <directory>.c:100 sdcdb>clear funcfoo sdcdb>clear foo.5
SDCDB Debugger Commands
As mentioned earlier the command interface for the debugger has been deliberately kept as close the GNU debugger gdb. The items in the directory list must be separated by ’:’. DEBUGGING
5. • -cd <directory> . ﬁnish Execute till the end of the current function. • -cpu <cpu-type> .

run Start debugged program. quit "Watch me now. Note this is an alternate method of loading ﬁle for debugging.5. proceeding through subroutine calls. so if a command like ’go’ is sent the debugger can loose its execution context and may display incorrect values.show information about the current execution frame.show the function call stack.1. ! simulator command Send the string following ’!’ to the simulator. DEBUGGING WITH SDCDB info [break | stack | frame | registers ] • info break . My name is Bobby Brown"
78
. • info frame . Iam going Down. Note the debugger does not interpret the command being sent to the simulator. • info registers .show content of all registers. next Step program. frame print information about current frame. print variable print value of variable. Note: pressing <return> repeats the last command. set srcmode Toggle between C source & assembly source. ﬁle ﬁlename load the given ﬁle name. DEBUGGING
Step program until it reaches a different source line. step
CHAPTER 5.list all breakpoints • info stack . ptype variable Print type information of the variable. the simulator response is displayed.

..5. The source was compiled with
sdcc/doc/figures/ddd_example. s sdcdb-step-from-src ..xemacs’ ﬁle (which can be found in your HOME directory): (load-file sdcdbsrc. these values maybe changed as required.xemacs is a lisp ﬁle so the () around the command is REQUIRED. The command line options that are passed to the simulator directly are bound to default values in the ﬁle sdcdbsrc. This can be done at XEmacs startup time by inserting the following into your ’. The ﬁles can also be loaded dynamically while XEmacs is running. Current Listing :: . DEBUGGING
5. displaying and changing variables. To start the interface enter the following command: ESC-x sdcdbsrc You will prompted to enter the ﬁle name to be debugged. sdcdb.net/viewvc/*checkout*/sdcc/trunk/ shows a screenshot of a debugging session with DDD (Unix only) on a simulated 8032.1. The variables are listed below. b sdcdb-back-from-src . DEBUGGING WITH SDCDB
CHAPTER 5..6
Interfacing SDCDB with DDD
The portable network graphics File http://sdcc. .el) .el..sourceforge. These ﬁles need to be loaded into XEmacs for the interface to work.. arg x) . then enter the following command ESC-x load-ﬁle sdcdbsrc.. The debugging session might not run as smoothly as the screenshot suggests. • sdcdbsrc-cpu-type ’51 • sdcdbsrc-frequency ’11059200 • sdcdbsrc-serial nil The following is a list of key mapping for the debugger interface.svn..7
Interfacing SDCDB with XEmacs
Two ﬁles (in emacs lisp) are provided for the interfacing with XEmacs.1.1. ? sdcdb-whatis-c-sexp at .el and sdcdbsrc. n sdcdb-next-from-src . set the environment variable ’EMACSLOADPATH’ to the installation bin directory (<installdir>/bin).c and DDD was invoked with ddd -debugger "sdcdb -cpu 8032 ddd_example"
5.--------.el. c sdcdb-cont-from-src . The debugger allows setting of breakpoints. m sdcdbsrc-frame 79
Comment ------SDCDB SDCDB SDCDB SDCDB SDCDB next command back command continue command step command ptypecommand for data
buffer point SDCDB Delete all breakpoints given or delete arg (C-u SDCDB Display current frame
. x sdcdbsrc-delete if no arg .. These two ﬁles can be found in the $(preﬁx)/bin directory after the installation is complete..png
sdcc --debug ddd_example. single stepping through C and assembler code... ..key binding ..

Don’t complain.
81
.c FAQ”: If well-deﬁned overﬂow characteristics are important and negative values are not. No. use one of the corresponding unsigned types. Therefore the results are different. if the result is the same. Another one: (unsigned char) -12 / (signed char) -3 = ... if (uc * uc < 0) /* this is true! { .lang. or if you want to steer clear of sign-extension problems when manipulating bits or bytes. This helps especially if you are doing division or multiplication. due to unpredictable sign extension and increased code size. bit-shifting or are using an array index. This promotion can be ! omitted. The effect of the promotion rules together with the sign-extension is often surprising: unsigned char uc = 0xfe. the result is not 4: (int) (int) (int) (int) (int) (int) (unsigned char) -12 / (int) (signed char) -3 = (unsigned char) 0xf4 / (int) (signed char) 0xfd = 0x00f4 / (int) 0xfffd = 0x00f4 / (int) 0xfffd = 244 / (int) -3 = -81 = (int) 0xffaf.Chapter 6
TIPS
Here are a few guidelines that will help the compiler generate more efﬁcient code. while SDCC uses 16 bit ints. Please note. that gcc gives you a different result. (Beware when mixing signed and unsigned values in expressions.) Although character types (especially unsigned char) can be used as "tiny" integers. that ANSI C requires both signed and unsigned chars to be promoted to ’signed int’ before doing any operation.. • Use the smallest data type to represent your data-value.. • Use unsigned when it is known in advance that the value is not going to be negative. though. }
*/
uc * uc is evaluated as (int) uc * (int) uc = (int) 0xfe * (int) 0xfe = (int) 0xfc04 = -1024. doing so is sometimes more trouble than it’s worth. gcc uses 32 bit ints. some of the tips are speciﬁc to this compiler others are generally good programming practice. From ”comp.. If it is known in advance that the value is going to be less than 256 then use an ’unsigned char’ instead of a ’short’ or ’int’.

PORTING CODE FROM OR TO OTHER COMPILERS • NEVER jump into a LOOP. Eventually include the ﬁle <compiler.1
Porting code from or to other compilers
• check whether endianness of the compilers differs and adapt where needed. cc2510fx. Eventually insert explicit casts to (char) or (unsigned char).1.svn. stack. See sections 6 and 1. TIPS
• Declare the variables to be local whenever possible. • check the resulting memory map.sourceforge.
6.h> http://sdcc. • check if some 16 or 32 bit hardware registers require a speciﬁc addressing order (least signiﬁcant or most signiﬁcant byte ﬁrst) and adapt if needed (ﬁrst and last relate to time and not to lower/upper memory location here. Usage of different memory spaces: code. especially loop control variables (induction). • check the assembly code generated for interrupt routines (f. for calls to possibly non-reentrant library functions). pdata.4.sourceforge.e. • check the device speciﬁc header ﬁles for compiler speciﬁc syntax.h?view=markup to allow using common header ﬁles. • check whether the startup code contains the correct initialization (watchdog.
82
. Provide a putchar() function if needed. • check and convert compiler speciﬁc extensions (interrupts.
CHAPTER 6. • check for differences in printf parameters (some compilers push (va_arg) char variables as int others push them as char. Eventually check if unexpected library functions are included.6.h?view=markup).svn. The compilers might differ in their optimization characteristics (as different versions of the same compiler might also use more clever optimizations this is good idea anyway). (see f. See section 3. Also check that the ~ operator is not used on bit variables.h http://sdcc. • check whether timing loops result in proper timing (or preferably consider a rewrite of the code with timer based delays instead). long match. peripherals).4).1. • check whether the sizes of short. use the ! operator instead.net/viewvc/sdcc/trunk/sdcc/device/include/ mcs51/compiler. int. • Have a look at the assembly listing to get a ”feeling” for the code generation. • check whether the keyword volatile is used where needed. • check for differences in type promotion. Especially check for math operations on char or unsigned char variables. data (for mcs51/ds390 additionally idata. See section 1. so this is not the same as endianness).9. xdata). pragmas etc.e.net/viewvc/sdcc/trunk/sdcc/device/include/ mcs51/cc2510fx. For the sake of C99 compatibility SDCC will probably promote these to int more often than other compilers.1. memory areas. • check that the compilers are not told to suppress warnings.).

labels. SOME QUESTIONS
CHAPTER 6.pdf http://pdfserv. tsp?literatureNumber=sbaa109&fileType=pdf
6.com/general/docs/lit/getliterature. some pointers given .it might be time to in turn ask you some questions: • can you solve your project with the selected microcontroller? Would you ﬁnd out early or rather late that your target is too small/slow/whatever? Can you switch to a slightly better device if it doesn’t ﬁt? • should you solve the problem with an 8 bit CPU? Or would a 16/32 bit CPU and/or another programming language be more adequate? Would an operating system on the target device help? • if you solved the problem. manual(s). production test software. patent issues? • is your project adequately positioned in that magic triangle: fame. internationali(z|s)ation.6. packaging.. will customers be happy? • if you’re the project manager. will the marketing department be happy? • if the marketing department is happy. update mechanism. fun? Maybe not all answers to these questions are known and some answers may even be no. 2nd source for components. electromagnetic compatability/interference.8
Some Questions
Some questions answered.maxim-ic. fortune..asp http://focus. marketing department and maybe even the customer in one person. programmers and motorcycle tyres
86
. have you tried to see the project from the outside? • is the project done if you think it is done? Or is just that other interface/protocol/feature/conﬁguration/option missing? How about website.silabs.ti.com/public/documents/tpub_doc/ anote/Microcontrollers/en/an198.pdf http://www. documentation for production.com/en/an/AN3346.ramtron.asp http://www. nevertheless knowing these questions may help you to avoid burnout1 .ramtron. TIPS
Vendor Maxim / Dallas Maxim / Dallas
Subject / Title Using the SDCC Compiler for the DS80C400 Using the Free SDCC C Compiler to Develop Firmware for the DS89C420/430/440/450 Family of Microcontrollers
Where to get http://pdfserv.
1 burnout
is bad for electronic devices.com/doc/Products/Microcontroller/ Support_Tools. Chances are you didn’t want to hear some of them.pdf
Silicon Laboratories / Cygnal Ramtron / Goal Semiconductor Ramtron / Goal Semiconductor Texas Instruments
Integrating SDCC 8051 Tools Into The Silicon Labs IDE Interfacing SDCC to Syn and Textpad Installing and Conﬁguring SDCC and Crimson Editor MSC12xx Programming with SDCC
http://www.com/doc/Products/Microcontroller/ Support_Tools.8.maxim-ic.com/en/an/AN3477.

Bug reports are automatically forwarded to the developer mailing list and will be ﬁxed ASAP. 5.
7. download area and Subversion code repository there. Specify the SDCC version (type "sdcc -v"). If you can isolate the problem by looking at the generated assembly code. The developers take pride in ﬁxing reported bugs. bug reporting system. 3. wiki. There are lots of ways to contribute. it will greatly improve your chance that SDCC users and developers will be able to help you. The compiler alone (without the preprocessor. This is the link for reporting bugs: http://sourceforge. Put something meaningful in the subject of your message. You’ll ﬁnd the complete set of mailing lists. so please be sure to provide sample code if you are reporting a bug! Please have a short check that you are using a recent version of SDCC and the bug is not yet known. Is SDCC perfect? No. With SDCC on average having more than 200 downloads on sourceforge per day1 there must be some users. Provide an exact copy of any error message or incorrect output. When reporting a bug please make sure you: 1. forums. You can help by reporting the bugs and helping other SDCC users. assembler and linker) is well over 150. 4. The SDCC project is hosted on the SDCC sourceforge site at http://sourceforge. as applicable. Please attempt to include these 5 important parts. Some SDCC developers are frustrated by bug reports without code provided that they can use to reproduce and ultimately ﬁx the problem. and operating system. rss-feed. You gain the beneﬁt and support of many active software developers and end users. The open source nature of this project is a key to its continued growth and support.
1 220 daily downloads on average Jan-Sept 2006 and about 150 daily downloads between 2002 and 2005. This does not include other methods of distribution. You can follow the status of bug reports there and have an overview about the known bugs. this can be very helpful. Attach the code you are compiling with SDCC.
87
. in all requests for support or when reporting any problems or bugs with SDCC.1
Reporting Bugs
The recommended way of reporting bugs is using the infrastructure of the sourceforge site. When reporting a bug. your platform. Specify the exact command you use to run SDCC.net/projects/ sdcc. that’s why we need your help. Though this will make your message lengthy. 2. it is very useful to include a small test program (the smaller the better) which reproduces the problem. patch submission system. or attach your Makeﬁle. and we encourage you to take part in making SDCC a great software package. So it’s not exactly easy to ﬁnd a new bug. If you ﬁnd one we need it: reporting bugs is good.Chapter 7
Support
SDCC has grown to be a large project.net/tracker/?group_id=599&atid=100599. Compiling your program with the --dumpall option can sometimes be useful in locating optimization problems.000 lines of code (blank stripped).

7.net/mail/?group_id= 5992 and the Forums http://sourceforge.patch” will do.2. The last digit of an ofﬁcial release is zero. Opteron.net/tracker/?group_id=599&atid=300599. The so called regression tests check that SDCC itself compiles ﬂawlessly on several host platforms (i386. If you modiﬁed more than one ﬁle a patch created f.7
Release policy
Historically there often were long delays between ofﬁcial releases and the sourceforge download area tended to get not updated at all.sourceforge. Solaris on Sparc) and checks the quality of the code generated by SDCC by running the code for several target platforms through simulators.2
Requesting Features
Like bug reports feature requests are forwarded to the developer mailing list. An on-line source code browser and detailled instructions are also available there.c.4
Getting Help
These links should take you directly to the Mailing lists http://sourceforge.net/tracker/?group_id=599&atid=350599.
7.3
Submitting patches
Like bug reports contributed patches are forwarded to the developer mailing list.5
ChangeLog
You can follow the status of the Subversion version of SDCC by watching the Changelog in the Subversion repository http://sdcc. You need to specify some parameters to the diff command for the patches to be useful. if you’re seriously using SDCC please consider subscribing to the lists.7.8
Quality control
The compiler is passed through daily snapshot build compile and build checks.c >my_changes.sourceforge. The SDCC Wiki at http://sdcc.sourceforge.net/snap. otherwise ”diff -u sourceﬁle. Starting with version 2.
7.net/viewcvs. Additionally there are daily snapshots available at snap http: //sdcc. SUPPORT
7.e.net/ also holds some information about past and future releases.0 SDCC in 2004 switched to a time-based release schedule with one ofﬁcial release usually during the ﬁrst half of the year. This is the link for submitting patches: http://sourceforge.
7. The regression test suite comprises more than 100 ﬁles which expand
2 Trafﬁc
on sdcc-devel and sdcc-user is about 100 mails/month each not counting automated messages (mid 2003)
88
.php#Source.patch” will be ﬁne. with ”diff -Naur unmodiﬁed_directory modiﬁed_directory >my_changes. net/svn/?group_id=599 (by number or by date). This is the link for requesting features: http://sourceforge.
7. lists and forums are archived and searchable so if you are lucky someone already had a similar problem. REQUESTING FEATURES
CHAPTER 7. SDCC versions starting from 1999 up to now are available (currently the versions prior to the conversion from cvs to Subversion (April 2006) are either by accessible by Subversion or by cvs).net/forum/?group_id=599.cgi/*checkout*/sdcc/trunk/sdcc/ChangeLog. ppc64. and you can always build the very last version from the source code available at Sourceforge http://sdcc. Subversion allows to download the source of recent or previous versions http://sourceforge. 64 bit Alpha.sourceforge.php.6
Subversion Source Code Repository
The output of sdcc --version or the ﬁlenames of the snapshot versions of SDCC include date and its Subversion number. Mac OS X on ppc and i386.orig sourceﬁle.net/snap.wiki.svn.4.
7. While mails to the lists themselves are delivered promptly their web front end on sourceforge sometimes shows a severe time lag (up to several weeks).

This connotation is not intended but nevertheless risked as the licensing of SDCC makes it difﬁcult to offer educational discounts
89
. not encourage students to use illegal copies of educational software 6.sourceforge. give students a chance to understand the complete steps of code generation 2. CPU simulation. submitting/applying patches. ”make test-mcs51” if you don’t want to run the complete tests). SUPPORT
to more than 500 test cases which include more than 4500 tests.10
Use of SDCC in Education
In short: highly encouraged3 . Mac OS X. Oregano http://www.php).sourceforge. over assembly programming. sf. have a curriculum that can be extended for years. You’ll ﬁnd the test code in the directory sdcc/support/regression. EXAMPLES
CHAPTER 7.oregano.org/wiki/Netiquette. The PIC14 port uses a different set of regression tests . growth models of Open Source Software. Then you could use an fpga board as target and your curriculum will seamlessly extend from logic synthesis (http://www. not tie students to a speciﬁc host platform and instead allow them to use a host platform of their choice (among them Alpha. Windows and eventually OLPC http:// www. More examples and libraries are available at The SDCC Open Knowledge Resource http://sdccokr. be able to change to a new target platform without having to adopt a new tool chain 8. be immune to licensing/availability/price changes of the chosen tool chain 7. be able to insert excursions about skills like using a revision control system. Sparc. compiler regression tests. probably SDCC might be the only choice. to C to FPGA compilers (FPGAC http://sf.de/ web site or at http://www. give back to the public as you are probably at least partially publicly funded 11.net/tracker/?group_id=599&atid=350599.
7. Mips.org) 5. The results of these tests are published daily on SDCC’s snapshot page (click on the red or green symbols on the right side of http://sdcc.e. pjrc.
3 the phrase "use in education" might evoke the association "only ﬁt for use in education". net/snap. i386. A using a type-setting (as opposed to word-processing) engine LYX/LTEX.org opencores. you’ll ﬁnd them in the directory sdcc/src/regression. The test code might also be interesting if you want to look for examples checking corner cases of SDCC or if you plan to submit patches.net/doc/test_suite_ spec. have complete control over and insight into the tool chain 9.pdf about the regression test suite. Well. 3.7.opencores. following some netiquette http://en.htm). And if there should be a shortage of ideas then you can always point students to the ever-growing feature request list http://sourceforge.com/tech/8051/.
7. make your students aware about the pros and cons of open source software development 10.net.9. understanding BSD/LGPL/GPL/Proprietary licensing. There is a separate document test_suite.net/projects/fpgac) and to C. 4.pdf http://sdcc. using SourceForge http://www.dl9sec.org. If your rationales are to: 1.laptop. give students a chance to publicly prove their skills and to possibly see a world wide impact then SDCC is probably among the ﬁrst choices.at/ip/ip01.9
Examples
You’ll ﬁnd some small examples in the directory sdcc/device/examples/. You can run these tests manually by running make in this directory (or f.wikipedia. i386_64.

As mentioned previously some loop invariants are not as apparent. j = i. changed to itemp1 = 0. this optimization substitutes an expression by a cheaper expression: for (i=0. i = 10. i < 100 . which may cause unwanted spilling of other temporary variables into the stack / data space. i++) ar[i*5] = i*3.
8.1. }
will be changed to int f() { int i.i < 100. for (i = 0. changed to itemp = k + l. Strength Reduction. i < 100. SDCC TECHNICAL DATA
8. i++) f += itemp.1. Loop Invariant: for (i = 0 . return j. If this extra space allocation is undesirable then induction optimization can be eliminated either for the entire source ﬁle (with --noinduction option) or for a given function only using #pragma noinduction. The compiler will generate a warning message when it is forced to allocate extra space either on the stack or data space. itemp2 = 0. }
CHAPTER 8. 91
. all static address computations are also moved out of the loop. } Note: the dead stores created by this copy propagation will be eliminated by dead-code elimination. OPTIMIZATIONS int global. j = 10. return 10. Because of this preference of the register allocator.1. j. In addition to the strength reduction the optimizer marks the induction variables and the register allocator tries to keep the induction variables in registers for the duration of the loop. void f () { global = 2. i ++) f += k + l.3
Copy-Propagation
int f() { int i. j.4
Loop Optimizations
Two types of loop optimizations are done by SDCC loop invariant lifting and strength reduction of loop induction variables. i = 10. loop induction optimization causes an increase in register pressure.8.

= j . the following is a small sub-set of these optimizations. .
.. It makes the decision based on an estimate of the generated code size. OPTIMIZATIONS for (i=0.. switch(i) { case 4: case 5: case 3: case 6: case 7: case 8: case 9: switch (i) { case 0: . = j / 1.. and the starting number need not be one or zero.1. <sym> [< | <=] <expression>.. SDCC uses a more simple minded analysis). SDCC checks for the following criterion to determine if a loop is reversible (note: more sophisticated compilers use data-dependency analysis to make this determination... • The ’for’ loop is of the form for(<symbol> = <expression>.7
’switch’ Statements
SDCC can optimize switch statements to jump tables.. [<sym>++ | <sym> += 1]) <for body> • The <for body> does not contain “continue” or ’break”. .. >>= 1..
8. SDCC is quite liberal in the requirements for jump table generation: • The labels need not be in order..
SDCC does numerous algebraic simpliﬁcations.. /= 2. ..
8. .1.5
Loop Reversing
This optimization is done to reduce the overhead of checking loop boundaries for every iteration.. = j.. . }
CHAPTER 8. = 0. case 1: .... SDCC TECHNICAL DATA
The more expensive multiplication is changed to a less expensive addition.1.8. • All goto’s are contained within the loop. /* /* /* /* changed changed changed changed to: to: to: to: */ */ */ */ i i i i = j...
.. . • No function calls within the loop.. case case case case 92 3: 4: 5: 6: .
8. • There are NO switch statements in the loop. . the case labels are in numerical sequence or not too many case labels are missing.
Note the subexpressions given above are generally introduced by macro expansions or as a result of copy/constant propagation.j. itemp1 += 5.i< 100...1..6
i i i i
Algebraic Simpliﬁcations
= j + 0. • The loop control variable <sym> is not assigned any value within the loop • The loop control variable does NOT participate in any arithmetic operation within the loop.i++) { ar[itemp1] = itemp2. . . itemp2 += 3... Some simple loops can be reversed and implemented using a “decrement and jump if not zero” instruction.

9
Bit-rotation
A special case of the bit-shift operation is bit rotation._i a a.1.: unsigned char i. The pragma nojtbound can be used to turn off checking the jump table boundaries..
8.8
Bit-shifting Operations. e. Use of this pragma is dangerous: if the switch argument is not matched by a case statement the processor will happily jump into Nirvana. ..a
8.#0x00 c a _i.(_i + 1) (_i + 1). SDCC TECHNICAL DATA
then both the switch statements will be implemented using jump-tables whereas the unmodiﬁed switch statement will not be...#0x0f _i. OPTIMIZATIONS
CHAPTER 8. SDCC tries to implement bit-shift operations in the most efﬁcient way possible. . Another example: unsigned int i.a
In general SDCC will never setup a loop if the shift count is known.a /* unsigned is needed for rotation */
SDCC uses pattern matching on the parse tree to determine this operation.._i a _i... /* left-bit rotation */
94
. i = ((i << 1) | (i >> 7)). .. will generate: mov mov clr rrc mov a.1.: i = ((i >> 7) | (i << 1)).8.Variations of this case will also be recognized as bit-rotation. SDCC recognizes the following expression to be a left bit-rotation: unsigned char i.. i >>= 9.
Bit shifting is one of the most frequently used operation in embedded programming.e. will generate the following code: mov rl mov a.. . i.. .g. .1. It has no effect if a default label is supplied. generates the following code: mov swap anl mov a. i >>= 4..

7.13
Peephole Optimizer
The compiler uses a rule based. some variants of the 8051 MCU allow only ajmp and acall. The optimizer will apply to the rules one by one from the top in the sequence of their appearance.1. replace { mov %1. thus the peephole optimizer can also be used as an assembly level macro expander.a mov a. this option for a rule is expensive (performance).%1 } by { mov %1. A default set of rules are compiled into the compiler. OPTIMIZATIONS
CHAPTER 8. you can use option --acall-ajmp. With the above rule. it is intended to be used in situations where a transformation will trigger the same rule again.a } The above rule will change the following assembly sequence: mov r1. additional rules may be added with the --peep-ﬁle <ﬁlename> option. The rules themselves are MCU dependent whereas the rule language infra-structure is MCU independent.g.a mov a.a mov a. it has side effects) is the following rule:
97
. pattern matching and re-writing mechanism for peep-hole optimization. Peephole optimization rules for other MCU can be easily programmed using the rule language. If the ’restart’ option is speciﬁed. The syntax for a rule is as follows: rule := replace [ restart ] ’{’ <assembly sequence> ’\n’ ’}’ by ’{’ ’\n’ <assembly sequence> ’\n’ ’}’ [if <functionName> ] ’\n’ <assembly sequence> := assembly instruction (each instruction including labels must be on a separate line). it will terminate when all rules are exhausted. E. then the optimizer will start matching the rules again from the top.1.a Note: All occurrences of a %n (pattern variable) must denote the same string.r2 will remain unmodiﬁed.r1 to mov r1.3 on. Other special case optimizations may be added by the user (via --peep-ﬁle option). which also takes care of aligning the interrupt vectors properly. An example of this (not a good one.8.) The inline-assembler code is also passed through the peep hole optimizer. Fraser (cwfraser @ microsoft. The rule language is best illustrated with examples. SDCC TECHNICAL DATA
8. It is inspired by copt a peep-hole optimizer by Christopher W.com). the assembly sequence: mov r1. The following two rules will change all ljmp and lcall to ajmp and acall replace { lcall %1 } by { acall %1 } replace { ljmp %1 } by { ajmp %1 } (NOTE: from version 2.

you can add your own rules in the default set there if you get tired of specifying the --peep-ﬁle option. but maybe some day we will have some better means. Currently implemented are labelInRange. 24bitMode. cannot be passed as function parameters or assigned to each other and cannot be a return value from a function. If you want to code more such functions.: 98
. nop A conditional function can be attached to a rule.8. ANSI-COMPLIANCE replace restart { pop %1 push %1 } by { . i.e. Deviations from the compliance: • functions are not reentrant unless explicitly declared as such or the --stack-auto command line option is speciﬁed. nop push ar1 with the restart option the rule will be applied again to the resulting code and then all the pop-push pairs will be eliminated to yield: .: pop ar1 pop ar2 push ar2 push ar1 would result in: pop ar1 .2. Without the ’restart’ option only the innermost ’pop’ ’push’ pair would be eliminated. labelIsReturnOnly. let me illustrate this with an example. replace { ljmp %5 %2: } by { sjmp %5 %2: } if labelInRange The optimizer does a look-up of a function name table deﬁned in function callFuncByName in the source ﬁle SDCCpeeph. operandsNotSame. SDCC TECHNICAL DATA
Note that the replace pattern cannot be a blank. but can be a comment line. in this case the use of %5 is crucial.html#9899. labelRefCount. • structures and unions cannot be assigned values directly. Note there can be no parameters speciﬁed for these functions. If you are looking at this ﬁle.c. with the name labelInRange. e. If it ﬁnds a corresponding entry the function is called. Attaching rules are somewhat more involved. take a close look at the function labelInRange and the calling mechanism in source ﬁle SDCCpeeph. nop }
CHAPTER 8.c. I know this whole thing is a little kludgey. since the function labelInRange expects to ﬁnd the label in that particular variable (the hash table containing the variable bindings is passed as a parameter).C should be available at: http://www. 24bitModeAndPortDS390 and notVolatile.g.
8.org/jtc1/sc22/wg14/www/standards.open-std.Programming languages . portIsDS390. xramMovcOption. nop . you will see the default rules that are compiled into the compiler.2
ANSI-Compliance
The latest publicly available version of the standard ISO/IEC 9899 .

it does however provide a good starting point for which functions you might look at for further optimization. Do control ﬂow & data ﬂow analysis on the basic blocks. For example if you have switch statement with more than 10 case labels.(number of nodes in control ﬂow graph) + 2. This phase is largely MCU independent (except for the language extensions). }
8. along with some initial optimizations like back patching labels and the pattern matching optimizations like bit-rotation etc. • The second phase involves generating an intermediate code which can be easy manipulated during the later phases. .4
Retargetting for other Processors
The issues for retargetting the compiler are far too numerous to be covered by this document. • This phase does the bulk of the standard optimizations and is also MCU independent. This phase is entirely MCU independent. The complexity level is by no means an absolute measure of the algorithmic complexity of the function. Syntax & semantic checks are also done in this phase. The compiler can be made to dump a human readable form of the code generated by using the --dumpraw option. CYCLOMATIC COMPLEXITY void vararg_func (char *str. SDCC uses the following formula to compute the complexity: complexity = (number of edges in control ﬂow graph) . Having said that the industry standard is 10. * is promoted to int before passing * to function if --std-cXX is defined */ vararg_func ("%bc". and small functions can have large complexity levels. 100
.. SDCC TECHNICAL DATA { str. /* argument u is not promoted to int. The accepted industry standard for complexity number is 10. you should be aware that in some cases it be may unavoidable to have a complexity level of less than 10..3.3
Cyclomatic Complexity
Cyclomatic complexity of a function is deﬁned as the number of independent paths the program can take during execution of the function. }
/* argument u is promoted to int before * passing to function */ vararg_func ("%c". Note that the complexity level is not related to the number of lines of code in a function. and designates them with the name iTemp. c). • Parsing the source and building the annotated parse tree. This phase can be broken down into several sub-phases: Break down intermediate code (iCode) into basic blocks. The intermediate code generation assumes the target machine has unlimited number of registers.) void main (void) { char c = 10. This is an important number since it deﬁnes the number test cases you have to generate to validate the function.
8. What follows is a brief description of each of the seven phases of the compiler and its MCU dependency. if the cyclomatic complexity reported by SDCC exceeds 10 you should think about simpliﬁcation of the function logic.
CHAPTER 8.8. Large functions can have low complexity. (char)u). * it is passed as char to function * if --std-cXX is not defined. each case label adds one to the complexity level.

However the scheme for allocating a homogenized assembler operand for each iCode operand may be reused. More information is available on SDCC Wiki (preliminary link http://sdcc. There are two parts to this process.sourceforge. RETARGETTING FOR OTHER PROCESSORS
CHAPTER 8. Live range analysis is essential for register allocation. by live range I mean those iTemp variables deﬁned by the compiler that still survive after all the optimizations.php? msg_id=13954144 .net/ SDCC+internals+and+porting) and in the thread http://sf. • The Code generation phase is (unhappily).4. entirely MCU dependent and very little (if any at all) of this code can be reused for other MCU.wiki. since these computation determines which of these iTemps will be assigned to registers.
101
. and for how long.8.net/mailarchive/message. which can reprogrammed for other MCUs. The ﬁrst part I call ’register packing’ (for lack of a better term). In this case several MCU speciﬁc expression folding is done to reduce register pressure. then global subexpression elimination Dead code elimination Loop optimizations If loop optimizations caused any changes then do ’global subexpression elimination’ and ’dead code elimination’ again. SDCC TECHNICAL DATA
Do local common subexpression elimination. • This phase determines the live-ranges. A lot of MCU speciﬁc code does creep into this phase because of the limited number of index registers available in the 8051. • Phase ﬁve is register allocation. The second part is more MCU independent and deals with allocating registers to the remaining live ranges. • As mentioned in the optimization section the peep-hole optimizer is rule based system.

xdata will be treated as a storage class speciﬁer when parsing 8051 C code but will be treated as a C identiﬁer when parsing z80 or ATMEL AVR C code. Live range analysis During intermediate code generation phase. Parsing Parsing the input source ﬁle and creating an AST (Annotated Syntax Tree). but pretty well exposes the guts of it all. common sub-expression elimination. Register Allocation The register allocation determines the type and number of registers needed by each operand. Bulk of the target independent optimizations is performed in this phase. The live range computation determines the lifetime of each of these compiler-generated temporaries. There are some MCU speciﬁc parsing rules. The live ranges are computed in terms of these numbers. The from number is the number of the iCode which ﬁrst deﬁnes the operand and the to number signiﬁes the iCode which uses this operand last. For example the storage classes. The compiler will try to allocate the appropriate register to pointer variables if it can. It is important to note here. ICode example sections show the live range annotations for each of the operand. A picture speaks a thousand words.1 The anatomy of the compiler
This is an excerpt from an article published in Circuit Cellar Magazine in August 2000. each iCode is assigned a number in the order of its execution in the function. It’s a little outdated (the compiler is much more efﬁcient now and user/developer friendly). ICode example section shows some examples of iCode generated for some simple C source functions. Optimizations. the extended storage classes are MCU speciﬁc while there may be a xdata storage class for 8051 there is no such storage class for z80 or Atmel AVR. In most MCUs only a few registers can be used for indirect addressing. In this phase the AST is broken down into three-operand form (iCode). loop invariant code movement. These three operand forms are represented as doubly linked lists. ICode is the term given to the intermediate form generated by the compiler. In case of 8051 for example the registers R0 & R1 can be used to indirectly address the internal ram and DPTR to indirectly address the external ram. The optimizations include constant propagation. i. the compiler assumes the target machine has inﬁnite number of registers and generates a lot of temporary variables. The compiler will try to keep operands in registers as much as possible. The current version of SDCC can generate code for Intel 8051 and Z80 MCU. there are several schemes the compiler uses to do achieve this. Here we take a look at some of the internals of the compiler.Chapter 9
Compiler internals
9. Generating iCode Intermediate code generation. This phase also involves propagating types (annotating each node of the parse tree with type information) and semantic analysis. When the compiler runs out of registers the compiler will check to see if there are any live operands which is not used or deﬁned in the current basic block
102
. SDCC allows MCU speciﬁc storage class extensions. strength reduction of loop induction variables and dead-code elimination.e. It is fairly easy to retarget for other 8-bit MCU. ICode example section shows the operands annotated with the registers assigned to them.

{ 7. short sum=10. 17. Live ranges are computed only for temporaries (i. a constant 3 is then added for each iteration of the loop. short function (__data int *x) 6. mul = 0. the same registers may be used for different temporaries if their live ranges do not overlap. while (*x) *x++ = *p++. 2. 11. In addition the allocator also takes into consideration the type and usage of a temporary. the multiplication of an induction variable in line 18 (gint = j * 3) is changed to addition. It is used 4. sum += i.c
Operands
Description
ICode Example This section shows some details of iCode. } In addition to the operands each iCode contains information about the ﬁlename and line it corresponds to in the source ﬁle. gen51Code() in src/mcs51/gen. for the purpose of explaining iCode */ 5. } 20. /* this multiplication changed to addition */ 19. and is last used in the iCode with sequence number 5).j to be induction variables */ 15. gint += j * 3.e. Operands are formatted in the following manner:
Operand Name [lr live-from : live-to ] { type information } [ registers allocated ]. i++. short i=10. Registers are allocated for temporaries only. /* this multiplication remains */ 18.e. /* dead initialization eliminated */ 9. Note that local variables and parameters are replaced by compiler generated temporaries. sum = 0 . There are several loop optimizations performed by the compiler. it is used as an example to illustrate the intermediate code generated by the compiler.g. iTemp13 is allocated to a pseudo register CC which tells the back end that the temporary is used only for a conditional jump the code generation makes use of this information to optimize a compare and jump ICode. /* This function does nothing useful. 21.9. 12. 10.e. i. i < 10 . For induction variables such as iTemp21 the live range computation extends the lifetime from the start to the end of the loop. THE ANATOMY OF THE COMPILER iCode
(some more have been added)
CHAPTER 9.
As mentioned earlier the live ranges are computed in terms of the execution sequence number of the iCodes. It can detect induction variables iTemp21(i) and iTemp23(j). return sum+mul.1. Also note the compiler does selective strength reduction. 1. a new temporary iTemp17 is allocated and assigned a initial value. for example the iTemp0 is live from (i. The example C code does not do anything useful. for (i = 0. /* dead initialization eliminated */ 8. The compiler does not change the multiplication in line 17 however since the processor does support an 8 * 8 bit multiplication. COMPILER INTERNALS C Equivalent
see f. 14. 3. 105
. int gint. j--) { 16. mul += i * 3. Some short lived temporaries are allocated to special registers which have meaning to the code generator e. used in GET_VALUE_AT_ADDRESS) so it is allocated a pointer register (r0). The ﬁrst ﬁeld in the listing should be interpreted as follows:
Filename(linenumber: iCode Execution sequence number : ICode hash table key : loop depth of the iCode). short mul. The register allocator used the live range information to allocate registers. Each operand of this triplet form can be of three basic types a) compiler generated temporary b) user deﬁned variable c) a constant value. for example r0 is allocated to both iTemp6 and to iTemp17 since their live ranges do not overlap. j = 10 . /* compiler detects i. live ranges are not computed for global variables). 13. int j . ﬁrst deﬁned in iCode with execution sequence number 3.e. for example itemp6 is a pointer to near space and is used as to fetch data from (i. __xdata int * p.
Then follows the human readable form of the ICode operation.e.

distribution sets.net/#Who Thanks to all the other volunteer developers who have helped with coding.Chapter 10
Acknowledgments
http://sdcc.
109
.
Alphabetical index
To avoid confusion. This document was initially written by Sandeep Dutta All product names mentioned herein may be trademarks of their respective companies.net which has hosted the project since 1999 and donates signiﬁcant download bandwidth. the installation and building options for SDCC itself (chapter 2) are not part of the index.sf. web-page creation. testing. You know who you are :-) Thanks to Sourceforge http://www.sourceforge. etc. Also thanks to all SDCC Distributed Compile Farm members for donating CPU cycles and bandwidth for snapshot builds.