Rev 835 | Blame | Compare with Previous | Last modification | View Log | Download
SDCC Compiler User GuideSDCC [Input: sdcc_version]$Date:: 2019-03-22 #$$Revision: 11139 $Table of ContentsChapter 1 Introduction1.1 About SDCC1.2 SDCC Suite Licenses1.3 Documentation1.4 Typographic conventions1.5 Compatibility with previous versions1.6 System Requirements1.7 Other ResourcesChapter 2 Installing SDCC2.1 Configure Options2.2 Install paths2.3 Search Paths2.4 Building SDCC2.4.1 Building SDCC on Linux2.4.2 Building SDCC on Mac OS X2.4.3 Cross compiling SDCC on Linux for Windows2.4.4 Building SDCC using Cygwin and Mingw322.4.5 Building SDCC Using Microsoft Visual C++ 2010 (MSVC)2.4.6 Windows Install Using a ZIP Package2.4.7 Windows Install Using the Setup Program2.4.8 VPATH feature2.5 Building the Documentation2.6 Reading the Documentation2.7 Testing the SDCC Compiler2.8 Install Trouble-shooting2.8.1 If SDCC does not build correctly2.8.2 What the ”./configure” does2.8.3 What the ”make” does2.8.4 What the ”make install” command does.2.9 Components of SDCC2.9.1 sdcc - The Compiler2.9.2 sdcpp - The C-Preprocessor2.9.3 sdas, sdld - The Assemblers and Linkage Editors2.9.4 s51, sz80, shc08, sstm8 - The Simulators2.9.5 sdcdb - Source Level DebuggerChapter 3 Using SDCC3.1 Standard-Compliance3.1.1 ISO C90 and ANSI C893.1.2 ISO C953.1.3 ISO C993.1.4 ISO C11 and ISO C173.1.5 ISO C2X3.1.6 Embedded C3.2 Compiling3.2.1 Single Source File Projects3.2.2 Postprocessing the Intel Hex file3.2.3 Projects with Multiple Source Files3.2.4 Projects with Additional Libraries3.2.5 Using sdar to Create and Manage Libraries3.3 Command Line Options3.3.1 Processor Selection Options3.3.2 Preprocessor Options3.3.3 Optimization Options3.3.4 Other Options3.3.5 Linker Options3.3.6 MCS51 Options3.3.7 DS390 / DS400 Options3.3.8 Options common to all z80-related ports (z80, z180, r2k, r3ka, gbz80, tlcs90, ez80_z80)3.3.9 Z80 Options (apply to z80, z180, r2k, r3ka, tlcs90, ez80_z80)3.3.10 GBZ80 Options3.3.11 Intermediate Dump Options3.3.12 Redirecting output on Windows Shells3.4 Environment variables3.5 SDCC Language Extensions3.5.1 MCS51/DS390 intrinsic named address spaces3.5.1.1 __data / __near3.5.1.2 __xdata / __far3.5.1.3 __idata3.5.1.4 __pdata3.5.1.5 __code3.5.1.6 __bit3.5.1.7 __sfr / __sfr16 / __sfr32 / __sbit3.5.1.8 Pointers to MCS51/DS390 intrinsic named address spaces3.5.1.9 Notes on MCS51 memory layout3.5.2 Z80/Z180/eZ80 intrinsic named address spaces3.5.2.1 __sfr (in/out to 8-bit addresses)3.5.2.2 __banked __sfr (in/out to 16-bit addresses)3.5.2.3 __sfr (in0/out0 to 8 bit addresses on Z180/HD64180)3.5.3 HC08/S08 intrinsic named address spaces3.5.3.1 __data3.5.3.2 __xdata3.5.4 PDK14/PDK15 intrinsic named address spaces3.5.4.1 __sfr3.5.4.2 __sfr163.5.5 Non-intrinsic named address spaces3.5.6 Absolute Addressing3.5.7 Preserved register specification3.5.8 Binary constants3.5.9 Returning void3.5.10 Omitting promotion on arguments of vararg function (does not apply to pdk14, pdk15)3.6 Parameters and Local Variables3.7 Overlaying3.8 Interrupt Service Routines3.8.1 General Information3.8.1.1 Common interrupt pitfall: variable not declared volatile3.8.1.2 Common interrupt pitfall: non-atomic access3.8.1.3 Common interrupt pitfall: stack overflow3.8.1.4 Common interrupt pitfall: use of non-reentrant functions3.8.2 MCS51/DS390 Interrupt Service Routines3.8.3 HC08 Interrupt Service Routines3.8.4 Z80 and Z180 Interrupt Service Routines3.8.5 Rabbit 2000, 3000, 3000A and 4000 Interrupt Service Routines3.8.6 GBZ80 and TLCS-90 Interrupt Service Routines3.8.7 STM8 Interrupt Service Routines3.9 Enabling and Disabling Interrupts3.9.1 Critical Functions and Critical Statements3.9.2 Enabling and Disabling Interrupts directly3.9.3 Semaphore locking (mcs51/ds390)3.10 Functions using private register banks (mcs51/ds390)3.11 Inline Assembler Code3.11.1 Inline Assembler Code Formats3.11.1.1 Old __asm ... __endasm; Format3.11.1.2 New __asm__ (”inline_assembler_code”) Format3.11.2 A Step by Step Introduction3.11.3 Naked Functions3.11.4 Use of Labels within Inline Assembler3.12 Support routines for integer multiplicative operators3.13 Floating Point Support3.14 Library Routines3.14.1 Compiler support routines (_gptrget, _mulint etc.)3.14.2 Stdclib functions (puts, printf, strcat etc.)3.14.2.1 <stdio.h>getchar(), putchar()printf()3.14.2.2 <malloc.h>3.14.3 Math functions (sinf, powf, sqrtf etc.)3.14.3.1 <math.h>3.14.4 Other libraries3.15 Memory Models3.15.1 MCS51 Memory Models3.15.1.1 Small, Medium, Large and Huge3.15.1.2 External Stack3.15.2 DS390 Memory Model3.15.3 STM8 Memory Models3.16 Pragmas3.17 Defines Created by the CompilerChapter 4 Notes on supported Processors4.1 MCS51 variants4.1.1 pdata access by SFR4.1.2 Other Features available by SFR4.1.3 Bankswitching4.1.3.1 Hardware4.1.3.2 Software4.1.4 MCS51/DS390 Startup Code4.1.5 Interfacing with Assembler Code4.1.5.1 Global Registers used for Parameter Passing4.1.5.2 Register usage4.1.5.3 Assembler Routine (non-reentrant)4.1.5.4 Assembler Routine (reentrant)4.2 DS400 port4.3 The Z80, Z180, Rabbit 2000/3000, Rabbit 3000A, GBZ80, eZ80 and TLCS-90 ports4.3.1 Startup Code4.3.2 Complex instructions4.3.3 Calling conventions4.3.4 Small-C calling convention4.3.5 Unsafe reads4.4 The HC08 and S08 ports4.4.1 Startup Code4.5 The STM8 port4.5.1 Calling convention4.6 The PIC14 port4.6.1 PIC Code Pages and Memory Banks4.6.2 Adding New Devices to the Port4.6.3 Interrupt Code4.6.4 Configuration Bits4.6.5 Linking and Assembling4.6.6 Command-Line Options4.6.7 Environment Variables4.6.8 The Library4.6.8.1 Enhanced cores4.6.8.2 Accessing bits of special function registers4.6.8.3 Naming of special function registers4.6.8.4 error: missing definition for symbol ``__gptrget1''4.6.8.5 Processor mismatch in file ``XXX''.4.6.9 Known Bugs4.6.9.1 Function arguments4.6.9.2 Regression tests fail4.7 The PIC16 port4.7.1 Global Options4.7.2 Port Specific Options4.7.2.1 Code Generation Options4.7.2.2 Optimization Options4.7.2.3 Assembling Options4.7.2.4 Linking Options4.7.2.5 Debugging Options4.7.3 Environment Variables4.7.4 Preprocessor Macros4.7.5 Directories4.7.6 Pragmas4.7.7 Header Files and Libraries4.7.8 Header Files4.7.9 LibrariesBuilding the librariesOutput of float values via printf()4.7.10 Adding New Devices to the Port4.7.11 Memory Models4.7.12 Stack4.7.13 Functions4.7.14 Function return values4.7.15 Interrupts4.7.16 Generic Pointers4.7.17 Configuration Bits4.7.18 PIC16 C Libraries4.7.18.1 Standard I/O Streams4.7.18.2 Printing functions4.7.18.3 Signals4.7.19 PIC16 Port – Tips4.7.19.1 Stack size4.7.20 Known Bugs4.7.20.1 Extended Instruction Set4.7.20.2 Regression TestsChapter 5 Debugging5.1 Debugging with SDCDB5.1.1 Compiling for Debugging5.1.2 How the Debugger Works5.1.3 Starting the Debugger SDCDB5.1.4 SDCDB Command Line Options5.1.5 SDCDB Debugger Commandsbreak [line | file:line | function | file:function]clear [line | file:line | function | file:function ]continuefinishdelete [n]info [break | stack | frame | registers ]stepnextrunptype variableprint variablefile filenameframeset srcmode! simulator commandquit5.1.6 Interfacing SDCDB with DDD5.1.7 Interfacing SDCDB with XEmacsChapter 6 TIPS6.1 Porting code from or to other compilers6.2 Tools included in the distribution6.3 Documentation included in the distribution6.4 Communication online at SourceForge6.5 Related open source tools6.6 Related documentation / recommended reading6.7 Application notes specifically for SDCC6.8 Some QuestionsChapter 7 Support7.1 Reporting Bugs7.2 Requesting Features7.3 Submitting patches7.4 Getting Help7.5 ChangeLog7.6 Subversion Source Code Repository7.7 Release policy7.8 Quality control7.9 Examples7.10 Use of SDCC in EducationChapter 8 SDCC Technical Data8.1 Optimizations8.1.1 Sub-expression Elimination8.1.2 Dead-Code Elimination8.1.3 Copy-Propagation8.1.4 Loop Optimizations8.1.5 Loop Reversing8.1.6 Algebraic Simplifications8.1.7 'switch' Statements8.1.8 Bit-shifting Operations.8.1.9 Bit-rotation8.1.10 Nibble and Byte Swapping8.1.11 Highest Order Bit / Any Order Bit8.1.12 Higher Order Byte / Higher Order Word8.1.13 Placement of Bank-Selection Instructions8.1.14 Lifetime-Optimal Speculative Partial Redundancy Elimination8.1.15 Register Allocation8.1.16 Peephole Optimizer8.2 Cyclomatic Complexity8.3 Retargetting for other ProcessorsChapter 9 Compiler internals9.1 The anatomy of the compilerParsingGenerating iCodeOptimizations.Live range analysisRegister AllocationCode generationICode Example9.2 A few words about basic block successors, predecessors and dominatorsChapter 10 AcknowledgmentsAlphabetical indexIntroduction1.1 About SDCCSDCC (Small Device C Compiler) is free open source,retargettable, optimizing standard (ANSI C89 / ISO C90, ISO C99,ISO C11 / ISO C17) C compiler suite originally written by SandeepDutta designed for 8 bit Microprocessors. The current versiontargets Intel MCS51 based Microprocessors (8031, 8032, 8051, 80528031, 8032, 8051, 8052, mcs51 CPU, etc.), Dallas DS80C390 variants, Freescale (formerly Motorola)HC08 based (hc08, s08), Zilog Z80 based MCUs (Z80, Z180, gbz80,Rabbit 2000/3000, Rabbit 3000A Z80, Z180, GBZ80, Rabbit 2000/3000, Rabbit 3000A CPU), Toshiba TLCS-90, Zilog eZ80 in Z80 mode, STMicroelectronicsSTM8 STM8 and Padauk PDK14. It can be retargeted for othermicroprocessors, support for Microchip PIC and Padauk PDK15 isunder development. The entire source code for the compiler isdistributed under GPL. SDCC uses a modified version of ASXXXXsdas (sdasgb, sdas6808, sdas8051, sdasz80)& ASLINKsdld, free open source retargetable assembler & linker.SDCC has extensive language extensions suitable for utilizingvarious microcontrollers and underlying hardware effectively.You might also want to have a look at the wiki http://sdcc.sourceforge.net/wiki/.In addition to the MCU specific optimizations SDCC also does ahost of standard optimizations like:• global sub expression elimination,• loop optimizations (loop invariant, strength reduction ofinduction variables and loop reversing),• constant folding & propagation,• copy propagation,• dead code elimination• jump tables for switch statements.For the back-end SDCC uses a global register allocation schemewhich should be well suited for other 8 bit MCUs.The peep hole optimizer uses a rule based substitution mechanismwhich is MCU independent.Supported data-types are:+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| type | width | default | signed range | unsigned range |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------++----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| _Bool / bool | 8 bits, 1 byte | unsigned | - | 0, 1 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| char | 8 bits, 1 byte | unsigned | -128, +127 | 0, +255 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| short | 16 bits, 2 bytes | signed | -32.768, +32.767 | 0, +65.535 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| int | 16 bits, 2 bytes | signed | -32.768, +32.767 | 0, +65.535 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| long | 32 bits, 4 bytes | signed | -2.147.483.648, +2.147.483.647 | 0, +4.294.967.295 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| long long[footnote:Incomplete support in the pic14 and pic16 backends.] | 64 bits, 8 bytes | signed | | |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------++----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| float | 4 bytes similar to IEEE 754 | signed | | 1.175494351E-38, 3.402823466E+38 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------++----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| pointer | 1, 2, 3 or 4 bytes | generic | | |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------++----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+| __bit[footnote:Only supported in the mcs51, ds390, ds400 backends.] | 1 bit | unsigned | - | 0, 1 |+----------------------------------------------------------------------------+------------------------------+-----------+---------------------------------+----------------------------------+The compiler also allows inline assembler code to be embeddedanywhere in a function. In addition, routines developed inassembly can also be called.SDCC also provides an option (--cyclomatic) to report therelative complexity of a function. These functions can then befurther optimized, or hand coded in assembly if needed.SDCC also comes with a companion source level debugger SDCDB. Thedebugger currently uses ucSim, a free open source simulator for8051 and other micro-controllers.The latest SDCC version can be downloaded from http://sdcc.sourceforge.net/snap.php. Please note: the compiler will probably always be some stepsahead of this documentationStatus of documentation[footnote:Obviously this has pros and cons].1.2 SDCC Suite LicensesSDCC suite is a collection of several components derived fromdifferent sources with different licenses:• executables:– sdcc compiler:sdcc compiler is licensed under the GPLv2.The code or object files generated by SDCC suite are notlicensed, so they can be used in FLOSS or proprietary (closedsource) applications.– sdcpp preprocessor:derived from GCC cpp preprocessor http://gcc.gnu.org/; GPLv3license– sdas assemblers and sdld linker:derived from ASXXXX http://shop-pdp.kent.edu/ashtml/asxxxx.htm;GPLv3 license– SDCC run-time libraries:The great majority of SDCC run-time libraries are licensed underthe GPLv2+LEGPLv2+LE which allows linking of SDCC run-timelibraries with proprietary (closed source) applications.Exception are pic device libraries and header files which arederived from Microchip header (.inc) and linker script (.lkr)files. Microchip requires that "The header files should statethat they are only to be used with authentic Microchipdevices" which makes them incompatible with the GPL. Picdevice libraries and header files are located at non-free/liband non-free/include directories respectively. SDCC should berun with the --use-non-free--use-non-free command line optionin order to include non-free header files and libraries.– sdbinutils utilities (sdar, sdranlib, sdnm, sdobjcopy):derived from GNU Binutils http://www.gnu.org/software/binutils/;GPLv3 license– ucsim simulators:GPLv2 license– sdcdb debugger:GPLv2 license– gcc-test regression tests:derived from gcc-testsuite; no license explicitely specified, butsince it is a part of GCC is probably GPLv3 licensed– packihx:public domain– makebin:zlib/libpng License• libraries:– dbuf library:zlib/libpng License– Boost C++ libraries:http://www.boost.org/; Boost Software License 1.0 (BSL-1.0)Links to licenses:• GPLv2 licenseGPLv2 license: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html• LGPLv2.1 licenseLGPLv2.1 license: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html• GPLv3 licenseGPLv3 license: http://www.gnu.org/licenses/gpl.html• zlib/libpng Licensezlib/libpng License: http://www.opensource.org/licenses/Zlib• Boost Software License 1.0 (BSL-1.0)Boost Software License 1.0 (BSL-1.0): http://www.opensource.org/licenses/BSL-1.01.3 DocumentationThis documentation is maintained using a free open source wordprocessor (LyX) http://www.lyx.org/.1.4 Typographic conventionsTypographic conventionsThroughout this manual, we will use the following convention.Commands you have to type in are printed in "sans serif". Codesamples are printed in typewriter font. Interesting items and newterms are printed in italic.1.5 Compatibility<sec:Compatibility-with-previous> with previousversionsCompatibility with previous versionsNewer versions have usually numerous bug fixes compared with theprevious version. But we also sometimes introduce someincompatibilities with older versions. Not just for the fun ofit, but to make the compiler more stable, efficient and standardcompliantStandard-compliance (see section [subsec:Standard-Compliance]for Standard-Compliance). This is a list of such changes .• short is now equivalent to int (16 bits), it used to beequivalent to char (8 bits) which is not ANSI compliant. Tomaintain compatibility, old programs could be compiled usingthe --short-is-8bits command line option (option removed afterthe 3.6.0 release).• the default directory for gcc-builds where include, library anddocumentation files are stored is now in /usr/local/share.• char type parameters to varargvararg, vaarg functions arecasted to int unless explicitly casted and --std-c89--std-c89and --std-c99--std-c99 command line option are not defined,e.g.:char a=3;printf ("%d %c\n", a, (char)a);will push a as an int and as a char resp if --std-c89--std-c89and --std-c99--std-c99 command line options are not defined,will push a as two ints if --std-c89--std-c89 or --std-c99--std-c99command line option is defined.• pointer type parameters to varargvararg, vaarg functions arecasted to generic pointers on Harvard architectures (e.g.mcs51, ds390) unless explicitly casted and --std-c89--std-c89and --std-c99--std-c99 command line option are not defined.• option --regextend has been removed.• option --noregparms has been removed.• option --stack-after-data has been removed.• bitbit and sbitsbitsbit types now consistently behave like theC99 _Bool type with respect to type conversiontype conversiontype promotion. The most common incompatibility resulting from this change isrelated to bit togglingBit toggling idioms, e.g.:bit b;b = ~~ Operatorb; /* equivalent to b=1 instead of toggling b */b = !b; /* toggles b */In previous versions, both forms would have toggled the bit.• in older versions, the preprocessor was always called with --std-c99--std-c99 regardless of the --std-xxx setting. This isno longer true, and can cause compilation failures on codebuilt with --std-c89--std-c89 but using c99 preprocessorfeatures, such as one-line (//) comments• in versions older than 2.8.4 the pic16 *printf() andprintf_tiny() library functions supported undocumented and notstandard compliant 'b' binary format specifier ("%b", "%hb" and"%lb"). The 'b' specifier is now disabled by default. It can beenabled by defining BINARY_SPECIFIER macro in filesdevice/lib/pic16/libc/stdio/vfprintf.c anddevice/lib/pic16/libc/stdio/printf_tiny.c and recompiling thelibrary.• in versions older then 2.8.5 the unnamed bit-field structuremembers participated in initialization, which is not conformingwith ISO/IEC 9899:1999 standard (see section Section 6.7.8Initialization, clause 9)Old behaviour, before version 2.8.5:struct {int a : 2;char : 2;int b : 2;} s = {1, 2, 3};/* s.a = 1, s.b = 3 */New behaviour:struct {int a : 2;char : 2;int b : 2;} s = {1, 2};/* s.a = 1, s.b = 2 */• In 2.9.0 libraries included in SDCC packages, are in ar format.See section [subsec:Using-sdar-to].• In 3.0.0 targets for xa51 and avr are disabled by default.• In 3.0.0 sdldgb and sdldz80 don't support generation of GameBoy binary image format. The makebin utility can be used toconvert Intel Hex format to Game Boy binary image format.• In 3.0.0 sdldgb and sdldz80 don't support generation of rrgb(Game Boy simulator) map file and no$gmb symbol file formats.The as2gbmap utility can be used to convert sdld map format torrgb and no$gmb file formats.• In 3.1.0 asranlib utility was renamed to sdranlib.• In 3.1.0 pic14 target, structured access to SFR via<sfrname>_bits.<bitname> is deprecated and replaced by<sfrname>bits.<bitname>. It will be obsoleted (removed) in oneof next SDCC releases. See section [subsec:Naming-of-special].• sdar archive managing utility and sdnm utilities wereintroduced in version 3.2.0. sdar, sdranlib and sdnm arederived from GNU Binutils package.• In 3.2.0 the sdcclib utility is deprecated. Sdar utility shouldbe used to create SDCC object file archives. Sdcclib utilitywill become obsolete in one of next SDCC releases and will beremoved from SDCC packages.• In 3.2.0 special SDCC keywords which are not preceded by adouble underscore are obsoleted (removed). See section [subsec:Standard-Compliance]Standard-Compliance.• In 3.2.0 compiler macro definitions not starting with doubleunderscore characters are deprecated if --std-cXX command lineoption is defined. They have been obsoleted (removed) after the3.4.0 release (except for the macro SDCC, which has beenremoved after the 3.6.0 release (and brought back for mcs51 forthe 3.7.0 release)).• In 3.2.0 new compiler macros for processor definition wereintroduced for pic14 and pic16 targets: -D__SDCC_PIC16XXXX and-D__SDCC_PIC18FXXX respectively. The pic16 macro definition-D__18fXXX is deprecated. It was obsoleted (removed) after the3.4.0 release.• In 3.2.0 pragma config for pic16 target was introduced. Seesection [subsec:PIC16_Pragmas]• In 3.2.0 new inline assembler format __asm__(inline_assembler_code”); as an addition to __asm ...__endasem; format introduced. See section [sec:Inline-Assembler-Code]• sdobjcopy utility was introduced in version 3.3.0. It isderived from GNU Binutils package.• Before 3.4.0 release, intrinsic named address spaces werecalled ”storage classes” in this manual.• In 3.6.0, the default for char changed from signed to unsigned.• In 3.7.0, the prototype for putchar() changed from voidputchar(char) to int putchar(int)• In 3.7.0 mcs51 and ds390 got a full _Bool/bool type, separatefrom __bit.• In 3.7.0, the option –nojtbound and the corresponding pragmahave been deprecated.• In 3.7.0, the prototype for getchar() changed from chargetchar(void) to int getchar().• In 3.8.6, the deprecated sdcclib was removed.1.6 System RequirementsWhat do you need before you start installation of SDCC? Acomputer, and a desire to compute. The preferred method ofinstallation is to compile SDCC from source using GNU GCC andmake. For Windows some pre-compiled binary distributions areavailable for your convenience. You should have some experiencewith command line tools and compiler use.1.7 Other ResourcesThe SDCC home page at http://sdcc.sourceforge.net/ is a greatplace to find distribution sets. You can also find links to theuser mailing lists that offer help or discuss SDCC with otherSDCC users. Web links to other SDCC related sites can also befound here. This document can be found in the doc directory ofthe source package. The latest snapshot build version of thisdocument in pdf format is available at http://sdcc.sourceforge.net/doc/sdccman.pdf. Some of the other tools (simulator and assembler) included withSDCC contain their own documentation and can be found in thesource distribution. If you want the latest unreleased software,the complete source package is available directly from Subversionon http://sourceforge.net/p/sdcc/code/8805/tree/trunk/sdcc/.Installing SDCCInstallationFor most users it is sufficient to skip to either section [subsec:Building-SDCC-on-Linux](Unix) or section [subsec:Windows-Install] (Windows). Moredetailed instructions follow below.2.1 Configure OptionsOptions SDCC configurationThe install paths, search paths and other options are definedwhen running 'configure'. The defaults can be overridden by:--prefix see table below--exec_prefix see table below--bindir see table below--datadir see table below--datarootdir see table belowdocdir environment variable, see table belowinclude_dir_suffix environment variable, see table belownon_free_include_dir_suffix environment variable, see tablebelowlib_dir_suffix environment variable, see table belownon_free_lib_dir_suffix environment variable, see table belowsdccconf_h_dir_separator environment variable, either / or \\makes sense here. This character will only be used in sdccconf.h;don't forget it's a C-header, therefore a double-backslash isneeded there.--disable-mcs51-port Excludes the Intel mcs51 port--disable-z80-port Excludes the z80 port--disable-z180-port Excludes the z180 port--disable-r2k-port Excludes the r2k port--disable-r3ka-port Excludes the r3ka port--disable-gbz80-port Excludes the Game Boy gbz80 port--disable-avr-port Excludes the AVR port (disabled by default)--disable-ds390-port Excludes the DS390 port--disable-hc08-port Excludes the HC08 port--disable-s08-port Excludes the S08 port--disable-stm8-port Excludes the STM8 port--disable-pic-port Excludes the PIC14 port--disable-pic16-port Excludes the PIC16 port--disable-xa51-port Excludes the XA51 port (disabled by default)--disable-ucsim Disables configuring and building of ucsim--disable-device-lib Disables automatically building devicelibraries--disable-packihx Disables building packihx--enable-doc Build pdf, html and txt files from the lyx sources--enable-libgc Use the Bohem memory allocator. Lower runtimefootprint.--without-ccache Do not use ccache even if availableFurthermore the environment variables CC, CFLAGS, ... the toolsand their arguments can be influenced. Please see `configure --help' and the man/info pages of `configure' for details.The names of the standard libraries STD_LIB, STD_INT_LIB,STD_LONG_LIB, STD_FP_LIB, STD_DS390_LIB, STD_XA51_LIB and theenvironment variables SDCC_DIR_NAME, SDCC_INCLUDE_NAME,SDCC_LIB_NAME are defined by `configure' too. At the moment it'snot possible to change the default settings (it was simply neverrequired).These configure options are compiled into the binaries, and canonly be changed by rerunning 'configure' and recompiling SDCC.The configure options are written in italics to distinguish themfrom run time environment variables (see section search paths).The settings for ”Win32 builds” are used by the SDCC team tobuild the official Win32 binaries. The SDCC team uses Mingw32 tobuild the official Windows binaries, because it's1. open source,2. a gcc compiler and last but not least3. the binaries can be built by cross compiling on SDCCDistributed Compile Farm.See the examples, how to pass the Win32 settings to 'configure'.The other Win32 builds using VC or whatever don't use'configure', but a header file sdcc_vc.h.in is the same assdccconf.h built by 'configure' for Win32.These defaults are:+------------------------------+------------------------+------------------+| Variable | default | Win32 builds |+------------------------------+------------------------+------------------++------------------------------+------------------------+------------------+| PREFIX | /usr/local | \sdcc |+------------------------------+------------------------+------------------+| EXEC_PREFIX | $PREFIX | $PREFIX |+------------------------------+------------------------+------------------+| BINDIR | $EXEC_PREFIX/bin | $EXEC_PREFIX\bin |+------------------------------+------------------------+------------------+| DATADIR | $DATAROOTDIR | $DATAROOTDIR |+------------------------------+------------------------+------------------+| DATAROOTDIR | $PREFIX/share | $PREFIX |+------------------------------+------------------------+------------------+| DOCDIR | $DATAROOTDIR/sdcc/doc | $DATAROOTDIR\doc |+------------------------------+------------------------+------------------+| INCLUDE_DIR_SUFFIX | sdcc/include | include |+------------------------------+------------------------+------------------+| NON_FREE_INCLUDE_DIR_SUFFIX | sdcc/non-free/include | non-free/include |+------------------------------+------------------------+------------------+| LIB_DIR_SUFFIX | sdcc/lib | lib |+------------------------------+------------------------+------------------+| NON_FREE_LIB_DIR_SUFFIX | sdcc/non-free/lib | non-free/lib |+------------------------------+------------------------+------------------+'configure' also computes relative paths. This is needed for fullrelocatability of a binary package and to complete search paths(see section search paths below):+----------------------+-------------+--------------+| Variable (computed) | default | Win32 builds |+----------------------+-------------+--------------++----------------------+-------------+--------------+| BIN2DATA_DIR | ../share | .. |+----------------------+-------------+--------------+| PREFIX2BIN_DIR | bin | bin |+----------------------+-------------+--------------+| PREFIX2DATA_DIR | share/sdcc | |+----------------------+-------------+--------------+Examples:./configure./configure --prefix=”/usr/bin” --datarootdir=”/usr/share”./configure --disable-avr-port --disable-xa51-portTo cross compile on linux for Mingw32 (see also'sdcc/support/scripts/sdcc_mingw32'):./configure \CC=”i586-mingw32msvc-gcc” CXX=”i586-mingw32msvc-g++” \RANLIB=”i586-mingw32msvc-ranlib” \STRIP=”i586-mingw32msvc-strip” \--prefix=”/sdcc” \--datarootdir=”/sdcc” \docdir=”\${datarootdir}/doc” \include_dir_suffix=”include” \non_free_include_dir_suffix=”non-free/include” \lib_dir_suffix=”lib” \non_free_lib_dir_suffix=”non-free/lib” \sdccconf_h_dir_separator=”\\\\” \--disable-device-lib\--host=i586-mingw32msvc\--build=unknown-unknown-linux-gnuTo ”cross”compile on Cygwin for Mingw32 (see alsosdcc/support/scripts/sdcc_cygwin_mingw32):./configure -C \--prefix=”/sdcc” \--datarootdir=”/sdcc” \docdir=”\${datarootdir}/doc” \include_dir_suffix=”include” \non_free_include_dir_suffix=”non-free/include” \lib_dir_suffix=”lib” \non_free_lib_dir_suffix=”non-free/lib” \sdccconf_h_dir_separator=”\\\\” \CC=”gcc -mno-cygwin” \CXX=”g++ -mno-cygwin”'configure' is quite slow on Cygwin (at least on windows beforeWin2000/XP). The option '--C' turns on caching, which gives alittle bit extra speed. However if options are changed, it can benecessary to delete the config.cache file.2.2 Install paths<subsec:Install-paths>Install paths+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Description | Path | Default | Win32 builds |+-------------------------+-----------------------------------------+------------------------------------------+------------------------++-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Binary files* | $EXEC_PREFIX | /usr/local/bin | \sdcc\bin |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Include files | $DATADIR/$INCLUDE_DIR_SUFFIX | /usr/local/share/sdcc/include | \sdcc\include |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Non-free include files | $DATADIR/non-free/$INCLUDE_DIR_SUFFIX | /usr/local/share/sdcc/non-free/include | \sdcc\non-free\include |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Library file** | $DATADIR/$LIB_DIR_SUFFIX | /usr/local/share/sdcc/lib | \sdcc\lib |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Library file** | $DATADIR/non-free/$LIB_DIR_SUFFIX | /usr/local/share/sdcc/non-free/lib | \sdcc\non-free\lib |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+| Documentation | $DOCDIR | /usr/local/share/sdcc/doc | \sdcc\doc |+-------------------------+-----------------------------------------+------------------------------------------+------------------------+*compiler, preprocessor, assembler, and linker**the model is auto-appended by the compiler, e.g. small, large,z80, ds390 etcThe install paths can still be changed during `make install' withe.g.:make install prefix=$(HOME)/local/sdccOf course this doesn't change the search paths compiled into thebinaries.Moreover the install path can be changed by defining DESTDIRDESTDIR:make install DESTDIR=$(HOME)/sdcc.rpm/Please note that DESTDIR must have a trailing slash!2.3 Search Paths<subsec:Search-Paths>Search pathSome search paths or parts of them are determined by configurevariables (in italics, see section above). Further search pathsare determined by environment variables during runtime.The paths searched when running the compiler are as follows (thefirst catch wins):1. Binary files (preprocessor, assembler and linker)+---------------------------------+------------------+-----------------+| Search path | default | Win32 builds |+---------------------------------+------------------+-----------------++---------------------------------+------------------+-----------------+| $SDCC_HOME/$PPREFIX2BIN_DIR | $SDCC_HOME/bin | $SDCC_HOME\bin |+---------------------------------+------------------+-----------------+| Path of argv[0] (if available) | Path of argv[0] | Path of argv[0] |+---------------------------------+------------------+-----------------+| $PATH | $PATH | $PATH |+---------------------------------+------------------+-----------------+2. Include files+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| # | Search path | default | Win32 builds |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------++----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 1 | --I dir | --I dir | --I dir |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 2 | $SDCC_INCLUDE | $SDCC_INCLUDE | $SDCC_INCLUDE |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 3 | $SDCC_HOME/$PREFIX2DATA_DIR/$INCLUDE_DIR_SUFFIX | $SDCC_HOME/share/sdcc/include | $SDCC_HOME\include |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 4 | path(argv[0])/$BIN2DATADIR/$INCLUDE_DIR_SUFFIX | path(argv[0])/../sdcc/include | path(argv[0])\..\include |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 5 | $DATADIR/$INCLUDE_DIR_SUFFIX | /usr/local/share/sdcc/include | (not on Win32) |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 6 | $SDCC_HOME/$PREFIX2DATA_DIR/non-free/$INCLUDE_DIR_SUFFIX | $SDCC_HOME/share/sdcc/non-free/include | $SDCC_HOME\non-free\include |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 7 | path(argv[0])/$BIN2DATADIR/non-free/$INCLUDE_DIR_SUFFIX | path(argv[0])/../sdcc/non-free/include | path(argv[0])\..\non-free\include |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+| 8 | $DATADIR/non-free/$INCLUDE_DIR_SUFFIX | /usr/local/share/sdcc/non-free/include | (not on Win32) |+----+--------------------------------------------------------------+------------------------------------------+-----------------------------------+The option --nostdinc disables all search paths except #1 and #2.3. Library filesWith the exception of ”--L dir” the model is auto-appended by thecompiler (e.g. small, large, z80, ds390 etc.).+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| # | Search path | default | Win32 builds |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------++----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 1 | --L dir | --L dir | --L dir |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 2 | $SDCC_LIB/<model> | $SDCC_LIB/<model> | $SDCC_LIB/<model> |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 3 | $SDCC_LIB | $SDCC_LIB | $SDCC_LIB |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 4 | $SDCC_HOME/$PREFIX2DATA_DIR/$LIB_DIR_SUFFIX/<model> | $SDCC_HOME/share/sdcc/lib/<model> | $SDCC_HOME\lib\<model> |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 5 | path(argv[0])/$BIN2DATADIR/$LIB_DIR_SUFFIX/<model> | path(argv[0])/../sdcc/lib/<model> | path(argv[0])\..\lib\<model> |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 6 | $DATADIR/non-free/$LIB_DIR_SUFFIX/<model> | /usr/local/share/sdcc/lib/<model> | (not on Win32) |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 7 | $SDCC_HOME/$PREFIX2DATA_DIR/non-free/$LIB_DIR_SUFFIX/<model> | $SDCC_HOME/share/sdcc/non-free/lib/<model> | $SDCC_HOME\lib\non-free\<model> |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 8 | path(argv[0])/$BIN2DATADIR/non-free/$LIB_DIR_SUFFIX/<model> | path(argv[0])/../sdcc/non-free/lib/<model> | path(argv[0])\..\lib\non-free\<model> |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+| 9 | $DATADIR/non-free/$LIB_DIR_SUFFIX/<model> | /usr/local/share/sdcc/non-free/lib/<model> | (not on Win32) |+----+-------------------------------------------------------------------+-----------------------------------------------+----------------------------------------+The option --nostdlib disables all search paths except #1 and #2.2.4 Building SDCCBuilding SDCC2.4.1 Building SDCC on Linux<subsec:Building-SDCC-on-Linux>1. Download the source package either from the SDCC Subversionrepository or from snapshot builds, it will be named somethinglike sdcc-src-yyyymmdd-rrrr.tar.bz2 http://sdcc.sourceforge.net/snap.php.2. Bring up a command line terminal, such as xterm.3. Unpack the file using a command like: "tar -xvjfsdcc-src-yyyymmdd-rrrr.tar.bz2”, this will create asub-directory called sdcc with all of the sources.4. Change directory into the main SDCC directory, for exampletype: "cd sdcc".5. Type "./configure". This configures the package forcompilation on your system. When the treedec library isavailable, it should be found and used automatically (improvingthe compilation time / code quality trade-off). As of SDCC3.7.0, the current develop branch fromhttps://github.com/freetdi/tdlib is a suitable version oftreedec.6. Type "make". All of the source packages will compile, this cantake a while.7. Type "make install" as root. This copies the binaryexecutables, the include files, the libraries and thedocumentation to the install directories. Proceed with section [sec:Testing-the-SDCC].2.4.2 Building SDCC on Mac OS XFollow the instruction for Linux.On Mac OS X 10.2.x it was reported, that the default gcc (version3.1 20020420 (prerelease)) fails to compile SDCC. Fortunatelythere's also gcc 2.9.x installed, which works fine. This compilercan be selected by running 'configure' with:./configure CC=gcc2 CXX=g++2Universal (ppc and i386) binaries can be produced on Mac OS X10.4.x with Xcode. Run 'configure' with:./configure \LDFLAGS="-Wl,-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk -archi386 -arch ppc" \CXXFLAGS = "-O2 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -archi386 -arch ppc" \CFLAGS = "-O2 -isysroot /Developer/SDKs/MacOSX10.4u.sdk -archi386 -arch ppc"2.4.3 Cross compiling SDCC on Linux for WindowsWith the Mingw32 gcc cross compiler it's easy to compile SDCC forWin32. See section 'Configure Options'.2.4.4 Building SDCC using Cygwin and Mingw32For building and installing a Cygwin executable follow theinstructions for Linux.On Cygwin a ”native” Win32-binary can be built, which will notneed the Cygwin-DLL. For the necessary 'configure' options seesection 'configure options' or the script'sdcc/support/scripts/sdcc_cygwin_mingw32'.In order to install Cygwin on Windows download setup.exe fromwww.cygwin.com http://www.cygwin.com/. Run it, set the ”defaulttext file type” to ”unix” and download/install at least thefollowing packages. Some packages are selected by default, otherswill be automatically selected because of dependencies with themanually selected packages. Never deselect these packages!• flex• bison• gcc ; version 3.x is fine, no need to use the old 2.9x• binutils ; selected with gcc• make• libboost-dev• rxvt ; a nice console, which makes life much easier underwindoze (see below)• man ; not really needed for building SDCC, but you'll miss itsooner or later• less ; not really needed for building SDCC, but you'll miss itsooner or later• svn ; only if you use Subversion accessIf you want to develop something you'll need:• python ; for the regression tests• gdb ; the gnu debugger, together with the nice GUI ”insight”• openssh ; to access the CF or commit changes• autoconf and autoconf-devel ; if you want to fight with'configure', don't use autoconf-stable!rxvt is a nice console with history. Replace in your cygwin.batthe linebash --login -iwith (one line):rxvt -sl 1000 -fn "Lucida Console-12" -sr -cr red-bg black -fg white -geometry 100x65 -e bash --loginText selected with the mouse is automatically copied to theclipboard, pasting works with shift-insert.The other good tip is to make sure you have no //c/-style pathsanywhere, use /cygdrive/c/ instead. Using // invokes a networklookup which is very slow. If you think ”cygdrive” is too long,you can change it with e.g.mount -s -u -c /mntSDCC sources use the unix line ending LF. Life is much easier, ifyou store the source tree on a drive which is mounted in binarymode. And use an editor which can handle LF-only line endings.Make sure not to commit files with windows line endings. Thetabulator spacingtabulator spacing (8 columns) used in theproject is 8. Although a tabulator spacing of 8 is a sensiblechoice for programmers (it's a power of 2 and allows to display8/16 bit signed variables without loosing columns) the plan is tomove towards using only spaces in the source.2.4.5 Building SDCC Using Microsoft Visual C++ 2010 (MSVC)Download the source package either from the SDCC Subversionrepository or from the snapshot builds http://sdcc.sourceforge.net/snap.php, it will be named something like sdcc-src-yyyymmdd-rrrr.tar.bz2.SDCC is distributed with all the project, solution and otherfiles you need to build it using Visual C++ 2010 (except forucSim). The solution name is 'sdcc.sln'. Please note that as itis now, all the executables are created in a folder calledsdcc\bin_vc. Once built you need to copy the executables fromsdcc\bin_vc to sdcc\bin before running SDCC.Apart from the SDCC sources you also need to have the BOOSTlibraries installed for MSVC. Get it here http://www.boost.org/In order to build SDCC with MSVC you need win32 executables ofbison.exe, flex.exe, and gawk.exe. One good place to get them ishere http://unxutils.sourceforge.netIf UnxUtils didn't work well, msysmsys (http://www.mingw.org/wiki/msys) or msys2msys2(https://msys2.github.io) can be an alternative.Download the file UnxUtilsUnxUtils.zip. Now you have to installthe utilities and setup MSVC so it can locate the requiredprograms. Here there are two alternatives (choose one!):1. The easy way:a) Extract UnxUtils.zip to your C:\ hard disk PRESERVING theoriginal paths, otherwise bison won't work. (If you are usingWinZip make certain that 'Use folder names' is selected)b) Add 'C:\user\local\wbin' to VC++ Directories / ExecutableDirectories.(As a side effect, you get a bunch of Unix utilities that couldbe useful, such as diff and patch.)2. A more compact way:This one avoids extracting a bunch of files you may not use, butrequires some extra work:a) Create a directory were to put the tools needed, or use adirectory already present. Say for example 'C:\util'.b) Extract 'bison.exe', 'bison.hairy', 'bison.simple','flex.exe', and gawk.exe to such directory WITHOUT preservingthe original paths. (If you are using WinZip make certain that'Use folder names' is not selected)c) Rename bison.exe to '_bison.exe'.d) Create a batch file 'bison.bat' in 'C:\util\' and add theselines:set BISON_SIMPLE=C:\util\bison.simpleset BISON_HAIRY=C:\util\bison.hairy_bison %1 %2 %3 %4 %5 %6 %7 %8 %9Steps 'c' and 'd' are needed because bison requires by defaultthat the files 'bison.simple' and 'bison.hairy' reside in someweird Unix directory, '/usr/local/share/' I think. So it isnecessary to tell bison where those files are located if theyare not in such directory. That is the function of theenvironment variables BISON_SIMPLE and BISON_HAIRY.e) Add 'C:\util' to VC++ Directories / Executable Directories.Note that you can use any other path instead of 'C:\util', eventhe path where the Visual C++ tools are, probably: 'C:\ProgramFiles\Microsoft Visual Studio\Common\Tools'. So you don't haveto execute step 'e' :)That is it. Open 'sdcc.sln' in Visual Studio, click 'build all',when it finishes copy the executables from sdcc\bin_vc tosdcc\bin, and you can compile using SDCC.2.4.6 Windows Install Using a ZIP Package1. Download the binary zip package from http://sdcc.sf.net/snap.phpand unpack it using your favorite unpacking tool (gunzip,WinZip, etc). This should unpack to a group of sub-directories.An example directory structure after unpacking the mingw32package is: C:\sdcc\bin for the executables, C:\sdcc\includeand C:\sdcc\lib for the include and libraries.2. Adjust your environment variable PATH to include the locationof the bin directory or start sdcc using the full path.2.4.7 Windows Install Using the Setup Program<subsec:Windows-Install>Download the setup program sdcc-x.y.z-setup.exe for an officialrelease fromhttp://sourceforge.net/projects/sdcc/files/ or a setup programfor one of the snapshots sdcc-yyyymmdd-xxxx-setup.exe from http://sdcc.sourceforge.net/snap.phpand execute it. A windows typical installer will guide youthrough the installation process.2.4.8 VPATHVPATH featureSDCC supports the VPATH feature provided by configure and make.It allows to separate the source and build trees. Here's anexample:cd ~ # cd $HOMEtar -xjf sdcc-src-yyyymmdd-rrrr.tar.bz2 # extract source todirectory sdccmkdir sdcc.build # put output insdcc.buildcd sdcc.build../sdcc/configure # configure is doing allthe magic!makeThat's it! configure will create the directory tree will all thenecessary Makefiles in ~/sdcc.build. It automagically computesthe variables srcdir, top_srcdir and top_buildir for eachdirectory. After running make the generated files will be in~/sdcc.build, while the source files stay in ~/sdcc.This is not only usefull for building different binaries, e.g.when cross compiling. It also gives you a much better overview inthe source tree when all the generated files are not scatteredbetween the source files. And the best thing is: if you want tochange a file you can leave the original file untouched in thesource directory. Simply copy it to the build directory, edit it,enter `make clean', `rm Makefile.dep' and `make'. make will dothe rest for you!2.5 Building the DocumentationAdd --enable-doc to the configure arguments to build thedocumentation together with all the other stuff. You will needseveral tools (LyX, LaTeX, LaTeX2HTML, pdflatex, dvipdf, dvipsand makeindex) to get the job done. Another possibility is tochange to the doc directory and to type ”make” there. You'reinvited to make changes and additions to this manual(sdcc/doc/sdccman.lyx). Using LyX http://www.lyx.org as editor isstraightforward. Prebuilt documentation is available from http://sdcc.sourceforge.net/snap.php.2.6 Reading the DocumentationDocumentationCurrently reading the document in pdf format is recommended, asfor unknown reason the hyperlinks are working there whereas inthe html version they are not[footnote:If you should know why please drop us a note].You'll find the pdf versionPDF version of this document at http://sdcc.sourceforge.net/doc/sdccman.pdf.This documentation is in some aspects different from a commercialdocumentation:• It tries to document SDCC for several processor architecturesin one document (commercially these probably would be separatedocuments/products). This documentStatus of documentationcurrently matches SDCC for mcs51 and DS390 best and does givetoo few information about f.e. Z80, PIC14, PIC16 and HC08.• There are many references pointing away from thisdocumentation. Don't let this distract you. If there f.e. was areference like http://www.opencores.org together with astatement ”some processors which are targeted by SDCC can beimplemented in a field programmable gate arrayFPGA (field programmable gate array)” or http://sourceforge.net/projects/fpgac/FpgaC ((subset of) C to FPGA compiler)”have you ever heard of an open source compiler that compilesa subset of C for an FPGA?” we expect you to have a quick lookthere and come back. If you read this you are on the righttrack.• Some sections attribute more space to problems, restrictionsand warnings than to the solution.• The installation section and the section about the debugger isintimidating.• There are still lots of typos and there are more differentwriting styles than pictures.2.7 Testing the SDCC Compiler<sec:Testing-the-SDCC>The first thing you should do after installing your SDCC compileris to see if it runs. Type "sdcc --version"version at the prompt,and the program should run and output its version like:SDCC : mcs51/z80/avr/ds390/pic16/pic14/ds400/hc08 2.5.6 #4169(May 8 2006) (UNIX)If it doesn't run, or gives a message about not finding sdccprogram, then you need to check over your installation. Make surethat the sdcc bin directory is in your executable search pathdefined by the PATH environment setting (see section [subsec:Install-Trouble-shooting]Install trouble-shooting for suggestions). Make sure that thesdcc program is in the bin folder, if not perhaps something didnot install correctly.SDCC is commonly installed as described in section ”Install andsearch paths”.Make sure the compiler works on a very simple example. Type inthe following test.c program using your favorite ASCII editor:char test;void main(void) {test=0;}Compile this using the following command: "sdcc -c test.c". Ifall goes well, the compiler will generate a test.asm and test.relfile. Congratulations, you've just compiled your first programwith SDCC. We used the -c option to tell SDCC not to link thegenerated code, just to keep things simple for this step.The next step is to try it with the linker. Type in "sdcctest.c". If all goes well the compiler will link with thelibraries and produce a test.ihx output file. If this step fails(no test.ihx, and the linker generates warnings), then theproblem is most likely that SDCC cannot find the/usr/local/share/sdcc/lib directory (see section [subsec:Install-Trouble-shooting]Install trouble-shooting for suggestions).The final test is to ensure SDCC can use the standard headerfiles and libraries. Edit test.c and change it to the following:#include <string.h>char str1[10];void main(void) {strcpy(str1, "testing");}Compile this by typing "sdcc test.c". This should generate atest.ihx output file, and it should give no warnings such as notfinding the string.h file. If it cannot find the string.h file,then the problem is that SDCC cannot find the/usr/local/share/sdcc/include directory (see the section [subsec:Install-Trouble-shooting]Install trouble-shooting section for suggestions). Use option --print-search-dirs--print-search-dirs to find exactly where SDCCis looking for the include and lib files.2.8 Install Trouble-shooting<subsec:Install-Trouble-shooting>Install trouble-shooting2.8.1 If SDCC does not build correctlyA thing to try is starting from scratch by unpacking the .tgzsource package again in an empty directory. Configure it like:./configure 2>&1 | tee configure.logand build it like:make 2>&1 | tee make.logIf anything goes wrong, you can review the log files to locatethe problem. Or a relevant part of this can be attached to anemail that could be helpful when requesting help from the mailinglist.2.8.2 What the ”./configure” doesThe ”./configure” command is a script that analyzes your systemand performs some configuration to ensure the source packagecompiles on your system. It will take a few minutes to run, andwill compile a few tests to determine what compiler features areinstalled.2.8.3 What the ”make” doesThis runs the GNU make tool, which automatically compiles all thesource packages into the final installed binary executables.2.8.4 What the ”make install” command does.This will install the compiler, other executables libraries andinclude files into the appropriate directories. See sections [subsec:Install-paths], [subsec:Search-Paths] about install and search paths.On most systems you will need super-user privileges to do this.2.9 Components of SDCCSDCC is not just a compiler, but a collection of tools by variousdevelopers. These include linkers, assemblers, simulators andother components. Here is a summary of some of the components.Note that the included simulator and assembler have separatedocumentation which you can find in the source package in theirrespective directories. As SDCC grows to include support forother processors, other packages from various developers areincluded and may have their own sets of documentation.You might want to look at the files which are installed in<installdir>. At the time of this writing, we find the followingprograms for gcc-builds:In <installdir>/bin:• sdcc - The compiler.• sdcpp - The C preprocessor.• sdas8051 - The assembler for 8051 type processors.• sdas390 - The assembler for DS80C390 processor.• sdasz80, sdasgb - The Z80 and GameBoy Z80 assemblers.• sdas6808 - The 6808 assembler.• sdasstm8 - The STM8 assembler.• sdld -The linker for 8051 and STM8 type processors.• sdldz80, sdldgb - The Z80 and GameBoy Z80 linkers.• sdld6808 - The 6808 linker.• s51 - The ucSim 8051 simulator.• sz80 - The ucSim Z80 simulator.• shc08 - The ucSim 6808 simulator.• sstm8 - The ucSim STM8 simulator.• sdcdb - The source debugger.• sdar, sdranlib, sdnm, sdobjcopy - The sdcc archive managing andindexing utilites.• packihx - A tool to pack (compress) Intel hex files.• makebin - A tool to convert Intel Hex file to a binary andGameBoy binary image file format.In <installdir>/share/sdcc/include• the include filesIn <installdir>/share/sdcc/non-free/include• the non-free include filesIn <installdir>/share/sdcc/lib• the src and target subdirectories with the precompiledrelocatables.In <installdir>/share/sdcc/non-free/lib• the src and target subdirectories with the non-free precompiledrelocatables.In <installdir>/share/sdcc/doc• the documentation2.9.1 sdcc - The CompilerThis is the actual compiler, it in turn uses the c-preprocessorand invokes the assembler and linkage editor.2.9.2 sdcpp - The C-PreprocessorPreprocessorThe preprocessorsdcpp (preprocessor) is a modified version of theGNU cppcpp|seesdcpp preprocessor http://gcc.gnu.org/. The Cpreprocessor is used to pull in #include sources, process #ifdefstatements, #defines and so on.2.9.3 sdas, sdld - The Assemblers and Linkage EditorsThis is a set of retargettable assemblers and linkage editors,which was developed by Alan Baldwin. John Hartman created theversion for 8051, and I (Sandeep) have made some enhancements andbug fixes for it to work properly with SDCC.SDCC used an about 1998 branch of asxxxx version 2.0 whichunfortunately is not compatible with the more advanced (f.e.macros, more targets) ASxxxx Cross Assemblers nowadays availablefrom Alan Baldwin http://shop-pdp.kent.edu/. In 2009 Alan madehis ASxxxx Cross Assemblers version 5.0 available under the GPLlicense (GPLv3 or later), so a reunion is now a work in progress.Thanks Alan!2.9.4 s51, sz80, shc08, sstm8 - The Simulatorss51s51 (simulator), sz80sz80 (simulator) shc08shc08 (simulator)and sstm8 sstm8 (simulator) are free open source simulatorsdeveloped by Daniel Drotos. The simulators are built as part ofthe build process. For more information visit Daniel's web siteat: http://mazsola.iit.uni-miskolc.hu/~drdani/embedded/s51. Itcurrently supports the core mcs51, the Dallas DS80C390, thePhillips XA51 family, the Z80, 6808 and the STM8.2.9.5 sdcdb - Source Level DebuggerSDCDBSDCDB (debugger) is the companion source level debugger.More about SDCDB in section [cha:Debugging-with-SDCDB]. Thecurrent version of the debugger uses Daniel's Simulator S51s51 (simulator), but can be easily changed to use other simulators.Using SDCC3.1 Standard-ComplianceStandard-compliance<subsec:Standard-Compliance>SDCC aims to be a conforming freestanding implementation of the Cprogramming language.3.1.1 ISO C90 and ANSI C89Use --std-c89--std-c89 to compile in this mode.The latest publicly available version of the standard ISO/IEC9899 - Programming languages - C should be available at: http://www.open-std.org/jtc1/sc22/wg14/www/standards.html#9899.Deviations from standard compliance:• structuresstruct and unionsunion cannot be passed as functionparameters and cannot be a return valuereturn value from afunction, e.g.:struct s { ... };struct s foo1 (struct s parms) /* invalid in SDCC althoughallowed in ANSI */{struct s rets;...return rets; /* is invalid in SDCC although allowed in ANSI*/}• initialization of structure arrays must be fully braced.struct s { char x } a[] = {1, 2}; /* invalid in SDCC */struct s { char x } a[] = {{1}, {2}}; /* OK */• 'doubledouble (not supported)' precision floating point Floating point supportnot supported. Instead a warning is emitted, and float is usedinstead. long double is not supported.• Old K&R styleKR style function declarations are not supported.foo(i,j) /* this old style of function declarations */int i,j; /* is valid in ANSI but not valid in SDCC */{...}Some features of this standard are not supported in some ports:• Functions are not reentrant unless explicitly declared as suchor --stack-auto is specified in the mcs51, ds390, hc08 and s08ports.3.1.2 ISO C95Use --std-c95--std-c95 to compile in this mode.Except for the issues mentioned in the section above, thisstandard is supported.3.1.3 ISO C99Use --std-c99--std-c99 to compile in this mode.In addition to what is mentioned in the section above, thefollowing features of this standard are not supported by SDCC:• Compound literals.• Variable-length arrays.Some features of this standard are not supported in some ports:• There is no support for data types long long, unsigned longlong, int_fast64_t, int_least64_t, int64_t, uint_fast64_t,uint_least64_t, uint64_t in the pic14 and pic16 ports.3.1.4 ISO C11 and ISO C17Use --std-c11--std-c11 to compile in this mode.Except for the issues mentioned in the section above, thisstandard is supported.3.1.5 ISO C2XUse --std-c2x--std-c2x to compile in this mode.Standard and support are still quite incomplete.3.1.6 Embedded CSDCC supports named address spaces. The support for fixed-pointmath in SDCC is inconsistent with the standard. Other parts ofthe standard are not supported.3.2 Compiling3.2.1 Single Source File ProjectsFor single source file 8051 projects the process is very simple.Compile your programs with the following command "sdccsourcefile.c". This will compile, assemble and link your sourcefile. Output files are as follows:• sourcefile.asm<file>.asm - Assembler sourceAssembler sourcefile created by the compiler• sourcefile.lst<file>.lst - Assembler listingAssembler listingfile created by the Assembler• sourcefile.rst<file>.rst - Assembler listingAssembler listingfile updated with linkedit information, created by linkageeditor• sourcefile.sym<file>.sym - symbol listingSymbol listing for thesourcefile, created by the assembler• sourcefile.rel<file>.rel - Object fileObject file created bythe assembler, input to Linkage editor• sourcefile.map<file>.map - The memory mapMemory map for theload module, created by the Linker• sourcefile.mem<file>.mem - A file with a summary of the memoryusage• sourcefile.ihx<file>.ihx - The load module in Intel hex formatIntel hex format(you can select the Motorola S19 formatMotorola S19 formatwith --out-fmt-s19--out-fmt-s19. If you need another format youmight want to use objdumpobjdump (tool) or srecordsrecord (bin, hex, ... tool)- see also section [subsec:Postprocessing-the-Intel]). Bothformats are documented in the documentation of srecordsrecord (bin, hex, ... tool)• sourcefile.adb<file>.adb - An intermediate file containingdebug information needed to create the .cdb file (with --debug--debug)• sourcefile.cdb<file>.cdb - An optional file (with --debug)containing debug information. The format is documented incdbfileformat.pdf• sourcefile.omf<file>.omf - An optional AOMF or AOMF51AOMF, AOMF51<OMF file>file containing debug information (generated withoption --debug). The (Intel) absolute object module format is asubformat of the OMF51 format and is commonly used by thirdparty tools (debuggersDebugger, simulators, emulators).• sourcefile.dump*<file>.dump* - Dump file to debug the compilerit self (generated with option --dumpall) (see section [subsec:Intermediate-Dump-Options]and section [subsec:The-anatomy-of] ”Anatomy of the compiler”).3.2.2 Postprocessing the Intel HexIntel hex format file<subsec:Postprocessing-the-Intel>In most cases this won't be needed but the Intel Hex file<file>.ihxwhich is generated by SDCC might include lines of varying lengthand the addresses within the file are not guaranteed to bestrictly ascending. If your toolchain or a bootloader does notlike this you can use the tool packihxpackihx (tool) which ispart of the SDCC distribution:packihx sourcefile.ihx >sourcefile.hexThe separately available srecordsrecord (bin, hex, ... tool)package additionally allows to set undefined locations to apredefined value, to insert checksumschecksum of various flavours(crc, add, xor) and to perform other manipulations (convert,split, crop, offset, ...).srec_cat sourcefile.ihx -intel -o sourcefile.hex -intelAn example for a more complex command line[footnote:the command backfillsbackfill unused memory unused memory with0x12 and the overall 16 bit sum of the complete 64 kByte block iszero. If the program counter on an mcs51 runs wild the backfillpattern 0x12 will be interpreted as an lcall to address 0x1212(where an emergency routine could sit).] could look like:srec_cat sourcefile.ihx -intel -fill 0x12 0x0000 0xfffe-little-endian-checksum-negative 0xfffe 0x02 0x02 -osourcefile.hex -intelThe srecord package is available at http://sourceforge.net/projects/srecord/.3.2.3 Projects with Multiple Source FilesSDCC can compile only ONE file at a time. Let us for exampleassume that you have a project containing the following files:foo1.c (contains some functions)foo2.c (contains some more functions)foomain.c (contains more functions and the function main)The first two files will need to be compiled separately with thecommands:sdcc -c foo1.csdcc -c foo2.cThen compile the source file containing the main() function andlinkLinker the files together with the following command:sdcc foomain.c foo1.rel foo2.rel<file>.relAlternatively, foomain.c can be separately compiled as well:sdcc -c foomain.csdcc foomain.rel foo1.rel foo2.relThe file containing the main() function must be the first filespecified in the command line, since the linkage editor processesfile in the order they are presented to it. The linker is invokedfrom SDCC using a script file with extension .lnk<file>.lnk. Youcan view this file to troubleshoot linking problems such as thosearising from missing libraries.3.2.4 Projects with Additional LibrariesLibrariesSome reusable routines may be compiled into a library, see thedocumentation for the assembler and linkage editor (which are in<installdir>/share/sdcc/doc) for how to create a .lib<file>.liblibrary file. Libraries created in this manner can be included inthe command line. Make sure you include the -L <library-path>option to tell the linker where to look for these files if theyare not in the current directory. Here is an example, assumingyou have the source file foomain.c and a library foolib.lib inthe directory mylib (if that is not the same as your currentproject):sdcc foomain.c foolib.lib -L mylibNote here that mylib must be an absolute path name.The most efficient way to use libraries is to keep separatemodules in separate source files. The lib file now should nameall the modules.rel<file>.rel files. For an example see thestandard library file libsdcc.lib in the directory<installdir>/share/lib/small.3.2.5 Using sdar to Create and Manage Librariessdar<subsec:Using-sdar-to>Support for sdar format libraries was introduced in SDCC 2.9.0.Both the GNU and BSD ar format variants are supported by sdldlinkers.To create a library containing sdas object files, you should usethe following sequence:sdar -rc <library name>.lib <list of .rel files>3.3 Command Line OptionsCommand Line Options<sec:Command-Line-Options>3.3.1 Processor Selection OptionsOptions processor selectionProcessor selection options-mmcs51-mmcs51 Generate code for the Intel MCS51MCS51 family ofprocessors. This is the default processor target.-mds390-mds390 Generate code for the Dallas DS80C390DS80C390processor.-mds400-mds400 Generate code for the Dallas DS80C400DS80C400processor.-mhc08-mhc08 Generate code for the Freescale/Motorola HC08 (aka68HC08) HC08 family of processors.-ms08-ms08 Generate code for the Freescale/Motorola S08 (aka68HCS08, HCS08, CS08) S08 family of processors.-mz80-mz80 Generate code for the Zilog Z80Z80 family ofprocessors.-mz180-mz180 Generate code for the Zilog Z180Z180 family ofprocessors.-mr2k-mr2k Generate code for the Rabbit 2000 / Rabbit 3000 familyof processors.-mr3ka-mr3ka Generate code for the Rabbit 3000A family ofprocessors.-mgbz80-mgbz80 Generate code for the LR35902 GameBoy Z80gbz80 (GameBoy Z80)processor.-mtlcs90-mtlcs90 Generate code for the Toshiba TLCS-90 processor.-mez80_z80-mez80_z80 Generate code for the Zilog eZ80 processorin Z80 mode.-mstm8-mstm8 Generate code for the STMicroelectronics STM8 familyof processors.-mpdk14-mpdk14 Generate code for Padauk processors with 14 bitwide program memory.-mpdk15-mpdk15 Generate code for Padauk processors with 15 bitwide program memory.-mpic14-mpic14 Generate code for the Microchip PIC 14PIC14-bitprocessors (p16f84 and variants. In development, not complete).-mpic16-mpic16 Generate code for the Microchip PIC 16PIC16-bitprocessors (p18f452 and variants. In development, not complete).SDCC inspects the program name it was called with so theprocessor family can also be selected by renaming the sdcc binary(to f.e. z80-sdcc) or by calling SDCC from a suitable link.Option -m has higher priority than setting from program name.3.3.2 Preprocessor OptionsOptions preprocessorPreprocessor!Optionssdcpp (preprocessor)SDCC uses sdcpp, an adapted version of the GNU CompilerCollectiongcc (GNU Compiler Collection) preprocessor cppcpp|seesdcpp(gcc http://gcc.gnu.org/). If you need more dedicated optionsthan those listed below please refer to the GCC CPP Manual at http://www.gnu.org/software/gcc/onlinedocs/.-I<path>-I<path> The additional location where the preprocessorwill look for <..h> or “..h” files.-D<macro[=value]>-D<macro[=value]> Command line definition ofmacros. Passed to the preprocessor.-M-M Tell the preprocessor to output a rule suitable for makedescribing the dependencies of each object file. For each sourcefile, the preprocessor outputs one make-rule whose target is theobject file name for that source file and whose dependencies areall the files `#include'd in it. This rule may be a single lineor may be continued with `\'-newline if it is long. The list ofrules is printed on standard output instead of the preprocessed Cprogram. `-M' implies `-E-E'.-C-C Tell the preprocessor not to discard comments. Used with the`-E' option.-MM-MM Like `-M' but the output mentions only the user headerfiles included with `#include “file"'. System header filesincluded with `#include <file>' are omitted.-Aquestion(answer)-Aquestion(answer) Assert the answer answer forquestion, in case it is tested with a preprocessor conditionalsuch as `#if #question(answer)'. `-A-' disables the standardassertions that normally describe the target machine.-Umacro-Umacro Undefine macro macro. `-U' options are evaluatedafter all `-D' options, but before any `-include' and `-imacros'options.-dM-dM Tell the preprocessor to output only a list of the macrodefinitions that are in effect at the end of preprocessing. Usedwith the `-E' option.-dD-dD Tell the preprocessor to pass all macro definitions intothe output, in their proper sequence in the rest of the output.-dN-dN Like `-dD' except that the macro arguments and contentsare omitted. Only `#define name' is included in the output.-pedantic-parse-numberpedantic-pedantic-parse-number<lyx:-pedantic-parse-number>Pedantic parse numbers so that situations like 0xfe-LO_B(3) areparsed properly and the macro LO_B(3) gets expanded. See also#pragma pedantic_parse_number [ite:pedantic_parse_number] insection[sec:Pragmas] Note: this functionality is not inconformance with C99 standard!-Wp preprocessorOption[,preprocessorOption]-Wp preprocessorOption[,preprocessorOption]... Pass the preprocessorOption to the preprocessor sdcppsdcpp (preprocessor).3.3.3 Optimization OptionsOptions optimizationOptimization options--nogcse--nogcse Will not do global common subexpressionelimination, this option may be used when the compiler createsundesirably large stack/data spaces to store compiler temporaries(spill locations, slocsloc (spill location)). A warning messagewill be generated when this happens and the compiler willindicate the number of extra bytes it allocated. It isrecommended that this option NOT be used, #pragma nogcsepragma nogcsecan be used to turn off global subexpression eliminationSubexpression eliminationfor a given function only.--noinvariant--noinvariant Will not do loop invariantoptimizations, this may be turned off for reasons explained forthe previous option. For more details of loop optimizationsperformed see Loop Invariants in section [subsec:Loop-Optimizations]. It is recommended that this option NOT be used, #pragmanoinvariantpragma noinvariant can be used to turn off invariantoptimizations for a given function only.--noinduction--noinduction Will not do loop inductionoptimizations, see section strength reduction for more details.It is recommended that this option is NOT used, #pragmanoinductionpragma noinduction can be used to turn off inductionoptimizations for a given function only.--noloopreverse--noloopreverse Will not do loop reversal Loop reversingoptimization.--nolabelopt --nolabelopt Will not optimize labels (makes thedumpfiles more readable).--no-xinit-opt--no-xinit-opt Will not memcpy initialized datafrom code space into xdata space. This saves a few bytes in codespace if you don't have initialized dataVariable initialization.--nooverlay--nooverlay The compiler will not overlay parametersand local variables of any function, see section Parameters andlocal variables for more details.--no-peep--no-peep Disable peep-hole optimization with built-inrules.--peep-file--peep-file <filename> This option can be used to useadditional rules to be used by the peep hole optimizer. Seesection [subsec:Peephole-Optimizer] Peep Hole optimizations fordetails on how to write these rules.--peep-asm--peep-asm Pass the inline assembler code through thepeep hole optimizer. This can cause unexpected changes to inlineassembler code, please go through the peephole optimizerPeephole optimizerrules defined in the source file tree '<target>/peeph.def'before using this option.--peep-return--peep-return Let the peep hole optimizer do returnoptimizations. This is the default without --debug--debug.--no-peep-return--no-peep-return Do not let the peep holeoptimizer do return optimizations. This is the default with --debug--debug.--opt-code-speed--opt-code-speed The compiler will optimize codegeneration towards fast code, possibly at the expense of codesize.--opt-code-size--opt-code-size The compiler will optimize codegeneration towards compact code, possibly at the expense of codespeed.--fomit-frame-pointer--fomit-frame-pointer Frame pointer will beomitted when the function uses no local variables. On thez80-related ports this option will result in the frame pointeralways being omitted.--max-allocs-per-node--max-allocs-per-node Setting this to a highvalue will result in increased compilation time and moreoptimized code being generated. Setting it to lower values speedup compilation, but does not optimize as much. The default valueis 3000. This option currently only affects the hc08, s08, z80,z180, r2k, r3ka and gbz80 ports.--nolospre--nolospre Disable lospre. lospre is an advancedredundancy elimination technique, essentially an improved variantof global subexpression elimination.--allow-unsafe-read--allow-unsafe-read Allow optimizations togenerate unsafe reads. This will enable additional optimizations,but can result in spurious reads from undefined memory addresses,which can be harmful if the target system uses certain ways ofdoing memory-mapped I/O.--nostdlibcall--nostdlibcall Disable the optimization of calls tothe standard library.3.3.4 Other OptionsOptions other-v --version--version-v displays the sdcc version.-c --compile-only--compile-only-c will compile and assemble thesource, but will not call the linkage editor.--c1mode--c1mode reads the preprocessed source from standardinput and compiles it. The file name for the assembler outputmust be specified using the -o option.-E-E Run only the C preprocessorPreprocessor. Preprocess all theC source files specified and output the results to standardoutput.-o <path/file>-o <path/file> The output path where everythingwill be placed or the file name used for all generated outputfiles. If the parameter is a path, it must have a trailing slash(or backslash for the Windows binaries) to be recognized as apath. Note for Windows users: if the path contains spaces, itshould be surrounded by quotes. The trailing backslash should bedoubled in order to prevent escaping the final quote, forexample: -o ”F:\Projects\test3\output 1\\” or put after the finalquote, for example: -o ”F:\Projects\test3\output 1”\. The pathusing slashes for directory delimiters can be used too, forexample: -o ”F:/Projects/test3/output 1/”.--stack-auto--stack-auto All functions in the source file will becompiled as reentrantreentrant, i.e. the parameters and localvariables will be allocated on the stackstack. See section [sec:Parameters-and-Local-Variables]Parameters and Local Variables for more details. If this optionis used all source files in the project should be compiled withthis option. It automatically implies --int-long-reent and --float-reent.--callee-saves--callee-saves <lyx:--callee-saves-function1[,function2][,function3]...>function1[,function2][,function3].... The compiler by defaultuses a caller saves convention for register saving acrossfunction calls, however this can cause unnecessary registerpushing and popping when calling small functions from largerfunctions. This option can be used to switch the register savingconvention for the function names specified. The compiler willnot save registers when calling these functions, no extra codewill be generated at the entry and exit (function prologuefunction prologueand epiloguefunction epilogue) for these functions to save andrestore the registers used by these functions, this canSUBSTANTIALLY reduce code and improve run time performance of thegenerated code. In the future the compiler (with inter proceduralanalysis) will be able to determine the appropriate scheme to usefor each function call. DO NOT use this option for built-infunctions such as _mulint..., if this option is used for alibrary function the appropriate library function needs to berecompiled with the same option. If the project consists ofmultiple source files then all the source file should be compiledwith the same --callee-saves option string. Also see #pragmacallee_saves pragma calleesaves [ite:callee_saves-function1[,function2[,function3...]]--].--all-callee-saves--all-callee-saves Function of --callee-saveswill be applied to all functions by default.--debug--debug When this option is used the compiler willgenerate debug information. The debug information collected in afile with .cdb extension can be used with the SDCDB. For moreinformation see documentation for SDCDB. Another file with a .omfextension contains debug information in AOMF or AOMF51AOMF, AOMF51format which is commonly used by third party tools.-S-S Stop after the stage of compilation proper; do not assemble.The output is an assembler code file for the input filespecified.--int-long-reent--int-long-reent Integer (16 bit) and long (32bit) libraries have been compiled as reentrant. Note by defaultthese libraries are compiled as non-reentrant. See sectionInstallation for more details.--cyclomatic--cyclomatic This option will cause the compiler togenerate an information message for each function in the sourcefile. The message contains some important information about thefunction. The number of edges and nodes the compiler detected inthe control flow graph of the function, and most importantly thecyclomatic complexityCyclomatic complexity see section onCyclomatic Complexity for more details.--float-reent--float-reent Floating point library is compiled asreentrantreentrant. See section Installation for more details.--fsigned-char--fsigned-char By default char is unsigned. To setthe signess for characters to signed, use the option --fsigned-char. If this option is set and no signedness keyword(unsigned/signed) is given, a char will be unsigned. All othertypes are unaffected.--nostdinc--nostdinc This will prevent the compiler from passingon the default include path to the preprocessor.--nostdlib--nostdlib This will prevent the compiler from passingon the default libraryLibraries path to the linker.--verbose--verbose Shows the various actions the compiler isperforming.-V-V Shows the actual commands the compiler is executing.--no-c-code-in-asm--no-c-code-in-asm Hides your ugly andinefficient c-code from the asm file, so you can always blame thecompiler :)--no-peep-comments--no-peep-comments Don't include peep-holecomments in the generated asm files even if --fverbose-asm optionis specified.--i-code-in-asm--i-code-in-asm Include i-codes in the asm file.Sounds like noise but is helpful for debugging the compileritself.--less-pedanticpedantic--less-pedantic<lyx:--less-pedantic>Disable some of the more pedantic warningsWarnings. For moredetails, see the less_pedantic pragma [ite:less_pedantic].--disable-warning <nnnn>--disable-warning Disable specificwarning with number <nnnn>.--Werror--Werror Treat all warnings as errors.--print-search-dirs--print-search-dirs Display the directories inthe compiler's search path--vc--vc Display errors and warnings using MSVC style, so you canuse SDCC with the visual studio IDEIDE. With SDCC both offering aGCC-like (the default) and a MSVC-likeMSVC output style outputstyle, integration into most programming editors should bestraightforward.--use-stdout--use-stdout Send errors and warnings to stdoutinstead of stderr.-Wa asmOption[,asmOption]-Wa asmOption[,asmOption]... Pass theasmOption to the assemblerOptions assemblerAssembler options. Seefile sdcc/sdas/doc/asmlnk.txt for assembler options.cd--std-sdcc89--std-sdcc89 Generally follow the ANSI C89 / ISO C90standard, but allow some SDCC behaviour that conflicts with thestandard.--std-c89--std-c89 Follow the ANSI C89 / ISO C90 standard.--std-sdcc99--std-sdcc99 Generally follow the ISO C99 standard,but allow some SDCC behaviour that conflicts with the standard.--std-c99--std-sdcc99 Follow the ISO C99 standard.--std-sdcc11--std-sdcc11 Generally follow the ISO C11 standard,but allow some SDCC behaviour that conflicts with the standard(default).--std-c11--std-sdcc11 Follow the ISO C11 standard.--codeseg--codeseg <Value><lyx:-codeseg> <Name> The name to beused for the codecode segment, default CSEG. This is useful ifyou need to tell the compiler to put the code in a specialsegment so you can later on tell the linker to put this segmentin a special place in memory. Can be used for instance when usingbank switching to put the code in a bank.--constseg--constseg <Value> <Name> The name to be used for theconstconst segment, default CONST. This is useful if you need totell the compiler to put the const data in a special segment soyou can later on tell the linker to put this segment in a specialplace in memory. Can be used for instance when using bankswitching to put the const data in a bank.--fdollars-in-identifiers--fdollars-in-identifiers Permit '$' asan identifier character.--more-pedantic--more-pedanticpedantic Actually this is not aSDCC compiler option but if you want more warnings you can use aseparate tool dedicated to syntax checking like splint<lyx:more-pedantic-SPLINT>lint (syntax checking tool) http://www.splint.org. To make yoursource files parseable by splint you will have to include lint.hsplint (syntax checking tool)in your source file and add brackets around extended keywords(like ”__at (0xab)” and ”__interrupt (2)”).Splint has an excellent on line manual at http://www.splint.org/manual/and it's capabilities go beyond pure syntax checking. You'llneed to tell splint the location of SDCC's include files so atypical command line could look like this:splint -I /usr/local/share/sdcc/include/mcs51/ myprogram.c--use-non-free--use-non-free<lyx:--use-non-free> Search / includenon-free licensed libraries and header files, located under thenon-free directory - see section [subsec:Search-Paths]3.3.5 Linker OptionsOptions linkerLinker options--lib-path--lib-path <path> <absolute path to additionallibraries> This option is passed to the linkage editor'sadditional librariesLibraries search path. The path name must beabsolute. Additional library files may be specified in thecommand line. See section Compiling programs for more details.-L -L <path> <absolute path to additional libraries> Same asabove.--xram-loc--xram-loc <Value> <Value> The start location of theexternal ramxdata (mcs51, ds390 named address space), defaultvalue is 0. The value entered can be in Hexadecimal or Decimalformat, e.g.: --xram-loc 0x8000 or --xram-loc 32768.--code-loc--code-loc <Value> <Value> The start location of thecodecode segment, default value 0. Note when this option is usedthe interrupt vector tableinterrupt vector table is alsorelocated to the given address. The value entered can be inHexadecimal or Decimal format, e.g.: --code-loc 0x8000 or --code-loc 32768.--stack-loc--stack-loc <Value> <Value> By default the stackstackis placed after the data segment for mcs51. By using this optionthe stack can be placed anywhere in the internal memory space ofthe mcs51. The value entered can be in Hexadecimal or Decimalformat, e.g. --stack-loc 0x20 or --stack-loc 32. Since the spregister is incremented before a push or call, the initial spwill be set to one byte prior the provided value. The providedvalue should not overlap any other memory areas such as usedregister banks or the data segment and with enough space for thecurrent application. The --pack-iram --pack-iram option (which isnow a default setting) will override this setting, so you shouldalso specify the --no-pack-iram --no-pack-iram option if you needto manually place the stack.For stm8, by default the stack is placed at the device-specificreset value. By using this option, the stack can be placedanywhere in the lower 16-bits of the stm8 memory space. This isparticularly useful for working around the stack roll-overantifeature present in some stm8 devices.--xstack-loc--xstack-loc <Value> <Value> By default the externalstackxstack is placed after the __pdatapdata (mcs51, ds390 named address space)segment. Using this option the xstack can be placed anywhere inthe external memory space of the 8051. The value entered can bein Hexadecimal or Decimal format, e.g. --xstack-loc 0x8000 or --stack-loc 32768. The provided value should not overlap any othermemory areas such as the pdata or xdata segment and with enoughspace for the current application.--data-loc--data-loc <Value> <Value> The start location of theinternal ram datadata (mcs51, ds390 named address space) segment.The value entered can be in Hexadecimal or Decimal format, eg. --data-loc 0x20 or --data-loc 32. (By default, the start locationof the internal ram data segment is set as low as possible inmemory, taking into account the used register banks and the bitsegment at address 0x20. For example if register banks 0 and 1are used without bit variables, the data segment will be set, if--data-loc is not used, to location 0x10.)--idata-loc--idata-loc <Value> <Value> The start location of theindirectly addressable internal ramidata (mcs51, ds390 named address space)of the 8051, default value is 0x80. The value entered can be inHexadecimal or Decimal format, eg. --idata-loc 0x88 or --idata-loc 136.--bit-loc <Value> The start location of the bitbit addressableinternal ram of the 8051. This is not implemented yet. Instead anoption can be passed directly to the linker: -Wl -bBSEG=<Value>.--out-fmt-ihx--out-fmt-ihx The linker output (final object code)is in Intel Hex format.Intel hex format This is the defaultoption. The format itself is documented in the documentation ofsrecordsrecord (bin, hex, ... tool).--out-fmt-s19--out-fmt-s19 The linker output (final object code)is in Motorola S19 formatMotorola S19 format. The format itselfis documented in the documentation of srecord.--out-fmt-elf--out-fmt-s19HC08!Options!--out-fmt-elf The linkeroutput (final object code) is in ELF formatELF format. (Currentlyonly supported for the HC08HC08 and S08 processors)-Wl linkOption[,linkOption]-Wl linkOption[,linkOption]<lyx:-Wl option>... Pass the linkOption to the linker. If a bootloader is used anoption like ”-Wl -bCSEG=0x1000” would be typical to set the startof the code segment. Either use the double quotes around thisoption or use no space (e.g. -Wl-bCSEG=0x1000). See also #pragmaconstseg and #pragma codeseg in section[sec:Pragmas]. Filesdcc/sdas/doc/asmlnk.txt has more on linker options.3.3.6 MCS51 OptionsOptions MCS51MCS51 options--model-small--model-small Generate code for Small modelprograms, see section Memory Models for more details. This is thedefault model.--model-medium--model-medium Generate code for Medium modelprograms, see section Memory Models for more details. If thisoption is used all source files in the project have to becompiled with this option. It must also be used when invoking thelinker.--model-large--model-large Generate code for Large modelprograms, see section Memory Models for more details. If thisoption is used all source files in the project have to becompiled with this option. It must also be used when invoking thelinker.--model-huge--model-huge Generate code for Huge model programs,see section Memory Models for more details. If this option isused all source files in the project have to be compiled withthis option. It must also be used when invoking the linker.--xstack--xstack Uses a pseudo stack in the __pdatapdata (mcs51, ds390 named address space)area (usually the first 256 bytes in the external ram) forallocating variables and passing parameters. See section [subsec:External-Stack]External Stack for more details.--iram-size <Value>--iram-size <Value> Causes the linker to checkif the internal ram usage is within limits of the given value.--xram-size <Value>--xram-size <Value> Causes the linker to checkif the external ram usage is within limits of the given value.--code-size <Value>--code-size <Value> Causes the linker to checkif the code memory usage is within limits of the given value.--stack-size <Value>--stack-size <Value> Causes the linker tocheck if there is at minimum <Value> bytes for stack.--pack-iram --pack-iram Causes the linker to use unused registerbanks for data variables and pack data, idata and stack together.This is the default and this option will probably be removedalong with the removal of --no-pack-iram.--no-pack-iram (deprecated)--no-pack-iram Causes the linker touse old style for allocating memory areas. This option is nowdeprecated and will be removed in future versions.--acall-ajmp --acall-ajmp Replaces the three byte instructionslcall/ljmp with the two byte instructions acall/ajmp. Only usethis option if your code is in the same 2k block of memory. Youmay need to use this option for some 8051 derivatives which lackthe lcall/ljmp instructions.--no-ret-without-call --no-ret-without-call Causes the codegenerator to insert an extra lcall or acall instruction wheneverit needs to use a ret instruction in a context other than afunction returning. This option is needed when using the InfineonInfineonXC800 series microcontrollers to keep its Memory Extension Stackbalanced.3.3.7 DS390 / DS400 OptionsOptions DS390DS390--model-flat24DS390!Options!--model-flat24 Generate 24-bit flatmode code. This is the one and only that the ds390 code generatorsupports right now and is default when using -mds390. See sectionMemory Models for more details.--protect-sp-updateDS390!Options!--protect-sp-update disableinterrupts during ESP:SP updates.--stack-10bitDS390!Options!--stack-10bit Generate code for the 10bit stack mode of the Dallas DS80C390 part. This is the one andonly that the ds390 code generator supports right now and isdefault when using -mds390. In this mode, the stack is located inthe lower 1K of the internal RAM, which is mapped to 0x400000.Note that the support is incomplete, since it still uses a singlebyte as the stack pointer. This means that only the lower 256bytes of the potential 1K stack space will actually be used.However, this does allow you to reclaim the precious 256 bytes oflow RAM for use for the DATA and IDATA segments. The compilerwill not generate any code to put the processor into 10 bit stackmode. It is important to ensure that the processor is in thismode before calling any re-entrant functions compiled with thisoption. In principle, this should work with the --stack-auto--stack-autooption, but that has not been tested. It is incompatible withthe --xstack--xstack option. It also only makes sense if theprocessor is in 24 bit contiguous addressing mode (see the --model-flat24 option).--stack-probeDS390!Options!--stack-probe insert call to function__stack_probe at each function prologue.--tini-libidDS390!Options!--tini-libid <nnnn> LibraryID used in-mTININative.--use-acceleratorDS390!Options!--use-accelerator generate codefor DS390 Arithmetic Accelerator.3.3.8 Options common to all z80-related ports (z80, z180, r2k,r3ka, gbz80, tlcs90, ez80_z80)--no-std-crt0Z80!Options!--no-std-crt0 When linking, skip thestandard crt0.rel object file. You must provide your own crt0.relfor your system when linking.--callee-saves-bcZ80!Options!--callee-saves-bc Force a calledfunction to always save BC.--codeseg <Value>Z80!Options!--codeseg <Value> Use <Value> forthe code segment name.--constseg <Value>Z80!Options!--constseg <Value> Use <Value> forthe const segment name.3.3.9 Z80 OptionsOptions Z80Z80 (apply to z80, z180, r2k, r3ka,tlcs90, ez80_z80)--portmode=<Value>Z80!Options!--portmode=<Value> Determinate PORTI/O mode (<Value> is z80 or z180).--asm=<Value>Z80!Options!--asm=<Value> Define assembler name(<Value> is rgbds, sdasz80, isas or z80asm).--reserve-regs-iyZ80!Options!--reserve-regs-iy This option tellsthe compiler that it is not allowed to use register pair iy. Theoption can be useful for systems where iy is reserved for the OS.This option is incompatible with --fomit-frame-pointer.--oldrallocZ80!Options!--oldralloc Use old register allocator.The old register allocator is typically is faster than thecurrent one, but the current one generates better code. Thisdifferences are the most noticeable, when a high value for --max-allocs-per-node is used.--fno-omit-frame-pointerZ80!Options!--fno-omit-frame-pointerNever omit the frame pointer.3.3.10 GBZ80 OptionsOptions GBZ80GBZ80-bo <Num>GBZ80!Options!-bo <Num> Use code bank <Num>.-ba <Num>GBZ80!Options!-ba <Num> Use data bank <Num>.3.3.11 Intermediate Dump Options<subsec:Intermediate-Dump-Options>Options intermediate dumpIntermediate dump optionsThe following options are provided for the purpose ofretargetting and debugging the compiler. They provide a means todump the intermediate code (iCodeiCode) generated by the compilerin human readable form at various stages of the compilationprocess. More on iCodes see chapter [subsec:The-anatomy-of] ”Theanatomy of the compiler”.--dum-ast--dump-ast This option will cause the compiler to dumpthe abstract syntax tree to the econsole.--dump-i-code--dump-i-code Will dump iCodes at various stagesinto files named <source filename>.dump<stage>.--dump-graphs--dump-graphs Will dump internal representations asgraphviz .dot files. Depending on other options, this can includethe control-flow graph at lospre, insertion of bank selectioninstructions or register allocation and the conflict graph andtree-decomposition at register allocation.--fverbose-asm--no-gen-comments Include code generator andpeep-hole comments in the generated asm files.3.3.12 Redirecting output on Windows ShellsBy default SDCC writes its error messages to ”standard error”. Toforce all messages to ”standard output” use --use-stdout--use-stdout. Additionally, if you happen to have visual studio installed inyour windows machine, you can use it to compile your sourcesusing a custom build and the SDCC --vc--vc option. Something likethis should work:c:\sdcc\bin\sdcc.exe --vc --model-large -c $(InputPath)3.4 Environment variablesEnvironment variablesSDCC recognizes the following environment variables:SDCC_LEAVE_SIGNALSSDCC!Environment variables!SDCCLEAVESIGNALSSDCC installs a signal handlersignal handler to be able to deletetemporary files after an user break (^C) or an exception. If thisenvironment variable is set, SDCC won't install the signalhandler in order to be able to debug SDCC.TMP, TEMP, TMPDIRSDCC!Environment variables!TMP, TEMP, TMPDIRPath, where temporary files will be created. The order of thevariables is the search order. In a standard *nix environmentthese variables are not set, and there's no need to set them. OnWindows it's recommended to set one of them.SDCC_HOMESDCC!Environment variables!SDCCHOME Path, see section [subsec:Install-paths]” Install Paths”.SDCC_INCLUDESDCC!Environment variables!SDCCINCLUDE Path, seesection [subsec:Search-Paths] ”Search Paths”.SDCC_LIBSDCC!Environment variables!SDCCLIB Path, see section [subsec:Search-Paths]”Search Paths”..There are some more environment variables recognized by SDCC, butthese are mainly used for debugging purposes. They can change ordisappear very quickly, and will never be documented[footnote:if you are curious search in SDCC's sources for ”getenv”]SDCC!Environment variables!undocumented.3.5 SDCC Language ExtensionsSDCC supports some language extensions useful for embeddedsystems. These include named address spaces (see also section 5.1of the Embedded C standard). SDCC supports both intrinsic namedaddress spaces (which ones are supported depends on the targetarchitecture) and non-intrinsic named address spaces (defined bythe user using the keyword __addressmod, they are particularlyuseful with custom bank-switching hardware). Unlike the EmbeddedC standard, SDCC allows local variables to have an intrinsicnamed address space even when not explicitly declared as staticor extern.3.5.1 MCS51/DS390 intrinsic named address spacesSDCC supports the following MCS51-specific intrinsic addressspaces:<Graphics file: /home/sdcc-builder/build/sdcc-build/amd64-unknown-linux2.5.build/sdcc/doc/MCS51_named.svg>3.5.1.1 __datadata (mcs51, ds390 named address space) / __nearnear (named address space)This is the default (generic) address space for the Small Memorymodel. Variables in this address space will be allocated in thedirectly addressable portion of the internal RAM of a 8051, e.g.:__data unsigned char test_data;Writing 0x01 to this variable generates the assembly code:75*00 01 mov _test_data,#0x013.5.1.2 __xdataxdata (mcs51, ds390 named address space) / __farfar (named address space)Variables in this address space will be placed in the externalRAM. This is the default (generic) address space for the LargeMemory model, e.g.:__xdata unsigned char test_xdata;Writing 0x01 to this variable generates the assembly code:90s00r00 mov dptr,#_test_xdata74 01 mov a,#0x01F0 movx @dptr,a3.5.1.3 __idataidata (mcs51, ds390 named address space)Variables in this address space will be allocated into theindirectly addressable portion of the internal ram of a 8051,e.g.:__idata unsigned char test_idata;Writing 0x01 to this variable generates the assembly code:78r00 mov r0,#_test_idata76 01 mov @r0,#0x01Please note, the first 128 byte of idata physically access thesame RAM as the data memory. The original 8051 had 128 byte idatamemory, nowadays most devices have 256 byte idata memory. Thestackstack is located in idata memory (unless --xstack isspecified).3.5.1.4 __pdatapdata (mcs51, ds390 named address space)Paged xdata access is just as straightforward as using the otheraddressing modes of a 8051. It is typically located at the startof xdata and has a maximum size of 256 bytes. The followingexample writes 0x01 to the pdata variable. Please note, pdataaccess physically accesses xdata memory. The high byte of theaddress is determined by port P2 P2 (mcs51 sfr)(or in case ofsome 8051 variants by a separate Special Function Register, seesection [subsec:MCS51-variants]). This is the default (generic)address space for the Medium Memory model, e.g.:__pdata unsigned char test_pdata;Writing 0x01 to this variable generates the assembly code:78r00 mov r0,#_test_pdata74 01 mov a,#0x01F2 movx @r0,aIf the --xstack--xstack option is used the pdata memory area isfollowed by the xstack memory area and the sum of their sizes islimited to 256 bytes.3.5.1.5 __codecode'Variables' in this address space will be placed in the codememory:__code unsigned char test_code;Read access to this variable generates the assembly code:90s00r6F mov dptr,#_test_codeE4 clr a93 movc a,@a+dptrchar indexed arrays of characters in code memory can be accessedefficiently:__code char test_array[] = {'c','h','e','a','p'};Read access to this array using an 8-bit unsigned index generatesthe assembly code:E5*00 mov a,_index90s00r41 mov dptr,#_test_array93 movc a,@a+dptr3.5.1.6 __bitbitThis is a data-type and an address space. When a variable isdeclared as a bit, it is allocated into the bit addressablememory of 8051, e.g.:__bit test_bit;Writing 1 to this variable generates the assembly code:D2*00 setb _test_bitThe bit addressable memory consists of 128 bits which are locatedfrom 0x20 to 0x2f in data memory.Apart from this 8051 specific intrinsic named address space mostarchitectures support ANSI-C bit-fieldsbit-fields[footnote:Not really meant as examples, but nevertheless showing whatbit-fields are about: device/include/mc68hc908qy.h andsupport/regression/tests/bitfields.c]. In accordance with ISO/IEC 9899 bits and bitfields without anexplicit signed modifier are implemented as unsigned.3.5.1.7 __sfrsfr / __sfr16sfr16 / __sfr32sfr32 / __sbitsbitLike the __bit keyword, __sfr / __sfr16 / __sfr32 / __sbitsignify both a data-type and named address space, they are usedto describe the special function registers and special __bitvariables of a 8051, eg:__sfr __atat (0x80) P0; /* special function register P0 atlocation 0x80 *//* 16 bit special function register combination for timer 0with the high byte at location 0x8C and the low byte atlocation 0x8A */__sfr16 __at (0x8C8A) TMR0;__sbit __atat (0xd7) CY; /* CY (Carry FlagFlagsCarry flag) */Special function registers which are located on an addressdividable by 8 are bit-addressable, an __sbit addresses aspecific bit within these sfr.16 Bit and 32 bit special function register combinations whichrequire a certain access order are better not declared using__sfr16 or __sfr32. Although SDCC usually accesses them LeastSignificant Byte (LSB) first, this is not guaranteed.Please note, if you use a header file which was written foranother compiler then the __sfr / __sfr16 / __sfr32 / __sbitintrinsic named address spaces will most likely be notcompatible. Specifically the syntax sfr P0 = 0x80; is compiledwithout warning by SDCC to an assignment of 0x80 to a variablecalled P0. Nevertheless with the file compiler.hcompiler.h (include file)it is possible to write header filesHeader filesInclude fileswhich can be shared among different compilers (see section [sec:Porting-code-to-other-compilers]).3.5.1.8 PointersPointer to MCS51/DS390 intrinsic named addressspacesSDCC allows (via language extensions) pointers to explicitlypoint to any of the named address spacesMemory model of the 8051.In addition to the explicit pointers, the compiler uses (bydefault) generic pointers which can be used to point to any ofthe memory spaces.Pointer declaration examples:/* pointer physically in internal ram pointing to object inexternal ram */__xdata unsigned char * __data p;/* pointer physically in external ram pointing to object ininternal ram */__data unsigned char * __xdata p;/* pointer physically in code rom pointing to data in xdata space*/__xdata unsigned char * __code p;/* pointer physically in code space pointing to data in codespace */__code unsigned char * __code p;/* generic pointer physically located in xdata space */unsigned char * __xdata p;/* generic pointer physically located in default memory space */unsigned char * p;/* the following is a function pointerfunction pointer physicallylocated in data space */char (* __data fp)(void);Well you get the idea.All unqualified pointers are treated as 3-byte (4-byte for theds390) generic pointers.The highest order byte of the generic pointers contains the dataspace information. Assembler support routines are called wheneverdata is stored or retrieved using generic pointers. These areuseful for developing reusable libraryLibraries routines.Explicitly specifying the pointerPointer type will generate themost efficient code.3.5.1.9 Notes on MCS51 memoryMCS51 memory layoutThe 8051 family of microcontrollers have a minimum of 128 bytesof internal RAM memory which is structured as follows:- Bytes 00-1F - 32 bytes to hold up to 4 banks of the registersR0 to R7,- Bytes 20-2F - 16 bytes to hold 128 bitbit variables and,- Bytes 30-7F - 80 bytes for general purpose use.Additionally some members of the MCS51 family may have up to 128bytes of additional, indirectly addressable, internal RAM memory(__idataidata (mcs51, ds390 named address space)). Furthermore,some chips may have some built in external memory (__xdataxdata (mcs51, ds390 named address space)) which should not be confused with the internal, directlyaddressable RAM memory (__datadata (mcs51, ds390 named address space)). Sometimes this built in __xdata memory has to be activatedbefore using it (you can probably find this information on thedatasheet of the microcontroller your are using, see also section[subsec:MCS51-Startup-Code] Startup-Code).Normally SDCC will only use the first bankregister bank (mcs51, ds390)of registers (register bank 0), but it is possible to specifythat other banks of registers (keyword __using using (mcs51, ds390 register bank)) should be used for example in interruptinterruptinterruptroutines. By default, the compiler will place the stack after thelast byte of allocated memory for variables. For example, if thefirst 2 banks of registers are used, and only four bytes are usedfor data variables, it will position the base of the internalstack at address 20 (0x14). This implies that as the stackstackgrows, it will use up the remaining register banks, and the 16bytes used by the 128 bit variables, and 80 bytes for generalpurpose use. If any bit variables are used, the data variableswill be placed in unused register banks and after the byteholding the last bit variable. For example, if register banks 0and 1 are used, and there are 9 bit variables (two bytes used),data variables will be placed starting from address 0x10 to 0x20and continue at address 0x22. You can also use --data-loc--data-loc <Value>to specify the start address of the data and --iram-size--iram-size <Value>to specify the size of the total internal RAM (data+idata).By default the 8051 linker will place the stack after the lastbyte of (i)data variables. Option --stack-loc--stack-loc <Value>allows you to specify the start of the stack, i.e. you couldstart it after any data in the general purpose area. If yourmicrocontroller has additional indirectly addressable internalRAM (idata) you can place the stack on it. You may also need touse --xdata-loc--xdata-loc<Value> to set the start address of theexternal RAM (xdata) and --xram-size--xram-size <Value> tospecify its size. Same goes for the code memory, using --code-loc--code-loc <Value>and --code-size--code-size <Value>. If in doubt, don't specifyany options and see if the resulting memory layout isappropriate, then you can adjust it.The linker generates two files with memory allocationinformation. The first, with extension .map<file>.map shows allthe variables and segments. The second with extension .mem<file>.memshows the final memory layout. The linker will complain eitherif memory segments overlap, there is not enough memory, or thereis not enough space for stack. If you get any linking warningsand/or errors related to stack or segments allocation, take alook at either the .map or .mem files to find out what theproblem is. The .mem file may even suggest a solution to theproblem.3.5.2 Z80/Z180/eZ80 intrinsic named address spaces3.5.2.1 __sfrsfr (in/out to 8-bit addresses)The Z80Z80 family has separate address spaces for memory andinput/output memory. I/O memoryI/O memory (Z80, Z180)Z80!I/O memoryZ180!I/O memory is accessed with special instructions, e.g.:__sfr __at 0x78 IoPort; /* define a var in I/O space at 78hcalled IoPort */Writing 0x01 to this variable generates the assembly code:3E 01 ld a,#0x01D3 78 out (_IoPort),a3.5.2.2 __banked __sfrsfr (in/out to 16-bit addresses)The keyword __banked is used to support 16 bit addresses in I/Omemory e.g.:__sfr __banked __atat 0x123 IoPort;Writing 0x01 to this variable generates the assembly code:01 23 01 ld bc,#_IoPort3E 01 ld a,#0x01ED 79 out (c),a3.5.2.3 __sfrsfr (in0/out0 to 8 bit addresses on Z180Z180/HD64180HD64180 (see Z180))The compiler option --portmodeZ180!Options!--portmode=180 (80)and a compiler #pragma portmodeZ180!Pragmas!pragma portmode z180(z80) is used to turn on (off) the Z180/HD64180 port addressinginstructions in0/out0 instead of in/out. If you include the filez180.h this will be set automatically.3.5.3 HC08/S08 intrinsic named address spaces3.5.3.1 __datadata (hc08 named address space)Variables int the address space __data resides in the first 256bytes of memory (the direct page). The HC08HC08 is most efficientat accessing variables (especially pointers) stored here.3.5.3.2 __xdataxdata (hc08 named address space)Variables in the address space__xdata can reside anywhere inmemory. This is the default (generic address space).3.5.4 PDK14/PDK15 intrinsic named address spaces3.5.4.1 __sfrsfrThe Padauk family has separate address spaces for memory andinput/output memory. I/O memory is accessed with specialinstructions, e.g.:__sfr __at 0x18 gpcc; /* define a var in I/O space at 18h calledgpcc */3.5.4.2 __sfr16sfr16The Padauk family has a 16-bit timer accessed with specialinstructions.3.5.5 Non-intrinsic named address spacesNon-intrinsic named address spacesSDCC supports user-defined non-intrinsic named address spaces. Sofar SDCC only supports them for bank-switching. You need to havea function that switches to the desired memory bank and declare acorresponding named address space:void setb0(void); // The function that sets the currently activememory bank to b0void setb1(void); // The function that sets the currently activememory bank to b1__addressmodaddressmod setb0 spaceb0; // Declare a named addressspace called spaceb0 that uses setb0()__addressmod setb1 spaceb1; // Declare a named address spacecalled spaceb1 that uses setb1()spaceb0 int x; // An int in address space spaceb0spaceb1 int *y; // A pointer to an int in address space spaceb1spaceb0 int *spaceb1 z; // A pointer in address space spaceb1that points to an int in address space spaceb0Non-intrinsic named address spaces for data in ROM are declaredusing the const keyword:void setb0(void); // The function that sets the currently activememory bank to b0void setb1(void); // The function that sets the currently activememory bank to b1__addressmodaddressmod setb0 const spaceb0; // Declare a namedaddress space called spaceb0 that uses setb0() and resides in ROM__addressmod setb1 spaceb1; // Declare a named address spacecalled spaceb1 that uses setb1() and resides in RAMconst spaceb0 int x = 42; // An int in address space spaceb0spaceb1 int *y; // A pointer to an int in address space spaceb1const spaceb0 int *spaceb1 z; // A pointer in address spacespaceb1 that points to a constant int in address space spaceb0Variables in non-intrinsic named address spaces will be placed inareas of the same name (this can be used for the placement ofnamed address spaces in memory by the linker).SDCC will automatically insert calls to the correspondingfunction before accessing the variable. SDCC inserts the minimumpossible number calls to the bank selection functions. SeePhilipp Klaus Krause, ”Optimal Placement of Bank SelectionInstructions in Polynomial Time” for details on how this works.3.5.6 Absolute AddressingAbsolute addressingData items can be assigned an absolute address with the __atat<address> keyword, which can also be used in addition to a namedaddress space, e.g.:__xdata __at (0x7ffe) unsigned int chksum;In the above example the variable chksum will be located at0x7ffe and 0x7fff of the external ram. The compiler does notreserve any space for variables declared in this way[margin:!] (they are implemented with an equate in the assembler). Thus itis left to the programmer to make sure there are no overlaps withother variables that are declared without the absolute address.The assembler listing file (.lst<file>.lst) and the linker outputfiles (.rst<file>.rst) and (.map<file>.map) are good places tolook for such overlaps.If however you provide an initializerVariable initializationactual memory allocation will take place and overlaps will bedetected by the linker. E.g.:__code __at (0x7ff0) char Id[5] = ”SDCC”;In the above example the variable Id will be located from 0x7ff0to 0x7ff4 in code memory.In case of memory mapped I/O devices the keyword volatile has tobe used to tell the compiler that accesses might not be removed:volatilevolatile __xdataxdata (mcs51, ds390 named address space)__atat (0x8000) unsigned char PORTA_8255;For some architectures (mcs51) array accesses are more efficientif an (xdata/far) arrayAligned array starts at a block (256 byte)boundaryblock boundary (section [subsec:A-Step-by Assembler Introduction]has an example).Absolute addresses can be specified for variables in all namedaddress spaces, e.g.:__bitbit __atat (0x02) bvar;The above example will allocate the variable at offset 0x02 inthe bit-addressable space. There is no real advantage toassigning absolute addresses to variables in this manner, unlessyou want strict control over all the variables allocated. Onepossible use would be to write hardware portable code. Forexample, if you have a routine that uses one or more of themicrocontroller I/O pins, and such pins are different for twodifferent hardwares, you can declare the I/O pins in your routineusing:extern volatilevolatile __bit MOSI; /* master out, slave in */extern volatile __bit MISO; /* master in, slave out */extern volatile __bit MCLK; /* master clock *//* Input and Output of a byte on a 3-wire serial bus.If needed adapt polarity of clock, polarity of data and bitorder*/unsigned char spi_io(unsigned char out_byte){unsigned char i=8;do {MOSI = out_byte & 0x80;out_byte <<= 1;MCLK = 1;/* __asm nop __endasm; */ /* for slow peripherals*/if(MISO)out_byte += 1;MCLK = 0;} while(--i);return out_byte;}Then, someplace in the code for the first hardware you would use__bit __atat (0x80) MOSI; /* I/O port 0, bit 0 */__bit __at (0x81) MISO; /* I/O port 0, bit 1 */__bit __at (0x82) MCLK; /* I/O port 0, bit 2 */Similarly, for the second hardware you would use__bit __at (0x83) MOSI; /* I/O port 0, bit 3 */__bit __at (0x91) MISO; /* I/O port 1, bit 1 */__bitbit __at (0x92) MCLK; /* I/O port 1, bit 2 */and you can use the same hardware dependent routine withoutchanges, as for example in a library. This is somehow similar tosbit, but only one absolute address has to be specified in thewhole project.3.5.7 Preserved register specificationSDCC allows to specify preserved registers in functiondeclarations, to enable further optimizations on calls tofunctions implemented in assembler. Example for the Z80architecture specifying that a function will preserve registerpairs bc and iy:void f(void) __preserves_regs(b, c, iyl, iyh);3.5.8 Binary constantsBinary constantsSDCC supports the use of binary constants, such as 0b01100010.This feature is only enabled when the compiler is invoked using --std-sdccxx.3.5.9 Returning voidSDCC allows functions to return expressions of type void. Thisfeature is only enabled when the compiler is invoked using --std-sdccxx.3.5.10 Omitting promotion on arguments of vararg function (doesnot apply to pdk14, pdk15)Arguments to vararg functions are not promoted when explicitlycast. This feature is only enabled when the compiler is invokedusing --std-sdccxx. This breaks compability with the C standards,so linking code compiled with --std-sdccxx with code compiledusing --std-cxx can result in failing programs when arguments tovararg functions are explicitly cast.3.6 ParametersParametersfunction parameter and Local Variableslocal variables<sec:Parameters-and-Local-Variables>Automatic (local) variables and parameters to functions areplaced on the stack for most targets. For MCS51/DS390/HC08/S08they can either be placed on the stack or in data-space. Thedefault action of the compiler is to place these variables in theinternal RAM (for small model) or external RAM (for medium orlarge model). This in fact makes them similar to staticstatic soby default functions are non-reentrantreentrant.They can be placed on the stackstack by using the --stack-auto--stack-autooption, by using #pragma stackautopragma stackauto or by usingthe __reentrantreentrant keyword in the function declaration,e.g.:unsigned char foo(char i) __reentrant{...}Since stack space on 8051 is limited, the __reentrant keyword orthe --stack-auto option should be used sparingly. Note that thereentrant keyword just means that the parameters & localvariables will be allocated to the stack, it does not mean thatthe function is register bankregister bank (mcs51, ds390)independent.Local variableslocal variables can be assigned intrinsic namedaddress spaces and absoluteAbsolute addressing addresses, e.g.:unsigned char foo(__xdata int parm){__xdata unsigned char i;__bit bvar;__data __atat (0x31) unsigned char j;...}In the above example the parameterfunction parameter parm and thevariable i will be allocated in the external ram, bvar in bitaddressable space and j in internal ram. When compiled with --stack-auto or when a function is declared as reentrant thisshould only be done for static variables.It is however allowed to use bit parameters in reentrantfunctions and also non-static local bit variables are supported.Efficient use is limited to 8 semi-bitregisters in bit space.They are pushed and popped to stackstack as a single byte justlike the normal registers.3.7 Overlaying<subsec:Overlaying>OverlayingFor non-reentrantreentrant functions SDCC will try to reduceinternal ram space usage by overlaying parameters and localvariables of a function (if possible). Parameters and localvariableslocal variables of a function will be allocated to anoverlayable segment if the function has no other function callsand the function is non-reentrant and the memory modelMemory modelis small. If an explicit intrinsic named address spaceintrinsic named address spaceis specified for a local variable, it will NOT be overlaid.Note that the compiler (not the linkage editor) makes thedecision for overlaying the data items. Functions that are calledfrom an interrupt service routine[margin:!] should be preceded by a #pragma nooverlaypragma nooverlay ifthey are not reentrant.Also note that the compiler does not do any processing of inlineassembler code, so the compiler might incorrectly assign localvariables and parameters of a function into the overlay segmentif the inline assembler code calls other c-functions that mightuse the overlay. In that case the #pragma nooverlay should beused.Parameters and local variables of functions that contain 16 or 32bit multiplicationMultiplication or divisionDivision will NOT beoverlaid since these are implemented using external functions,e.g.:#pragma save#pragma nooverlaypragma nooverlayvoid set_error(unsigned char errcd){P3 = errcd;}#pragma restorevoid some_isr () __interruptinterrupt (2){...set_error(10);...}In the above example the parameter errcd for the functionset_error would be assigned to the overlayable segment if the#pragma nooverlay was not present, this could cause unpredictableruntime behaviour when called from an interrupt service routine.The #pragma nooverlay ensures that the parameters and localvariables for the function are NOT overlaid.3.8 Interrupt Service Routines<subsec:Interrupt-Service-Routines>3.8.1 General InformationSDCC allows interrupt service routines to be coded in C, withsome extended keywords.void timer_isr (void) __interrupt (1) __using (1){...}The optional number following the __interruptinterruptinterruptkeyword is the interrupt number this routine will service. Whenpresent, the compiler will insert a call to this routine in theinterrupt vector tableinterrupt vector table for the interruptnumber specified. If you have multiple source files in yourproject, interrupt service routines can be present in any ofthem, but a prototype of the isr MUST be present or included inthe file that contains the function main. The optional (8051specific) keyword __usingusing (mcs51, ds390 register bank) canbe used to tell the compiler to use the specified register bankwhen generating code for this function.Interrupt service routines open the door for some veryinteresting bugs:3.8.1.1 <subsec:Common-interrupt-pitfall-volatile>Commoninterrupt pitfall: variable not declared volatileIf an interrupt service routine changes variables which areaccessed by other functions these variables have to be declaredvolatilevolatile. See http://en.wikipedia.org/wiki/Volatile_variable.3.8.1.2 <subsec:Common-interrupt-pitfall-non-atomic>Commoninterrupt pitfall: non-atomic accessIf the access to these variables is not atomicatomic (i.e. theprocessor needs more than one instruction for the access andcould be interrupted while accessing the variable) the interruptmust be disabled during the access to avoid inconsistent data.Access to 16 or 32 bit variables is obviously not atomic on 8 bitCPUs and should be protected by disabling interrupts. You're notautomatically on the safe side if you use 8 bit variables though.We need an example here: f.e. on the 8051 the harmless looking ”flags |= 0x80;” is not atomic if flags resides in xdata. Setting ”flags |= 0x40;” from within an interrupt routine might get lostif the interrupt occurs at the wrong time. ”counter += 8;” is notatomic on the 8051 even if counter is located in data memory.Bugs like these are hard to reproduce and can cause a lot oftrouble.3.8.1.3 <subsec:Common-interrupt-pitfall-stack-overflow>Commoninterrupt pitfall: stack overflowThe return address and the registers used in the interruptservice routine are saved on the stackstack so there must besufficient stack space. If there isn't variables or registers (oreven the return address itself) will be corrupted. This stackoverflowstack overflow is most likely to happen if the interruptoccurs during the ”deepest” subroutine when the stack is alreadyin use for f.e. many return addresses.3.8.1.4 <subsec:Common-interrupt-pitfall-non-reentrant>Commoninterrupt pitfall: use of non-reentrant functionsA special note here, integer multiplicative operators andfloating-pointFloating point support operations might beimplemented using external support routines, depending on thetarget architecture. If an interrupt service routine needs to doany of these operations on a target where functions arenon-reentrant by default, then the support routines (as mentionedin a following section) will have to be recompiled using the --stack-auto--stack-auto option and the source file will need tobe compiled using the --int-long-reent--int-long-reent compileroption.Note, the type promotiontype promotion required by ANSI C cancause 16 bit routines to be used[margin:!] without the programmer being aware of it. See f.e. the cast(unsigned char)(tail-1) within the if clause in section [subsec:A-Step-by Assembler Introduction].Calling other functions from an interrupt service routine on atarget where functions are non-reentrant by default is notrecommended, avoid it if possible. Note that when some functionis called from an interrupt service routine it should be precededby a #pragma nooverlaypragma nooverlay if it is not reentrant.Furthermore non-reentrant functions should not be called from themain program while the interrupt service routine might be active.They also must not be called from low priority interrupt serviceroutines while a high priority interrupt service routine might beactive. You could use semaphores or make the function critical ifall parameters are passed in registers.Also see section [subsec:Overlaying] about Overlaying andsection [subsec:Functions-using-private-banks] about Functionsusing private register banks.3.8.2 MCS51/DS390 Interrupt Service RoutinesInterruptinterrupt numbers and the corresponding address &descriptions for the Standard 8051/8052 are listed below. SDCCwill automatically adjust the interrupt vector table to themaximum interrupt number specified.+--------------+-----------------+----------------+| Interrupt # | Description | Vector Address |+--------------+-----------------+----------------++--------------+-----------------+----------------+| 0 | External 0 | 0x0003 |+--------------+-----------------+----------------+| 1 | Timer 0 | 0x000b |+--------------+-----------------+----------------+| 2 | External 1 | 0x0013 |+--------------+-----------------+----------------+| 3 | Timer 1 | 0x001b |+--------------+-----------------+----------------+| 4 | Serial | 0x0023 |+--------------+-----------------+----------------+| 5 | Timer 2 (8052) | 0x002b |+--------------+-----------------+----------------+| ... | | ... |+--------------+-----------------+----------------+| n | | 0x0003 + 8*n |+--------------+-----------------+----------------+If the interrupt service routine is defined without __usingusing (mcs51, ds390 register bank)using (mcs51, ds390 register bank) a register bank or withregister bank 0 (__using 0), the compiler will save the registersused by itself on the stack upon entry and restore them at exit,however if such an interrupt service routine calls anotherfunction then the entire register bank will be saved on thestack. This scheme may be advantageous for small interruptservice routines which have low register usage.If the interrupt service routine is defined to be using aspecific register bank then only a, b, dptr & psw are saved andrestored, if such an interrupt service routine calls anotherfunction (using another register bank) then the entire registerbank of the called function will be saved on the stackstack. Thisscheme is recommended for larger interrupt service routines.3.8.3 HC08HC08 Interrupt Service RoutinesSince the number of interruptsHC08!interrupt available is chipspecific and the interrupt vector table always ends at the lastbyte of memory, the interrupt numbers corresponds to theinterrupt vectors in reverse order of address. For example,interrupt 1 will use the interrupt vector at 0xfffc, interrupt 2will use the interrupt vector at 0xfffa, and so on. However,interrupt 0 (the reset vector at 0xfffe) is not redefinable inthis way; instead see section [subsec:MCS51-Startup-Code] fordetails on customizing startup.3.8.4 Z80 and Z180 Interrupt Service RoutinesThe Z80Z80 uses several different methods for determining thecorrect interruptZ80!interrupt vector depending on the hardwareimplementation. Therefore, SDCC does not attempt to generate aninterrupt vector table.By default, SDCC generates code for a maskable interrupt, whichuses a RETI instruction to return from the interrupt. To write aninterrupt handler for the non-maskable interrupt, which needs aRETN instruction instead, leave out the interrupt number:void nmi_isr (void) __critical __interrupt{...}Since interrupts on the Z80 and Z180 are level-triggered (exceptfor the NMI), interruptible interrupt handlers should only beused where hardware acknowledge is available.+--------------------------------------+-----------------------------------------+------------------------------------------------------------+| Type | Syntax | Behaviour |+--------------------------------------+-----------------------------------------+------------------------------------------------------------++--------------------------------------+-----------------------------------------+------------------------------------------------------------+| Interruptible interrupt handler | void f(void) __interrupt | Interrupt handler can be interrupted by further interrupts |+------------------------------------------------------------++--------------------------------------+-----------------------------------------+------------------------------------------------------------+| Non-interruptible interrupt handler | void f(void) __critical __interrupt(0) | Interrupt handler can be interrupted by NMI only |+--------------------------------------+-----------------------------------------+------------------------------------------------------------+| NMI handler | void f(void) __critical __interrupt | Interrupt handler can be interrupted by NMI only |+--------------------------------------+-----------------------------------------+------------------------------------------------------------+3.8.5 Rabbit 2000, 3000, 3000A and 4000 Interrupt ServiceRoutinesSDCC does not attempt to generate an interrupt vector table.+--------------------------------------+-----------------------------------------+------------------------------------------------------------------------------+| Type | Syntax | Behaviour |+--------------------------------------+-----------------------------------------+------------------------------------------------------------------------------++--------------------------------------+-----------------------------------------+------------------------------------------------------------------------------+| Interruptible interrupt handler | void f(void) __interrupt | Interrupt handler can be interrupted by further interrupts ofsame priority |+------------------------------------------------------------------------------++--------------------------------------+-----------------------------------------+------------------------------------------------------------------------------+| Non-interruptible interrupt handler | void f(void) __critical __interrupt(0) | Interrupt handler can be interrupted by interrupts of higherpriority only |+--------------------------------------+-----------------------------------------+------------------------------------------------------------------------------+3.8.6 GBZ80 and TLCS-90 Interrupt Service RoutinesSDCC does not attempt to generate an interrupt vector table.+--------------------------------------+-----------------------------------------+---------------------------------------------------------------+| Type | Syntax | Behaviour |+--------------------------------------+-----------------------------------------+---------------------------------------------------------------++--------------------------------------+-----------------------------------------+---------------------------------------------------------------+| Interruptible interrupt handler | void f(void) __interrupt | Interrupt handler can be interrupted by further interrupts |+---------------------------------------------------------------++--------------------------------------+-----------------------------------------+---------------------------------------------------------------+| Non-interruptible interrupt handler | void f(void) __critical __interrupt(0) | Interrupt handler cannot be interrupted by further interrupts |+--------------------------------------+-----------------------------------------+---------------------------------------------------------------+3.8.7 STM8 Interrupt Service RoutinesThe STM8 interrupt table contains 31 entries: Reset (used by SDCCfor program startup), trap and user interrupts 0 to 29. Where thekeyword __interruptinterrupt is used for normal user interrupts,the __trap keyword is used for the trap handler:void handler (void) __trap{...}3.9 Enabling and Disabling Interrupts3.9.1 Critical Functions and Critical StatementsA special keyword may be associated with a block or a functiondeclaring it as __critical. SDCC will generate code to disableall interruptsinterrupt upon entry to a critical function andrestore the interrupt enable to the previous state beforereturning. Nesting critical functions will need one additionalbyte on the stackstack for each call.int foo () __criticalcriticalcritical{......}The critical attribute maybe used with other attributes likereentrant.The keyword __critical may also be used to disable interruptsmore locally:__critical{ i++; }More than one statement could have been included in the block.3.9.2 Enabling and Disabling Interrupts directlyInterruptsinterrupt can also be disabled and enabled directly(8051):EA = 0; or: EA_SAVE = EA;... EA = 0;EA = 1; ...EA = EA_SAVE;On other architectures which have separate opcodes for enablingand disabling interrupts you might want to make use of defineswith inline assemblyAssembler routines (HC08HC08!interrupt):#define CLI __asmasm cli __endasmendasm;#define SEI __asm sei __endasm;or for SDCC version 3.2.0 or newer:#define CLI asm (”cli”);#define SEI asm (”sei”);Note: it is sometimes sufficient to disable only a specificinterrupt source like f.e. a timer or serial interrupt bymanipulating an interrupt maskinterrupt mask register.Usually the time during which interrupts are disabled should bekept as short as possible. This minimizes both interrupt latencyinterrupt latency(the time between the occurrence of the interrupt and theexecution of the first code in the interrupt routine) andinterrupt jitterinterrupt jitter (the difference between theshortest and the longest interrupt latency). These really aresomething different, f.e. a serial interrupt has to be servedbefore its buffer overruns so it cares for the maximum interruptlatency, whereas it does not care about jitter. On a loudspeakerdriven via a digital to analog converter which is fed by aninterrupt a latency of a few milliseconds might be tolerable,whereas a much smaller jitter will be very audible.You can re-enable interrupts within an interrupt routine and onsome architectures you can make use of two (or more) levels ofinterrupt prioritiesinterrupt priority. On some architectureswhich don't support interrupt priorities these can be implementedby manipulating the interrupt mask and re-enabling interruptswithin the interrupt routine. Check there is sufficient space onthe stackstack and don't add complexity unless you have to.3.9.3 Semaphoresemaphore locking (mcs51/ds390)Some architectures (mcs51/ds390) have an atomicatomic bit testand clear instruction. These type of instructions are typicallyused in preemptive multitasking systems, where a routine f.e.claims the use of a data structure ('acquires a locklock on it'),makes some modifications and then releases the lock when the datastructure is consistent again. The instruction may also be usedif interrupt and non-interrupt code have to compete for aresource. With the atomic bit test and clear instructioninterruptsinterrupt don't have to be disabled for the lockingoperation.SDCC generates this instruction if the source follows thispattern:volatilevolatile bit resource_is_free;if (resource_is_free){resource_is_free=0;...resource_is_free=1;}Note, mcs51 and ds390 support only an atomicatomic bit test andclear instruction (as opposed to atomic bit test and set).3.10 Functions using private register banks<subsec:Functions-using-private-banks>(mcs51/ds390)Some architectures have support for quickly changing registersets. SDCC supports this feature with the __usingusing (mcs51, ds390 register bank)using (mcs51, ds390 register bank) attribute (which tells thecompiler to use a register bankregister bank (mcs51, ds390) otherthan the default bank zero). It should only be applied tointerruptinterrupt functions (see footnote below). This will inmost circumstances make the generated ISR code more efficientsince it will not have to save registers on the stack.The __using attribute will have no effect on the generated codefor a non-interrupt function (but may occasionally be usefulanyway[footnote:possible exception: if a function is called ONLY from 'interrupt'functions using a particular bank, it can be declared with thesame 'using' attribute as the calling 'interrupt' functions. Forinstance, if you have several ISRs using bank one, and all ofthem call memcpy(), it might make sense to create a specializedversion of memcpy() 'using 1', since this would prevent the ISRfrom having to save bank zero to the stack on entry and switch tobank zero before calling the function]).(pending: Note, nowadays the __using attribute has an effect onthe generated code for a non-interrupt function.)An interrupt function using a non-zero bank will assume that itcan trash that register bank, and will not save it. Sincehigh-priority interruptsinterruptsinterrupt priority caninterrupt low-priority ones on the 8051 and friends, this meansthat if a high-priority ISR using a particular bank occurs whileprocessing a low-priority ISR using the same bank, terrible andbad things can happen. To prevent this, no single register bankshould be used by both a high priority and a low priority ISR.This is probably most easily done by having all high priorityISRs use one bank and all low priority ISRs use another. If youhave an ISR which can change priority at runtime, you're on yourown: I suggest using the default bank zero and taking the smallperformance hit.It is most efficient if your ISR calls no other functions. Ifyour ISR must call other functions, it is most efficient if thosefunctions use the same bank as the ISR (see note 1 below); thenext best is if the called functions use bank zero. It is veryinefficient to call a function using a different, non-zero bankfrom an ISR.3.11 Inline Assembler Code<sec:Inline-Assembler-Code>Assembler routines3.11.1 Inline Assembler Code FormatsSDCC supports two formats for inline assembler code definition:3.11.1.1 Old __asm ... __endasm; FormatMost of inline assembler code examples in this manual use the oldinline assembler code format, but the new format could be usedequivalently.Example:__asm; This is a commentlabel:nop__endasm;3.11.1.2 New __asm__ (”inline_assembler_code”) FormatThe __asm__ inline assembler code format was introduced in SDCCversion 3.2.0.Example:__asm__ (”; This is a comment\nlabel:\n\tnop”);3.11.2 A Step by Step Introduction<subsec:A-Step-by Assembler Introduction>Starting from a small snippet of c-code this example shows forthe MCS51 how to use inline assembly, access variables, afunction parameter and an array in xdata memory. The example usesan MCS51 here but is easily adapted for other architectures. Thisis a buffer routine which should be optimized:unsigned char __farfar (named address space) __atat(0x7f00)buf[0x100];Aligned arrayunsigned char head, tail; /* if interruptsinterruptare involved seesection [subsec:Common-interrupt-pitfall-volatile]about volatile */void to_buffer( unsigned char c ){if( head != (unsigned char)(tail-1) ) /* cast needed to avoidpromotionpromotion to signed inttype promotion to integer */[margin:!]buf[ head++ ] = c; /* access to a 256 bytealigned array */}If the code snippet (assume it is saved in buffer.c) is compiledwith SDCC then a corresponding buffer.asm file is generated. Wedefine a new function to_buffer_asm() in file buffer.c in whichwe cut and paste the generated code, removing unwanted commentsand some ':'. Then add ”__asm” and ”__endasm;”[footnote:Note, that the single underscore form (_asm and _endasm) are notC99 compatible, and for C99 compatibility, the double-underscoreform (__asm and __endasm) has to be used. The latter is also usedin the library functions.] to the beginning and the end of the function body:/* With a cut and paste from the .asm file, we have something tostart with.The function is not yet OK! (registers aren't saved) */void to_buffer_asm( unsigned char c ){__asmasmmov r2,dpl;buffer.c if( head != (unsigned char)(tail-1) ) /* cast neededto avoid promotionpromotion to signed inttype promotion tointeger */mov a,_taildec amov r3,amov a,_headcjne a,ar3,00106$ret00106$:;buffer.c buf[ head++ ] = c; /* access to a 256 byte alignedarray */Aligned arraymov r3,_headinc _headmov dpl,r3mov dph,#(_buf >> 8)mov a,r2movx @dptr,a00103$:ret__endasmendasm;}The new file buffer.c should compile with only one warning aboutthe unreferenced function argument 'c'. Now we hand-optimize theassembly code and insert an #define USE_ASSEMBLY (1) and finallyhave:unsigned char __far __at(0x7f00) buf[0x100];unsigned char head, tail;#define USE_ASSEMBLY (1)#if !USE_ASSEMBLYvoid to_buffer( unsigned char c ){if( head != (unsigned char)(tail-1) )buf[ head++ ] = c;}#elsevoid to_buffer( unsigned char c ){c; // to avoid warning: unreferenced function argument__asmasm; save used registers here.; If we were still using r2,r3 we would have to push themhere.; if( head != (unsigned char)(tail-1) )mov a,_taildec axrl a,_head; we could do an ANL a,#0x0f here to use a smaller buffer(see below)jz t_b_end$;; buf[ head++ ] = c;mov a,dpl ; dpl holds lower byte of functionargumentmov dpl,_head ; buf is 0x100 byte aligned so head canbe used directlymov dph,#(_buf>>8)movx @dptr,ainc _head; we could do an ANL _head,#0x0f here to use a smallerbuffer (see above)t_b_end$:; restore used registers here__endasmendasm;}#endifThe inline assembler code can contain any valid code understoodby the assembler, this includes any assembler directives andcomment lines. The assembler does not like some characters like':' or ''' in comments. You'll find an 100+ pages assemblermanual in sdcc/sdas/doc/asmlnk.txtsdas (sdasgb, sdas6808, sdas8051, sdasz80)Assembler documentation or online at http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/sdas/doc/asmlnk.txt.The compiler does not do any validation of the code within the__asmasm ... __endasmendasm; keyword pair. Specifically it willnot know which registers are used and thus registerpushing/poppingpush/pop has to be done manually.It is required that each assembly instruction be placed on aseparate line. This is also recommended for labels (as theexample shows). This is especially important to note when theinline assembler is placed in a C preprocessor macro as thepreprocessor will normally put all replacing code on a singleline. Only when the macro has each assembly instruction on asingle line that ends with a line continuation character will itbe placed as separate lines in the resulting .asm file.#define DELAY \__asm \nop \nop \__endasmWhen the --peep-asm--peep-asm command line option is used, theinline assembler code will be passed through the peepholeoptimizerPeephole optimizer. There are only a few (if any) caseswhere this option makes sense, it might cause some unexpectedchanges in the inline assembler code. Please go through thepeephole optimizer rules defined in file peeph.def before usingthis option.3.11.3 Naked Functions<subsec:Naked-Functions>Naked functionsA special keyword may be associated with a function declaring itas __nakednakednaked. The _naked function modifier attributeprevents the compiler from generating prologuefunction prologueand epiloguefunction epilogue code for that function. This meansthat the user is entirely responsible for such things as savingany registers that may need to be preserved, selecting the properregister bank, generating the return instruction at the end, etc.Practically, this means that the contents of the function must bewritten in inline assembler. This is particularly useful forinterrupt functions, which can have a large (and oftenunnecessary) prologue/epilogue. For example, compare the codegenerated by these two functions:volatilevolatile data unsigned char counter;void simpleInterrupt(void) __interruptinterruptinterrupt (1){counter++;}void nakedInterrupt(void) __interrupt (2) __naked{__asmasminc _counter ; does not change flags, no need to savepswreti ; MUST explicitly include ret or reti in _nakedfunction.__endasmendasm;}For an 8051 target, the generated simpleInterrupt looks like:Note, this is an outdated example, recent versions of SDCCgeneratethe same code for simpleInterrupt() and nakedInterrupt()!_simpleInterrupt:push accpush bpush dplpush dphpush pswmov psw,#0x00inc _counterpop pswpop dphpop dplpop bpop accretiwhereas nakedInterrupt looks like:_nakedInterrupt:inc _counter ; does not change flags, no need to save pswreti ; MUST explicitly include ret or reti in_naked functionThe related directive #pragma excludepragma exclude allows a morefine grained control over pushing & poppingpush/pop theregisters.While there is nothing preventing you from writing C code insidea _naked function, there are many ways to shoot yourself in thefoot doing this, and it is recommended that you stick to inlineassembler.3.11.4 Use of Labels within Inline AssemblerSDCC allows the use of in-line assembler with a few restrictionsregarding labels. All labels defined within inline assembler codehave to be of the form nnnnn$ where nnnnn is a number less than100 (which implies a limit of utmost 100 inline assembler labelsper function).[footnote:This is a slightly more stringent rule than absolutely necessary,but stays always on the safe side. Labels in the form of nnnnn$are local labels in the assembler, locality of which is confinedwithin two labels of the standard form. The compiler uses thesame form for labels within a function (but starting fromnnnnn=00100); and places always a standard label at the beginningof a function, thus limiting the locality of labels within thescope of the function. So, if the inline assembler part would beembedded into C-code, an improperly placed non-local label in theassembler would break up the reference space for labels createdby the compiler for the C-code, leading to an assembling error.The numeric part of local labels does not need to have 5 digits(although this is the form of labels output by the compiler), anyvalid integer will do. Please refer to the assemblersdocumentation for further details.]__asmasmmov b,#1000001$:djnz b,00001$__endasmendasm ;Inline assembler code cannot reference any C-labels, however itcan reference labelsLabels defined by the inline assembler, e.g.:foo() {/* some c code */__asm; some assembler codeljmp 0003$__endasm;/* some more c code */clabel: /* inline assembler cannot reference this label */ [footnote:Here, the C-label clabel is translated by the compiler into alocal label, so the locality of labels within the function is notbroken.]__asm0003$: ;label (can be referenced by inline assembler only)__endasmendasm ;/* some more c code */}In other words inline assembly code can access labels defined ininline assembly within the scope of the function. The same goesthe other way, i.e. labels defines in inline assembly can not beaccessed by C statements.3.12 Support routines for integer multiplicative operatorsDepending on the target architecture, some integer multiplicativeoperators might be implemented by support routines. These supportroutines exist in portable C versions to facilitate porting toother MCUs, although depending on the target, assembler routinesmight be used instead. The following files contain some of thedescribed routines, all of them can be found in<installdir>/share/sdcc/lib.+---------------+------------------------------------------+| Function | Description |+---------------+------------------------------------------++---------------+------------------------------------------+| _mulint.c | 16 bit multiplication |+---------------+------------------------------------------+| _divsint.c | signed 16 bit division (calls _divuint) |+---------------+------------------------------------------+| _divuint.c | unsigned 16 bit division |+---------------+------------------------------------------+| _modsint.c | signed 16 bit modulus (calls _moduint) |+---------------+------------------------------------------+| _moduint.c | unsigned 16 bit modulus |+---------------+------------------------------------------+| _mullong.c | 32 bit multiplication |+---------------+------------------------------------------+| _divslong.c | signed 32 division (calls _divulong) |+---------------+------------------------------------------+| _divulong.c | unsigned 32 division |+---------------+------------------------------------------+| _modslong.c | signed 32 bit modulus (calls _modulong) |+---------------+------------------------------------------+| _modulong.c | unsigned 32 bit modulus |+---------------+------------------------------------------+In the mcs51, ds390, hc08, s08, pic14 and pic16 backends they areby default compiled as non-reentrantreentrant; when targeting onof these architectures, interruptinterrupt service routinesshould not do any of the above operations. If this is unavoidablethen the above routines will need to be compiled with the --stack-auto--stack-auto option, after which the source programwill have to be compiled with --int-long-reent--int-long-reentoption. Notice that you don't have to call these routinesdirectly. The compiler will use them automatically every time aninteger operation is required.3.13 Floating Point SupportFloating point supportSDCC supports (single precision 4 bytes) floating point numbers;the format is somewhat similar to IEEE, but it is not IEEE; inparticular, denormalized floating -point numbers are notsupported. The floating point support routines are derived fromgcc's floatlib.c and consist of the following routines:+--------------+------------------------------------------------+| Function | Description |+--------------+------------------------------------------------++--------------+------------------------------------------------+| _fsadd.c | add floating point numbers |+--------------+------------------------------------------------+| _fssub.c | subtract floating point numbers |+--------------+------------------------------------------------+| _fsdiv.c | divide floating point numbers |+--------------+------------------------------------------------+| _fsmul.c | multiply floating point numbers |+--------------+------------------------------------------------+| _fs2uchar.c | convert floating point to unsigned char |+--------------+------------------------------------------------+| _fs2char.c | convert floating point to signed char |+--------------+------------------------------------------------+| _fs2uint.c | convert floating point to unsigned int |+--------------+------------------------------------------------+| _fs2int.c | convert floating point to signed int |+--------------+------------------------------------------------+| _fs2ulong.c | convert floating point to unsigned long |+--------------+------------------------------------------------+| _fs2long.c | convert floating point to signed long |+--------------+------------------------------------------------+| _uchar2fs.c | convert unsigned char to floating point |+--------------+------------------------------------------------+| _char2fs.c | convert char to floating point number |+--------------+------------------------------------------------+| _uint2fs.c | convert unsigned int to floating point |+--------------+------------------------------------------------+| _int2fs.c | convert int to floating point numbers |+--------------+------------------------------------------------+| _ulong2fs.c | convert unsigned long to floating point number |+--------------+------------------------------------------------+| _long2fs.c | convert long to floating point number |+--------------+------------------------------------------------+3.14 Library RoutinesLibraries<pending: this is messy and incomplete - a little moreinformation is athttp://sdcc.sourceforge.net/wiki/index.php/List_of_the_SDCC_library>3.14.1 Compiler support routines (_gptrget, _mulint etc.)3.14.2 Stdclib functions (puts, printf, strcat etc.)3.14.2.1 <stdio.h>getchar(), putchar()<stdio.h>As usual on embedded systems you have to provide yourown getchar()getchar() and putchar()putchar()printf()!putchar()routines. SDCC does not know whether the system connects to aserial line with or without handshake, LCD, keyboard or otherdevice. And whether a lf to crlf conversion within putchar() isintended. You'll find examples for serial routines f.e. insdcc/device/lib. For the mcs51 this minimalistic pollingputchar() routine might be a start:int putchar (int c) {while (!TI) /* assumes UART is initialized */;TI = 0;SBUF = c;return c;}printf()The default printf()printf() implementation in printf_large.cdoes not support floatFloating point support (except on ds390),only <NO FLOAT><NO FLOAT>printf()!floating point support will beprinted instead of the value. To enable floating point output,recompile it with the option -DUSE_FLOATS=1USEFLOATS on thecommand line. Use --model-large--model-large for the mcs51 port,since this uses a lot of memory. To enable float support for thepic16 targets, see [subsec:pic16Libraries].If you're short on code memory you might want to useprintf_small()printf()!printfsmall() instead of printf(). For themcs51 there additionally are assembly versions printf_tiny()printf()!printftiny() (mcs51)(subset of printf using less than 270 bytes) and printf_fast()printf()!printffast() (mcs51)and printf_fast_f()printf()!printffastf() (mcs51)(floating-point aware version of printf_fast) which should fitthe requirements of many embedded systems (printf_fast() can becustomized by unsetting #defines to not support long variablesand field widths). Be sure to use only one of these printfoptions within a project.Feature matrix of different printf options on mcs51.+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| mcs51 | printfprintf() | printf USE_FLOATS=1 | printf_small | printf_fast | printf_fast_f | printf_tiny |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| filename | printf_large.c | printf_large.c | printfl.c | printf_fast.c | printf_fast_f.c | printf_tiny.c |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| ”Hello World” sizesmall / large | 1.7k / 2.4k | 4.3k / 5.6k | 1.2k / 1.8k | 1.3k / 1.3k | 1.9k / 1.9k | 0.44k / 0.44k |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| code sizesmall / large | 1.4k / 2.0k | 2.8k / 3.7k | 0.45k / 0.47k (+ _ltoa) | 1.2k / 1.2k | 1.6k / 1.6k | 0.26k / 0.26k |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| formats | cdiopsux | cdfiopsux | cdosx | cdsux | cdfsux | cdsux |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| long (32 bit) support | x | x | x | x | x | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| byte arguments on stack | b | b | - | - | - | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| float formatFloating point support | - | %f | - | - | %f[footnote:Range limited to +/- 4294967040, precision limited to 8 digitspast decimal] | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| float formats %e %g | - | - | - | - | - | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| field width | x | x | - | x | x | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| string speed[footnote:Execution time of printf("%s%c%s%c%c%c", "Hello", ' ', "World",'!', '\r', '\n'); standard 8051 @ 22.1184 MHz, empty putchar()],small / large | 1.52 / 2.59 ms | 1.53 / 2.62 ms | 0.92 / 0.93 ms | 0.45 / 0.45 ms | 0.46 / 0.46 ms | 0.45 / 0.45 ms |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| int speed[footnote:Execution time of printf("%d", -12345); standard 8051 @ 22.1184MHz, empty putchar()],small / large | 3.01 / 3.61 ms | 3.01 / 3.61 ms | 3.51 / 18.13 ms | 0.22 / 0.22 ms | 0.23 / 0.23 ms | 0.25 / 0.25 ms[footnote:printf_tiny integer speed is data dependent, worst case is 0.33ms] |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| long speed[footnote:Execution time of printf("%ld", -123456789); standard 8051 @22.1184 MHz, empty putchar()],small / large | 5.37 / 6.31 ms | 5.37 / 6.31 ms | 8.71 / 40.65 ms | 0.40 / 0.40 ms | 0.40 / 0.40 ms | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+| float speed[footnote:Execution time of printf("%.3f", -12345.678); standard 8051 @22.1184 MHz, empty putchar()],small / large | - | 7.49 / 22.47 ms | - | - | 1.04 / 1.04 ms | - |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------+----------------------+--------------------------+-----------------+---------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------+3.14.2.2 <malloc.h>malloc.hAs of SDCC 2.6.2 you no longer need to call an initializationroutine before using dynamic memory allocationdynamic memory allocation (malloc)and a default heapheap (malloc) space of 1024 bytes is providedfor malloc to allocate memory from. If you need a different heapsize you need to recompile _heap.c with the required size definedin HEAP_SIZE. It is recommended to make a copy of this file intoyour project directory and compile it there with:sdcc -c _heap.c -D HEAP_SIZE=2048And then link it with:sdcc main.rel _heap.rel3.14.3 Math functions (sinf, powf, sqrtf etc.)3.14.3.1 <math.h>See definitions in file <math.h>.3.14.4 Other librariesLibrariesLibraries included in SDCC should have a license atleast as liberal as the GPLv2+LEGPLv2+LE. Exception are picdevice libraries and header files which are derived fromMicrochip header (.inc) and linker script (.lkr) files. Microchiprequires that "The header files should state that they are onlyto be used with authentic Microchip devices" which makes themincompatible with GPL.If you have ported some library or want to share experience aboutsome code which f.e. falls into any of these categories Busses (I^{\textrm{2}}C, CAN, Ethernet, Profibus, Modbus, USB, SPI, JTAG ...), Media(IDE, Memory cards, eeprom, flash...), En-/Decryption, Remotedebugging, Realtime kernel, Keyboard, LCD, RTC, FPGA, PID thenthe sdcc-user mailing list http://sourceforge.net/p/sdcc/mailman/sdcc-user/would certainly like to hear about it.Programmers coding for embedded systems are not especially famousfor being enthusiastic, so don't expect a big hurray but as themailing list is searchable these references are very valuable.Let's help to create a climate where information is shared.3.15 Memory Models3.15.1 MCS51 Memory ModelsMemory modelMCS51 memory model3.15.1.1 Small, Medium, Large and HugeSDCC allows four memory models for MCS51 code, small, medium,large and huge. Modules compiled with different memory modelsshould never be combined together or the results would beunpredictable. The library routines supplied with the compilerare compiled for all models (however, the libraries for–stack-auto are compiled for the small and large models only).The compiled library modules are contained in separatedirectories as small, medium, large and huge so that you can linkto the appropriate set.When the medium, large or huge model is used all variablesdeclared without specifying an intrinsic named address space willbe allocated into the external ram, this includes all parametersand local variables (for non-reentrantreentrant functions).Medium model uses pdata and large and huge models use xdata. Whenthe small model is used variables without an explicitly specifiedintrinsic named address space are allocated in the internal ram.The huge model compiles all functions as banked[subsec:Bankswitching]and is otherwise equal to large for now. All other modelscompile the functions without bankswitching by default.Judicious usage of the processor specific intrinsic named addressspacesintrinsic named address space and the 'reentrant' functiontype will yield much more efficient code, than using the largemodel. Several optimizations are disabled when the program iscompiled using the large model, it is therefore recommended thatthe small model be used unless absolutely required.3.15.1.2 External Stack<subsec:External-Stack>stackExternal stack (mcs51)The external stack (--xstack option--xstack) is located in pdatapdata (mcs51, ds390 named address space)memory (usually at the start of the external ram segment) anduses all unused space in pdata (max. 256 bytes). When --xstackoption is used to compile the program, the parameters and localvariableslocal variables of all reentrant functions are allocatedin this area. This option is provided for programs with largestack space requirements. When used with the --stack-auto--stack-autooption, all parameters and local variables are allocated on theexternal stack (note: support libraries will need to berecompiled with the same options. There is a predefined target inthe library makefile).The compiler outputs the higher order address byte of theexternal ram segment into port P2P2 (mcs51 sfr) (see also section[subsec:MCS51-variants]), therefore when using the External Stackoption, this port may not be used by the application program.3.15.2 DS390 Memory ModelMemory modelDS390 memory modelThe only model supported is Flat 24Flat 24 (DS390 memory model).This generates code for the 24 bit contiguous addressing mode ofthe Dallas DS80C390 part. In this mode, up to four meg ofexternal RAM or code space can be directly addressed. See thedata sheets at www.dalsemi.com for further information on thispart.Note that the compiler does not generate any code to place theprocessor into 24 bit mode (although tinibios in the ds390libraries will do that for you). If you don't use tinibiosTinibios (DS390), the boot loader or similar code must ensure that the processoris in 24 bit contiguous addressing mode before calling the SDCCstartup code.Like the --model-large option, variables will by default beplaced into the XDATA segment.Segments may be placed anywhere in the 4 meg address space usingthe usual --*-loc options. Note that if any segments are locatedabove 64K, the -r flag must be passed to the linker to generatethe proper segment relocations, and the Intel HEX output formatmust be used. The -r flag can be passed to the linker by usingthe option -Wl-r on the SDCC command line. However, currently thelinker can not handle code segments > 64k.3.15.3 STM8 Memory ModelsMemory modelSTM8 memory modelsSDCC implements two memory models for the STM8: medium (default)and large. Modules compiled with different memory models shouldnever be combined together. The library routines supplied withthe compiler are compiled for all models.In the medium model the address space is 16 bits for both objectsand functions, allowing for a memory space of 64 KB. Since theSTM8 typically has Flash starting at 0x8000, this means that onlyup to 32 KB of Flash can be used (most STM8 devices don't havemore than 32 KB of Flash).In the large memory model, the address space is 16 bits forobjects and 24 bits for functions. Since the STM8 typically hasflash starting at 0x8000, this means that up to 32 KB of flashcan be used for constant data, while the whole Flash can be usedfor functions. Code generated for the large model is slightlybigger and slower and needs slightly more stack space than codegenerated for the medium model.3.16 Pragmas<sec:Pragmas>PragmasPragmas are used to turn on and/or off certain compiler options.Some of them are closely related to corresponding command-lineoptions (see section [sec:Command-Line-Options]).Pragmas should be placed before and/or after a function, placingpragmas inside a function body could have unpredictable results.SDCC supports the following #pragma directives:• savepragma save - this will save most current options to thesave/restore stack. See #pragma restore.• restorepragma restore - will restore saved options from thelast save. saves & restores can be nested. SDCC uses asave/restore stack: save pushes current options to the stack,restore pulls current options from the stack. See #pragma save.• callee_savespragma calleesavesfunction prologuefunction1[,function2[,function3...]] <ite:callee_saves-function1[,function2[,function3...]]-->- The compiler by default uses a caller saves convention forregister saving across function calls, however this can causeunnecessary register pushing and poppingpush/pop when callingsmall functions from larger functions. This option can be usedto switch off the register saving convention for the functionnames specified. The compiler will not save registers whencalling these functions, extra code need to be manuallyinserted at the entry and exit for these functions to save andrestore the registers used by these functions, this canSUBSTANTIALLY reduce code and improve run time performance ofthe generated code. In the future the compiler (with interprocedural analysis) may be able to determine the appropriatescheme to use for each function call. If --callee-saves commandline option is used (see page [lyx:--callee-saves-function1[,function2][,function3]...]), the function names specified in #pragma callee_savespragma calleesavesis appended to the list of functions specified in the commandline.• excludepragma exclude none | {acc[,b[,dpl[,dph[,bits]]]]} - Theexclude pragma disables the generation of pairs of push/poppush/popinstructions in Interruptinterrupt Service Routines. Thedirective should be placed immediately before the ISR functiondefinition and it affects ALL ISR functions following it. Toenable the normal register saving for ISR functions use #pragmaexclude nonepragma exclude. See also the related keyword__nakednakednaked.• less_pedanticpedanticpragma lesspedantic<ite:less_pedantic> -the compiler will not warn you anymore for obvious mistakes,you're on your own now ;-(. See also the command line option --less-pedantic [lyx:--less-pedantic].More specifically, the following warnings will be disabled:comparison is always [true/false] due to limited range of datatype (94); overflow in implicit constant conversion (158); [the(in)famous] conditional flow changed by optimizer: so saidEVELYN the modified DOG (110); function '[function name]' mustreturn value (59).Furthermore, warnings of less importance (of PEDANTIC and INFOwarning level) are disabled, too, namely: constant value '[]',out of range (81); [left/right] shifting more than size ofobject changed to zero (116); unreachable code (126); integeroverflow in expression (165); unmatched #pragma save and#pragma restore (170); comparison of 'signed char' with'unsigned char' requires promotion to int (185); ISO C90 doesnot support flexible array members (187); extended stack by[number] bytes for compiler temp(s) :in function '[functionname]': [] (114); function '[function name]', # edges [number], # nodes [number] , cyclomatic complexity [number] (121).• disable_warning <nnnn>pragma disablewarning - the compiler willnot warn you anymore about warning number <nnnn>.• nogcsepragma nogcse - will stop global common subexpressionelimination.• noinductionpragma noinduction - will stop loop inductionoptimizations.• noinvariantpragma noinvariant - will not do loop invariantoptimizations. For more details see Loop Invariants in section[subsec:Loop-Optimizations].• noivpragma noiv - Do not generate interruptinterrupt vectortableinterrupt vector table entries for all ISR functionsdefined after the pragma. This is useful in cases where theinterrupt vector table must be defined manually, or when thereis a secondary, manually defined interrupt vector table (e.g.for the autovector feature of the Cypress EZ-USB FX2). Moreelegantly this can be achieved by omitting the optionalinterrupt number after the __interrupt keyword, see section [subsec:Interrupt-Service-Routines]about interrupts.• noloopreversepragma noloopreverse - Will not do loop reversaloptimization• nooverlaypragma nooverlay - the compiler will not overlay theparameters and local variables of a function.• stackautopragma stackauto- See option --stack-auto--stack-autoand section [sec:Parameters-and-Local-Variables] Parameters andLocal Variables.• opt_code_speed pragma optcodespeed- The compiler will optimizecode generation towards fast code, possibly at the expense ofcode size.• opt_code_size pragma optcodesize- The compiler will optimizecode generation towards compact code, possibly at the expenseof code speed.• opt_code_balanced pragma optcodebalanced- The compiler willattempt to generate code that is both compact and fast, as longas meeting one goal is not a detriment to the other (this isthe default).• std_sdcc89 pragma stdsdcc89- Generally follow the C89 standard,but allow SDCC features that conflict with the standard.• std_c89 pragma stdc89- Follow the C89 standard and disable SDCCfeatures that conflict with the standard.• std_sdcc99 pragma stdsdcc99- Generally follow the C99 standard,but allow SDCC features that conflict with the standard.• std_c99 pragma stdc99- Follow the C99 standard and disable SDCCfeatures that conflict with the standard.• codeseg <name>pragma codeseg- Use this name (max. 8 characters)for the code segment. See option --codeseg.• constseg <name>pragma constseg- Use this name (max. 8characters) for the const segment. See option --constseg.The preprocessorPreprocessor SDCPPsdcpp (preprocessor) supportsthe following #pragma directives:• pedantic_parse_numberpedanticpragma pedanticparsenumber (+ | -)<ite:pedantic_parse_number>- Pedantic parse numbers so thatsituations like 0xfe-LO_B(3) are parsed properly and the macroLO_B(3) gets expanded. Default is off. See also the --pedantic-parse-number command line option [lyx:-pedantic-parse-number].Below is an example on how to use this pragma. Note: thisfunctionality is not in conformance with standard!#pragma pedantic_parse_number +pragma pedanticparsenumber#define LO_B(x) ((x) & 0xff)unsigned char foo(void){unsigned char c=0xfe-LO_B(3);return c;}• preproc_asmpragma preprocasm (+ | -) - switch the __asm__endasm block preprocessing on / off. Default is on. Below isan example on how to use this pragma.#pragma preproc_asm -pragma preprocasm/* 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 isdisabledNOP__endasm;...}The pragma preproc_asm should not be used to define multilines ofassembly code (even if it supports it), since this behavior isonly a side effect of sdcpp __asm __endasm implementation incombination with pragma preproc_asm and is not in conformancewith the C standard. This behavior might be changed in the futuresdcpp versions. To define multilines of assembly code you have toinclude each assembly line into it's own __asm __endasm block.Below is an example for multiline assembly defines.#define Nop __asm \nop \__endasm#define ThreeNops Nop; \Nop; \Nopvoid foo (void){...ThreeNops;...}• sdcc_hashpragma sdcchash (+ | -) - Allow "naked" hash in macrodefinition, 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 +pragma sdcchash#define ROMCALL(x) \mov R6_B3, #(x & 0xff) \mov R7_B3, #((x >> 8) & 0xff) \lcall __romcall...__asmROMCALL(72)__endasm;...Some of the pragmas are intended to be used to turn-on or offcertain optimizations which might cause the compiler to generateextra stack and/or data space to store compiler generatedtemporary variables. This usually happens in large functions.Pragma directives should be used as shown in the followingexample, they are used to control options and optimizations for agiven function.#pragma savepragma save /* save the current settings */#pragma nogcsepragma nogcse /* turnoff global subexpressionelimination */#pragma noinductionpragma noinduction /* turn off inductionoptimizations */int foo (){.../* large code */...}#pragma restorepragma restore /* turn the optimizations back on*/The compiler will generate a warning message when extra space isallocated. It is strongly recommended that the save and restorepragmas be used when changing options for a function.3.17 Defines Created by the CompilerBesides defines from the C standards, the compiler creates thefollowing #definesdefinesDefines created by the compiler:+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| #define | Description |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------++--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCCSDCC!Defines!__SDCC (version macro)version macro | Always defined. Version number string (e.g. SDCC_3_2_0 for sdcc3.2.0). |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| SDCC | OBSOLETE. WILL BE REMOVED IN THE FUTURE. CURRENTLY Only definedfor the mcs51 backend (and only if –std-cXX is not used). Thismacro has been available since SDCC 2.5.6 and is the versionnumber as an int (ex. 256). PLEASE USE OTHER VERSION MACROSINSTEAD! |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_mcs51SDCC!Defines!__SDCCmcs51 or __SDCC_ds390SDCC!Defines!__SDCCds390or __SDCC_z80SDCC!Defines!__SDCCz80, etc. | depending on the model used (e.g.: -mds390). Older versions usedSDCC_mcs51, etc instead. |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_STACK_AUTOSDCC!Defines!SDCCSTACKAUTO | when --stack-auto option is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_MODEL_SMALLSDCC!Defines!SDCCMODELSMALL | when --model-small is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_MODEL_MEDIUMSDCC!Defines!SDCCMODELMEDIUM | when --model-medium is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_MODEL_LARGESDCC!Defines!SDCCMODELLARGE | when --model-large is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_MODEL_HUGESDCC!Defines!SDCCMODELLARGE | when --model-huge is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_USE_XSTACKSDCC!Defines!SDCCUSEXSTACK | when --xstack option is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_STACK_TENBITSDCC!Defines!SDCCSTACKTENBIT (ds390) | when -mds390 is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_MODEL_FLAT24SDCC!Defines!SDCCMODELFLAT24 (ds390) | when -mds390 is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_VERSION_MAJOR | Always defined. SDCC major version number. E.g. 3 for SDCC 3.5.0 |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_VERSION_MINOR | Always defined. SDCC minor version number. E.g. 5 for SDCC 3.5.0 |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_VERSION_PATCH | Always defined. SDCC patchlevel version number. E.g. 0 for SDCC3.5.0 |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_REVISIONSDCC!Defines!SDCCREVISION (svn revision number) | Always defined. SDCC svn revision number. Older versions of sdccused SDCC_REVISION instead. |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| SDCC_PARMS_IN_BANK1SDCC!Defines!SDCCPARMSINBANK1 | when --parms-in-bank1 is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_ALL_CALLEE_SAVESSDCC!Defines!SDCCALLCALLEESAVES | when --all-callee-saves is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_FLOAT_REENTSDCC!Defines!SDCCFLOATREENT | when --float-reent is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| __SDCC_INT_LONG_REENTSDCC!Defines!SDCCINTLONGREENT | when --int-long-reent is used |+--------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+Notes on supported Processors4.1 MCS51 variants<subsec:MCS51-variants>MCS51 variantsMCS51 processors are available from many vendors and come in manydifferent flavours. While they might differ considerably inrespect to Special Function Registers the core MCS51 is usuallynot modified or is kept compatible.4.1.1 pdata access by SFRWith the upcome of devices with internal xdata and flash memorydevices using port P2P2 (mcs51 sfr) as dedicated I/O port isbecoming more popular. Switching the high byte for __pdatapdata (mcs51, ds390 named address space)access which was formerly done by port P2 is then achieved by aSpecial Function Registersfr. In well-established MCS51 traditionthe address of this sfr is where the chip designers decided toput it. Needless to say that they didn't agree on a common nameeither. So that the startup code can correctly initialize xdatavariables, you should define an sfr with the name _XPAGEXPAGE (mcs51)at the appropriate location if the default, port P2, is not usedfor this. Some examples are:__sfr __at (0x85) _XPAGE; /* Ramtron VRS51 family a.k.a. MPAGE */__sfr __at (0x92) _XPAGE; /* Cypress EZ-USB family, TexasInstruments (Chipcon) a.k.a. MPAGE */__sfr __at (0x91) _XPAGE; /* Infineon (Siemens) C500 familya.k.a. XPAGE */__sfr __at (0xaf) _XPAGE; /* some Silicon Labs (Cygnal) chipsa.k.a. EMI0CN */__sfr __at (0xaa) _XPAGE; /* some Silicon Labs (Cygnal) chipsa.k.a. EMI0CN */There are also devices without anything resembling _XPAGE, butluckily they usually have dual data-pointers. For these devices adifferent method can be used to correctly initialize xdatavariables. A default implementation is already in crtxinit.asmbut it needs to be assembled manually with DUAL_DPTR set to 1.For more exotic implementations further customizations may beneeded. See section [subsec:MCS51-Startup-Code] for otherpossibilities.4.1.2 Other Features available by SFRSome MCS51 variants offer features like Dual DPTRDPTR, multipleDPTR, decrementing DPTR, 16x16 Multiply. These are currently notused for the MCS51 port. If you absolutely need them you can fallback to inline assembly or submit a patch to SDCC.4.1.3 Bankswitching<subsec:Bankswitching>BankswitchingBankswitching (a.k.a. code bankingcode banking) is atechnique to increase the code space above the 64k limit of the8051.4.1.3.1 Hardware+---------+--------+-------+8000-FFFF | bank1 | bank2 | bank3 |+---------+--------+-------++---------0000-7FFF | common |+---------SiLabs C8051F120 exampleUsually the hardware uses some sfr (an output port or an internalsfr) to select a bank and put it in the banked area of the memorymap. The selected bank usually becomes active immediately uponassignment to this sfr and when running inside a bank it willswitch out this code it is currently running. Therefor you cannotjump or call directly from one bank to another and need to use aso-called trampoline in the common area. For SDCC an exampletrampoline is in crtbank.asm and you may need to change it toyour 8051 derivative or schematic. The presented code is writtenfor the C8051F120.When calling a banked function SDCC will put the LSB of thefunctions address in register R0, the MSB in R1 and the bank inR2 and then call this trampoline __sdcc_banked_call. The currentselected bank is saved on the stack, the new bank is selected andan indirect jump is made. When the banked function returns itjumps to __sdcc_banked_ret which restores the previous bank andreturns to the caller.4.1.3.2 SoftwareWhen writing banked software using SDCC you need to use somespecial keywords and options. You also need to take over a bit ofwork from the linker.To create a function that can be called from another bank itrequires the keyword __bankedbanked. The caller must see this inthe prototype of the callee and the callee needs it for a properreturn. Called functions within the same bank as the caller donot need the __banked keyword nor do functions in the commonarea. Beware: SDCC does not know or check if functions are in thesame bank. This is your responsibility!Normally all functions you write end up in the segment CSEG. Ifyou want a function explicitly to reside in the common area putit in segment HOME. This applies for instance to interruptservice routines as they should not be banked.Functions that need to be in a switched bank must be put in anamed segment. The name can be mostly anything up to eightcharacters (e.g. BANK1). To do this you either use --codesegBANK1 (See [lyx:-codeseg]) on the command line when compiling or#pragma codeseg BANK1 (See [sec:Pragmas]) at the top of the Csource file. The segment name always applies to the whole sourcefile and generated object so functions for different banks needto be defined in different source files.When linking your objects you need to tell the linker where toput your segments. To do this you use the following command lineoption to SDCC: -Wl-b BANK1=0x18000 (See [lyx:-Wl option]). Thissets the virtual start address of this segment. It sets thebanknumber to 0x01 and maps the bank to 0x8000 and up. The linkerwill not check for overflows, again this is your responsibility.4.1.4 MCS51/DS390 Startup Code<subsec:MCS51-Startup-Code>The compiler triggers the linker to link certain initializationmodules from the runtime libraryRuntime library calledcrt<something>. Only the necessary ones are linked, for instancecrtxstack.asm (GSINIT1, GSINIT5) is not linked unless the --xstack option is used. These modules are highly entangled by theuse of special segments/areas, but a common layout is shownbelow:(main.asm).area HOME (CODE)__interrupt_vect:ljmp __sdcc_gsinit_startup(crtstart.asm).area GSINIT0 (CODE)__sdcc_gsinit_startup::mov sp,#__start__stack - 1(crtxstack.asm).area GSINIT1 (CODE)__sdcc_init_xstack::; Need to initialize in GSINIT1 in case the user's__sdcc_external_startup uses the xstack.mov __XPAGE,#(__start__xstack >> 8)mov _spx,#__start__xstack(crtstart.asm).area GSINIT2 (CODE)lcall __sdcc_external_startupmov a,dpljz __sdcc_init_dataljmp __sdcc_program_startup__sdcc_init_data:(crtxinit.asm).area GSINIT3 (CODE)__mcs51_genXINIT::mov r1,#l_XINITmov a,r1orl a,#(l_XINIT >> 8)jz 00003$mov r2,#((l_XINIT+255) >> 8)mov dptr,#s_XINITmov r0,#s_XISEGmov __XPAGE,#(s_XISEG >> 8)00001$: clr amovc a,@a+dptrmovx @r0,ainc dptrinc r0cjne r0,#0,00002$inc __XPAGE00002$: djnz r1,00001$djnz r2,00001$mov __XPAGE,#0xFF00003$:(crtclear.asm).area GSINIT4 (CODE)__mcs51_genRAMCLEAR::clr amov r0,#(l_IRAM-1)00004$: mov @r0,adjnz r0,00004$; _mcs51_genRAMCLEAR() end(crtxclear.asm).area GSINIT4 (CODE)__mcs51_genXRAMCLEAR::mov r0,#l_PSEGmov a,r0orl a,#(l_PSEG >> 8)jz 00006$mov r1,#s_PSEGmov __XPAGE,#(s_PSEG >> 8)clr a00005$: movx @r1,ainc r1djnz r0,00005$00006$:mov r0,#l_XSEGmov a,r0orl a,#(l_XSEG >> 8)jz 00008$mov r1,#((l_XSEG + 255) >> 8)mov dptr,#s_XSEGclr a00007$: movx @dptr,ainc dptrdjnz r0,00007$djnz r1,00007$00008$:(crtxstack.asm).area GSINIT5 (CODE); Need to initialize in GSINIT5 because __mcs51_genXINIT modifies__XPAGE; and __mcs51_genRAMCLEAR modifies _spx.mov __XPAGE,#(__start__xstack >> 8)mov _spx,#__start__xstack(application modules).area GSINIT (CODE)(main.asm).area GSFINAL (CODE)ljmp __sdcc_program_startup;--------------------------------------------------------; Home;--------------------------------------------------------.area HOME (CODE).area CSEG (CODE)__sdcc_program_startup:lcall _main; return from main will lock upsjmp .One of these modules (crtstart.asm) contains a call to the Croutine _sdcc_external_startup()sdccexternalstartup() at thestart of the CODE area. This routine is also in the runtimelibraryRuntime library and returns 0 by default. If this routinereturns a non-zero value, the static & global variableinitialization will be skipped and the function main will beinvoked. Otherwise static & global variables will be initializedbefore the function main is invoked. You could add an_sdcc_external_startup() routine to your program to override thedefault if you need to setup hardware or perform some othercritical operation prior to static & global variableinitializationVariable initialization. On some mcs51 variants__xdataxdata (mcs51, ds390 named address space memory has to beexplicitly enabled before it can be accessed or if the watchdogwatchdogneeds to be disabled, this is the place to do it. The startupcode clears all internal data memory, 256 bytes by default, butfrom 0 to n-1 if --iram-size--iram-size <Value>n is used.(recommended for Chipcon CC1010).See also the compiler option --no-xinit-opt--no-xinit-opt andsection [subsec:MCS51-variants] about MCS51-variants.While these initialization modules are meant as generic startupcode there might be the need for customization. Let's assume thereturn value of _sdcc_external_startup() in crtstart.asm shouldnot be checked (or _sdcc_external_startup() should not be calledat all). The recommended way would be to copy crtstart.asm (f.e.fromhttp://svn.code.sf.net/p/sdcc/code/trunk/sdcc/device/lib/mcs51/crtstart.asm) into the source directory, adapt it there, then assemble itwith sdas8051 -plosgff[footnote:”-plosgff” are the assembler options used inhttp://sdcc.svn.sourceforge.net/viewvc/sdcc/trunk/sdcc/device/lib/mcs51/Makefile.in?view=markup] crtstart.asm and when linking your project explicitly specifycrtstart.rel. As a bonus a listing of the relocated object filecrtstart.rst is generated.4.1.5 Interfacing with Assembler CodeAssembler routines4.1.5.1 Global Registers used for Parameter PassingParameter passingThe compiler always uses the global registers DPL, DPHDPTR, DPH, DPLDPTR, BB (mcs51, ds390 register) and ACCACC (mcs51, ds390 register)to pass the first (non-bit) parameter to a function, and also topass the return value return valueof function; according to thefollowing scheme: one byte return value in DPL, two byte value inDPL (LSB) and DPH (MSB). three byte values (generic pointers) inDPH, DPL and B, and four byte values in DPH, DPL, B and ACC.Generic pointersgeneric pointer contain type of accessed memoryin B: 0x00 – xdata/far, 0x40 – idata/near – , 0x60 – pdata, 0x80– code.The second parameter onwards is either allocated on the stack(for reentrant routines or if --stack-auto is used) or indata/xdata memory (depending on the memory model).Bit parameters are passed in a virtual register called 'bits' inbit-addressable space for reentrant functions or allocateddirectly in bit memory otherwise.Functions (with two or more parameters or bit parameters) thatare called through function pointersfunction pointers musttherefor be reentrant so the compiler knows how to pass theparameters.4.1.5.2 Register usageUnless the called function is declared as _nakednaked, or the --callee-saves--callee-saves/--all-callee-saves command lineoption or the corresponding callee_saves pragma are used, thecaller will save the registers (R0-R7) around the call, so thecalled function can destroy they content freely.If the called function is not declared as _naked, the caller willswap register banks around the call, if caller and callee usedifferent register banks (having them defined by the __usingmodifier).The called function can also use DPL, DPH, B and ACC observingthat they are used for parameter/return value passing.4.1.5.3 Assembler Routine (non-reentrant)In the following examplereentrantAssembler routines (non-reentrant)the function c_func calls an assembler routine asm_func, whichtakes two parametersfunction parameter.extern int asm_func(unsigned char, unsigned char);int c_func (unsigned char i, unsigned char j){return asm_func(i,j);}int main(){return c_func(10,9);}The corresponding assembler function is:.globl _asm_func_PARM_2.globl _asm_func.area OSEG_asm_func_PARM_2:.ds 1.area CSEG_asm_func:mov a,dpladd a,_asm_func_PARM_2mov dpl,amov dphDPTR, DPH, DPL,#0x00retThe parameter naming convention is _<function_name>_PARM_<n>,where n is the parameter number starting from 1, and countingfrom the left. The first parameter is passed in DPH, DPL, B andACC according to the description above. The variable name for thesecond parameter will be _<function_name>_PARM_2.Assemble the assembler routine with the following command:sdas8051 -losg asmfunc.asmThen compile and link the assembler routine to the C source filewith the following command:sdcc cfunc.c asmfunc.rel4.1.5.4 Assembler Routine (reentrant)In this casereentrantAssembler routines (reentrant) the secondparameterfunction parameter onwards will be passed on the stack,the parameters are pushed from right to left i.e. before the callthe second leftmost parameter will be on the top of the stack(the leftmost parameter is passed in registers). Here is anexample:extern int asm_func(unsigned char, unsigned char, unsigned char)reentrant;int c_func (unsigned char i, unsigned char j, unsigned char k)reentrant{return asm_func(i,j,k);}int main(){return c_func(10,9,8);}The corresponding (unoptimized) assembler routine is:.globl _asm_func_asm_func:push _bpmov _bp,sp ;stack contains: _bp, return address, secondparameter, third parametermov r2,dplmov a,_bpadd a,#0xfd ;calculate pointer to the second parametermov r0,amov a,_bpadd a,#0xfc ;calculate pointer to the rightmostparametermov r1,amov a,@r0add a,@r1add a,r2 ;calculate the result (= sum of all threeparameters)mov dpl,a ;return value goes into dptr (cast into int)mov dph,#0x00mov sp,_bppop _bpretThe compiling and linking procedure remains the same, howevernote the extra entry & exit linkage required for the assemblercode, _bp is the stack frame pointer and is used to compute theoffset into the stack for parameters and local variables.4.2 DS400 portThe DS80C400DS80C400DS400 microcontroller has a rich set ofperipherals. In its built-in ROM library it includes functions toaccess some of the features, among them is a TCP stack with IP4and IP6 support. Library headers (currently in beta status) andother files are provided atftp://ftp.dalsemi.com/pub/tini/ds80c400/c_libraries/sdcc/index.html.4.3 The Z80, Z180, Rabbit 2000/3000, Rabbit 3000A, GBZ80, eZ80and TLCS-90 portsSDCC can target the Z80Z80, Z180, Rabbit 2000/3000, Rabbit 3000Aand LR35902, the Nintendo GameBoy's Z80-like gbz80gbz80 (GameBoy Z80).When a frame pointer is used, it resides in IX. Register A, B, C,D, E, H, L and IY are used as a temporary registers for holdingvariables. Return valuesZ80!return value for the Z80 port arestored in L (one byte), HL (two bytes), or DEHL (four bytes). Thegbz80 port use the same set of registers for the return values,but in a different order of significance: E (one byte), DE (twobytes), or HLDE (four bytes).When enabling optimizations using --opt-code size and asufficiently high value for --max-allocs-per-node sdcc typicallygenerates much better code for these architectures than manyother compilers. A comparison of compilers for these architecturecan be found at http://sdcc.sourceforge.net/wiki/index.php/Z80_code_size.4.3.1 Startup CodeOn the Z80Z80 the startup code is inserted by linking withcrt0.rel which is generated from sdcc/device/lib/z80/crt0.s. Ifyou need a different startup code you can use the compiler option--no-std-crt0--no-std-crt0 and provide your own crt0.rel. Whenusing a custom crt0.rel it needs to be listed first when linking.4.3.2 Complex instructionsThe Z80 and some derivatives support complex instructions, suchas ldir, cpir, ... . SDCC only emits these instructions forfunctions in the standard library. Thus, e.g. copying one arrayinto another is more efficient when using memcpy() than by usinga a user-written loop.Depending on the target, code generation options and theparameters to the call, SDCC emits ldir for memcpy(), ldir orlsidr for memset(), ldi for strcpy(), ldi for strncpy(). Otherlibrary functions use the complex instructions as well, but forthose, function calls are generated.4.3.3 Calling conventionsBy default, all parameters are passed on the stack,right-to-left. 8-bit return values are passed in l, 16-bit valuesin hl, 32-bit values in dehl. Except for the GBZ80, where 8-bitvalues are passed in e, 16-bit values in de, 32-bit values inhlde. Larger return values are passed in memory in a locationspecified by the caller through a hidden pointer argument.There are three other calling conventions supported, which can bespecified using the keywords __smallc, __z88dk_fastcall (not onGBZ80) and __z88dk_callee. They are primarily intended forcompability with libraries written for other compilers. For__z88dk_fastcall, there may be only one parameter of at most 32bits, which is passed the same way as the return value. For__z88dk_callee, parameters are passed on the stack, but the stackis not adjusted for the parameters after the call (thus thecallee has to do this instead). __z88dk_callee is currentlysupported on the caller side only. __z88dk_callee can be combinedwith __smallc.4.3.4 Small-C calling conventionFunctions declared as __smallc are called using the Small-Ccalling convention (passing arguments on-stack left-to-right, 1byte arguments are passed as 2 bytes, with the value in the lowerbyte). This way assembler routines originally written for Small-Cor code generated by Small-C can be called from SDCC. Currentlyvariable arguments are not yet supported (neither on the callernor on the callee side).4.3.5 Unsafe readsUsually, Z80-based systems (except for the Gameboy) have separateI/O and memory spaces, and any memory location can be readwithout side-effects. For such systems, the option–allow-unsafe-reads can be used to enable some extraoptimizations.4.4 The HC08 and S08 portsThe port to the Freescale/Motorola HC08HC08 and S08 does not yetgenerate code as compact as that generated by some non-freecompilers. A comparison of compilers for these architecture canbe found at http://sdcc.sourceforge.net/wiki/index.php/Hc08_code_size.4.4.1 Startup CodeThe HC08HC08 startup code follows the same scheme as the MCS51startup code.4.5 The STM8 port4.5.1 Calling conventionArguments are passed on the stack right-to-left. Return valuesare in a (8 bit), x (16 bit), xyl (24 bit), xy (32 bit) or use ahidden extra pointer parameter pointing to the location (anythingwider than 32 bit).4.6 The PIC14PIC14 portThe PIC14 port adds support for MicrochipMicrochip^{\text{TM}}PICPIC14^{\text{TM}} MCUs with 14 bit wide instructions. Thisport is not yet mature and still lacks many features. However, itcan work for simple code.Currently supported devices include:10F320, 10F322, 10LF320, 10LF32212F609, 12F615, 12F617, 12F629, 12F635, 12F675, 12F68312F75212HV75216C62, 16C63A, 16C65B16C71, 16C72, 16C73B, 16C74B16C432, 16C43316C554, 16C557, 16C55816C620, 16C620A, 16C621, 16C621A, 16C622, 16C622A16C710, 16C711, 16C715, 16C717, 16C745, 16C765, 16C770, 16C771,16C773, 16C774, 16C781, 16C78216C925, 16C92616CR73, 16CR74, 16CR76, 16CR7716CR620A16F72 ,16F73, 16F74, 16F76, 16F7716F84, 16F84A, 16F87, 16F8816F610, 16F616, 16F627, 16F627A, 16F628, 16F628A, 16F630, 16F631,16F636, 16F639, 16F648A16F676, 16F677, 16F684, 16F685, 16F687, 16F688, 16F689, 16F69016F707, 16F716, 16F720, 16F721, 16F722, 16F722A, 16F723, 16F723A,16F724, 16F726, 16F72716F737, 16F747, 16F753, 16F767, 16F777, 16F78516F818, 16F819, 16F870, 16F871, 16F872, 16F873, 16F873A, 16F874,16F874A, 16F876, 16F876A16F877, 16F877A, 16F882, 16F883, 16F884, 16F886, 16F88716F913, 16F914, 16F916, 16F917, 16F94616LF74, 16LF76, 16LF7716LF84, 16LF84A, 16LF87, 16LF8816LF627, 16LF627A, 16LF628, 16LF628A, 16LF648A16LF707, 16LF720, 16LF721, 16LF722, 16LF722A, 16LF723, 16LF723A,16LF724, 16LF726, 16LF72716LF747, 16LF767, 16LF77716LF818, 16LF819, 16LF870, 16LF871, 16LF872, 16LF873, 16LF873A,16LF874, 16LF874A16LF876, 16LF876A, 16LF877, 16LF877A16HV610, 16HV616, 16HV753, 16HV785Supported devices with enhanced cores:12F1501, 12F1571, 12F1572, 12F1612, 12F1822, 12F184012LF1501, 12LF1552, 12LF1571, 12LF1572, 12LF1612, 12LF1822,12LF1840, 12LF1840T39A, 12LF1840T48A16F1454, 16F1455, 16F1458, 16F145916F1503, 16F1507, 16F1508, 16F1509, 16F1512, 16F1513, 16F1516,16F1517, 16F1518, 16F151916F1526, 16F1527, 16F1574, 16F1575, 16F1578, 16F157916F1613, 16F1614, 16F1615, 16F1618, 16F161916F1703, 16F1704, 16F1705, 16F1707, 16F1708, 16F1709, 16F1713,16F1716, 16F1717, 16F1718, 16F171916F1764, 16F1765, 16F1768, 16F1769, 16F1773, 16F1776, 16F1777,16F1778, 16F177916F1782, 16F1783, 16F1784, 16F1786, 16F1787, 16F1788, 16F178916F1823, 16F1824, 16F1825, 16F1826, 16F1827, 16F1828, 16F1829,16F1829LIN, 16F184716F1933, 16F1934, 16F1936, 16F1937, 16F1938, 16F1939, 16F1946,16F194716F18313, 16F18323, 16F18324, 16F18325, 16F18344, 16F18345,16F18855, 16F1887516LF1454, 16LF1455, 16LF1458, 16LF145916LF1503, 16LF1507, 16LF1508, 16LF1509, 16LF1512, 16LF1513,16LF1516, 16LF1517, 16LF1518, 16LF1519,16LF1526, 16LF152716LF1554, 16LF1559, 16LF1566, 16LF1567, 16LF1574, 16LF1575,16LF1578, 16LF157916LF1613, 16LF1614, 16LF1615, 16LF1618, 16LF161916LF1703, 16LF1704, 16LF1705, 16LF1707, 16LF1708, 16LF1709,16LF1713, 16LF1716, 16LF1717, 16LF1718, 16LF171916LF1764, 16LF1765, 16LF1768, 16LF1769, 16LF1773, 16LF1776,16LF1777, 16LF1778, 16LF177916LF1782, 16LF1783, 16LF1784, 16LF1786, 16LF1787, 16LF1788,16LF1789,16LF1823, 16LF1824, 16LF1824T39A16LF1825, 16LF1826, 16LF1827, 16LF1828, 16LF1829, 16LF184716LF1902, 16LF1903, 16LF1904, 16LF1906, 16LF190716LF1933, 16LF1934, 16LF1936, 16LF1937, 16LF1938, 16LF1939,16LF1946, 16LF194716LF18313, 16LF18323, 16LF18324, 16LF18325, 16LF18344, 16LF1834516LF18855, 16LF18875An up-to-date list of currently supported devices can be obtainedvia sdcc -mpic14 -phelp foo.c (foo.c must exist...).4.6.1 PIC Code Pagescode page (pic14) and Memory BanksMemory bank (pic14)The linker organizes allocation for the code page and RAM banks.It does not have intimate knowledge of the code flow. It will putall the code section of a single .asm file into a single codepage. In order to make use of multiple code pages, separate asmfiles must be used. The compiler assigns all static functions ofa single .c file into the same code page.To get the best results, follow these guidelines:1. Make local functions static, as non static functions requirecode page selection overhead.Due to the way sdcc handles functions, place called functionsprior to calling functions in the file wherever possible:Otherwise sdcc will insert unnecessary pagesel directivesaround the call, believing that the called function isexternally defined.2. For devices that have multiple code pages it is more efficientto use the same number of files as pages: Use up to 4 separate.c files for the 16F877, but only 2 files for the 16F874. Thisway the linker can put the code for each file into differentcode pages and there will be less page selection overhead.3. And as for any 8 bit micro (especially for PIC14 as they havea very simple instruction set), use `unsigned char' whereverpossible instead of `int'.4.6.2 Adding New Devices to the PortAdding support for a new 14bit PIC MCU requires the followingsteps:1. Create a new device description.Each device is described in two files: pic16f*.h and pic16f*.c.These files primarily define SFRs, structs to access theirbits, and symbolic configuration options. Both files can begenerated from gputils' .inc files using the perl scriptsupport/scripts/inc2h.pl. This file also contains furtherinstructions on how to proceed.2. Copy the .h file into SDCC's include path and either add the.c file 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 specification here to make the memorylayout (code banks, RAM, aliased memory regions, ...) known tothe compiler. Probably you can copy and modify an existingentry. The file format is documented at the top of the file.4.6.3 Interrupt CodeFor the interrupt function, use the keyword __interruptPIC14!interruptwith level number of 0 (PIC14 only has 1 interrupt so thisnumber is only there to avoid a syntax error - it ought to befixed). E.g.:void Intr(void) __interrupt 0{T0IF = 0; /* Clear timer interrupt */}4.6.4 Configuration BitsConfiguration bits (also known as fuses) can be configured using`__code' and `__at' modifiers. Possible options should be ANDedand can be found in your processor header file. Example forPIC16F88:#include <pic16f88.h> //Contains config addresses and options#include <stdint.h> //Needed for uint16_tstatic __code uint16_t __at (_CONFIG1) configword1 = _INTRC_IO &_CP_ALL & _WDT_OFF & [...];static __code uint16_t __at (_CONFIG2) configword2 = [...];Although data type is ignored if the address (__at()) refers to aconfig word location, using a type large enough for theconfiguration word (uint16_t in this case) is recommended toprevent changes in the compiler (implicit, early range check andenforcement) from breaking the definition.If your processor header file doesn't contain config addressesyou can declare it manually or use a literal address:static __code uint16_t __at (0x2007) configword1 = _INTRC_IO &_CP_ALL & _WDT_OFF & [...];4.6.5 Linking and AssemblingFor assembling you can use either GPUTILS'gputils (pic tools)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'smplink.exe. If you use MPLAB and an interrupt function then thelinker script file vectors section will need to be enlarged tolink with mplink.Pic device specific header and c source files are automaticallygenerated from MPLAB include files, which are published byMicrochip with a special requirement that they are only to beused with authentic Microchip devices. This reqirement preventsto publish generated header and c source files under the GPLcompatible license, so they are located in non-free directory(see section [subsec:Search-Paths]). In order to include them ininclude and library search paths, the --use-non-free--use-non-freecommand line option should be defined.NOTE: the compiled code, which use non-free pic device specificlibraries, is not GPL compatible!Here is a Makefile using GPUTILS:.c.o:sdcc -V --use-non-free -mpic14 -p16f877 -c $<$(PRJ).hex: $(OBJS)gplink -m -s $(PRJ).lkr -o $(PRJ).hex $(OBJS) libsdcc.libHere is a Makefile using MPLAB:.c.o:sdcc -S -V --use-non-free -mpic14 -p16f877 $<mpasmwin /q /o $*.asm$(PRJ).hex: $(OBJS)mplink /v $(PRJ).lkr /m $(PRJ).map /o $(PRJ).hex $(OBJS)libsdcc.libPlease note that indentations within a Makefile have to be donewith a tabulator character.4.6.6 Command-Line OptionsBesides the switches common to all SDCC backends, the PIC14 portaccepts the following options (for an updated list see sdcc --help):--debug-xtraPIC14!Options!--debug-extra emit debug info inassembly output--no-pcode-optPIC14!Options!--no-pcode-opt disable (slightlyfaulty) optimization on pCode--stack-locPIC14!Options!--stack-loc sets the lowest address ofthe argument passing stack (defaults to a suitably large shareddatabank to reduce BANKSEL overhead)--stack-sizePIC14!Options!--stack-size sets the size if theargument passing stack (default: 16, minimum: 4)--use-non-freePIC14!Options!--use-non-free make non-free deviceheaders and libraries available in the compiler's search paths(implicit -I and -L options)--no-extended-instructions forbid use of the extendedinstruction set (e.g., ADDFSR)4.6.7 Environment VariablesThe PIC14 port recognizes the following environment variables:SDCC_PIC14_SPLIT_LOCALSPIC14!Environment variables!SDCCPIC14SPLITLOCALSSDCC!Environment variables!SDCCPIC14SPLITLOCALS If set and notempty, sdcc will allocate each temporary register (the onescalled r0xNNNN) in a section of its own. By default (if thisvariable is unset), sdcc tries to cluster registers in sectionsin order to reduce the BANKSEL overhead when accessing them.4.6.8 The LibraryThe PIC14 library currently only contains support routinesrequired by the compiler to implement multiplication, division,and floating point support. No libc-like replacement is availableat the moment, though many of the common sdcc library sources (indevice/lib) should also compile with the PIC14 port.4.6.8.1 Enhanced coresSDCC/PIC14 has experimental support for devices with the enhanced14-bit cores (such as pic12f1822). Due to differences in requiredcode, the libraries provided with SDCC (libm.lib and libsdcc.lib)are now provided in two variants: libm.lib and libsdcc.lib arecompiled for the regular, non-enhanced devices. libme.lib andlibsdcce.lib (note the trailing 'e') are compiled for enhanceddevices. When linking manually, make sure to select the propervariant!When SDCC is used to invoke the linker, SDCC will automaticallyselect the libsdcc.lib-variant suitable for the target device.However, no such magic has been conjured up for libm.lib!4.6.8.2 Accessing bits of special function registersIndividual bits within SFRs can be accessed either using<sfrname>bits.<bitname> or using a shorthand <bitname>, which isdefined in the respective device header for all <bitname>s. Inorder to avoid polluting the global namespace with the names ofall the bits, you can #define NO_BIT_DEFINES before inclusion ofthe device header file.4.6.8.3 Naming of special function registers<subsec:Naming-of-special>If NO_BIT_DEFINES is used, individual bits of the SFRs can beaccessed as <sfrname>bits.<bitname>. With the 3.1.0 release, thepreviously used <sfrname>_bits.<bitname> (note the underscore) isdeprecated. This was done to align the naming conventions withthe PIC16 port and competing compiler vendors. To avoid pollutingthe global namespace with the legacy names, you can prevent theirdefinition using #define NO_LEGACY_NAMES prior to the inclusionof the device header.You must also #define NO_BIT_DEFINES in order to access SFRs as<sfrname>bits.<bitname>, otherwise <bitname> will expand to<sfrname>bits.<bitname>, yielding the undefined expression<sfrname>bits.<sfrname>bits.<bitname>.4.6.8.4 error: missing definition for symbol ``__gptrget1''The PIC14 port uses library routines to provide more complexoperations like multiplication, division/modulus and (generic)pointer dereferencing. In order to add these routines to yourproject, you must link with PIC14's libsdcc.lib. For singlesource file projects this is done automatically, more complexprojects must add libsdcc.lib to the linker's arguments. Makesure you also add an include path for the library (using the -Iswitch to the linker)!4.6.8.5 Processor mismatch in file ``XXX''.This warning can usually be ignored due to the very goodcompatibility amongst 14bit PICPIC14 devices.You might also consider recompiling the library for your specificdevice by changing the ARCH=p16f877 (default target) entry indevice/lib/pic/Makefile.in and device/lib/pic/Makefile to reflectyour device. This might even improve performance for smallerdevices as unnecessary BANKSELs might be removed.4.6.9 Known Bugs4.6.9.1 Function argumentsFunctions with variable argument lists (like printf) are not yetsupported. Similarly, taking the address of the first argumentpassed into a function does not work: It is currently passed inWREG and has no address...4.6.9.2 Regression tests failThough the small subset of regression tests in src/regressionpasses, SDCC regression test suite does not, indicating thatthere are still major bugs in the port. However, many smallerprojects have successfully used SDCC in the past...4.7 The PIC16PIC16 portThe PIC16 port adds support for MicrochipMicrochip^{\text{TM}}PICPIC^{\text{TM}} MCUs with 16 bit wide instructions. This portis not yet mature and still lacks many features. However, it canwork for simple code. Currently this family of microcontrollerscontains the PIC18Fxxx and PIC18Fxxxx; devices supported by theport include:18F13K22 18F13K5018F14K22 18F14K5018F23K20 18F23K2218F24J10 18F24J11 18F24J50 18F24K20 18F24K22 18F24K5018F25J10 18F25J11 18F25J50 18F25K20 18F25K22 18F25K50 18F25K8018F26J11 18F26J13 18F26J50 18F26J53 18F26K20 18F26K22 18F26K8018F27J13 18F27J5318F43K20 18F43K2218F44J10 18F44J11 18F44J50 18F44K20 18F44K2218F45J10 18F45J11 18F45J50 18F45K20 18F45K22 18F45K50 18F45K8018F46J11 18F46J13 18F46J50 18F46J53 18F46K20 18F46K22 18F46K8018F47J13 18F47J5318F63J11 18F63J9018F64J11 18F64J9018F65J10 18F65J11 18F65J15 18F65J50 18F65J90 18F65J94 18F65K2218F65K80 18F65K9018F66J10 18F66J11 18F66J15 18F66J16 18F66J50 18F66J55 18F66J6018F66J6518F66J90 18F66J93 18F66J94 18F66J99 18F66K22 18F66K80 18F66K9018F67J10 18F67J11 18F67J50 18F67J60 18F67J90 18F67J93 18F67J9418F67K22 18F67K9018F83J11 18F83J9018F84J11 18F84J9018F85J10 18F85J11 18F85J15 18F85J50 18F85J90 18F85J94 18F85K2218F85K9018F86J10 18F86J11 18F86J15 18F86J16 18F86J50 18F86J55 18F86J6018F86J6518F86J72 18F86J90 18F86J93 18F86J94 18F86J99 18F86K22 18F86K9018F87J10 18F87J11 18F87J50 18F87J60 18F87J72 18F87J90 18F87J9318F87J94 18F87K22 18F87K9018F95J94 18F96J60 18F96J65 18F96J94 18F96J9918F97J60 18F97J9418F242 18F248 18F252 18F25818F442 18F448 18F452 18F45818F1220 18F123018F1320 18F133018F2220 18F222118F2320 18F2321 18F233118F2410 18F2420 18F2423 18F2431 18F2439 18F2450 18F2455 18F245818F248018F2510 18F2515 18F2520 18F2523 18F2525 18F2539 18F2550 18F255318F2580 18F258518F2610 18F2620 18F2680 18F2682 18F268518F4220 18F422118F4320 18F4321 18F433118F4410 18F4420 18F4423 18F4431 18F4439 18F4450 18F4455 18F445818F448018F4510 18F4515 18F4520 18F4523 18F4525 18F4539 18F4550 18F455318F4580 18F458518F4610 18F4620 18F4680 18F4682 18F468518F6310 18F6390 18F639318F6410 18F6490 18F649318F6520 18F6525 18F6527 18F658518F6620 18F6621 18F6622 18F6627 18F6628 18F668018F6720 18F6722 18F672318F8310 18F8390 18F839318F8410 18F8490 18F849318F8520 18F8525 18F8527 18F858518F8620 18F8621 18F8622 18F8627 18F8628 18F868018F8720 18F8722 18F872318LF13K22 18LF13K5018LF14K22 18LF14K5018LF23K22 18LF24J10 18LF24J11 18LF24J50 18LF24K22 18LF24K5018LF25J10 18LF25J11 18LF25J50 18LF25K22 18LF25K50 18LF25K8018LF26J11 18LF26J13 18LF26J50 18LF26J53 18LF26K22 18LF26K8018LF27J13 18LF27J5318LF43K2218LF44J10 18LF44J11 18LF44J50 18LF44K2218LF45J10 18LF45J11 18LF45J50 18LF45K22 18LF45K50 18LF45K8018LF46J11 18LF46J13 18LF46J50 18LF46J53 18LF46K22 18LF46K8018LF47J13 18LF47J5318LF65K8018LF66K8018LF242 18LF248 18LF252 18LF25818LF442 18LF448 18LF452 18LF45818LF1220 18LF123018LF1320 18LF133018LF2220 18LF222118LF2320 18LF2321 18LF233118LF2410 18LF2420 18LF2423 18LF2431 18LF2439 18LF2450 18LF245518LF2458 18LF248018LF2510 18LF2515 18LF2520 18LF2523 18LF2525 18LF2539 18LF255018LF2553 18LF2580 18LF258518LF2610 18LF2620 18LF2680 18LF2682 18LF268518LF4220 18LF422118LF4320 18LF4321 18LF433118LF4410 18LF4420 18LF4423 18LF4431 18LF4439 18LF4450 18LF445518LF4458 18LF448018LF4510 18LF4515 18LF4520 18LF4523 18LF4525 18LF4539 18LF455018LF4553 18LF4580 18LF458518LF4610 18LF4620 18LF4680 18LF4682 18LF468518LF6310 18LF6390 18LF639318LF6410 18LF6490 18LF649318LF6520 18LF6525 18LF6527 18LF658518LF6620 18LF6621 18LF6622 18LF6627 18LF6628 18LF668018LF6720 18LF6722 18LF672318LF8310 18LF8390 18LF839318LF8410 18LF8490 18LF849318LF8520 18LF8525 18LF8527 18LF858518LF8620 18LF8621 18LF8622 18LF8627 18LF8628 18LF868018LF8720 18LF8722 18LF8723An up-to-date list of supported devices is also available via'sdcc -mpic16 -plist'.4.7.1 Global OptionsPIC16 port supports the standard command line arguments assupposed, with the exception of certain cases that will bementioned in the following list:--callee-savesPIC16!Options!--callee-saves See --all-callee-saves--use-non-freePIC16!Options!--use-non-free Make non-free deviceheaders and libraries available in the compiler's search paths(implicit -I and -L options).4.7.2 Port Specific OptionsOptions PIC16The port specific options appear after the global options in thesdcc --help output.4.7.2.1 Code Generation OptionsThese options influence the generated assembler code.--pstack-model=[model] Used in conjunction with the commandabove. Defines the stack model to be used, valid stack modelsare:small Selects small stack model. 8 bit stack and framepointers. Supports 256 bytes stack size.large Selects large stack model. 16 bit stack and framepointers. Supports 65536 bytes stack size.--pno-banksel Do not generate BANKSEL assembler directives.--extended Enable extended instruction set/literal offsetaddressing mode. Use with care!4.7.2.2 Optimization Options--obanksel=n Set optimization level for inserting BANKSELs.0 no optimization1 checks previous used register and if it is the same then doesnot emit BANKSEL, accounts only for labels.2 tries to check the location of (even different) symbols andremoves BANKSELs if they are in the same bank.Important: There might be problems if the linker script has datasections across bank borders!--denable-peeps Force the usage of peepholes. Use with care.--no-optimize-goto Do not use (conditional) BRA instead ofGOTO.--optimize-cmp Try to optimize some compares.--optimize-df Analyze the dataflow of the generated code andimprove it.4.7.2.3 Assembling Options--asm= Sets the full path and name of an external assembler tocall.--mplab-comp MPLABPIC16!MPLAB compatibility option. Currentlyonly suppresses special gpasm directives.4.7.2.4 Linking Options--link= Sets the full path and name of an external linker tocall.--preplace-udata-with=[kword] Replaces the default udatakeyword for allocating unitialized data variables with [kword].Valid keywords are: "udata_acs", "udata_shr", "udata_ovr".--ivt-loc=n Place the interrupt vector table at address n.Useful for bootloaders.--nodefaultlibs Do not link default libraries when linking.--use-crt= Use a custom run-time module instead of the default(crt0i).--no-crt Don't link the default run-time modules4.7.2.5 Debugging OptionsDebugging options enable extra debugging information in theoutput files.--debug-xtra Similar to --debug--debug, but dumps moreinformation.--debug-ralloc Force register allocator to dump <source>.d filewith debugging information. <source> is the name of the filebeing compiled.--pcode-verbose Enable pcode debugging information intranslation.--calltree Dump call tree in .calltree file.--gstack Trace push/pops for stack pointer overflow.4.7.3 Environment VariablesThere is a number of environmental variables that can be usedwhen running SDCC to enable certain optimizations or force aspecific program behaviour. these variables are primarily fordebugging purposes so they can be enabled/disabled at will.Currently there is only two such variables available:OPTIMIZE_BITFIELD_POINTER_GETPIC16!Environment variables!OPTIMIZEBITFIELDPOINTERGETSDCC!Environment variables!OPTIMIZEBITFIELDPOINTERGET (PIC16)When this variable exists, reading of structure bit-fields isoptimized by directly loading FSR0 with the address of thebit-field structure. Normally SDCC will cast the bit-fieldstructure to a bit-field pointer and then load FSR0. This stepsaves data ram and code space for functions that make heavy useof bit-fields. (i.e., 80 bytes of code space are saved whencompiling malloc.c with this option).NO_REG_OPTPIC16!Environment variables!NOREGOPTSDCC!Environment variables!NOREGOPTDo not perform pCode registers optimization. This should beused for debugging purposes. If bugs in the pcode optimizer arefound, users can benefit from temporarily disabling theoptimizer until the bug is fixed.4.7.4 Preprocessor MacrosPreprocessor!PIC16 MacrosPIC16PIC16 port defines the following preprocessor macros whiletranslating a source.+---------------------------------------------+------------------------------------------------------------------------------------------+| Macro | Description |+---------------------------------------------+------------------------------------------------------------------------------------------++---------------------------------------------+------------------------------------------------------------------------------------------+| __SDCC_pic16SDCC!Defines!__SDCCpic16 | Port identification |+---------------------------------------------+------------------------------------------------------------------------------------------+| pic18fxxxxPIC16!Defines!pic18fxxxx | MCU Identification. xxxx is the microcontrol identificationnumber, i.e. 452, 6620, etc |+---------------------------------------------+------------------------------------------------------------------------------------------+| __18FxxxxPIC16!Defines!pic18fxxxx | MCU Identification (same as above) |+---------------------------------------------+------------------------------------------------------------------------------------------+| STACK_MODEL_nnnPIC16!Defines!STACKMODELnnn | nnn = SMALL or LARGE respectively according to the stack modelused |+---------------------------------------------+------------------------------------------------------------------------------------------+In addition the following macros are defined when callingassembler:+-------------------+------------------------------------------------------------------------------------------+| Macro | Description |+-------------------+------------------------------------------------------------------------------------------++-------------------+------------------------------------------------------------------------------------------+| __18Fxxxx | MCU Identification. xxxx is the microcontrol identificationnumber, i.e. 452, 6620, etc |+-------------------+------------------------------------------------------------------------------------------+| __SDCC_MODEL_nnn | nnn = SMALL or LARGE respectively according to the memory modelused for SDCC |+-------------------+------------------------------------------------------------------------------------------+| STACK_MODEL_nnn | nnn = SMALL or LARGE respectively according to the stack modelused |+-------------------+------------------------------------------------------------------------------------------+4.7.5 DirectoriesPIC16PIC16 port uses the following directories for searchingheader files and libraries.+----------------------------+--------------------------+------------+----------------+| Directory | Description | Target | Command prefix |+----------------------------+--------------------------+------------+----------------++----------------------------+--------------------------+------------+----------------+| PREFIX/sdcc/include/pic16 | PIC16 specific headers | Compiler | -I |+----------------------------+--------------------------+------------+----------------+| PREFIX/sdcc/lib/pic16 | PIC16 specific libraries | Linker | -L |+----------------------------+--------------------------+------------+----------------+If the --use-non-free--use-non-free command line option isspecified, non-free directories are searched:+-------------------------------------+-----------------------------------+------------+----------------+| Directory | Description | Target | Command prefix |+-------------------------------------+-----------------------------------+------------+----------------++-------------------------------------+-----------------------------------+------------+----------------+| PREFIX/sdcc/non-free/include/pic16 | PIC16 specific non-free headers | Compiler | -I |+-------------------------------------+-----------------------------------+------------+----------------+| PREFIX/sdcc/non-free/lib/pic16 | PIC16 specific non-free libraries | Linker | -L |+-------------------------------------+-----------------------------------+------------+----------------+4.7.6 Pragmas<subsec:PIC16_Pragmas>The PIC16PIC16 port currently supports the following pragmas:stackPIC16!Pragmas!pragma stack This forces the code generatorto initialize the stack & frame pointers at a specific address.This is an ad hoc solution for cases where no STACK directiveis available in the linker script or gplink is not instructedto create a stack section.The stack pragma should be used only once in a project. Multiplepragmas may result in indeterminate behaviour of the program.[footnote:The old format (ie. #pragma stack 0x5ff) is deprecated and willcause the stack pointer to cross page boundaries (or even exceedthe available data RAM) and crash the program. Make sure thatstack does not cross page boundaries when using the SMALL stackmodel.]The format is as follows:#pragma stack bottom_address [stack_size]bottom_address is the lower bound of the stack section. The stackpointer initially will point at address(bottom_address+stack_size-1).Example:/* initializes stack of 100 bytes at RAM address 0x200 */#pragma stack 0x200 100If the stack_size field is omitted then a stack is created withthe default size of 64. This size might be enough for mostprograms, but its not enough for operations with deep functionnesting or excessive stack usage.codePIC16!Pragmas!pragma code Force a function to a staticFLASH address.Example:/* place function test_func at 0x4000 */#pragma code test_func 0x4000libraryPIC16!Pragmas!pragma library instructs the linker to usea library module.Usage:#pragma library module_namemodule_name can be any library or object file (including itspath). Note that there are four reserved keywords which havespecial meaning. These are:+----------+-----------------------------+----------------+| Keyword | Description | Module to link |+----------+-----------------------------+----------------++----------+-----------------------------+----------------+| ignore | ignore all library pragmas | (none) |+----------+-----------------------------+----------------+| c | link the C library | libc18f.lib |+----------+-----------------------------+----------------+| math | link the Math libarary | libm18f.lib |+----------+-----------------------------+----------------+| io | link the I/O library | libio18f*.lib |+----------+-----------------------------+----------------+| debug | link the debug library | libdebug.lib |+----------+-----------------------------+----------------+* is the device number, i.e. 452 for PIC18F452 MCU.This feature allows for linking with specific libraries withouthaving to explicit name them in the command line. Note that theignore keyword will reject all modules specified by the librarypragma.udataPIC16!Pragmas!pragma udata The pragma udata instructs thecompiler to emit code so that linker will place a variable at aspecific memory bank.Example:/* places variable foo at bank2 */#pragma udata bank2 foochar foo;In order for this pragma to work extra SECTION directives shouldbe added in the .lkr script. In the following example a sample.lkr file is shown:// Sample linker script for the PIC18F452 processorLIBPATH .CODEPAGE NAME=vectors START=0x0 END=0x29PROTECTEDCODEPAGE NAME=page START=0x2A END=0x7FFFCODEPAGE NAME=idlocs START=0x200000 END=0x200007PROTECTEDCODEPAGE NAME=config START=0x300000 END=0x30000DPROTECTEDCODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFFPROTECTEDCODEPAGE NAME=eedata START=0xF00000 END=0xF000FFPROTECTEDACCESSBANK NAME=accessram START=0x0 END=0x7FDATABANK NAME=gpr0 START=0x80 END=0xFFDATABANK NAME=gpr1 START=0x100 END=0x1FFDATABANK NAME=gpr2 START=0x200 END=0x2FFDATABANK NAME=gpr3 START=0x300 END=0x3FFDATABANK NAME=gpr4 START=0x400 END=0x4FFDATABANK NAME=gpr5 START=0x500 END=0x5FFACCESSBANK NAME=accesssfr START=0xF80 END=0xFFFPROTECTEDSECTION NAME=CONFIG ROM=configSECTION NAME=bank0 RAM=gpr0 # these SECTIONdirectivesSECTION NAME=bank1 RAM=gpr1 # should be added tolinkSECTION NAME=bank2 RAM=gpr2 # section name 'bank?'withSECTION NAME=bank3 RAM=gpr3 # a specific DATABANKnameSECTION NAME=bank4 RAM=gpr4SECTION NAME=bank5 RAM=gpr5The linker will recognise the section name set in the pragmastatement and will position the variable at the memory bank setwith the RAM field at the SECTION line in the linker script file.configPIC16!Pragmas!pragma config The pragma config instructsthe compiler to emit config directive.The format is as follows:#pragma config setting=value [, setting=value]Multiple settings may be defined on a single line, separated bycommas. Settings for a single configuration byte may also bedefined on separate lines.Example:#pragma configCP0=OFF,OSCS=ON,OSC=LP,BOR=ON,BORV=25,WDT=ON,WDTPS=128,CCP2MUX=ON#pragma config STVR=ON4.7.7 Header Files and Libraries<subsec:PIC16_Header-Files-and-Libraries>Pic device specific header and c source files are automaticallygenerated from MPLAB include files, which are published byMicrochip with a special requirement that they are only to beused with authentic Microchip devices. This requirement preventsto publish generated header and c source files under the GPLcompatible license, so they are located in the non-free directory(see section [subsec:Search-Paths]). In order to include them ininclude and library search paths, the --use-non-free--use-non-freecommand line option should be defined.NOTE: the compiled code, which use non-free pic device specificlibraries, is not GPL compatible!4.7.8 Header Files<subsec:PIC16_Header-Files>There is one main header filePIC16!Header files that can beincluded to the source files using the pic16PIC16 port. That fileis the pic18fregs.h. This header file contains the definitionsfor the processor special registers, so it is necessary if thesource accesses them. It can be included by adding the followingline in the beginning of the file:#include <pic18fregs.h>The specific microcontroller is selected within the pic18fregs.hautomatically, so the same source can be used with a variety ofdevices.4.7.9 Libraries<subsec:pic16Libraries>The librariesPIC16!Libraries that PIC16PIC16 port depends on arethe microcontroller device libraries which contain the symboldefinitions for the microcontroller special function registers.These libraries have the format pic18fxxxx.lib, where xxxx is themicrocontroller identification number. The specific library isselected automatically by the compiler at link stage according tothe selected device.Libraries are created with gplib which is part of the gputilspackage http://sourceforge.net/projects/gputils.Building the librariesBefore using SDCC/pic16 there are some libraries that need to becompiled. This process is done automatically if gputils are foundat SDCC's compile time. Should you require to rebuild the pic16libraries manually (e.g. in order to enable output of floatvaluesprintf()!PIC16 Floating point support via printf(), seebelow), these are the steps required to do so under Linux or MacOS X (cygwin might work as well, but is untested):cd device/lib/pic16./configure.gnucd ..make model-pic16su -c 'make install' # install the libraries, you need theroot passwordcd ../..If you need to install the headers too, do:cd device/includesu -c 'make install' # install the headers, you need the rootpasswordOutput of float values via printf()The library is normally built without support for displayingfloat values, only <NO FLOAT><NO FLOAT>printf()!PIC16 floating point supportwill appear instead of the value. To change this, rebuild thelibrary as stated above, but call ./configure.gnu --enable-floatsinstead of just ./configure.gnu. Also make sure that at leastlibc/stdio/vfprintf.c is actually recompiled, e.g. by touching itafter the configure run or deleting its .o file.The more common approach of compiling vfprintf.c manually with-DUSE_FLOATS=1 should also work, but is untested.4.7.10 Adding New Devices to the PortAdding support for a new 16bit PIC MCU requires the followingsteps:1. Create picDEVICE.c and picDEVICE.h from pDEVICE.inc usingperl /path/to/sdcc/support/scripts/inc2h-pic16.pl \/path/to/gputils/header/pDEVICE.inc2. mv picDEVICE.h /path/to/sdcc/device/non-free/include/pic163. mv picDEVICE.c /path/to/sdcc/device/non-free/lib/pic16/libdev4. Either(a) add the new device to/path/to/sdcc/device/lib/pic16/libio/*.ignore to suppressbuilding any of the I/O libraries for the new device[footnote:In fact, the .ignore files are only used when auto-generatingMakefile.am using the .../libio/mkmk.sh script.], or(b) add the device (family) to/path/to/sdcc/support/scripts/pic18fam-h-gen.pl to assign I/Ostyles, run the pic18fam-h-gen.pl script to generatepic18fam.h.gen, replace your existing pic18fam.h with thegenerated file, and (if required) implement new I/O styles in/path/to/sdcc/device/include/pic16/{adc,i2c,usart}.h and/path/to/sdcc/device/lib/pic16/libio/*/*.5. Edit /path/to/sdcc/device/include/pic16/pic18fregs.hThe file format is self-explanatory, just add#elif defined(picDEVICE)#include <picDEVICE.h>at the right place (keep the file sorted, please).6. Edit /path/to/sdcc/device/include/pic16devices.txtCopy and modify an existing entry or create a new one and insertit at the correct place (keep the file sorted, please).7. ( cd /path/to/sdcc/device/non-free/lib/pic16 && sh update.sh )8. Recompile the pic16 libraries as described in [subsec:pic16Libraries]or just configure and build sdcc again from scratch(recommended).4.7.11 Memory ModelsThe following memory models are supported by the PIC16 port:• small model• large modelMemory model affects the default size of pointers within thesource. The sizes are shown in the next table:+-----------------------------------------++--------------+-------------+| Pointer sizes according to memory model || small model | large model |+-----------------------------------------++--------------+-------------++-----------------------------------------++--------------+-------------+| code pointers || 16-bits | 24-bits |+-----------------------------------------+ +-------------++-----------------------------------------++--------------+-------------+| data pointers || 16-bits | 16-bits |+-----------------------------------------++--------------+-------------+It is advisable that all sources within a project are compiledwith the same memory model. If one wants to override the defaultmemory model, this can be done by declaring a pointer as far ornear. Far selects large memory model's pointers, while nearselects small memory model's pointers.The standard device libraries (see [subsec:PIC16_Header-Files])contain no reference to pointers, so they can be used with bothmemory models.4.7.12 StackThe stackPIC16!stack implementation for the PIC16 port uses twoindirect registers, FSR1 and FSR2.FSR1 is assigned as stack pointerFSR2 is assigned as frame pointerThe following stack models are supported by the PIC16 port• small model• large modelSmall model means that only the FSRxL byte is used to accessstack and frame, while large uses both FSRxL and FSRxH registers.The following table shows the stack/frame pointers sizesaccording to stack model and the maximum space they can address:+------------------------------------------------------++---------+---------+| Stack & Frame pointer sizes according to stack model || small | large |+------------------------------------------------------++---------+---------++------------------------------------------------------++---------+---------+| Stack pointer FSR1 || 8-bits | 16-bits |+------------------------------------------------------++---------+---------+| Frame pointer FSR2 || 8-bits | 16-bits |+------------------------------------------------------++---------+---------+Large stack model is currently not working properly throughoutthe code generator. So its use is not advised. Also there aresome other points that need special care:1. Do not create stack sections with size more than one physicalbank (that is 256 bytes)2. Stack sections should no cross physical bank limits (i.e.#pragma stack 0x50 0x100)These limitations are caused by the fact that only FSRxL ismodified when using SMALL stack model, so no more than 256 bytesof stack can be used. This problem will disappear after LARGEmodel is fully implemented.4.7.13 FunctionsIn addition to the standard SDCC function keywords, PIC16PIC16port makes available two more:__wparamPIC16!wparam Use the WREG to pass one byte of the firstfunction argument. This improves speed but you may not use thisfor functions with arguments that are called via functionpointers, otherwise the first byte of the first parameter willget lost. 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 largestack model) */...}__shadowregsPIC16!shadowregs When entering/exiting an ISR, itis possible to take advantage of the PIC18F hardware shadowregisters which hold the values of WREG, STATUS and BSRregisters. This can be done by adding the keyword __shadowregsbefore the __interrupt keyword in the function's header.void isr_shadow(void) __shadowregs __interrupt 1{...}__shadowregs instructs the code generator not to store/restoreWREG, STATUS, BSR when entering/exiting the ISR.4.7.14 Function return valuesReturn values from functions are placed to the appropriateregisters following a modified Microchip policy optimized forSDCC. The following table shows these registers:+-----------+----------------------------------------+| size | destination register |+-----------+----------------------------------------++-----------+----------------------------------------+| 8 bits | WREG |+-----------+----------------------------------------+| 16 bits | PRODL:WREG |+-----------+----------------------------------------+| 24 bits | PRODH:PRODL:WREG |+-----------+----------------------------------------+| 32 bits | FSR0L:PRODH:PRODL:WREG |+-----------+----------------------------------------+| >32 bits | on stack, FSR0 points to the beginning |+-----------+----------------------------------------+4.7.15 InterruptsAn interruptPIC16!interrupt service routine (ISR) is declaredusing the __interrupt keyword.void isr(void) __interrupt n{...}n is the interrupt number, which for PIC18F devices can be:+----+---------------------------+--------------------------+| n | Interrupt Vector | Interrupt Vector Address |+----+---------------------------+--------------------------++----+---------------------------+--------------------------+| 0 | RESET vector | 0x000000 |+----+---------------------------+--------------------------+| 1 | HIGH priority interrupts | 0x000008 |+----+---------------------------+--------------------------+| 2 | LOW priority interrupts | 0x000018 |+----+---------------------------+--------------------------+When generating assembly code for ISR the code generator places agoto instruction at the Interrupt Vector Address which points atthe generated ISR. This single GOTO instruction is part of anautomatically generated interrupt entry point function. Theactual ISR code is placed as normally would in the code space.Upon interrupt request, the GOTO instruction is executed whichjumps to the ISR code. When declaring interrupt functions as_naked this GOTO instruction is not generated. The wholeinterrupt functions is therefore placed at the Interrupt VectorAddress of the specific interrupt. This is not a problem for theLOW priority interrupts, but it is a problem for the RESET andthe HIGH priority interrupts because code may be written at thenext interrupt's vector address and cause indeterminate programbehaviour if that interrupt is raised.[footnote:This is not a problem when1. this is a HIGH interrupt ISR and LOW interrupts are disabledor not used.2. when the ISR is small enough not to reach the next interrupt'svector address.]n may be omitted. This way a function is generated similar to anISR, but it is not assigned to any interrupt.When entering an interrupt, currently the PIC16PIC16 portautomatically saves the following registers:• WREG• STATUS• BSR• PROD (PRODL and PRODH)• FSR0 (FSR0L and FSR0H)These registers are restored upon return from the interruptroutine.[footnote:NOTE that when the _naked attribute is specified for an interruptroutine, then NO registers are stored or restored.]4.7.16 Generic PointersGeneric pointers are implemented in PIC16 port as 3-byte (24-bit)types. There are 3 types of generic pointers currentlyimplemented data, code and eeprom pointers. They aredifferentiated by the value of the 7th and 6th bits of the upperbyte:+-----------------+-----------+---------+-----------------------------------------------------------------------+| pointer type | 7th bit | 6th bit | rest of the pointer description |+-----------------+-----------+---------+-----------------------------------------------------------------------++-----------------+-----------+---------+-----------------------------------------------------------------------+| data | 1 | 0 | uuuuuu uuuuxxxx xxxxxxxx a 12-bit data pointer in data RAM memory |+-----------------+-----------+---------+-----------------------------------------------------------------------+| code | 0 | 0 | uxxxxx xxxxxxxx xxxxxxxx a 21-bit code pointer in FLASH memory |+-----------------+-----------+---------+-----------------------------------------------------------------------+| eeprom | 0 | 1 | uuuuuu uuuuuuxx xxxxxxxx a 10-bit eeprom pointer in EEPROM memory |+-----------------+-----------+---------+-----------------------------------------------------------------------+| (unimplemented) | 1 | 1 | xxxxxx xxxxxxxx xxxxxxxx unimplemented pointer type |+-----------------+-----------+---------+-----------------------------------------------------------------------+Generic pointer are read and written with a set of libraryfunctions which read/write 1, 2, 3, 4 bytes.4.7.17 Configuration BitsConfiguration bits (also known as fuses) can be configured usingone of two methods:• using #pragma config (see section [subsec:PIC16_Pragmas]),which is a preferred method for the new code. Example:#pragma configCP0=OFF,OSCS=ON,OSC=LP,BOR=ON,BORV=25,WDT=ON,WDTPS=128,CCP2MUX=ON#pragma config STVR=ON• using `__code' and `__at' modifiers. This method is deprecated.Possible options should be ANDed and can be found in yourprocessor header file. Example for PIC18F2550:#include <pic18fregs.h> //Contains config addresses and optionsstatic __code char __at(__CONFIG1L) configword1l =_USBPLL_CLOCK_SRC_FROM_96MHZ_PLL_2_1L &_PLLDIV_NO_DIVIDE__4MHZ_INPUT__1L & [...];static __code char __at(__CONFIG1H) configword1h = [...];static __code char __at(__CONFIG2L) configword2l = [...];//More configuration wordsMixing both methods is not allowed and throws an error message ”mixing __CONFIG and CONFIG directives”.4.7.18 PIC16 C Libraries4.7.18.1 Standard I/O StreamsIn the stdio.h the type FILE is defined as:typedef char * FILE;This type is the stream type implemented I/O in the PIC18Fdevices. Also the standard input and output streams are declaredin stdio.h:extern FILE * stdin;extern FILE * stdout;The FILE type is actually a generic pointer which defines onemore type of generic pointers, the stream pointer. This new typehas the format:+--------------+---------+------+------+-------+-----------------------------------------------------------------------------+| pointer type | <7:6> | <5> | <4> | <3:0> | rest of the pointer descrption |+--------------+---------+------+------+-------+-----------------------------------------------------------------------------++--------------+---------+------+------+-------+-----------------------------------------------------------------------------+| stream | 00 | 1 | 0 | nnnn | uuuuuuuu uuuuuuuu upper byte high nubble is 0x2n, the rest are zeroes |+--------------+---------+------+------+-------+-----------------------------------------------------------------------------+Currently implemented there are 3 types of streams defined:+---------------+-------------+---------+----------------------------------------------------+| stream type | value | module | description |+---------------+-------------+---------+----------------------------------------------------++---------------+-------------+---------+----------------------------------------------------+| STREAM_USART | 0x200000UL | USART | Writes/Reads characters via the USART peripheral |+---------------+-------------+---------+----------------------------------------------------+| STREAM_MSSP | 0x210000UL | MSSP | Writes/Reads characters via the MSSP peripheral |+---------------+-------------+---------+----------------------------------------------------+| STREAM_USER | 0x2f0000UL | (none) | Writes/Reads characters via used defined functions |+---------------+-------------+---------+----------------------------------------------------+The stream identifiers are declared as macros in the stdio.hheader.In the libc library there exist the functions that are used towrite to each of the above streams. These are__stream_usart_putchar writes a character at the USART stream__stream_mssp_putchar writes a character at the MSSP streamputchar dummy function. This writes a character to a userspecified manner.In order to increase performance putchar is declared in stdio.has having its parameter in WREG (it has the __wparam keyword). Instdio.h exists the macro PUTCHAR(arg) that defines the putcharfunction in a user-friendly way. arg is the name of the variablethat holds the character to print. An example follows:#include <pic18fregs.h>#include <stdio.h>PUTCHAR( c ){PORTA = c; /* dump character c to PORTA */}void main(void){stdout = STREAM_USER; /* this is not necessary, sincestdout points* by default to STREAM_USER */printf (”This is a printf test\n”);}4.7.18.2 Printing functionsPIC16 contains an implementation of the printf-familyprintf()!PIC16of functions. There exist the following functions:extern unsigned int sprintf(char *buf, char *fmt, ...);extern unsigned int vsprintf(char *buf, char *fmt, va_list ap);extern unsigned int printf(char *fmt, ...);extern unsigned int vprintf(char *fmt, va_lista ap);extern unsigned int fprintf(FILE *fp, char *fmt, ...);extern unsigned int vfprintf(FILE *fp, char *fmt, va_list ap);For sprintf and vsprintf buf should normally be a data pointerwhere the resulting string will be placed. No range checking isdone so the user should allocate the necessary buffer. Forfprintf and vfprintf fp should be a stream pointer (i.e. stdout,STREAM_MSSP, etc...).4.7.18.3 SignalsThe PIC18F family of microcontrollers supports a number ofinterrupt sources. A list of these interrupts is shown in thefollowing table:+--------------+----------------------------++--------------+---------------------------------------+| signal name | description || signal name | description |+--------------+----------------------------++--------------+---------------------------------------++--------------+----------------------------++--------------+---------------------------------------+| SIG_RB | PORTB change interrupt || SIG_EE | EEPROM/FLASH write complete interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_INT0 | INT0 external interrupt || SIG_BCOL | Bus collision interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_INT1 | INT1 external interrupt || SIG_LVD | Low voltage detect interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_INT2 | INT2 external interrupt || SIG_PSP | Parallel slave port interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_CCP1 | CCP1 module interrupt || SIG_AD | AD convertion complete interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_CCP2 | CCP2 module interrupt || SIG_RC | USART receive interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_TMR0 | TMR0 overflow interrupt || SIG_TX | USART transmit interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_TMR1 | TMR1 overflow interrupt || SIG_MSSP | SSP receive/transmit interrupt |+--------------+----------------------------++--------------+---------------------------------------+| SIG_TMR2 | TMR2 matches PR2 interrupt || | |+--------------+----------------------------++--------------+---------------------------------------+| SIG_TMR3 | TMR3 overflow interrupt || | |+--------------+----------------------------++--------------+---------------------------------------+The prototypes for these names are defined in the header filesignal.h.In order to simplify signal handling, a number of macros isprovided:DEF_INTHIGH(name) begin the definition of the interrupt dispatchtable for high priority interrupts. name is the function name touse.DEF_INTLOW(name) begin the definition of the interrupt dispatchtable for low priority interrupt. name is the function name touse.DEF_HANDLER(sig,handler) define a handler for signal sig.END_DEF end the declaration of the dispatch table.Additionally there are two more macros to simplify thedeclaration of the signal handler:SIGHANDLER(handler) this declares the function prototype for thehandler function.SIGHANDLERNAKED(handler) same as SIGHANDLER() but declares anaked function.An example of using the macros above is shown below:#include <pic18fregs.h>#include <signal.h>DEF_INTHIGH(high_int)DEF_HANDLER(SIG_TMR0, _tmr0_handler)DEF_HANDLER(SIG_BCOL, _bcol_handler)END_DEFSIGHANDLER(_tmr0_handler){/* action to be taken when timer 0 overflows */}SIGHANDLERNAKED(_bcol_handler){__asm/* action to be taken when bus collision occurs */retfie__endasm;}NOTES: Special care should be taken when using the above scheme:• do not place a colon (;) at the end of the DEF_* and END_DEFmacros.• when declaring SIGHANDLERNAKED handler never forget to useretfie for proper returning.4.7.19 PIC16 Port – TipsHere you can find some general tips for compiling programs withSDCC/pic16.4.7.19.1 Stack sizeThe default stackPIC16!stack size (that is 64 bytes) probably isenough for many programs. One must take care that when there aremany levels of function nesting, or there is excessive usage ofstack, its size should be extended. An example of such a case isthe printf/sprintf family of functions. If you encounter problemslike not being able to print integers, then you need to set thestack size around the maximum (256 for small stack model). Thefollowing diagram shows what happens when calling printf to printan integer:printf () --> ltoa () --> ultoa () --> divschar ()It is should be understood that stack is easily consumed whencalling complicated functions. Using command line arguments like--fomit-frame-pointer might reduce stack usage by not creatingunnecessary stack frames. Other ways to reduce stack usage mayexist.4.7.20 Known Bugs4.7.20.1 Extended Instruction SetThe PIC16 port emits code which is incompatible with the extendedinstruction set available with many newer devices. Make sure toalways explicitly disable it, usually using:• #pragma config XINST=OFFor deprecated:• static __code char __at(__CONFIG4L) conf4l = /* more flags & */_XINST_OFF_4L;Some devices (namely 18f2455, 18f2550, 18f4455, and 18f4550) use_ENHCPU_OFF_4L instead of _XINST_OFF_4L.4.7.20.2 Regression TestsThe PIC16 port currently passes most but not all of the tests inSDCC's regression testRegression test (PIC16) suite (see section [sec:Quality-control]), thus no automatic regression tests are currently performed forthe PIC16 target.DebuggingThere are several approaches to debugging your code. This chapteris 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,put conceptually similar variables into structs, use structuredcode, have strategic points within your code where allvariables are consistent, ...)• run a syntax-checking tool like splintsplint (syntax checking tool)lint (syntax checking tool) (see --more-pedantic [lyx:more-pedantic-SPLINT]) over the code.• for the high level code use a C-compiler (like f.e. GCC) tocompile run and debug the code on your host. See (see --more-pedantic [lyx:more-pedantic-SPLINT]) on how to handlesyntax extensions like __xdata, __at(), ...• use another C-compiler to compile code for your target. Alwaysan option but not recommended:) And not very likely to helpyou. If you seriously consider walking this path you should atleast occasionally check portability of your code. Mostcommercial compiler vendors will offer an evaluation version soyou can test compile your code or snippets of your code.Debugging on a simulator:• there is a separate section about SDCDB (section [cha:Debugging-with-SDCDB]) below.• or (8051 specific) use a free open source/commercial simulatorwhich interfaces to the AOMFAOMF, AOMF51 file (see [OMF file])optionally generated by SDCC.Debugging On-target:• use a MCU port pin to serially output debug data to the RS232port of your host. You'll probably want some level shiftingdevice typically involving a MAX232 or similar IC. If thehardware serial port of the MCU is not available search for'Software UART' in your favourite search machine.• use an on-target monitor. In this context a monitor is a smallprogram which usually accepts commands via a serial line andallows to set program counter, to single step through a programand read/write memory locations. For the 8051 good examples ofmonitors are paulmon and cmon51 (see section [sec:Related-open-source-tools]).• toggle MCU port pins at strategic points within your code anduse an oscilloscope. A digital oscilloscopeOscilloscope withdeep trace memory is really helpful especially if you have todebug a realtime application. If you need to monitor more pinsthan your oscilloscope provides you can sometimes get away witha small R-2R network. On a single channel oscilloscope youcould for example monitor 2 push-pull driven pins by connectingone via a 10 k\Omega resistor and the other one by a 5 k\Omegaresistor to the oscilloscope probe (check output drivecapability of the pins you want to monitor). If you need tomonitor many more pins a logic analyzer will be handy.• use an ICE (in circuit emulatorICE (in circuit emulator)).Usually very expensive. And very nice to have too. And usuallylocks you (for years...) to the devices the ICE can emulate.• use a remote debugger. In most 8-bit systems the symbolinformation is not available on the target, and a completedebugger is too bulky for the target system. Therefore usuallya debugger on the host system connects to an on-targetdebugging stub which accepts only primitive commands.Terms to enter into your favourite search engine could be 'remotedebugging', 'gdb stub' or 'inferior debugger'. (is there one?)• use an on target hardware debugger. Some of the more modernMCUs include hardware support for setting break points andmonitoring/changing variables by using dedicated hardware pins.This facility doesn't require additional code to run on thetarget and usually doesn't affect runtime behaviour until abreakpoint is hit. For the mcs51 most hardware debuggers usethe AOMFAOMF, AOMF51 file (see [OMF file]) as input file.Last not least:• if you are not familiar with any of the following terms you'relikely to run into problems rather sooner than later: volatile,atomic, memory map, overlay. As an embedded programmer you haveto know them so why not look them up before you have problems?)• tell someone else about your problem (actually this is asurprisingly effective means to hunt down the bug even if thelistener is not familiar with your environment). As 'failure tocommunicate' is probably one of the job-induced deformations ofan embedded programmer this is highly encouraged.5.1 Debugging with SDCDB<cha:Debugging-with-SDCDB>SDCDB (debugger)SDCC is distributed with a source level debuggerDebugger. Thedebugger uses a command line interface, the command repertoire ofthe debugger has been kept as close to gdbgdb (the GNU debugger)as possible. The configuration and build process is part of thestandard compiler installation, which also builds and installsthe debugger in the target directory specified duringconfiguration. The debugger allows you debug BOTH at the C sourceand at the ASM source level.5.1.1 Compiling for DebuggingThe --debug--debug option must be specified for all files forwhich debug information is to be generated. The compilergenerates a .adb file for each of these files. The linker createsthe .cdb<file>.cdb file from the .adb<file>.adb files and theaddress information. This .cdb is used by the debugger.5.1.2 How the Debugger WorksWhen the --debug option is specified the compiler generates extrasymbol information some of which are put into the assemblersource and some are put into the .adb file. Then the linkercreates the .cdb file from the individual .adb files with theaddress information for the symbols. The debugger reads thesymbolic information generated by the compiler & the addressinformation generated by the linker. It uses the SIMULATOR(Daniel's S51) to execute the program, the program execution iscontrolled by the debugger. When a command is issued for thedebugger, it translates it into appropriate commands for thesimulator. (Currently SDCDM only connects to the simulator butnewcdb at http://ec2drv.sourceforge.net/ is an effort to connectdirectly to the hardware.)5.1.3 Starting the Debugger SDCDBThe debugger can be started using the following command line.(Assume the file you are debugging has the file name foo).sdcdb fooThe debugger will look for the following files.• foo.c - the source file.• foo.cdb - the debugger symbol information file.• foo.ihx - the Intel hex formatIntel hex format object file.5.1.4 SDCDB Command Line Options• --directory=<source file directory> this option can used tospecify the directory search list. The debugger will look intothe directory list specified for source, cdb & ihx files. Theitems in the directory list must be separated by ':', e.g. ifthe source files can be in the directories /home/src1 and/home/src2, the --directory option should be --directory=/home/src1:/home/src2. Note there can be no spacesin the option.• -cd <directory> - change to the <directory>.• -fullname - used by GUI front ends.• -cpu <cpu-type> - this argument is passed to the simulatorplease see the simulator docs for details.• -X <Clock frequency > this options is passed to the simulatorplease see the simulator docs for details.• -s <serial port file> passed to simulator see the simulatordocs for details.• -S <serial in,out> passed to simulator see the simulator docsfor details.• -k <port number> passed to simulator see the simulator docs fordetails.5.1.5 SDCDB Debugger CommandsAs mentioned earlier the command interface for the debugger hasbeen deliberately kept as close the GNU debugger gdb, aspossible. This will help the integration with existing graphicaluser interfaces (like ddd, xxgdb or xemacs) existing for the GNUdebugger. If you use a graphical user interface for the debuggeryou can skip this section.break [line | file:line | function | file:function]Set breakpoint at specified line or function:sdcdb>break 100sdcdb>break foo.c:100sdcdb>break funcfoosdcdb>break foo.c:funcfooclear [line | file:line | function | file:function ]Clear breakpoint at specified line or function:sdcdb>clear 100sdcdb>clear foo.c:100sdcdb>clear funcfoosdcdb>clear foo.c:funcfoocontinueContinue program being debugged, after breakpoint.finishExecute till the end of the current function.delete [n]Delete breakpoint number 'n'. If used without any option clearALL user defined break points.info [break | stack | frame | registers ]• info break - list all breakpoints• info stack - show the function call stack.• info frame - show information about the current executionframe.• info registers - show content of all registers.stepStep program until it reaches a different source line. Note:pressing <return> repeats the last command.nextStep program, proceeding through subroutine calls.runStart debugged program.ptype variablePrint type information of the variable.print variableprint value of variable.file filenameload the given file name. Note this is an alternate method ofloading file for debugging.frameprint information about current frame.set srcmodeToggle between C source & assembly source.! simulator commandSend the string following '!' to the simulator, the simulatorresponse is displayed. Note the debugger does not interpret thecommand being sent to the simulator, so if a command like 'go' issent the debugger can loose its execution context and may displayincorrect values.quit"Watch me now. Iam going Down. My name is Bobby Brown"5.1.6 Interfacing SDCDB with DDDThe portable network graphics File http://sdcc.sourceforge.net/wiki_images/ddd_example.pngshows a screenshot of a debugging session with DDDDDD (debugger)(Unix only) on a simulated 8032. The debugging session might notrun as smoothly as the screenshot suggests. The debugger allowssetting of breakpoints, displaying and changing variables, singlestepping through C and assembler code.The source was compiled withsdcc --debug ddd_example.cand DDD was invoked withddd -debugger "sdcdb -cpu 8032 ddd_example"5.1.7 Interfacing SDCDB with XEmacsXEmacsEmacsTwo files (in emacs lisp) are provided for the interfacing withXEmacs, sdcdb.el and sdcdbsrc.el. These two files can be found inthe $(prefix)/bin directory after the installation is complete.These files need to be loaded into XEmacs for the interface towork. This can be done at XEmacs startup time by inserting thefollowing into your '.xemacs' file (which can be found in yourHOME directory):(load-file sdcdbsrc.el).xemacs is a lisp file so the () around the command is REQUIRED.The files can also be loaded dynamically while XEmacs is running,set the environment variable 'EMACSLOADPATH' to the installationbin directory (<installdir>/bin), then enter the followingcommand ESC-x load-file sdcdbsrc. To start the interface enterthe following command:ESC-x sdcdbsrcYou will prompted to enter the file name to be debugged.The command line options that are passed to the simulatordirectly are bound to default values in the file sdcdbsrc.el. Thevariables are listed below, these values maybe changed asrequired.• sdcdbsrc-cpu-type '51• sdcdbsrc-frequency '11059200• sdcdbsrc-serial nilThe following is a list of key mapping for the debuggerinterface.;; Current Listing ::;;key binding Comment;;--- ------- -------;;;; n sdcdb-next-from-src SDCDB nextcommand;; b sdcdb-back-from-src SDCDB backcommand;; c sdcdb-cont-from-src SDCDB continuecommand;; s sdcdb-step-from-src SDCDB stepcommand;; ? sdcdb-whatis-c-sexp SDCDBptypecommand for data at;; buffer point;; x sdcdbsrc-delete SDCDB Delete allbreakpoints if no arg;; given or deletearg (C-u arg x);; m sdcdbsrc-frame SDCDB Displaycurrent frame if no arg,;; given or displayframe arg;; buffer point;; ! sdcdbsrc-goto-sdcdb Goto the SDCDBoutput buffer;; p sdcdb-print-c-sexp SDCDB printcommand for data at;; buffer point;; g sdcdbsrc-goto-sdcdb Goto the SDCDBoutput buffer;; t sdcdbsrc-mode Toggles Sdcdbsrcmode (turns it off);;;; C-c C-f sdcdb-finish-from-src SDCDB finishcommand;;;; C-x SPC sdcdb-break Set break forline with point;; ESC t sdcdbsrc-mode Toggle Sdcdbsrcmode;; ESC m sdcdbsrc-srcmode Toggle list mode;;TIPSHere are a few guidelines that will help the compiler generatemore efficient code, some of the tips are specific to thiscompiler others are generally good programming practice.• Use the smallest data type to represent your data-value. If itis known in advance that the value is going to be less than 256then use an 'unsigned char' instead of a 'short' or 'int'.Please note, that ANSI C requires both signed and unsignedchars to be promoted to 'signed int'promotion to signed int[margin:!] before doing any operation. This promotiontype promotion<type promotion>can be omitted, if the result is the same. The effect of thepromotion rules together with the sign-extension is oftensurprising:unsigned char uc = 0xfe;if (uc * uc < 0) /* this is true! */{....}uc * uc is evaluated as (int) uc * (int) uc = (int) 0xfe *(int) 0xfe = (int) 0xfc04 = -1024.Another one:(unsigned char) -12 / (signed char) -3 = ...No, the result is not 4:(int) (unsigned char) -12 / (int) (signed char) -3 =(int) (unsigned char) 0xf4 / (int) (signed char) 0xfd =(int) 0x00f4 / (int) 0xfffd =(int) 0x00f4 / (int) 0xfffd =(int) 244 / (int) -3 =(int) -81 = (int) 0xffaf;Don't complain, that gcc gives you a different result. gcc uses32 bit ints, while SDCC uses 16 bit ints. Therefore the resultsare different.From ”comp.lang.c FAQ”:If well-defined overflow characteristics are important andnegative values are not, or if you want to steer clear ofsign-extension problems when manipulating bits or bytes, useone of the corresponding unsigned types. (Beware when mixingsigned and unsigned values in expressions, though.)Although character types (especially unsigned char) can be usedas "tiny" integers, doing so is sometimes more trouble thanit's worth, due to unpredictable sign extension and increasedcode size.• Use unsigned when it is known in advance that the value is notgoing to be negative. This helps especially if you are doingdivision or multiplication, bit-shifting or are using an arrayindex.• NEVER jump into a LOOP.• Declare the variables to be locallocal variables wheneverpossible, especially loop control variables (induction).• Have a look at the assembly listing to get a ”feeling” for thecode generation.6.1 Porting code from or to other compilers<sec:Porting-code-to-other-compilers>• check whether endiannessEndianness of the compilers differs andadapt where needed.• check the device specific header filesHeader filesInclude filesfor compiler specific syntax. Eventually include the file<compiler.hcompiler.h (include file)>http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/device/include/mcs51/compiler.hto allow using common header files. (see f.e. cc2510fx.hhttp://svn.code.sf.net/p/sdcc/code/trunk/sdcc/device/include/mcs51/cc2510fx.h).• check whether the startup code contains the correctinitialization (watchdogwatchdog, peripherals).• check whether the sizes of short, int, long match.• check if some 16 or 32 bit hardware registers require aspecific addressing order (least significant or mostsignificant byte first) and adapt if needed (first and lastrelate to time and not to lower/upper memory location here, sothis is not the same as endianness).• check whether the keyword volatilevolatile is used whereneeded. The compilers might differ in their optimizationcharacteristics (as different versions of the same compilermight also use more clever optimizations this is good ideaanyway). See section [subsec:Common-interrupt-pitfall-volatile].• check that the compilers are not told to suppress warnings.• check and convert compiler specific extensions (interrupts,memory areas, pragmas etc.).• check for differences in type promotion. Especially check formath operations on char or unsigned char variables. For thesake of C99 compatibility SDCC will probably promote these toint more often than other compilers. Eventually insert explicitcasts to (char) or (unsigned char). Also check that the ~operator~ Operator is not used on bitbit variables, use the !operator instead. See sections [type promotion] and [sec:Compatibility-with-previous].• check the assembly code generated for interrupt routines (f.e.for calls to possibly non-reentrant library functions).• check whether timing loops result in proper timing (orpreferably consider a rewrite of the code with timer baseddelays instead).• check for differences in printf parametersprintf()!parameters(some compilers push (va_argvararg, vaarg) char variables asint others push them as char. See section [sec:Compatibility-with-previous]). Provide a putchar()printf()!putchar() function if needed.• check the resulting memory mapMemory map. Usage of differentmemory spaces: code, stack, data (for mcs51/ds390 additionallyidata, pdata, xdata). Eventually check if unexpected libraryfunctions are included.6.2 ToolsTools included in the distribution+---------------------------+-----------------------------------------------------------------------+----------------------+| Name | Purpose | Directory |+---------------------------+-----------------------------------------------------------------------+----------------------++---------------------------+-----------------------------------------------------------------------+----------------------+| as2gbmap.py | sdas map to rrgb map and no$gmb sym file format converter | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| cinc2h.pl | gpasm inc to c header file converter | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| gen_known_bugs.pl | generate knownbugs.html | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| keil2sdcc.pl | Keil header Header filesInclude files to SDCC header fileconverter | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| makebin | Intel Hex to binary and GameBoy binay format converter | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| mcs51-disasm.pl | disassembler to the mcs51 instructions contained hex files | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| mh2h.c | header file conversion | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| optimize_pic16devices.pl | optimizes or unoptimizes the pic16devices.txt file | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| packihx | Intel Hex packer packihx (tool) | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| pic14-header-parser.pl | helper to realization of peripheral-handling (PIC14) | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| pic16-header-parser.pl | helper to realization of peripheral-handling (PIC16) | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| pic16fam-h-gen.pl | helper to realization of peripheral-handling (PIC14) | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| pic18fam-h-gen.pl | helper to realization of peripheral-handling (PIC16) | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| repack_release.sh | repack sdcc to release package | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdas390 | assembler | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdas6808 | assembler | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdas8051 | assembler | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdasgb | assembler | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdasz80 | assembler | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdcc_cygwin_mingw32 | cross compile the sdcc with mingw32 under Cygwin | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdcc_mingw32 | cross compile the sdcc with mingw32 | sdcc/support/scripts |+---------------------------+-----------------------------------------------------------------------+----------------------+| SDCDB | simulator | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdld | linker | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdld6808 | linker | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdldgb | linker | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| sdldz80 | linker | sdcc/bin |+---------------------------+-----------------------------------------------------------------------+----------------------+| uCsimuCsim | simulator for various architectures | sdcc/sim/ucsim |6.3 DocumentationDocumentation included in the distribution+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| Subject / Title | Filename / Where to get |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------++-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| SDCC Compiler User Guide | You're reading it right now online at:http://sdcc.sourceforge.net/doc/sdccman.pdf |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| Changelog of SDCC | sdcc/Changelog online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/ChangeLog |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| ASXXXXsdas (sdasgb, sdas6808, sdas8051, sdasz80)Assembler documentationAssemblers andASLINKsdldLinker documentation Relocating Linker | sdcc/sdas/doc/asmlnk.txt online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/sdas/doc/asmlnk.txt |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| SDCC regression testRegression test | test_suite_spec online at:http://sdcc.sourceforge.net/wiki/index.php/Proposed_Test_Suite_Design |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| Various notes | sdcc/doc/* online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/doc/ |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| Notes on debugging with SDCDBSDCDB (debugger) | sdcc/debugger/README online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/debugger/README |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| uCsimuCsim Software simulator for microcontrollers | sdcc/sim/ucsim/doc/index.html online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/sim/ucsim/doc/index.html |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| Temporary notes on the pic16PIC16 port | sdcc/src/pic16/NOTES online at:http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/src/pic16/NOTES |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+| SDCC internal documentation (debugging file format)| sdcc/doc/cdbfileformat.pdf online at:http://sdcc.sourceforge.net/wiki/index.php/CDB_File_Format |+-------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------+6.4 Communication online at SourceForge+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| Subject / Title | Note | Link |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------++------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| wikiwikiCommunication!wiki | | http://sdcc.sourceforge.net/wiki/ |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| sdcc-user mailing listmailing listCommunication!Mailing lists | around 650 subscribers mid 2009 | https://lists.sourceforge.net/mailman/listinfo/sdcc-user |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| sdcc-devel mailing list | | https://lists.sourceforge.net/mailman/listinfo/sdcc-devel |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| help forumCommunication!Forums | similar scope as sdcc-user mailing list | http://sourceforge.net/p/sdcc/discussion/1865 |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| open discussion forum | | http://sourceforge.net/p/sdcc/discussion/1864 |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| trackers (bug tracker, feature requests, patches, supportrequests, webdocs)Communication!Trackers | | http://sourceforge.net/p/sdcc/_list/tickets |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+| rss feedRSS feedCommunication!RSS feed | stay tuned with most (not all) sdcc activities | http://sourceforge.net/export/rss2_keepsake.php?group_id=599 |+------------------------------------------------------------------------------------------------------+-------------------------------------------------+--------------------------------------------------------------+With a sourceforge account you can ”monitor”Communication!Monitorforums and trackers, so that you automatically receive mail onchanges. You can digg out earlier communication by using thesearch function http://sourceforge.net/search/?group_id=599.6.5 Related open source tools<sec:Related-open-source-tools>Related tools+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| Name | Purpose | Where to get |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------++---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| gpsimgpsim (pic simulator) | PIC simulator | http://www.dattalo.com/gnupic/gpsim.html |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| gputilsgputils (pic tools) | GNU PIC utilities | http://sourceforge.net/projects/gputils |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| flP5 | PIC programmer | http://freshmeat.net/projects/flp5/ |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| ec2drv/newcdb | Tools for Silicon Laboratories JTAG debug adapter, partly basedon SDCDB (Unix only) | http://sourceforge.net/projects/ec2drv |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| indentindent (source formatting tool) | Formats C source - Master of the white spaces | http://directory.fsf.org/GNU/indent.html |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| srecordsrecord (bin, hex, ... tool) | Object file conversion, checksumming, ... | http://sourceforge.net/projects/srecord |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| objdumpobjdump (tool) | Object file conversion, ... | Part of binutils (should be there anyway) |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| cmon51 | 8051 monitor (hex up-/download, single step, disassemble) | http://sourceforge.net/projects/cmon51 |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| doxygendoxygen (source documentation tool) | Source code documentation system | http://www.doxygen.org |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| kdevelop | IDE (has anyone tried integrating SDCC & SDCDB? Unix only) | http://www.kdevelop.org |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| paulmon | 8051 monitor (hex up-/download, single step, disassemble) | http://www.pjrc.com/tech/8051/paulmon2.html |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| splintsplint (syntax checking tool) | Statically checks c sources (see [lyx:more-pedantic-SPLINT]) | http://www.splint.org |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| dddDDD (debugger) | Debugger, serves nicely as GUI to SDCDBSDCDB (debugger) (Unixonly) | http://www.gnu.org/software/ddd/ |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| d52d52d52 (disassembler) | Disassembler, can count instruction cyclesinstruction cycles (count), use with options -pnd | http://www.8052.com/users/disasm/ |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+| cmakecmake | Cross platform build system, generates MakefilesMakefile andproject workspacesproject workspace | http://www.cmake.org and a dedicated wiki entry: http://www.cmake.org/Wiki/CmakeSdcc |+---------------------------------------------+----------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------+6.6 Related documentation / recommended reading+--------------------+--------------------------------------------+----------------------------------------------------------------+| Name | Subject / Title | Where to get |+--------------------+--------------------------------------------+----------------------------------------------------------------++--------------------+--------------------------------------------+----------------------------------------------------------------+| c-refcard.pdf | C Reference CardC Reference card, 2 pages | http://refcards.com/refcards/c/index.html |+--------------------+--------------------------------------------+----------------------------------------------------------------+| c-faq | C-FAQC FAQ | http://www.c-faq.com |+--------------------+--------------------------------------------+----------------------------------------------------------------+| ISO/IEC 9899:TC2 | ”C-Standard” | http://www.open-std.org/jtc1/sc22/wg14/www/standards.html#9899 |+--------------------+--------------------------------------------+----------------------------------------------------------------+| ISO/IEC DTR 18037 | ”Extensions for Embedded C” | http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1021.pdf |+--------------------+--------------------------------------------+----------------------------------------------------------------+| | Latest datasheet of target CPU | vendor |+--------------------+--------------------------------------------+----------------------------------------------------------------+| | Revision history of datasheet | vendor |+--------------------+--------------------------------------------+----------------------------------------------------------------+6.7 Application notes specifically for SDCCSDCC makes no claims about the completeness of this list andabout up-to-dateness or correctness of the application notesApplication notes.+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Vendor | Subject / Title | Where to get |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------++--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Maxim / Dallas | Using the SDCC Compiler for the DS80C400DS80C400 | http://pdfserv.maxim-ic.com/en/an/AN3346.pdf |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Maxim / Dallas | Using the Free SDCC C Compiler to Develop Firmware for theDS89C420/430/440/450DS89C4x0 Family of Microcontrollers | http://pdfserv.maxim-ic.com/en/an/AN3477.pdf |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Silicon Laboratories / Cygnal | Integrating SDCC 8051 Tools Into The Silicon Labs IDEIDE |http://www.silabs.com/public/documents/tpub_doc/anote/Microcontrollers/en/an198.pdf |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Ramtron / Goal Semiconductor | Interfacing SDCC to Syn and Textpad |http://www.ramtron.com/doc/Products/Microcontroller/Support_Tools.asp |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Ramtron / Goal Semiconductor | Installing and Configuring SDCC and Crimson Editor |http://www.ramtron.com/doc/Products/Microcontroller/Support_Tools.asp |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+| Texas Instruments | MSC12xx Programming with SDCC |http://focus.ti.com/general/docs/lit/getliterature.tsp?literatureNumber=sbaa109&fileType=pdf |+--------------------------------+----------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------+6.8 Some QuestionsSome questions answered, some pointers given - it might be timeto in turn ask you some questions:• can you solve your project with the selected microcontroller?Would you find out early or rather late that your target is toosmall/slow/whatever? Can you switch to a slightly better deviceif it doesn't fit?• should you solve the problem with an 8 bit CPU? Or would a16/32 bit CPU and/or another programming language be moreadequate? Would an operating system on the target device help?• if you solved the problem, will the marketing department behappy?• if the marketing department is happy, will customers be happy?• if you're the project manager, marketing department and maybeeven the customer in one person, have you tried to see theproject from the outside?• is the project done if you think it is done? Or is just thatother interface/protocol/feature/configuration/option missing?How about website, manual(s), internationali(z|s)ation,packaging, labels, 2nd source for components, electromagneticcompatability/interference, documentation for production,production test software, update mechanism, patent issues?• is your project adequately positioned in that magic triangle:fame, fortune, fun?Maybe not all answers to these questions are known and someanswers may even be no, nevertheless knowing these questions mayhelp you to avoid burnout[footnote:burnout is bad for electronic devices, programmers and motorcycletyres]. Chances are you didn't want to hear some of them...SupportSupportSDCC has grown to be a large project. The compiler alone (withoutthe preprocessor, assembler and linker) is well over 150,000lines of code (blank stripped). The open source nature of thisproject is a key to its continued growth and support. You gainthe benefit and support of many active software developers andend users. Is SDCC perfect? No, that's why we need your help. Thedevelopers take pride in fixing reported bugs. You can help byreporting the bugs and helping other SDCC users. There are lotsof ways to contribute, and we encourage you to take part inmaking SDCC a great software package.The SDCC project is hosted on the SDCC SourceForge site at http://sourceforge.net/projects/sdcc. You'll find the complete set of mailing listsMailing list(s),forums, bug reporting system, patch submissionPatch submissionsystem, wiki, rss-feed, downloaddownload area and Subversion coderepositorySubversion code repository there.7.1 Reporting BugsBug reportingReporting bugsCommunication!Bug reportThe recommended way of reporting bugs is using the infrastructureof the SourceForge site. You can follow the status of bug reportsthere and have an overview about the known bugs.Bug reports are automatically forwarded to the developer mailinglist and will be fixed ASAP. When reporting a bug, it is veryuseful to include a small test program (the smaller the better)which reproduces the problem. If you can isolate the problem bylooking at the generated assembly code, this can be very helpful.Compiling your program with the --dumpall--dumpall option cansometimes be useful in locating optimization problems. Whenreporting a bug please make sure you:1. Attach the code you are compiling with SDCC.2. Specify the exact command you use to run SDCC, or attach yourMakefile.3. Specify the SDCC version (type "sdcc -v"), your platform, andoperating system.4. Provide an exact copy of any error message or incorrectoutput.5. Put something meaningful in the subject of your message.Please attempt to include these 5 important parts, as applicable,in all requests for support or when reporting any problems orbugs with SDCC. Though this will make your message lengthy, itwill greatly improve your chance that SDCC users and developerswill be able to help you. Some SDCC developers are frustrated bybug reports without code provided that they can use to reproduceand ultimately fix the problem, so please be sure to providesample code if you are reporting a bug!Please have a short check that you are using a recent version ofSDCC and the bug is not yet known. This is the link for reportingbugs: http://sourceforge.net/p/sdcc/bugs/. With SDCC on averagehaving more than 200 downloadsdownload on SourceForge per day[footnote:220 daily downloads on average Jan-Sept 2006 and about 150 dailydownloads between 2002 and 2005. This does not include othermethods of distribution.] there must be some users. So it's not exactly easy to find anew bug. If you find one we need it: reporting bugs is good.7.2 Requesting Features<subsec:Requesting-Features>Feature requestRequesting featuresCommunication!Feature requestLike bug reports feature requests are forwarded to the developermailing list. This is the link for requesting features: http://sourceforge.net/p/sdcc/feature-requests/.7.3 Submitting patchesCommunication!Patch submissionLike bug reports contributed patches are forwarded to thedeveloper mailing list. This is the link for submitting patchesPatch submission: http://sourceforge.net/p/sdcc/patches/.You need to specify some parameters to the diff command for thepatches to be useful. If you modified more than one file a patchcreated f.e. with ”diff -Naur unmodified_directorymodified_directory >my_changes.patch” will be fine, otherwise ”diff -u sourcefile.c.orig sourcefile.c >my_changes.patch” willdo.7.4 Getting HelpThese links should take you directly to the Mailing lists http://sourceforge.net/p/sdcc/mailman/sdcc-user/[footnote:Traffic on sdcc-devel and sdcc-user is about 100 mails/month eachnot counting automated messages (mid 2003)] and the Forums http://sourceforge.net/p/sdcc/discussion/, listsMailing list(s)Communication!Mailing lists and forums are archived andsearchable so if you are lucky someone already had a similarproblem. While mails to the lists themselves are deliveredpromptly their web front end on SourceForge sometimes shows asevere time lag (up to several weeks), if you're seriously usingSDCC please consider subscribing to the lists.7.5 ChangeLogYou can follow the status of the Subversion versionversion ofSDCC by watching the ChangelogChangelog in the Subversionrepository http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/ChangeLog.7.6 Subversion Source Code RepositoryThe output of sdcc --version or the filenames of the snapshotversions of SDCC include date and its SubversionSubversion code repositorynumber. Subversion allows to download the source of recent orprevious versions http://sourceforge.net/p/sdcc/code/8805/tree/(by number or by date).7.7 Release policyRelease policyStarting with version 2.4.0 SDCC in 2004 uses a time-basedrelease schedule with one official release usually during thefirst half of the year.The last digit of an official release is zero. Additionally thereare daily snapshots available at http://sdcc.sourceforge.net/snap.php, and you can always build the very last version from the sourcecode available at Sourceforge http://sdcc.sourceforge.net/snap.php#Source. The SDCC WikiwikiSDCC Wiki at http://sdcc.sourceforge.net/wiki/also holds some information about past and future releases.7.8 Quality control<sec:Quality-control>Quality controlThe compiler is passed through daily snapshot build compile andbuild checks. The so called regression testsRegression test checkthat SDCC itself compiles flawlessly on several host platforms(i386, Opteron, 64 bit Alpha, ppc64, Mac OS X on ppc and i386,Solaris on Sparc) and checks the quality of the code generated bySDCC by running the code for several target platforms throughsimulators. The regression test suite comprises about 1000 fileswhich expand to more than 1500 test cases which include about7000 tests. A large number of tests from the GCC test suite isincluded in this. The results of these tests are published dailyon SDCC's snapshot page (click on the red or green symbols on theright side of http://sdcc.sourceforge.net/snap.php).You'll find the test code in the directorysdcc/support/regression. You can run these tests manually byrunning make in this directory (or f.e. ”make test-mcs51” if youdon't want to run the complete tests). The test code might alsobe interesting if you want to look for examplesExamples checkingcorner cases of SDCC or if you plan to submit patchesPatch submission.The PIC14 port uses a different set of regression tests Regression test (PIC14), you'll find them in the directory sdcc/src/regression.7.9 ExamplesExamplesYou'll find some small examples in the directorysdcc/device/examples/. More examples and libraries are availableat The SDCC Open Knowledge Resource http://sdccokr.dl9sec.de/ website or at http://www.pjrc.com/tech/8051/.7.10 Use of SDCC in EducationIn short: highly encouraged[footnote:the phrase "use in education" might evoke the association "onlyfit for use in education". This connotation is not intended butnevertheless risked as the licensing of SDCC makes it difficultto offer educational discounts]. If your rationales are to:1. give students a chance to understand the complete steps ofcode generation2. have a curriculum that can be extended for years. Then youcould use an FPGA board as target and your curriculum willseamlessly extend from logic synthesis(http://www.opencores.org opencores.org, Oregano http://www.oregano.at/ip/ip01.htm), over assembly programming, to C to FPGA compilers (FPGAC http://sourceforge.net/projects/fpgac/) and to C.3. be able to insert excursions about skills like using arevision control system, submitting/applying patches, using atype-setting (as opposed to word-processing) engine LyX/LaTeX,using SourceForge http://sourceforge.net/, following somenetiquette http://en.wikipedia.org/wiki/Netiquette,understanding BSD/LGPL/GPL/Proprietary licensing, growth modelsof Open Source Software, CPU simulation, compiler regressiontestsRegression test.And if there should be a shortage of ideas then you can alwayspoint students to the ever-growing feature request list http://sourceforge.net/p/sdcc/feature-requests/.4. not tie students to a specific host platform and instead allowthem to use a host platform of their choice (among them Alpha,i386, i386_64, Mac OS X, Mips, Sparc, Windows and eventuallyOLPC http://www.laptop.org)5. not encourage students to use illegal copies of educationalsoftware6. be immune to licensing/availability/price changes of thechosen tool chain7. be able to change to a new target platform without having toadopt a new tool chain8. have complete control over and insight into the tool chain9. make your students aware about the pros and cons of opensource software development10. give back to the public as you are probably at leastpartially publicly funded11. give students a chance to publicly prove their skills and topossibly see a world wide impactthen SDCC is probably among the first choices. Well, probablySDCC might be the only choice.SDCC Technical Data8.1 OptimizationsOptimizationsSDCC performs a host of standard optimizations in addition tosome MCU specific optimizations.8.1.1 Sub-expression EliminationSubexpression eliminationThe compiler does local and global common subexpressionelimination, e.g.:i = x + y + 1;j = x + y;will be translated toiTemp = x + y;i = iTemp + 1;j = iTemp;Some subexpressions are not as obvious as the above example,e.g.:a->b[i].c = 10;a->b[i].d = 11;In this case the address arithmetic a->b[i] will be computed onlyonce; the equivalent code in C would be.iTemp = a->b[i];iTemp.c = 10;iTemp.d = 11;The compiler will try to keep these temporary variables inregisters.8.1.2 Dead-Code EliminationDead-code eliminationint global;void f () {int i;i = 1; /* dead store */global = 1; /* dead store */global = 2;return;global = 3; /* unreachable */}will be changed toint global;void f () {global = 2;}8.1.3 Copy-PropagationCopy propagationint f() {int i, j;i = 10;j = i;return j;}will be changed toint f() {int i, j;i = 10;j = 10;return 10;}Note: the dead stores created by this copy propagation will beeliminated by dead-code elimination.8.1.4 Loop OptimizationsLoop optimization<subsec:Loop-Optimizations>Two types of loop optimizations are done by SDCC loop invariantlifting and strength reduction of loop induction variables. Inaddition to the strength reduction the optimizer marks theinduction variables and the register allocator tries to keep theinduction variables in registers for the duration of the loop.Because of this preference of the register allocatorRegister allocation, loop induction optimization causes an increase in registerpressure, which may cause unwanted spilling of other temporaryvariables into the stackstack / data space. The compiler willgenerate a warning message when it is forced to allocate extraspace either on the stack or data space. If this extra spaceallocation is undesirable then induction optimization can beeliminated either for the entire source file (with --noinductionoption) or for a given function only using #pragma noinductionpragma noinduction.Loop Invariant:for (i = 0 ; i < 100 ; i ++)f += k + l;changed toitemp = k + l;for (i = 0; i < 100; i++)f += itemp;As mentioned previously some loop invariants are not as apparent,all static address computations are also moved out of the loop.Strength ReductionStrength reduction, this optimizationsubstitutes an expression by a cheaper expression:for (i=0;i < 100; i++)ar[i*5] = i*3;changed toitemp1 = 0;itemp2 = 0;for (i=0;i< 100;i++) {ar[itemp1] = itemp2;itemp1 += 5;itemp2 += 3;}The more expensive multiplicationMultiplication is changed to aless expensive addition.8.1.5 Loop ReversingLoop reversingThis optimization is done to reduce the overhead of checking loopboundaries for every iteration. Some simple loops can be reversedand implemented using a “decrement and jump if not zero”instruction. SDCC checks for the following criterion to determineif a loop is reversible (note: more sophisticated compilers usedata-dependency analysis to make this determination, SDCC uses amore simple minded analysis).• The 'for' loop is of the formfor(<symbol> = <expression>; <sym> [< | <=] <expression>;[<sym>++ | <sym> += 1])<for body>• The <for body> does not contain “continue” or 'break”.• All goto's are contained within the loop.• No function calls within the loop.• The loop control variable <sym> is not assigned any valuewithin the loop• The loop control variable does NOT participate in anyarithmetic operation within the loop.• There are NO switch statements in the loop.8.1.6 Algebraic SimplificationsSDCC does numerous algebraic simplifications, the following is asmall sub-set of these optimizations.i = j + 0; /* changed to: */ i = j;i /= 2; /* for unsigned i changed to: */ i >>= 1;i = j - j; /* changed to: */ i = 0;i = j / 1; /* changed to: */ i = j;Note the subexpressionsSubexpression given above are generallyintroduced by macro expansions or as a result of copy/constantpropagation.8.1.7 'switch' Statements<subsec:'switch'-Statements>switch statementSDCC can optimize switch statements to jump tablesjump tables. Itmakes the decision based on an estimate of the generated codesize. SDCC is quite liberal in the requirements for jump tablegeneration:• The labels need not be in order, and the starting number neednot be one or zero, the case labels are in numerical sequenceor not too many case labels are missing.switch(i) { switch (i) {case 4: ... case 0: ...case 5: ... case 1: ...case 3: ...case 6: ... case 3: ...case 7: ... case 4: ...case 8: ... case 5: ...case 9: ... case 6: ...case 10: ... case 7: ...case 11: ... case 8: ...} }Both the above switch statements will be implemented using ajump-table. The example to the right side is slightly moreefficient as the check for the lower boundary of the jump-tableis not needed.• The number of case labels is not larger than supported by thetarget architecture.• If the case labels are not in numerical sequence ('gaps'between cases) SDCC checks whether a jump table withadditionally inserted dummy cases is still attractive.• If the starting number is not zero and a check for the lowerboundary of the jump-table can thus be eliminated SDCC mightinsert dummy cases 0, ... .Switch statements which have large gaps in the numeric sequenceor those that have too many case labels can be split into morethan one switch statement for efficient code generation, e.g.:switch (i) {case 1: ...case 2: ...case 3: ...case 4: ...case 5: ...case 6: ...case 7: ...case 101: ...case 102: ...case 103: ...case 104: ...case 105: ...case 106: ...case 107: ...}If the above switch statement is broken down into two switchstatementsswitch (i) {case 1: ...case 2: ...case 3: ...case 4: ...case 5: ...case 6: ...case 7: ...}andswitch (i) {case 101: ...case 102: ...case 103: ...case 104: ...case 105: ...case 106: ...case 107: ...}then both the switch statements will be implemented usingjump-tables whereas the unmodified switch statement will not be.8.1.8 Bit-shifting OperationsBit shifting.Bit shifting is one of the most frequently used operation inembedded programming. SDCC tries to implement bit-shiftoperations in the most efficient way possible, e.g.:unsigned char i;...i >>= 4;...generates the following code:mov a,_iswap aanl a,#0x0fmov _i,aIn general SDCC will never setup a loop if the shift count isknown. Another example:unsigned int i;...i >>= 9;...will generate:mov a,(_i + 1)mov (_i + 1),#0x00clr crrc amov _i,a8.1.9 Bit-rotationBit rotationA special case of the bit-shift operation is bit rotationrotating bits, SDCC recognizes the following expression to be a leftbit-rotation:unsigned char i; /* unsigned is needed for rotation */...i = ((i << 1) | (i >> 7));...will generate the following code:mov a,_irl amov _i,aSDCC uses pattern matching on the parse tree to determine thisoperation.Variations of this case will also be recognized asbit-rotation, i.e.:i = ((i >> 7) | (i << 1)); /* left-bit rotation */8.1.10 Nibble and Byte SwappingOther special cases of the bit-shift operations are nibble orbyte swappingswapping nibbles/bytes, SDCC recognizes thefollowing expressions:unsigned char i;unsigned int j;...i = ((i << 4) | (i >> 4));j = ((j << 8) | (j >> 8));and generates a swap instruction for the nibble swappingNibble swappingor move instructions for the byte swappingByte swapping. The ”j”example can be used to convert from little to big-endian or viceversa. If you want to change the endianness of a signed integeryou have to cast to (unsigned int) first.Note that SDCC stores numbers in little-endian[footnote:Usually 8-bit processors don't care much about endianness. Thisis not the case for the standard 8051 which only has aninstruction to increment its dptrDPTR-datapointer solittle-endian is the more efficient byte order.]little-endianEndianness format (i.e. lowest order first).8.1.11 Highest Order BitHighest Order Bit / Any Order BitAny Order BitIt is frequently required to obtain the highest order bit of anintegral type (long, int, short or char types). Also obtainingany other order bit is not uncommon. SDCC recognizes thefollowing expressions to yield the highest order bit andgenerates optimized code for it, e.g.:unsigned int gint;foo () {unsigned char hob1, aob1;bit hob2, hob3, aob2, aob3;...hob1 = (gint >> 15) & 1;hob2 = (gint >> 15) & 1;hob3 = gint & 0x8000;aob1 = (gint >> 9) & 1;aob2 = (gint >> 8) & 1;aob3 = gint & 0x0800;...}will generate the following code:61 ; hob.c 7000A E5*01 62 mov a,(_gint + 1)000C 23 63 rl a000D 54 01 64 anl a,#0x01000F F5*02 65 mov _foo_hob1_1_1,a66 ; hob.c 80011 E5*01 67 mov a,(_gint + 1)0013 33 68 rlc a0014 92*00 69 mov _foo_hob2_1_1,c66 ; hob.c 90016 E5*01 67 mov a,(_gint + 1)0018 33 68 rlc a0019 92*01 69 mov _foo_hob3_1_1,c70 ; hob.c 10001B E5*01 71 mov a,(_gint + 1)001D 03 72 rr a001E 54 01 73 anl a,#0x010020 F5*03 74 mov _foo_aob1_1_1,a75 ; hob.c 110022 E5*01 76 mov a,(_gint + 1)0024 13 77 rrc a0025 92*02 78 mov _foo_aob2_1_1,c79 ; hob.c 120027 E5*01 80 mov a,(_gint + 1)0029 A2 E3 81 mov c,acc[3]002B 92*03 82 mov _foo_aob3_1_1,cOther variations of these cases however will not be recognized.They are standard C expressions, so I heartily recommend these bethe only way to get the highest order bit, (it is portable). Ofcourse it will be recognized even if it is embedded in otherexpressions, e.g.:xyz = gint + ((gint >> 15) & 1);will still be recognized.8.1.12 Higher Order ByteHigher Order Byte / Higher Order WordHigher Order WordIt is also frequently required to obtain a higher order byte orword of a larger integral type (long, int or short types). SDCCrecognizes the following expressions to yield the higher orderbyte or word and generates optimized code for it, e.g.:unsigned int gint;unsigned long int glong;foo () {unsigned char hob1, hob2;unsigned int how1, how2;...hob1 = (gint >> 8) & 0xFF;hob2 = glong >> 24;how1 = (glong >> 16) & 0xFFFF;how2 = glong >> 8;...}will generate the following code:91 ; hob.c 150037 85*01*06 92 mov _foo_hob1_1_1,(_gint +1)93 ; hob.c 16003A 85*05*07 94 mov _foo_hob2_1_1,(_glong+ 3)95 ; hob.c 17003D 85*04*08 96 mov _foo_how1_1_1,(_glong+ 2)0040 85*05*09 97 mov (_foo_how1_1_1 +1),(_glong + 3)0043 85*03*0A 98 mov _foo_how2_1_1,(_glong+ 1)0046 85*04*0B 99 mov (_foo_how2_1_1 +1),(_glong + 2)Again, variations of these cases may not be recognized. They arestandard C expressions, so I heartily recommend these be the onlyway to get the higher order byte/word, (it is portable). Ofcourse it will be recognized even if it is embedded in otherexpressions, e.g.:xyz = gint + ((gint >> 8) & 0xFF);will still be recognized.8.1.13 Placement of Bank-Selection InstructionsFor non-intrinsic named address spaces, SDCC will place the bankselection instructions optimally. For details see Philipp KlausKrause, ”Optimal Placement of Bank Selection Instructions inPolynomial Time”, Proceedings of the 16th International Workshopon Software and Compilers for Embedded Systems, M-SCOPES ’13, pp23–30. Association for Computing Machinery, 2013.8.1.14 Lifetime-Optimal Speculative Partial RedundancyEliminationSDCC has an implementation of lifetime-optimal speculativepartial redundancy elimination based on tree-decompositions.8.1.15 Register Allocation<subsec:Register-Allocation>Register-AllocationSDCC currently has two register allocators. One of them isoptimal when optimizing for code size. This register allocator isused by default on the hc08, s08, z80, z180, r2k, r3ka, gbz80 andstm8 ports. Even though it runs in polynomial time, it can bequite slow; therefore the --max-allocs-per-node command lineoption can be used for a trade-off between compilation speed andquality of the generated code: Lower values result in fastercompilation, higher values can result in better code beinggenerated.It first creates a tree-decomposition of the control-flow graph,and then uses dynamic programming bottom-up along thetree-decomposition. Optimality is achieved through the use of acost function, which gives cost for instructions under registerassignments. The cost function is target-specific and has to beimplemented for each port; in all current SDCC ports the costfunction is integrated into code generation.For more details on how this register allocator works, see:Philipp Klaus Krause, ”Optimal Register Allocation in PolynomialTime”, Compiler Construction - 22nd International Conference, CC2013, Held as Part of the European Joint Conferences on Theoryand Practice of Software, ETAPS 2013. Proceedings, Lecture Notesin Computer Science, volume 7791, pp. 1-20. Springer, 2013. Also:Philipp Klaus Krause, ”Bytewise Register Allocation”, Proceedingsof the 18th International Workshop on Software and Compilers forEmbedded Systems, SCOPES ’15, pp 22–27. Association for ComputingMachinery, 2015.8.1.16 Peephole Optimizer<subsec:Peephole-Optimizer>Peephole optimizerThe compiler uses a rule based, pattern matching and re-writingmechanism for peep-hole optimization. It is inspired by copt apeep-hole optimizer by Christopher W. Fraser (cwfraser @microsoft.com). A default set of rules are compiled into thecompiler, additional rules may be added with the --peep-file--peep-file<filename> option. The rule language is best illustrated withexamples.replace {mov %1,amov a,%1} by {mov %1,a}The above rule will change the following assemblyAssembler routinessequence:mov r1,amov a,r1tomov r1,aNote: All occurrences of a %n (pattern variable) must denote thesame string. With the above rule, the assembly sequence:mov r1,amov a,r2will remain unmodified.Other special case optimizations may be added by the user (via --peep-file option). E.g. some variants of the 8051 MCUMCS51 variantsallow only ajmp and acall. The following two rules will changeall ljmp and lcall to ajmp and acallreplace { lcall %1 } by { acall %1 }replace { ljmp %1 } by { ajmp %1 }(NOTE: from version 2.7.3 on, you can use option --acall-ajmp--acall-ajmp, which also takes care of aligning the interrupt vectorsproperly.)The inline-assembler code is also passed through the peep holeoptimizer, thus the peephole optimizer can also be used as anassembly level macro expander. The rules themselves are MCUdependent whereas the rule language infra-structure is MCUindependent. Peephole optimization rules for other MCU can beeasily programmed using the rule language.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 instructionincluding labels must be on a separate line).The optimizer will apply to the rules one by one from the top inthe sequence of their appearance, it will terminate when allrules are exhausted. If the 'restart' option is specified, thenthe optimizer will start matching the rules again from the top,this option for a rule is expensive (performance), it is intendedto be used in situations where a transformation will trigger thesame rule again. An example of this (not a good one, it has sideeffects) is the following rule:replace restart {pop %1push %1 } by {; nop}Note that the replace pattern cannot be a blank, but can be acomment line. Without the 'restart' option only the innermost'pop' 'push' pair would be eliminated, i.e.:pop ar1pop ar2push ar2push ar1would result in:pop ar1; noppush ar1with the restart option the rule will be applied again to theresulting code and then all the pop-push pairs will be eliminatedto yield:; nop; nopA conditional function can be attached to a rule. Attaching rulesare somewhat more involved, let's illustrate this with anexample.replace {ljmp %5%2:} by {sjmp %5%2:} if labelInRangeThe optimizer does a look-up of a function name table defined infunction callFuncByName in the source file SDCCpeeph.c, with thename labelInRange. If it finds a corresponding entry the functionis called. Note there can be no parameters specified for some ofthese functions, in this case the use of %5 is crucial, since thefunction labelInRange expects to find the label in thatparticular variable (the hash table containing the variablebindings is passed as a parameter). If you want to code more suchfunctions, take a close look at the function labelInRange and thecalling mechanism in source file SDCCpeeph.c. Currentlyimplemented are labelInRange, labelRefCount, labelRefCountChange,labelIsReturnOnly, xramMovcOption, portIsDS390, 24bitMode,notVolatile. notUsed, notSame, operandsNotRelated,labelJTInRange, canAssign, optimizeReturn, notUsedFrom,labelIsReturnOnly, operandsLiteral, labelIsUncondJump, deadMove,useAcallAjmp and okToRemoveSLOC.This whole thing is a little kludgy, but maybe some day SDCC willhave some better means. If you are looking at the peeph*.deffiles, you will see the default rules that are compiled into thecompiler, you can add your own rules in the default set there ifyou get tired of specifying the --peep-file option.8.2 Cyclomatic ComplexityCyclomatic complexityCyclomatic complexity of a function is defined as the number ofindependent paths the program can take during execution of thefunction. This is an important number since it defines the numbertest cases you have to generate to validate the function. Theaccepted industry standard for complexity number is 10, if thecyclomatic complexity reported by SDCC exceeds 10 you shouldthink about simplification of the function logic. Note that thecomplexity level is not related to the number of lines of code ina function. Large functions can have low complexity, and smallfunctions can have large complexity levels.SDCC uses the following formula to compute the complexity:complexity = (number of edges in control flow graph) - (number ofnodes in control flow graph) + 2;Having said that the industry standard is 10, you should be awarethat in some cases it be may unavoidable to have a complexitylevel of less than 10. For example if you have switch statementwith more than 10 case labels, each case label adds one to thecomplexity level. The complexity level is by no means an absolutemeasure of the algorithmic complexity of the function, it doeshowever provide a good starting point for which functions youmight look at for further optimization.8.3 Retargetting for other ProcessorsThe issues for retargetting the compiler are far too numerous tobe covered by this document. What follows is a brief descriptionof each of the phases of the compiler and its MCU dependency.• Parsing the source and building the annotated parse tree. Thisphase is largely MCU independent (except for the languageextensions). Syntax & semantic checks are also done in thisphase, along with some initial optimizations like back patchinglabels and the pattern matching optimizations like bit-rotationetc.• The second phase involves generating an intermediate code whichcan be easy manipulated during the later phases. This phase isentirely MCU independent. The intermediate code generationassumes the target machine has unlimited number of registers,and designates them with the name iTemp. The compiler can bemade to dump a human readable form of the code generated byusing the --dumpraw option.• This phase does the bulk of the standard optimizations and isalso MCU independent. This phase can be broken down intoseveral sub-phases:Break down intermediate code (iCode) into basic blocks.Do control flow & data flow analysis on the basic blocks.Do local common subexpression elimination, then globalsubexpression eliminationDead code eliminationLoop optimizationsIf loop optimizations caused any changes then do 'globalsubexpression elimination' and 'dead code elimination' again.• This phase determines the live-ranges; by live range I meanthose iTemp variables defined by the compiler that stillsurvive after all the optimizations. Live range analysisLive range analysisis essential for register allocation, since these computationdetermines which of these iTemps will be assigned to registers,and for how long.• Phase five is register allocation. For new ports registerallocator described above in [subsec:Register-Allocation]should be used in most cases, since it can result insubstantially better code. In the old register allocator, thereare two parts to register allocation.The first part I call 'register packing' (for lack of a betterterm). In this case several MCU specific expression folding isdone to reduce register pressure.The second part is more MCU independent and deals with allocatingregisters to the remaining live ranges. A lot of MCU specificcode does creep into this phase because of the limited numberof index registers available in the 8051.• The Code generation phase is (unhappily), entirely MCUdependent and very little (if any at all) of this code can bereused for other MCU. However the scheme for allocating ahomogenized assembler operand for each iCode operand may bereused.• As mentioned in the optimization section the peep-holeoptimizer is rule based system, which can reprogrammed forother MCUs.More information is available on SDCC Wikiwiki (preliminary linkhttp://sdcc.sourceforge.net/wiki/index.php/SDCC_internals_and_porting) and in the thread http://sourceforge.net/mailarchive/message.php?msg_id=13954144.Compiler internalsCompiler internals9.1 The anatomy of the compiler<subsec:The-anatomy-of>This is an excerpt from an article published in Circuit CellarMagazine in August 2000. It's outdated (the compiler is much moreefficient now and user/developer friendly), but pretty wellexposes the guts of it all.The current version of SDCC can generate code for Intel 8051 andZ80 MCU. It is fairly easy to retarget for other 8-bit MCU. Herewe take a look at some of the internals of the compiler.ParsingParsingParsing the input source file and creating an AST (AnnotatedSyntax TreeAnnotated syntax tree). This phase also involvespropagating types (annotating each node of the parse tree withtype information) and semantic analysis. There are some MCUspecific parsing rules. For example the intrinsic named addressspaces are MCU specific: While there may be an __xdata intrinsicnamed address space for 8051 there none for z80. SDCC has MCUspecific intrinsic named address spacess, i.e. __xdata will betreated as a named address space when parsing 8051 C code butwill be treated as a C identifier when parsing z80 code.Generating iCodeiCodeIntermediate code generation. In this phase the AST is brokendown into three-operand form (iCode). These three operand formsare represented as doubly linked lists. ICode is the term givento the intermediate form generated by the compiler. ICode examplesection shows some examples of iCode generated for some simple Csource functions.OptimizationsOptimizations.Bulk of the target independent optimizations is performed in thisphase. The optimizations include constant propagation, commonsub-expression elimination, loop invariant code movement,strength reduction of loop induction variables and dead-codeelimination.Live range analysisLive range analysisDuring intermediate code generation phase, the compiler assumesthe target machine has infinite number of registers and generatesa lot of temporary variables. The live range computationdetermines the lifetime of each of these compiler-generatedtemporaries. A picture speaks a thousand words. ICode examplesections show the live range annotations for each of the operand.It is important to note here, each iCode is assigned a number inthe order of its execution in the function. The live ranges arecomputed in terms of these numbers. The from number is the numberof the iCode which first defines the operand and the to numbersignifies the iCode which uses this operand last.Register AllocationRegister allocationThe register allocation determines the type and number ofregisters needed by each operand. In most MCUs only a fewregisters can be used for indirect addressing. In case of 8051for example the registers R0 & R1 can be used to indirectlyaddress the internal ram and DPTR to indirectly address theexternal ram. The compiler will try to allocate the appropriateregister to pointer variables if it can. ICode example sectionshows the operands annotated with the registers assigned to them.The compiler will try to keep operands in registers as much aspossible; there are several schemes the compiler uses to doachieve this. When the compiler runs out of registers thecompiler will check to see if there are any live operands whichis not used or defined in the current basic block beingprocessed, if there are any found then it will push that operandand use the registers in this block, the operand will then bepopped at the end of the basic block.There are other MCU specific considerations in this phase. SomeMCUs have an accumulator; very short-lived operands could beassigned to the accumulator instead of a general-purposeregister.Code generationFigure II gives a table of iCodeiCode operations supported by thecompiler. The code generation involves translating theseoperations into corresponding assembly code for the processor.This sounds overly simple but that is the essence of codegeneration. Some of the iCode operations are generated on a MCUspecific manner for example, the z80 port does not use registersto pass parameters so the SEND and RECV iCode operations will notbe generated, and it also does not support JUMPTABLES.Figure II+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| iCodeiCode | Operands | Description | C Equivalent |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------++------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '!' | IC_LEFT() IC_RESULT() | NOT operation | IC_RESULT = ! IC_LEFT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '~' | IC_LEFT() IC_RESULT() | Bitwise complement of | IC_RESULT = ~IC_LEFT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| RRC | IC_LEFT() IC_RESULT() | Rotate right with carry | IC_RESULT = (IC_LEFT << 1) | (IC_LEFT >> (sizeof(IC_LEFT)*8-1)); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| RLC | IC_LEFT() IC_RESULT() | Rotate left with carry | IC_RESULT = (IC_LEFT << (sizeof(LC_LEFT)*8-1) ) | (IC_LEFT >> 1); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| GETHBIT | IC_LEFT() IC_RESULT() | Get the highest order bit of IC_LEFT | IC_RESULT = (IC_LEFT >> (sizeof(IC_LEFT)*8 -1)); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| UNARYMINUS | IC_LEFT() IC_RESULT() | Unary minus | IC_RESULT = - IC_LEFT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| IPUSH | IC_LEFT() | Push the operand into stack | NONE |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| IPOP | IC_LEFT() | Pop the operand from the stack | NONE |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| CALL | IC_LEFT() IC_RESULT() | Call the function represented by IC_LEFT | IC_RESULT = IC_LEFT(); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| PCALL | IC_LEFT() IC_RESULT() | Call via function pointer | IC_RESULT = (*IC_LEFT)(); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| RETURN | IC_LEFT() | Return the value in operand IC_LEFT | return IC_LEFT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| LABEL | IC_LABEL() | Label | IC_LABEL: |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| GOTO | IC_LABEL() | Goto label | goto IC_LABEL(); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '+' | IC_LEFT() IC_RIGHT() IC_RESULT() | Addition | IC_RESULT = IC_LEFT + IC_RIGHT |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '-' | IC_LEFT() IC_RIGHT() IC_RESULT() | Subtraction | IC_RESULT = IC_LEFT - IC_RIGHT |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '*' | IC_LEFT() IC_RIGHT() IC_RESULT() | Multiplication | IC_RESULT = IC_LEFT * IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '/' | IC_LEFT() IC_RIGHT() IC_RESULT() | Division | IC_RESULT = IC_LEFT / IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '%' | IC_LEFT() IC_RIGHT() IC_RESULT() | Modulus | IC_RESULT = IC_LEFT % IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '<' | IC_LEFT() IC_RIGHT() IC_RESULT() | Less than | IC_RESULT = IC_LEFT < IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '>' | IC_LEFT() IC_RIGHT() IC_RESULT() | Greater than | IC_RESULT = IC_LEFT > IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| EQ_OP | IC_LEFT() IC_RIGHT() IC_RESULT() | Equal to | IC_RESULT = IC_LEFT == IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| AND_OP | IC_LEFT() IC_RIGHT() IC_RESULT() | Logical and operation | IC_RESULT = IC_LEFT && IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| OR_OP | IC_LEFT() IC_RIGHT() IC_RESULT() | Logical or operation | IC_RESULT = IC_LEFT || IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '^' | IC_LEFT() IC_RIGHT() IC_RESULT() | Exclusive OR | IC_RESULT = IC_LEFT ^ IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '|' | IC_LEFT() IC_RIGHT() IC_RESULT() | Bitwise OR | IC_RESULT = IC_LEFT | IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| BITWISEAND | IC_LEFT() IC_RIGHT() IC_RESULT() | Bitwise AND | IC_RESULT = IC_LEFT & IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| LEFT_OP | IC_LEFT() IC_RIGHT() IC_RESULT() | Left shift | IC_RESULT = IC_LEFT << IC_RIGHT |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| RIGHT_OP | IC_LEFT() IC_RIGHT() IC_RESULT() | Right shift | IC_RESULT = IC_LEFT >> IC_RIGHT |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| GET_VALUE_AT_ ADDRESS | IC_LEFT() IC_RESULT() | Indirect fetch | IC_RESULT = (*IC_LEFT); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| POINTER_SET | IC_RIGHT() IC_RESULT() | Indirect set | (*IC_RESULT) = IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| '=' | IC_RIGHT() IC_RESULT() | Assignment | IC_RESULT = IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| IFX | IC_COND IC_TRUE IC_LABEL | Conditional jump. If true label is present then jump to truelabel if condition is true else jump to false label if conditionis false | if (IC_COND) goto IC_TRUE;OrIf (!IC_COND) goto IC_FALSE; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| ADDRESS_OF | IC_LEFT() IC_RESULT() | Address of | IC_RESULT = &IC_LEFT(); |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| JUMPTABLE | IC_JTCOND IC_JTLABELS | Jump to list of labels depending on the value of JTCOND | Switch statement |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| CAST | IC_RIGHT() IC_LEFT() IC_RESULT() | Cast types | IC_RESULT = (typeof IC_LEFT) IC_RIGHT; |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| SEND | IC_LEFT() | This is used for passing parameters in registers;move IC_LEFT to the next available parameter register. | None |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| RECV | IC_RESULT() | This is used for receiving parameters passed in registers;Move the values in the next parameter register to IC_RESULT | None |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+| (some more have been added) | | | see f.e. gen51Code() in src/mcs51/gen.c |+------------------------------+------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------+ICode ExampleiCodeThis section shows some details of iCode. The example C code doesnot do anything useful; it is used as an example to illustratethe intermediate code generated by the compiler.1. __xdata int * p;2. int gint;3. /* This function does nothing useful. It is used4. for the purpose of explaining iCode */5. short function (__data int *x)6. {7. short i=10; /* dead initialization eliminated */8. short sum=10; /* dead initialization eliminated */9. short mul;10. int j ;11. while (*x) *x++ = *p++;12. sum = 0 ;13. mul = 0;14. /* compiler detects i,j to be induction variables */15. for (i = 0, j = 10 ; i < 10 ; i++, j--) {16. sum += i;17. mul += i * 3; /* this multiplication remains */18. gint += j * 3; /* this multiplication changed to addition*/19. }20. return sum+mul;21. }In addition to the operands each iCode contains information aboutthe filename and line it corresponds to in the source file. Thefirst field in the listing should be interpreted as follows:Filename(linenumber: iCode Execution sequence number : ICode hashtable key : loop depth of the iCode).Then follows the human readable form of the ICode operation. Eachoperand of this triplet form can be of three basic types a)compiler generated temporary b) user defined variable c) aconstant value. Note that local variables and parameters arereplaced by compiler generated temporaries. Live rangesLive range analysisare computed only for temporaries (i.e. live ranges are notcomputed for global variables). RegistersRegister allocation areallocated for temporaries only. Operands are formatted in thefollowing manner:Operand Name [lr live-from : live-to ] { type information } [registers allocated ].As mentioned earlier the live ranges are computed in terms of theexecution sequence number of the iCodes, for examplethe iTemp0 is live from (i.e. first defined in iCode withexecution sequence number 3, and is last used in the iCode withsequence number 5). For induction variables such as iTemp21 thelive range computation extends the lifetime from the start to theend of the loop.The register allocator used the live range information toallocate registers, the same registers may be used for differenttemporaries if their live ranges do not overlap, for example r0is allocated to both iTemp6 and to iTemp17 since their liveranges do not overlap. In addition the allocator also takes intoconsideration the type and usage of a temporary, for exampleitemp6 is a pointer to near space and is used as to fetch datafrom (i.e. used in GET_VALUE_AT_ADDRESS) so it is allocated apointer register (r0). Some short lived temporaries are allocatedto special registers which have meaning to the code generatore.g. iTemp13 is allocated to a pseudo register CC which tells theback end that the temporary is used only for a conditional jumpthe code generation makes use of this information to optimize acompare and jump ICode.There are several loop optimizationsLoop optimization performedby the compiler. It can detect induction variables iTemp21(i) andiTemp23(j). Also note the compiler does selective strengthreductionStrength reduction, i.e. the multiplication of aninduction variable in line 18 (gint = j * 3) is changed toaddition, a new temporary iTemp17 is allocated and assigned ainitial value, a constant 3 is then added for each iteration ofthe loop. The compiler does not change the multiplicationMultiplicationin line 17 however since the processor does support an 8 * 8 bitmultiplication.Note the dead code eliminationDead-code elimination optimizationeliminated the dead assignments in line 7 & 8 to I and sumrespectively.Sample.c (5:1:0:0) _entry($9) :Sample.c(5:2:1:0) proc _function [lr0:0]{function short}Sample.c(11:3:2:0) iTemp0 [lr3:5]{_near * int}[r2] = recvSample.c(11:4:53:0) preHeaderLbl0($11) :Sample.c(11:5:55:0) iTemp6 [lr5:16]{_near * int}[r0] := iTemp0[lr3:5]{_near * int}[r2]Sample.c(11:6:5:1) _whilecontinue_0($1) :Sample.c(11:7:7:1) iTemp4 [lr7:8]{int}[r2 r3] = @[iTemp6[lr5:16]{_near * int}[r0]]Sample.c(11:8:8:1) if iTemp4 [lr7:8]{int}[r2 r3] == 0 goto_whilebreak_0($3)Sample.c(11:9:14:1) iTemp7 [lr9:13]{_far * int}[DPTR] := _p[lr0:0]{_far * int}Sample.c(11:10:15:1) _p [lr0:0]{_far * int} = _p [lr0:0]{_far *int} + 0x2 {short}Sample.c(11:13:18:1) iTemp10 [lr13:14]{int}[r2 r3] = @[iTemp7[lr9:13]{_far * int}[DPTR]]Sample.c(11:14:19:1) *(iTemp6 [lr5:16]{_near * int}[r0]) :=iTemp10 [lr13:14]{int}[r2 r3]Sample.c(11:15:12:1) iTemp6 [lr5:16]{_near * int}[r0] = iTemp6[lr5:16]{_near * int}[r0] + 0x2 {short}Sample.c(11:16:20:1) goto _whilecontinue_0($1)Sample.c(11:17:21:0)_whilebreak_0($3) :Sample.c(12:18:22:0) iTemp2 [lr18:40]{short}[r2] := 0x0 {short}Sample.c(13:19:23:0) iTemp11 [lr19:40]{short}[r3] := 0x0 {short}Sample.c(15:20:54:0)preHeaderLbl1($13) :Sample.c(15:21:56:0) iTemp21 [lr21:38]{short}[r4] := 0x0 {short}Sample.c(15:22:57:0) iTemp23 [lr22:38]{int}[r5 r6] := 0xa {int}Sample.c(15:23:58:0) iTemp17 [lr23:38]{int}[r7 r0] := 0x1e {int}Sample.c(15:24:26:1)_forcond_0($4) :Sample.c(15:25:27:1) iTemp13 [lr25:26]{char}[CC] = iTemp21[lr21:38]{short}[r4] < 0xa {short}Sample.c(15:26:28:1) if iTemp13 [lr25:26]{char}[CC] == 0 goto_forbreak_0($7)Sample.c(16:27:31:1) iTemp2 [lr18:40]{short}[r2] = iTemp2[lr18:40]{short}[r2] + ITemp21 [lr21:38]{short}[r4]Sample.c(17:29:33:1) iTemp15 [lr29:30]{short}[r1] = iTemp21[lr21:38]{short}[r4] * 0x3 {short}Sample.c(17:30:34:1) iTemp11 [lr19:40]{short}[r3] = iTemp11[lr19:40]{short}[r3] + iTemp15 [lr29:30]{short}[r1]Sample.c(18:32:36:1:1) iTemp17 [lr23:38]{int}[r7 r0]= iTemp17[lr23:38]{int}[r7 r0]- 0x3 {short}Sample.c(18:33:37:1) _gint [lr0:0]{int} = _gint [lr0:0]{int} +iTemp17 [lr23:38]{int}[r7 r0]Sample.c(15:36:42:1) iTemp21 [lr21:38]{short}[r4] = iTemp21[lr21:38]{short}[r4] + 0x1 {short}Sample.c(15:37:45:1) iTemp23 [lr22:38]{int}[r5 r6]= iTemp23[lr22:38]{int}[r5 r6]- 0x1 {short}Sample.c(19:38:47:1) goto _forcond_0($4)Sample.c(19:39:48:0)_forbreak_0($7) :Sample.c(20:40:49:0) iTemp24 [lr40:41]{short}[DPTR] = iTemp2[lr18:40]{short}[r2] + ITemp11 [lr19:40]{short}[r3]Sample.c(20:41:50:0) ret iTemp24 [lr40:41]{short}Sample.c(20:42:51:0)_return($8) :Sample.c(20:43:52:0) eproc _function [lr0:0]{ ia0 re0rm0}{function short}Finally the code generated for this function:.area DSEG (DATA)_p::.ds 2_gint::.ds 2; sample.c 5; ———————————————-; function function; ———————————————-_function:; iTemp0 [lr3:5]{_near * int}[r2] = recvmov r2,dpl; iTemp6 [lr5:16]{_near * int}[r0] := iTemp0 [lr3:5]{_near *int}[r2]mov ar0,r2;_whilecontinue_0($1) :00101$:; iTemp4 [lr7:8]{int}[r2 r3] = @[iTemp6 [lr5:16]{_near *int}[r0]]; if iTemp4 [lr7:8]{int}[r2 r3] == 0 goto _whilebreak_0($3)mov ar2,@r0inc r0mov ar3,@r0dec r0mov a,r2orl a,r3jz 00103$00114$:; iTemp7 [lr9:13]{_far * int}[DPTR] := _p [lr0:0]{_far * int}mov dpl,_pmov dph,(_p + 1); _p [lr0:0]{_far * int} = _p [lr0:0]{_far * int} + 0x2 {short}mov a,#0x02add a,_pmov _p,aclr aaddc a,(_p + 1)mov (_p + 1),a; iTemp10 [lr13:14]{int}[r2 r3] = @[iTemp7 [lr9:13]{_far *int}[DPTR]]movx a,@dptrmov r2,ainc dptrmovx a,@dptrmov r3,a; *(iTemp6 [lr5:16]{_near * int}[r0]) := iTemp10[lr13:14]{int}[r2 r3]mov @r0,ar2inc r0mov @r0,ar3; iTemp6 [lr5:16]{_near * int}[r0] =; iTemp6 [lr5:16]{_near * int}[r0] +; 0x2 {short}inc r0; goto _whilecontinue_0($1)sjmp 00101$; _whilebreak_0($3) :00103$:; iTemp2 [lr18:40]{short}[r2] := 0x0 {short}mov r2,#0x00; iTemp11 [lr19:40]{short}[r3] := 0x0 {short}mov r3,#0x00; iTemp21 [lr21:38]{short}[r4] := 0x0 {short}mov r4,#0x00; iTemp23 [lr22:38]{int}[r5 r6] := 0xa {int}mov r5,#0x0Amov r6,#0x00; iTemp17 [lr23:38]{int}[r7 r0] := 0x1e {int}mov r7,#0x1Emov r0,#0x00; _forcond_0($4) :00104$:; iTemp13 [lr25:26]{char}[CC] = iTemp21 [lr21:38]{short}[r4] <0xa {short}; if iTemp13 [lr25:26]{char}[CC] == 0 goto _forbreak_0($7)clr cmov a,r4xrl a,#0x80subb a,#0x8ajnc 00107$00115$:; iTemp2 [lr18:40]{short}[r2] = iTemp2 [lr18:40]{short}[r2] +; iTemp21 [lr21:38]{short}[r4]mov a,r4add a,r2mov r2,a; iTemp15 [lr29:30]{short}[r1] = iTemp21 [lr21:38]{short}[r4] *0x3 {short}mov b,#0x03mov a,r4mul abmov r1,a; iTemp11 [lr19:40]{short}[r3] = iTemp11 [lr19:40]{short}[r3] +; iTemp15 [lr29:30]{short}[r1]add a,r3mov r3,a; iTemp17 [lr23:38]{int}[r7 r0]= iTemp17 [lr23:38]{int}[r7 r0]-0x3 {short}mov a,r7add a,#0xfdmov r7,amov a,r0addc a,#0xffmov r0,a; _gint [lr0:0]{int} = _gint [lr0:0]{int} + iTemp17[lr23:38]{int}[r7 r0]mov a,r7add a,_gintmov _gint,amov a,r0addc a,(_gint + 1)mov (_gint + 1),a; iTemp21 [lr21:38]{short}[r4] = iTemp21 [lr21:38]{short}[r4] +0x1 {short}inc r4; iTemp23 [lr22:38]{int}[r5 r6]= iTemp23 [lr22:38]{int}[r5 r6]-0x1 {short}dec r5cjne r5,#0xff,00104$dec r6; goto _forcond_0($4)sjmp 00104$; _forbreak_0($7) :00107$:; ret iTemp24 [lr40:41]{short}mov a,r3add a,r2mov dpl,a; _return($8) :00108$:ret9.2 A few words about basic block successors, predecessors anddominatorsSuccessors are basic blocksBasic blocks that might execute afterthis basic block.Predecessors are basic blocks that might execute before reachingthis basic block.Dominators are basic blocks that WILL execute before reachingthis basic block.[basic block 1]if (something)[basic block 2]else[basic block 3][basic block 4]a) succList of [BB2] = [BB4], of [BB3] = [BB4], of [BB1] =[BB2,BB3]b) predList of [BB2] = [BB1], of [BB3] = [BB1], of [BB4] =[BB2,BB3]c) domVect of [BB4] = BB1 ... here we are not sure if BB2 or BB3was executed but we are SURE that BB1 was executed.Acknowledgmentshttp://sdcc.sourceforge.net/#WhoThanks to all the other volunteer developers who have helped withcoding, testing, web-page creation, distribution sets, etc. Youknow who you are :-)Thanks to Sourceforge http://sourceforge.net/ which has hostedthe project since 1999 and donates significant downloadbandwidth.Also thanks to all SDCC Distributed Compile Farm members fordonating CPU cycles and bandwidth for snapshot builds.This document was initially written by Sandeep Dutta and updatedby SDCC developers.All product names mentioned herein may be trademarksTrademarks oftheir respective companies.Alphabetical indexTo avoid confusion, the installation and building options forSDCC itself (chapter 2) are not part of the index.[LaTeX Command: printindex]