XC16 Users Guide
XC16 Users Guide
XC16 Users Guide
User’s Guide
• Microchip believes that its family of products is one of the most secure families of its kind on the market today, when used in the
intended manner and under normal conditions.
• There are dishonest and possibly illegal methods used to breach the code protection feature. All of these methods, to our
knowledge, require using the Microchip products in a manner outside the operating specifications contained in Microchip’s Data
Sheets. Most likely, the person doing so is engaged in theft of intellectual property.
• Microchip is willing to work with the customer who is concerned about the integrity of their code.
• Neither Microchip nor any other semiconductor manufacturer can guarantee the security of their code. Code protection does not
mean that we are guaranteeing the product as “unbreakable.”
Code protection is constantly evolving. We at Microchip are committed to continuously improving the code protection features of our
products. Attempts to break Microchip’s code protection feature may be a violation of the Digital Millennium Copyright Act. If such acts
allow unauthorized access to your software or other copyrighted work, you may have a right to sue for relief under that Act.
NOTICE TO CUSTOMERS
All documentation becomes dated, and this manual is no exception. Microchip tools and documenta-
tion are constantly evolving to meet customer needs, so some actual dialogs and/or tool descriptions
may differ from those in this document.
For the most up-to-date information on development tools, see the MPLAB® X IDE Help. Select the
Help menu and then “Topics” or “Help Contents” to open a list of available Help files.
For the most current PDFs, please refer to our web site (https://www.microchip.com). Documents are
identified by “DSXXXXXXXXA”, where “XXXXXXXX” is the document number and “A” is the revision
level of the document. This number is located on the bottom of each page, in front of the page number.
Introduction
MPLAB XC16 C Compiler documentation and support information is discussed in the
sections below:
• Document Layout
• Conventions Used
• Recommended Reading
Document Layout
This document describes how to use GNU language tools to write code for 16-bit
applications. The document layout is as follows:
• Chapter 1. “Compiler Overview” – describes the compiler, development tools and
feature set.
• Chapter 2. “Common C Interface” – describes the common C interface that may
be used to enhance code portability between MPLAB XC compilers.
• Chapter 3. “How To’s” – a list of “how to” questions with brief explanations and
links to relevant sections in the manual.
• Chapter 4. “XC16 Toolchain and MPLAB X IDE” – explains the basics of how to
setup and use the compiler and related tools with MPLAB X IDE.
• Chapter 5. “Compiler Command-Line Driver” – describes how to use the compiler
from the command line.
• Chapter 6. “Device-Related Features” – describes the compiler header and regis-
ter definition files, as well as how to use with SFRs.
• Chapter 7. “Differences Between MPLAB XC16 and ANSI C” – describes the
differences between the C language supported by the compiler syntax and the
standard ANSI-89 C.
• Chapter 8. “Supported Data Types and Variables” – describes the compiler inte-
ger, floating point and pointer data types.
Conventions Used
The following conventions may appear in this documentation:
Documentation Conventions
Description Represents Examples
Arial font:
Italic characters Referenced books MPLAB® XC16 C Compiler
User’s Guide
Emphasized text ...is the only compiler...
Initial caps A window the Output window
A dialog the Settings dialog
A menu selection select Enable Programmer
Quotes A field name in a window or “Save project before build”
dialog
Underlined, italic text with A menu path File>Save
right angle bracket
Bold characters A dialog button Click OK
A tab Click the Power tab
Text in angle brackets < > A key on the keyboard Press <Enter>, <F1>
Courier font:
Plain Courier Sample source code #define START
File names autoexec.bat
File paths c:\mcc18\h
Keywords _asm, _endasm, static
Command-line options -Opa+, -Opa-
Bit values 0, 1
Constants 0xFF, ’A’
Italic Courier A variable argument file.c, where file can be
any valid file name
Square brackets [ ] Optional arguments mpasmwin [options]
file [options]
Curly brackets and pipe Choice of mutually exclusive errorlevel {0|1}
character: { | } arguments; an OR selection
Ellipses... Replaces repeated text var_name [,
var_name...]
Represents code supplied by void main (void)
user { ...
}
Sidebar Text
Device Dependent. xmemory attribute
This feature is not supported
DD on all devices. Devices sup-
ported will be listed in the title
or text.
Recommended Reading
This guide describes how to use the MPLAB XC16 C Compiler. Other useful
documents are listed below. The following Microchip documents are available and
recommended as supplemental reference resources.
Release Notes (Readme Files)
For the latest information on Microchip tools, read the associated Release Notes
(HTML files) included with the software.
MPLAB® XC16 Assembler, Linker and Utilities User’s Guide (DS50002106)
A guide to using the 16-bit assembler, object linker, object archiver/librarian, and vari-
ous utilities.
16-Bit Language Tools Libraries Reference Manual (DS50001456)
A descriptive listing of libraries available for Microchip 16-bit devices. This includes
standard (including math) libraries and C compiler built-in functions. DSP and 16-bit
peripheral libraries are described in Release Notes provided with each peripheral
library type.
Device-Specific Documentation
The Microchip website contains many documents that describe 16-bit device functions
and features. Among these are:
• Individual and family data sheets
• Family reference manuals
• Programmer’s reference manuals
C Standards Information
American National Standard for Information Systems – Programming Language – C.
American National Standards Institute (ANSI), 11 West 42nd. Street, New York,
New York, 10036.
This standard specifies the form and establishes the interpretation of programs
expressed in the programming language C. Its purpose is to promote portability, reli-
ability, maintainability and efficient execution of C language programs on a variety of
computing systems.
C Reference Manuals
Harbison, Samuel P. and Steele, Guy L., C A Reference Manual, Fourth Edition,
Prentice-Hall, Englewood Cliffs, N.J. 07632.
Kernighan, Brian W. and Ritchie, Dennis M., The C Programming Language, Second
Edition. Prentice Hall, Englewood Cliffs, N.J. 07632.
Kochan, Steven G., Programming In ANSI C, Revised Edition. Hayden Books,
Indianapolis, Indiana 46268.
Plauger, P.J., The Standard C Library, Prentice-Hall, Englewood Cliffs, N.J. 07632.
Van Sickle, Ted., Programming Microcontrollers in C, First Edition. LLH Technology
Publishing, Eagle Rock, Virginia 24085.
1.3.2 Optimization
The compiler uses a set of sophisticated optimization passes that employ many
advanced techniques for generating efficient, compact code from C source. The
optimization passes include high-level optimizations that are applicable to any C code,
as well as 16-bit device-specific optimizations that take advantage of the particular
features of the device architecture.
For more on optimizations, see Chapter 18. “Optimizations.”
1.3.7 Documentation
The compiler is supported under both the MPLAB® X IDE and MPLAB IDE v8.xx and
above. In this document, only the MPLAB X IDE is discussed.
Features that are unique to specific devices and therefore specific compilers, are noted
with a “DD” icon next to the section and text that identifies the specific devices to which
the information applies (see the Preface).
1. For example, the mid-range PIC® microcontrollers do not have a data stack. Because a com-
piler targeting this device cannot implement recursion, it (strictly speaking) cannot conform to
the ANSI C Standard. This example illustrates a situation in which the standard is too strict for
mid-range devices and tools.
Refinement of the The CCI documents specific behavior for some code in which
ANSI C Standard actions are implementation-defined behavior under the ANSI
C Standard. For example, the result of right-shifting a signed
integer is fully defined by the CCI. Note that many
implementation-defined items that closely couple with device
characteristics, such as the size of an int, are not defined by
the CCI.
Consistent syntax The CCI non-standard extensions are mostly implemented
for non-standard using keywords with a uniform syntax. They replace keywords,
extensions macros and attributes that are the native compiler implementa-
tion. The interpretation of the keyword can differ across each
compiler, and any arguments to the keywords can be device
specific.
Coding guidelines The CCI can indicate advice on how code should be written so
that it can be ported to other devices or compilers. While you
may choose not to follow the advice, it will not conform to the
CCI.
2.4.1.1 Example
The following shows a string constant being defined that uses escaped characters.
const char myName[] = "Bj\370rk\n";
2.4.1.2 Differences
All compilers have used this character set.
2.4.2.1 Example
The following shows an example of how main() might be defined:
int main(void)
{
while(1)
process();
}
2.4.2.2 Differences
The 8-bit compilers used a void return type for this function.
2.4.3.1 Example
The following example shows two conforming include directives.
#include <usb_main.h>
#include "global.h"
2.4.3.2 Differences
Header file specifications that use directory separators have been allowed in previous
versions of all compilers. Compatibility problems arose when Windows-style separa-
tors “\” were used and the code was compiled under other host operating systems.
Under the CCI, no directory separators should be used.
2.4.4.1 Example
If including a header file, as in the following directive:
#include "myGlobals.h"
The header file should be locatable in the current working directory, or the paths spec-
ified by any -I options, or the standard compiler directories. A header file being located
elsewhere does not conform to the CCI.
2.4.5.1 Example
The following example shows two poorly named variables, but names which are
considered unique under the CCI.
int stateOfPortBWhenTheOperatorHasSelectedAutomaticModeAndMotorIsRunningFast;
int stateOfPortBWhenTheOperatorHasSelectedAutomaticModeAndMotorIsRunningSlow;
2.4.5.2 Differences
Former 8-bit compilers used 31 significant characters by default, but an option allowed
this to be extended.
The 16- and 32-bit compilers did not impose a limit on the number of significant
characters.
2.4.6.1 Example
The following example shows the definition of a variable, native, whose size will allow
efficient access on the target device; and a variable, fixed, whose size is clearly indi-
cated and remains fixed, even though it may not allow efficient access on every device.
int native;
int16_t fixed;
2.4.6.2 Differences
This is consistent with previous types implemented by the compiler.
2.4.7.1 Example
The following example
char foobar;
defines an unsigned char object called foobar.
2.4.7.2 Differences
The 8-bit compilers have always treated plain char as an unsigned type.
The 16- and 32-bit compilers used signed char as the default plain char type. The
-funsigned-char option on those compilers changed the default type to be
unsigned char.
2.4.8.1 Example
The following shows a variable, test, that is assigned the value -28 decimal.
signed char test = 0xE4;
2.4.8.2 Differences
All compilers have represented signed integers in the way described in this section.
2.4.9.2 Differences
All compilers have performed integer conversion in an identical fashion to that
described in this section.
2.4.10.1 Example
The following example shows a negative quantity involved in a bitwise AND operation.
signed char output, input = -13;
output = input & 0x7E;
Under the CCI, the value of output after the assignment is 0x72.
2.4.10.2 Differences
All compilers have performed bitwise operations in an identical fashion to that
described in this section.
2.4.11.1 Example
The following shows an example of a negative quantity involved in a right-shift
operation.
signed char output, input = -13;
output = input >> 3;
Under the CCI, the value of output after the assignment is -2 (i.e., the bit pattern
0xFE).
2.4.11.2 Differences
All compilers have performed right-shifting as described in this section.
2.4.12.1 Example
The following example shows a union defining several members.
union {
signed char code;
unsigned int data;
float offset;
} foobar;
Code that attempts to extract offset by reading data is not guaranteed to read the
correct value.
float result;
result = foobbar.data;
2.4.12.2 Differences
All compilers have not converted union members accessed via other members.
2.4.13.1 Example
The following example shows a structure tag containing bit-fields that are unsigned
integers with the size specified.
struct OUTPUTS {
int direction :1;
int parity :3;
int value :4;
};
2.4.13.2 Differences
The 8-bit compilers have previously issued a warning if type int was used for bit-fields,
but would implement the bit-field with an unsigned int type.
The 16- and 32-bit compilers have implemented bit-fields defined using int as having
a signed int type, unless the option -funsigned-bitfields was specified.
2.4.14.1 Example
The following example shows a structure containing bit-fields being defined.
struct {
unsigned first : 6;
unsigned second :6;
} order;
Under the CCI and using MPLAB XC8, the storage allocation unit is byte sized. The
bit-field, second, is allocated a new storage unit since there are only 2 bits remaining
in the first storage unit in which first is allocated. The size of this structure, order,
is 2 bytes.
2.4.14.2 Differences
This allocation is identical with that used by all previous compilers.
2.4.15.2 Differences
This is identical with the previous operation of all compilers.
2.4.16.1 Example
The following example shows a pointer being assigned a null pointer constant via the
NULL macro.
int * ip = NULL;
The value of NULL (0) is implicitly converted to the destination type.
2.4.16.2 Differences
The 32-bit compilers previously assigned NULL the expression ((void *)0).
2.4.17.1 Example
The following example shows the definition for outY, which is at least 32 bits in size.
float outY;
2.4.17.2 Differences
The 8-bit compilers have allowed the use of 24-bit float and double types.
2.5.1.1 Example
The following example shows this header file being included, thus allowing confor-
mance with the CCI, as well as allowing access to SFRs.
#include <xc.h>
2.5.1.2 Differences
Some 8-bit compilers used <htc.h> as the equivalent header. Previous versions of
the 16- and 32-bit compilers used a variety of headers to do the same job.
2.5.2.1 Example
The following example shows two variables and a function being made absolute.
int scanMode __at(0x200);
const char keys[] __at(124) = { ’r’, ’s’, ’u’, ’d’};
2.5.2.2 Differences
The 8-bit compilers have used an @ symbol to specify an absolute address.
The 16- and 32-bit compilers have used the address attribute to specify an object’s
address.
2.5.2.4 Caveats
If the __at() and __section() specifiers are both applied to an object when using
MPLAB XC8, the __section() specifier is currently ignored.
The __at() specifier must be placed at the beginning of function prototypes for the
16- and 32-bit compilers. If you prefer to use the specifier at the end of the prototype,
use the specifier with a declaration and leave it off the definition, for example:
int modify(int x) __at(0x1000);
int modify(int x)
{ ... }
2.5.3.1 Example
The following example shows a variable and function qualified using __far.
__far int serialNo;
__far int ext_getCond(int selector);
2.5.3.2 Differences
The 8-bit compilers have used the qualifier far to indicate this meaning. Functions
could not be qualified as far.
The 16-bit compilers have used the far attribute with both variables and functions.
The 32-bit compilers have used the far attribute with functions only.
2.5.3.4 Caveats
None.
2.5.4.1 Example
The following example shows a variable and function qualified using __near.
__near int serialNo;
__near int ext_getCond(int selector);
2.5.4.2 Differences
The 8-bit compilers have used the qualifier near to indicate this meaning. Functions
could not be qualified as near.
The 16-bit compilers have used the near attribute with both variables and functions.
The 32-bit compilers have used the near attribute for functions only.
2.5.4.4 Caveats
None.
2.5.5.1 Example
The following example shows a variable qualified using __persistent.
__persistent int serialNo;
2.5.5.2 Differences
The 8-bit compilers have used the qualifier, persistent, to indicate this meaning.
The 16- and 32-bit compilers have used the persistent attribute with variables to
indicate they were not to be cleared.
2.5.5.4 Caveats
None.
2.5.6.1 Example
The following example shows a variable qualified using __xdata, as well as another
variable qualified with __ydata.
__xdata char data[16];
__ydata char coeffs[4];
2.5.6.2 Differences
The 16-bit compilers have used the xmemory and ymemory space attribute with
variables.
Equivalent specifiers have never been defined for any other compiler.
2.5.6.4 Caveats
None.
2.5.7.1 Example
The following example shows a variable qualified using __bank().
__bank(0) char start;
__bank(5) char stop;
2.5.7.4 Caveats
This feature is not yet implemented in MPLAB XC8.
2.5.8.1 Example
The following example shows variables qualified using __align() to ensure they end
on an address that is a multiple of 8, and start on an address that is a multiple of 2,
respectively.
__align(-8) int spacer;
__align(2) char coeffs[6];
2.5.8.2 Differences
An alignment feature has never been implemented on 8-bit compilers.
The 16- and 32-bit compilers used the aligned attribute with variables.
2.5.8.4 Caveats
This feature is not yet implemented on MPLAB XC8.
2.5.9.1 Example
The following example shows a variable qualified using __eeprom.
__eeprom int serialNos[4];
2.5.9.2 Differences
The 8-bit compilers have used the qualifier, eeprom, to indicate this meaning for some
devices.
The 16-bit compilers have used the space attribute to allocate variables to the memory
space used for EEPROM.
2.5.9.4 Caveats
MPLAB XC8 does not implement the __eeprom qualifiers for any PIC18 devices; this
qualifier works as expected for other 8-bit devices.
2.5.10.1 Example
The following example shows a function qualified using __interrupt.
__interrupt(low_priority) void getData(void) {
if (TMR0IE && TMR0IF) {
TMR0IF=0;
++tick_count;
}
}
2.5.10.4 Caveats
None.
2.5.11.1 Example
The following example shows a structure qualified using __pack, as well as a structure
where one member has been explicitly packed.
__pack struct DATAPOINT {
unsigned char type;
int value;
} x-point;
struct LINETYPE {
unsigned char type;
__pack int start;
long total;
} line;
2.5.11.2 Differences
The __pack specifier is a new CCI specifier that is available with MPLAB XC8. This
specifier has no apparent effect since the device memory is byte addressable for all
data objects.
The 16- and 32-bit compilers have used the packed attribute to indicate that a
structure member was not aligned with a memory gap.
2.5.11.4 Caveats
None.
2.5.12.1 Example
The following example shows a function that uses the __deprecate keyword.
void __deprecate getValue(int mode)
{
//...
}
2.5.12.2 Differences
No deprecate feature was implemented on 8-bit compilers.
The 16- and 32-bit compilers have used the deprecated attribute (note the different
spelling) to indicate that objects should be avoided, if possible.
2.5.12.4 Caveats
None.
2.5.13.1 Example
The following example shows a variable which uses the __section keyword.
int __section("comSec") commonFlag;
2.5.13.2 Differences
The 8-bit compilers have previously used the #pragma psect directive to redirect
objects to a new section, or psect; however, the __section() specifier is the
preferred method to perform this task, even if you are not using the CCI.
The 16- and 32-bit compilers have used the section attribute to indicate a different
destination section name. The __section() specifier works in a similar way to the
attribute.
2.5.13.4 Caveats
None.
2.5.14.1 Example
The following example shows Configuration bits being specified using this pragma.
#pragma config WDT=ON, WDTPS = 0x1A
2.5.14.2 Differences
The 8-bit compilers have used the __CONFIG() macro for some targets that did not
already have support for the #pragma config.
The 16-bit compilers have used a number of macros to specify the configuration
settings.
The 32-bit compilers supported the use of #pragma config.
2.5.14.4 Caveats
None.
2.5.15.1 Example
The following example shows code that is conditionally compiled dependent on the
device having EEPROM memory.
#ifdef __XC16__
void __interrupt(__auto_psv__) myIsr(void)
#else
void __interrupt(low_priority) myIsr(void)
#endif
2.5.15.2 Differences
Some of these CCI macros are new (for example __CCI__), and others have different
names to previous symbols with identical meaning (e.g., __18F452 is now
__18F452__).
2.5.16.1 Example
The following example shows a MOVLW instruction being inserted in-line.
asm("MOVLW _foobar");
2.5.16.2 Differences
The 8-bit compilers have used either the asm() or #asm ... #endasm constructs to
insert in-line assembly code.
This is the same syntax used by the 16- and 32-bit compilers.
2.6.1.1 Differences
This option has never been implemented previously.
2.6.1.3 Caveats
None.
3.2.2 How Can I Tell If the Compiler Has Installed and Activated
Successfully?
To verify installation and activation of the compiler, you must compile code. You can use
the example code that comes with the compiler. It is located, by default, in the following
folder: c:\Program Files\Microchip\xc16\examples
Depending on your operating system, find the file run_hello.bat (Windows OS) or
run_hello.sh (Mac/Linux OS) in the xc16_getting_started folder. Edit the opti-
mization level for your expected license level. For more information, see the following
chapter and section in this user’s guide:
Chapter 18. “Optimizations”
Section 5.7.6 “Options for Controlling Optimization”
Run the edited batch or shell file. If the tools are installed correctly, the output should
show the various steps in the compilation and execution process, ending with the text:
Hello, world!
3.2.3 Can I Install More Than One Version of the Same Compiler?
The compilers and installation process have been designed to allow you to have more
than one version of the same compiler installed. In MPLAB X IDE, you can easily switch
between compiler versions by changing options in the IDE. For details, see the follow-
ing section in this user’s guide:
Section 3.3.3 “How Can I Select Which Compiler Version to Build With?”
Compilers should be installed into a directory that is named according to the compiler
version. This is reflected in the default directory specified by the installer. For example,
the MPLAB XC16 compilers v1.00 and v1.10 would typically be placed in separate
directories, as shown below:
C:\Program Files\Microchip\xc16\v1.00\
C:\Program Files\Microchip\xc16\v1.10\
3.3.8 How Do I Know What the Build Options in MPLAB X IDE Do?
Most of the widgets and controls in the MPLAB X IDE Project Properties window, XC16
options, map directly to a corresponding command-line driver option or suboption. For
a list of options and any corresponding command-line options, refer to the following
section of this user’s guide:
Section 4.5 “Project Setup”
3.4.2.6 Which Device-Specific Symbols Does the Compiler Define, and Can I Use
Them?
The compiler defines some device-specific, and other, symbols or macros. They are
discussed in the following section in this user’s guide:
Section 19.4 “Predefined Macro Names”
3.4.3.3 How Do I Allocate Space for a Variable But Not Initialize/Load Any Value?
To allocate memory space for a variable without initializing or loading the variable in
memory, you can use the noload attribute. For more on variable attributes, see the
following section in this user’s guide:
Section 8.11 “Variable Attributes”
3.4.3.4 How Do I Stop the Compiler from Using Certain Memory Locations?
Concatenating an address attribute with the noload attribute can be used to block
out sections of memory. For more on variable attributes and options, see the following
sections in this user’s guide:
Section 8.11 “Variable Attributes”
Section 5.7.1 “Options Specific to 16-Bit Devices”
Also, you can use the option -mreserve. See the MPLAB® XC16 Assembler, Linker
and Utilities User’s Guide (DS50002106).
3.4.4 Variables
This section includes questions that relate to the definition and usage of variables and
types within a program.
• Why Are My Floating-point Results Not Quite What I Am Expecting?
• How Do I Retain the Value of a Variable Even After a Soft Reset?
• How Do I Save C Variables When an ISR Is Invoked?
• How Long Can I Make My Variable and Macro Names?
• How Do I Access Values Stored in a PSV or EDS Page?
• Why Would I Need to Place Data Into Its Own Section?
• How Can I Load a Value Into Flash Memory?
• How Can I Pack Data Into Flash Memory?
• How Can I Define a Large Array?
• See also, How Do I Share Data Between Interrupt and Main-line Code?
• See also, How Do I Position Variables or Functions at an Address I Nominate?
• See also, How Do I Place Variables in Program Memory?
• See also, How Do I Place Variables in Off-Chip Memory?
• See also, How Can I Rotate a Variable?
• See also, How Do I Learn Where Variables and Functions Have Been Positioned?
3.4.4.6 Why Would I Need to Place Data Into Its Own Section?
The MPLAB XC16 Object Linker will place data into sections efficiently. However, you
may want to manually place groups of variables into sections because it is easier than
manually placing each individual variable at a specific address. If necessary, absolute
starting addresses may be specified in user-defined sections within the device linker
script. To place data into its own section, you can use the section attribute, discussed
in the following section in this user’s guide:
Section 8.11 “Variable Attributes”
To edit user-defined sections within the linker script, see the following document. It is
available for download from the Microchip Technology website, www.microchip.com.
“MPLAB® XC16 Assembler, Linker, and Utilities User's Guide” (DS50002106),
Section 9.5 “Contents of a Linker Script”
3.4.5 Functions
This section includes questions that relate to functions.
• How Do I Stop A Function From Being Removed?
• Why Should I Inline My Function?
• Why is My Function Not Inline?
• Why Should I Place a Function Into its Own Section?
• How Do I Prevent the Compiler From Saving or Restoring Any Registers?
• How Can I Tell if a Function is Being Used?
• How Can I Find Out Which Functions are Contained Inside of the Compiler?
• Where are Arguments That Are Passed to Functions Located in Memory?
• See also, How Can I Tell How Big a Function Is?
• See also, How Do I Learn Where Variables and Functions Have Been Positioned?
• See also, How Do I Use Interrupts in C?
3.4.5.7 How Can I Find Out Which Functions are Contained Inside of the
Compiler?
You can see compiler predefined symbols/macros and functions by running, and
stopping the preprocessor, and then examining the output. Options to do this are dis-
cussed in the following section of this user’s guide:
Section 5.7.2 “Options for Controlling the Kind of Output”
3.4.5.8 Where are Arguments That Are Passed to Functions Located in Memory?
You will need to run compiler code to determine this. See the application binary inter-
face when running the compiler. Some built-ins may also be helpful. See the following
location of this user’s guide:
Appendix G. “Built-in Functions”
3.4.6 Interrupts
Interrupt and interrupt service routine (ISR) questions are discussed in this section.
• How Do I Use Interrupts in C?
• How Do I Add a Trap Interrupt Vector to a Project?
• Can/Should My Application be able to Return from a Trap?
• How Do I Share Data between Two Interrupt Routines?
• What is the Default Interrupt, Where is it Defined, and How Do I Use It?
• See also, How Can I Make My Interrupt Routine Faster?
• See also, How Do I Share Data Between Interrupt and Main-line Code?
• See also, How Do I Save C Variables When an ISR Is Invoked?
3.4.6.5 What is the Default Interrupt, Where is it Defined, and How Do I Use It?
The “default interrupt” fills in the vector table when no other named vector exists. If it is
not defined, the compiler will create one that will halt in a debugging environment or
Reset in a normal execution (non-debug) environment.
You can define your own handler by simply defining an ISR named:
_DefaultInterrupt.
.text
.global _foo
_foo: retlw #0,w0
main.c:
• When initializing an SFR, use the full name of the SFR instead of bit names. You
can initialize several fields at once with this technique.
• Instead of copying code literally into several places in your program, reorganize
the shared code into functions.
• Use the small code, small scalar, and large data memory models. Refer to the
following section of this user’s guide:
Section 10.15 “Memory Models”
3.6.7 How Can I Control Where the Language Tool Places Objects in
Memory?
In most situations, you should allow the language tool to place objects in memory. If you
still want to place objects, consult the following section of this user’s guide for details:
Section 3.4.3 “Memory Allocation”
3.7.5 What Can Cause Corrupted Variables and Code Failure When
Using Interrupts?
This is usually caused by having variables used in both interrupt and main-line code. If
the compiler optimizes access to a variable, or access is interrupted by an interrupt
routine, then corruption can occur. See the following section of this user’s guide:
Section 3.5.3 “How Do I Share Data Between Interrupt and Main-line Code?”
C Source Files
(*.c)
Compiler
Assembly Source Driver
C Compiler
Files (*.S) Program
Assembler
Object Files
Archiver (Librarian) (*.o)
MPLAB® X IDE
Debug Tool
Debug File
(*.cof,*.elf)
Command-Line
Simulator
bin2hex Utility
4.4.2 References
For more information on compiler operation see:
• Chapter 5. “Compiler Command-Line Driver.”
• MPLAB® X IDE User’s Guide (DS50002027),
“Basic Tasks,” ”Create a New Project.”
• MPLAB® XC16 Assembler, Linker and Utilities User’s Guide (DS50002106).
Note: If you add more than one file, the order in which you add these files to the
project is the order in which they will be linked.
It is assumed in this manual that the compiler applications are either in the console’s
search path (see Section 5.2.2 “Environment Variables.”) or the full path is specified
when executing any application.
It is conventional to supply options (identified by a leading dash “-”) before the file
names, although this is not mandatory.
The files may be any mixture of C and assembler source files and precompiled inter-
mediate files, such as relocatable object (.o) files. The order of the files is not import-
ant, except that it may affect the order in which code or data appears in memory.
For example, to compile, assemble and link the C source file hello.c, creating a
relocatable object output, hello.elf.
There are no compiler restrictions imposed on the names of source files, but be aware
of case, name-length and other restrictions imposed by your operating system. If you
are using an IDE, avoid assembly source files whose basename is the same as the
basename of any project in which the file is used. This may result in the source file
being overwritten by a temporary file during the build process.
The terms “source file” and “module” are often used when talking about computer
programs. They are often used interchangeably, but they refer to the source code at
different points in the compilation sequence.
A source file is a file that contains all or part of a program. Source files are initially
passed to the preprocessor by the driver.
A module is the output of the preprocessor, for a given source file, after inclusion of any
header files (or other source files) which are specified by #include preprocessor
directives. These modules are then passed to the remainder of the compiler applica-
tions. Thus, a module may consist of several source and header files. A module is also
often referred to as a translation unit. These terms can also be applied to assembly
files, as they too can include other header and source files.
The names of many output files use the same base name as the source file from which
they were derived. For example the source file input.c will create an object file called
input.o when the -c option is used.
The default output file is a ELF file called a.out, unless you override that name using
the -o option.
If you are using MPLAB X IDE to specify options to the compiler, there is typically a proj-
ect file that is created for each application. The name of this project is used as the base
name for project-wide output files, unless otherwise specified by the user. However
check the manual for the IDE you are using for more details.
Note: Throughout this manual, the term project name will refer to the name of the
project created in the IDE.
The compiler is able to directly produce a number of the output file formats which are
used by Microchip development tools.
The default behavior of xc16-gcc is to produce a ELF output. To make changes to the
files output or the file names, see Section 5.7 “Driver Option Descriptions.”
int f() {
union a_union t;
t.d = 3.0;
return t.i;
}
The practice of reading from a different union member than the one most recently written
to (called “type-punning”) is common. Even with -fstrict-aliasing, type-punning is
allowed, provided the memory is accessed through the union type. So the code above
will work as expected, but the following code might not:
int f() {
a_union t;
int* ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
-fthread-jumps Perform optimizations where a check is made to see if a jump branches to a location
where another comparison subsumed by the first is found. If so, the first branch is redi-
rected to either the destination of the second branch or a point immediately following it,
depending on whether the condition is known to be true or false.
-funroll-loops Perform the optimization of loop unrolling. This is only done for loops whose number of
iterations can be determined at compile time or run time. -funroll-loops implies both
-fstrength-reduce and -frerun-cse-after-loop.
-funroll-all-loops Perform the optimization of loop unrolling. This is done for all loops and usually makes
programs run more slowly. -funroll-all-loops implies -fstrength-reduce, as
well as -frerun-cse-after-loop.
address and end_address will specify the range of program memory addresses to fill. If
end_address is not provided then the expression will be written to the specific memory
location at address address. The optional literal value unused may be specified to indicate
that all unused memory will be filled. If none of the location parameters are provided, all unused
memory will be filled. expression will describe how to fill the specified memory. The following
options are available:
A single value
xc16-ld --fill=0x12345678@unused
Range of values
xc16-ld --fill=1,2,3,4,097@0x9d000650:0x9d000750
An incrementing value
xc16-ld --fill=7+=911@unused
By default, the linker will fill using data that is instruction-word length. For 16-bit devices, the
default fill width is 24 bits. However, you may specify the value width using [wn:], where n is
the fill value's width and n belongs to [1, 3].
Multiple fill options may be specified on the command line; the linker will always process fill
options at specific locations first.
--gc-sections Remove dead functions from code at link time.
Support is for ELF projects only. In order to make the best use of this feature, add the
-ffunction-sections option to the compiler command line.
-Ldir Add directory dir to the list of directories to be searched for libraries specified by the com-
mand-line option -l.
-legacy-libc Use legacy include files and libraries (v3.24 and before).
The format of include file and libraries changed in v3.25 to match HI-TECH C compiler format.
-x none
Turn off any specification of a language, so that subsequent files are handled according to
their file name suffixes. This is the default behavior but is needed if another -x option has
been used.
For example:
xc16-gcc -x assembler foo.asm bar.asm -x none main.c mabonga.s
Without the -x none, the compiler will assume all the input files are for the assembler.
6.4 Stack
The 16-bit devices use what is referred to in this user’s guide as a “software stack.” This
is the typical stack arrangement employed by most computers and is ordinary data
memory accessed by a push-and-pop type instruction and a stack pointer register. The
term “hardware stack” is used to describe the stack employed by Microchip 8-bit
devices, which is only used for storing function return addresses.
The 16-bit devices dedicate register W15 for use as a software Stack Pointer. All
processor stack operations, including function calls, interrupts and exceptions, use the
software stack. The stack grows upward, towards higher memory addresses.
The dsPIC DSC device also supports stack overflow detection. If the Stack Pointer
Limit register, SPLIM, is initialized, the device will test for overflow on all stack
operations. If an overflow should occur, the processor will initiate a stack error
exception. By default, this will result in a processor Reset. Applications may also install
a stack error exception handler by defining an interrupt function named _StackError.
See Chapter 14. “Interrupts,” for details.
The C run-time startup module initializes the Stack Pointer (W15) and the Stack Pointer
Limit register during the startup and initialization sequence. The initial values are
normally provided by the linker, which allocates the largest stack possible from unused
data memory. The location of the stack is reported in the link map output file.
Applications can ensure that at least a minimum-sized stack is available with the
--stack linker command-line option. See the MPLAB® XC16 Assembler, Linker and
Utilities User’s Guide (DS50002106) for details.
Alternatively, a stack of specific size may be allocated with a user-defined section from
an assembly source file. In the following example, 0x100 bytes of data memory are
reserved for the stack:
.section *,data,stack
.space 0x100
The linker will allocate an appropriately sized section and initialize __SP_init and
__SPLIM_init so that the run-time startup code can properly initialize the stack. Note
that since this is a normal assembly code section, attributes such as address may be
used to further define the stack. Please see the MPLAB® XC16 Assembler, Linker and
Utilities User’s Guide (DS50002106) for more information.
Note: The symbols CORCON and CORCONbits refer to the same register and will
resolve to the same address at link time.
See MPLAB® XC16 Assembler, Linker and Utilities User’s Guide (DS50002106) for
more information on using linker scripts.
#include <xc.h>
struct clockType
{
unsigned int timer; /* countdown timer, milliseconds */
unsigned int ticks; /* absolute time, milliseconds */
unsigned int seconds; /* absolute time, seconds */
} volatile RTclock;
void reset_clock(void)
{
RTclock.timer = 0; /* clear software registers */
RTclock.ticks = 0;
RTclock.seconds = 0;
6.8.2 Optimizations
Using the EDS/PSV address space qualifiers may be expensive. If your application
footprint does not need to access these variables often, then it may be more efficient
to use the const-in-data memory model and manually place the less -often -accessed
data into a Flash space (using the named address attributes and qualifiers). This can
reduce the overhead by allowing the compiler to not force the EDS access to return to
a single page. This model does not preclude the use of an automatically managed PSV
space; using space(auto_psv) allows the programmer to nominate which const
variables go into this area.
By default the compiler will arrange to assert the const-in-code page at the start of an
interrupt service routine. If an ISR does not need to access const data, then specifying
__attribute__((no_auto_psv)) will let the compiler know that the ISR, or any
function it calls, does not use any auto PSV data.
The compiler also has an optimization setting that attempts to reduce the number of
page swaps; not as a cache, but modifications of the DSR/DSW/PSV Page SFR regis-
ter. This is a separate switch, -moptimize-page-setting, which can be applied at
any optimization level. Like many optimizations, it generally reduces the number page
setting operations which may reduce code-size and improve application performance.
8.2 Identifiers
A C variable identifier (as well as a function identifier) is a sequence of letters and digits
where the underscore character, “_”, counts as a letter. Identifiers cannot start with a
digit. Although they may start with an underscore, such identifiers are reserved for the
compiler’s use and should not be defined by your programs. Such is not the case for
assembly domain identifiers, which often begin with an underscore, see the MPLAB®
XC16 Assembler, Linker and Utilities User’s Guide (DS50002106).
Identifiers are case sensitive, so main is different from Main. All characters are signif-
icant in an identifier, although identifiers longer than 31 characters in length are less
portable.
w4 w5
0x5678 0x1234
Signed values are stored as a two’s complement integer value. Preprocessor macros
that specify integer minimum and maximum values are available after including <lim-
its.h> in your source code, located by default in:
<install directory>\include
As the size of data types is not fully specified by the ANSI Standard, these macros allow
for more portable code which can check the limits of the range of values held by the
type on this implementation.
For information on implementation-defined behavior of integers, see
Section A.6 “Integers”
All floating point values are specified in little endian format, which means:
• The least significant byte (LSB) is stored at the lowest address
• The least significant bit (LSb) is stored at the lowest-numbered bit position
As an example, the double value of 1.2345678 is stored at address 0x100 as follows:
w4 w5
0x0651 0x3F9E
Floating-point types are always signed and the unsigned keyword is illegal when
specifying a floating-point type. Preprocessor macros that specify valid ranges are
available after including <float.h> in your source code. For information on imple-
mentation-defined behavior of floating point numbers, see section
Section A.7 “Floating Point”
As with integer and floating point data types, all fixed-point values are represented in a
little endian format, which means:
• The Least Significant Byte (LSB) is stored at the lowest address
• The Least Significant bit (LSb) is stored at the lowest-numbered bit position
struct bar {
long long I:40;
char J:8;
int K:16;
} y;
struct foo will have a size of 10 bytes using the compiler. i will be allocated at bit
offset 0 (through 39). There are 8 bits of padding before j, allocated at bit offset 48. If
j were allocated at the next available bit offset (40), it would cross a storage boundary
for a 16 bit integer. k will be allocated after j, at bit offset 64. The structure will contain
8 bits of padding at the end to maintain the required alignment in the case of an array.
The alignment is 2 bytes because the largest alignment in the structure is 2 bytes.
struct bar will have a size of 8 bytes using the compiler. I will be allocated at bit
offset 0 (through 39). There is no need to pad before J because it will not cross a
storage boundary for a char. J is allocated at bit offset 40. K can be allocated starting
at bit offset 48, completing the structure without wasting any space.
Unnamed bit-fields may be declared to pad out unused space between active bits in
control registers. For example:
struct foo {
unsigned lo : 1;
unsigned : 6;
unsigned hi : 1;
} x;
A structure with bit-fields may be initialized by supplying a comma-separated list of ini-
tial values for each field. For example:
struct foo {
unsigned lo : 1;
unsigned mid : 6;
unsigned hi : 1;
} x = {1, 8, 0};
Structures with unnamed bit-fields may be initialized. No initial value should be supplied
for the unnamed members, for example:
struct foo {
unsigned lo : 1;
unsigned : 6;
unsigned hi : 1;
} x = {1, 0};
will initialize the members lo and hi correctly.
Note: Care must be taken when describing pointers. Is a “const pointer” a pointer
that points to const objects, or a pointer that is const itself? You can talk
about “pointers to const” and “const pointers” to help clarify the definition,
but such terms may not be universally understood.
Any integral literal constant will have a type of int, long int or long long int,
so that the type can hold the value without overflow. Literal constants specified in octal
or hexadecimal may also be assigned a type of unsigned int, unsigned long
int or unsigned long long int if the signed counterparts are too small to hold
the value.
The default types of literal constants may be changed by the addition of a suffix after
the digits, e.g., 23U, where U is the suffix. Table 8-5 shows the possible combination of
suffixes, and the types that are considered when assigning a type. So, for example, if
the suffix l is specified and the value is a decimal literal constant, the compiler will
assign the type long int, if that type will hold the lineal constant; otherwise, it will
assign long long int. If the literal constant was specified as an octal or hexadecimal
constant, then unsigned types are also considered.
void main(void)
{
shifter = 20;
result = 1 << shifter;
// code that uses result
}
The literal constant 1 will be assigned an int type; hence the result of the shift opera-
tion will be an int and the upper bits of the long variable, result, can never be set,
regardless of how much the literal constant is shifted. In this case, the value 1 shifted
left 20 bits will yield the result 0, not 0x100000.
The following uses a suffix to change the type of the literal constant, hence ensure the
shift result has an unsigned long type.
result = 1UL << shifter;
Floating-point literal constants have double type unless suffixed by f or F, in which
case it is a float constant. The suffixes l or L specify a long double type. In
MPLAB XC16, the double type equates to a 32-bit float type. The command line
option, -fno-short-double, may be use to specify double as a 64-bit long
double type.
Fixed-point literal constants look like floating point numbers, suffixed with combinations
of [u][h,l]<r,k>. The suffix u means unsigned. The suffixes h and l signify short and
long respectively. The suffix r denotes a _Fract type and k specifies an _Accum type.
So for example, -1.0r is a signed _Fract and 0.5uhk is an unsigned short _Accum.
Character literal constants are enclosed by single quote characters, ’, for example
‘a’. A character literal constant has int type, although this may be optimized to a
char type later in the compilation.
Multi-byte character literal constants are supported by this implementation.
String constants, or string literals, are enclosed by double quote characters ", for exam-
ple "hello world". The type of string literal constants is const char * and the
character that make up the string may be stored in the program memory.
To comply with the ANSI C standard, the compiler does not support the extended char-
acter set in characters or character arrays. Instead, they need to be escaped using the
backslash character, as in the following example:
const char name[] = "Bj\xf8k";
printf("%s's Resum\xe9", name); \\ prints "Bjørk's Resumé"
Defining and initializing a non-const array (i.e., not a pointer definition) with a string,
for example:
char ca[]= "two"; // "two" different to the above
is a special case and produces an array in data space which is initialized at startup with
the string "two", whereas a string literal constant used in other contexts represents an
unnamed array, accessed directly from its storage location.
The compiler will use the same storage location and label for strings that have identical
character sequences, except where the strings are used to initialize an array residing
in the data space as shown in the last statement in the previous example.
Two adjacent string literal constants (i.e., two strings separated only by white space)
are concatenated by the C preprocessor. Thus:
const char * cp = "hello " "world"; will assign the pointer with the address
of the string "hello world."
Note: Some devices use DSRPAG to represent extended read access to Flash or
the extended data space (EDS).
For more on this qualifier, see Section 10.7 “Extended Data Space Access”
aligned (alignment)
This attribute specifies a minimum alignment for the variable, measured in bytes. The
alignment must be a power of two. For example, the declaration:
int x __attribute__ ((aligned (16))) = 0;
causes the compiler to allocate the global variable x on a 16-byte boundary. On the
dsPIC DSC device, this could be used in conjunction with an asm expression to access
DSP instructions and addressing modes that require aligned operands.
As in the preceding example, you can explicitly specify the alignment (in bytes) that you
wish the compiler to use for a given variable. Alternatively, you can leave out the
alignment factor and just ask the compiler to align a variable to the maximum useful
alignment for the dsPIC DSC device. For example, you could write:
short array[3] __attribute__ ((aligned));
Whenever you leave out the alignment factor in an aligned attribute specification, the
compiler automatically sets the alignment for the declared variable to the largest
alignment for any data type on the target machine – which in the case of the dsPIC DSC
device is two bytes (one word).
The aligned attribute can only increase the alignment; you can decrease it by spec-
ifying packed (see below). The aligned attribute conflicts with the reverse attribute.
It is an error condition to specify both.
The aligned attribute can be combined with the section attribute. This will allow the
alignment to take place in a named section. By default, when no section is specified,
the compiler will generate a unique section for the variable. This will provide the linker
with the best opportunity for satisfying the alignment restriction without using internal
padding that may happen if other definitions appear within the same aligned section.
boot
This attribute can be used to define protected variables in Boot Segment (BS) RAM:
int __attribute__((boot)) boot_dat[16];
Variables defined in BS RAM will not be initialized on startup. Therefore all variables in
BS RAM must be initialized using inline code. A diagnostic will be reported if initial
values are specified on a boot variable.
An example of initialization is as follows:
int __attribute__((boot)) time = 0; /* not supported */
int __attribute__((boot)) time2;
void __attribute__((boot)) foo()
{
time2 = 55; /* initial value must be assigned explicitly */
}
eds
In the attribute context, the eds (extended data space) attribute indicates to the com-
piler that the variable will be allocated anywhere within data memory. Variables with this
attribute will likely also have the __eds__ type qualifier (see Section 10.7 “Extended
Data Space Access”) for the compiler to properly generate the correct access
sequence. Not that the __eds__ qualifier and the eds attribute are closely related, but
not identical. On some devices, eds may need to be specified when allocating vari-
ables into certain memory spaces such as space (ymemory) or space (dma) as
this memory may only exist in the extended data space.
fillupper
This attribute can be used to specify the upper byte of a variable stored into a
space(prog) section.
For example:
int foo[26] __attribute__((space(prog),fillupper(0x23))) = { 0xDEAD };
will fill the upper bytes of array foo with 0x23, instead of 0x00. foo[0] will still be
initialized to 0xDEAD.
The command line option -mfillupper=0x23 will perform the same function.
far
The far attribute tells the compiler that the variable will not necessarily be allocated in
near (first 8 KB) data space, (i.e., the variable can be located anywhere in data memory
between 0x0000 and 0x7FFF).
mode (mode)
This attribute specifies the data type for the declaration as whichever type corresponds
to the mode mode. This in effect lets you request an integer or floating point type
according to its width. Valid values for mode are as follows:
near
The near attribute tells the compiler that the variable is allocated in near data space
(the first 8 KB of data memory). Such variables can sometimes be accessed more
efficiently than variables not allocated (or not known to be allocated) in near data
space.
int num __attribute__ ((near));
noload
The noload attribute indicates that space should be allocated for the variable, but that
initial values should not be loaded. This attribute could be useful if an application is
designed to load a variable into memory at run time, such as from a serial EEPROM.
int table1[50] __attribute__ ((noload)) = { 0 };
packed
The packed attribute specifies that a structure member should have the smallest
possible alignment unless you specify a larger value with the aligned attribute.
Here is a structure in which the member x is packed, so that it immediately follows a,
with no padding for alignment:
struct foo
{
char a;
int x[2] __attribute__ ((packed));
};
Note: The device architecture requires that words be aligned on even byte
boundaries, so care must be taken when using the packed attribute to
avoid run-time addressing errors.
page
This attribute specifies that the object cannot exceed a page boundary. The page
boundary applied depends upon where the object is allocated. An object located in a
psv space cannot cross a 32K boundary; an object located in prog space cannot cross
a 64K boundary.
unsigned int var[10] __attribute__ ((space(auto_psv)));
The space(auto_psv) or space(psv) attribute will use a single memory page by
default.
__eds__ unsigned int var[10] __attribute__ ((eds, page));
When dealing with eds, please refer to Section 10.7 “Extended Data Space Access”
for more information.
int main()
{
if ((RCONbits.POR == 0) &&
(RCONbits.BOR == 0)) {
/* last_mode is valid */
} else {
/* initialize persistent data */
last_mode = 0;
}
}
This attribute can only be used in conjunction with a RAM resident object, i.e. not in
FLASH.
preserved
The preserved attribute can be applied to a variable to indicate that this variable's
value should be preserved on a restart. A restart is a user-defined event which can be
different from a cold or warm reset. Preserved variables require information from a pre-
viously linked executable in order to function; please see the linker option
--preserved=.
priority(n)
The priority attribute can be applied to a variable to group initializations together.
n must be between 1 and 65535, with 1 being the highest level. All initializations with
the same priority are initialized before moving onto the next priority level. Level 1 vari-
ables are initialized first and variables without a priority level are initialized last. The
attribute can also be applied to void functions (void result and argument types); in
this case the function(s) for level n will be executed immediately after all the
initializations for level n are complete.
reverse (alignment)
The reverse attribute specifies a minimum alignment for the ending address of a
variable, plus one. The alignment is specified in bytes and must be a power of two.
Reverse-aligned variables can be used for decrementing modulo buffers in dsPIC DSC
assembly language. This attribute could be useful if an application defines variables in
C that will be accessed from assembly language.
int buf1[128] __attribute__ ((reverse(256)));
The reverse attribute conflicts with the aligned and section attributes. An attempt
to name a section for a reverse-aligned variable will be ignored with a warning. It is an
error condition to specify both reverse and aligned for the same variable. A variable
with the reverse attribute cannot be placed into the auto_psv space (see the
space() attribute or the -mconst-in-code option); attempts to do so will cause a
warning and the compiler will place the variable into the PSV space.
secure
This attribute can be used to define protected variables in Secure Segment (SS) RAM:
int __attribute__((secure)) secure_dat[16];
Variables defined in SS RAM will not be initialized on startup. Therefore all variables in
SS RAM must be initialized using inline code. A diagnostic will be reported if initial
values are specified on a secure variable.
String literals can be assigned to secure variables using inline code, but they require
extra processing by the compiler. For example:
char *msg __attribute__((secure)) = "Hello!\n"; /* not supported */
char *msg2 __attribute__((secure));
void __attribute__((secure)) foo2()
{
*msg2 = "Goodbye..\n"; /* value assigned explicitly */
}
In this case, storage must be allocated for the string literal in a memory space which is
accessible to the enclosing secure function. The compiler will allocate the string in a
psv constant section designated for the secure segment.
sfr (address)
The sfr attribute tells the compiler that the variable is an SFR and may also specify
the run-time address of the variable, using the address parameter.
extern volatile int __attribute__ ((sfr(0x200)))u1mod;
The use of the extern specifier is required in order to not produce an error.
Note: By convention, the sfr attribute is used only in processor header files. To
define a general user variable at a specific address use the address attri-
bute in conjunction with near or far to specify the correct addressing
mode.
shared
Used with co-resident applications. The variable may be used outside of the applica-
tion. A data item will be initialized at startup of any application in the co-resident set.
space (space)
Normally, the compiler allocates variables in general data space. The space attribute
can be used to direct the compiler to allocate a variable in specific memory spaces.
Memory spaces are discussed further in Section 10.2 “Address Spaces” The following
arguments to the space attribute are accepted:
data
Allocate the variable in general data space. Variables in general data space can
be accessed using ordinary C statements. This is the default allocation.
dataflash
Allocate the variable in dataflash.
DD
xmemory - dsPIC30F, dsPIC33EP/F DSCs only
Note: Variables placed in the auto_psv section are not loaded into data
memory at startup. This attribute may be useful for reducing RAM
usage.
int main()
{
DMA1STA = __builtin_dmaoffset(BufferA);
DMA1STB = __builtin_dmaoffset(BufferB);
/* ... */
}
psv
Allocate the variable in program space, in a section designated for program space
visibility window access. The linker will locate the section so that the entire vari-
able can be accessed using a single setting of the PSVPAG register. Variables in
PSV space are not managed by the compiler and can not be accessed using ordi-
nary C statements. They must be explicitly accessed by the programmer, usually
using table-access inline assembly instructions, or using the program space
visibility window.
transparent_union
This attribute, attached to a function parameter which is a union, means that the
corresponding argument may have the type of any union member, but the argument is
passed as if its type were that of the first union member. The argument is passed to the
function using the calling conventions of the first member of the transparent union, not
the calling conventions of the union itself. All members of the union must have the same
machine representation; this is necessary for this argument passing to work properly.
unordered
The unordered attribute indicates that the placement of this variable may move
relative to other variables within the current C source file.
const int __attribute__ ((unordered)) i;
unsupported(message)
This attribute will display a custom message when the object is used.
int foo __attribute__((unsupported("This object is unsupported"));
Access to foo will generate a warning message.
unused
This attribute, attached to a variable, means that the variable is meant to be possibly
unused. The compiler will not produce an unused variable warning for this variable.
update
The update attribute can be applied to a variable to indicate that this variable should be
initialized on a restart. This is particularly useful if -mpreserve-all or
--preserve-all is being used.
weak
The weak attribute causes the declaration to be emitted as a weak symbol. A weak
symbol may be superseded by a global definition. When weak is applied to a reference
to an external symbol, the symbol is not required for linking. For example:
extern int __attribute__((__weak__)) s;
int foo() {
if (&s) return s;
return 0; /* possibly some other value */
}
In the above program, if s is not defined by some other module, the program will still
link but s will not be given an address. The conditional verifies that s has been defined
(and returns its value if it has). Otherwise ‘0’ is returned. There are many uses for this
feature, mostly to provide generic code that can link with an optional library.
void foo() {
i = 1;
}
/* weak2.c */
int i;
extern void foo(void);
void bar() {
i = 2;
}
main() {
foo();
bar();
}
Here the definition in weak2.c of i causes the symbol to become a strong definition.
No link error is emitted and both i’s refer to the same storage location. Storage is
allocated for weak1.c’s version of i, but this space is not accessible.
There is no check to ensure that both versions of i have the same type; changing i in
weak2.c to be of type float will still allow a link, but the behavior of function foo will
be unexpected. foo will write a value into the least significant portion of our 32-bit float
value. Conversely, changing the type of the weak definition of i in weak1.c to type
float may cause disastrous results. We will be writing a 32-bit floating point value into
a 16-bit integer allocation, overwriting any variable stored immediately after our i.
In the cases where only weak definitions exist, the linker will choose the storage of the
first such definition. The remaining definitions become inaccessible.
The behavior is identical, regardless of the type of the symbol; functions and variables
behave in the same manner.
9.4 Rounding
Three rounding modes are supported, corresponding to the three rounding modes sup-
ported by the 16-bit device fixed-point multiplication facilities.
All operations on fixed point variables, whether intrinsically supported by the hardware
or not, are performed according to the prevailing rounding mode chosen. The rounding
mode may be specified globally via the -menable-fixed compiler switch, as
described in Section 5.7 “Driver Option Descriptions.” or on a function-by-function
basis, via the -round attribute, as described in Section 13.2.2 “Function Attributes.”
These modes are described in more detail in the “16-bit MCU and DSC Programmer’s
Reference Manual” (DS70157).
10.3.1 Auto and Non-Auto Variables vs. Local and Global Variables
The terms “local” and “global” are commonly used to describe variables, but are not
defined by the language standard. The term “local variable” is often taken to mean a
variable which has scope inside a function and “global variable” is one which has scope
throughout the entire program. However, the C language has three common scopes:
block, file (i.e., internal linkage) and program (i.e., external linkage). So using only two
terms to describe these can be confusing.
For example, a static variable defined outside a function has scope only in that file,
so it is not globally accessible, but it can be accessed by more than one function inside
that file, so it is not local to any one function either.
file2.c
/* to be compiled without -mlarge-arrays */
extern __prog__ int array1[] __attribute__((space(prog)));
extern __prog__ int array2[] __attribute__((space(prog)));
main() {
fprintf(stderr,"Answer is: %d\n", access_large_array(array1,
39543));
fprintf(stderr,"Answer is: %d\n", access_large_array(array2,
16));
}
For example, to declare two variables that retain their values across a device Reset:
int _PERSISTENT var1,var2;
The C run-time startup modules in libpic30-omf.a initialize the Stack Pointer W15
to point to the bottom of the stack and initialize the Stack Pointer Limit register to point
to the top of the stack. The stack grows up and if it should grow beyond the value in the
Stack Pointer Limit register, then a stack error trap will be taken. The user may initialize
the Stack Pointer Limit register to further restrict stack growth.
SP (W15)
Parameter n
FP (W14)
Caller Frame
The called function (callee) can now allocate space for its local context (Figure 10-3).
SP (W15)
Previous FP
Parameter n-1
Parameter n
Caller Frame
SP (W15)
Callee-Saved
Registers [W14+n] accesses
local context
Local Variables FP (W14)
and Temporaries [W14-n] accesses
stack-based
Previous FP function parameters
Stack grows
toward Return addr [23:16]
greater
addresses Return addr [15:0]
Parameter 1
Parameter n-1
Parameter n
Caller Frame
Note: PMP attributes are not supported on devices with EPMP. Use Extended
Data Space (EDS) instead. See Section 10.7 “Extended Data Space
Access.”
The peripheral can require a substantial amount of configuration, depending upon the
type and brand of memory device that is connected. This configuration is not done
automatically by the compiler.
The extensions presented here allow the definition of a variable as PMP. This means
that the compiler will communicate with the PMP peripheral to access the variable.
To use this feature:
• Initialize PMP - define the initialization function: void __init_PMP(void)
• Declare a New Memory Space
• Define Variables within PMP Space
read_external
void __read_external(unsigned int address,
unsigned int memory_space,
void *buffer,
unsigned int len)
This function is a generic Read function and will be called if one of the next functions
are required but not defined. This function should perform the steps necessary to fill
len bytes of memory in the buffer from the external memory named memory_space
starting at address address.
read_external8
unsigned char __read_external8(unsigned int address,
unsigned int memory_space)
Read 8 bits from external memory space memory_space starting from address
address. The compiler would like to call this function if trying to access an 8-bit sized
object.
read_external16
unsigned int __read_external16(unsigned int address,
unsigned int memory_space)
Read 16 bits from external memory space memory_space starting from address
address. The compiler would like to call this function if trying to access an 16-bit sized
object.
read_external32
unsigned long __read_external32(unsigned int address,
unsigned int memory_space)
Read 32 bits from external memory space memory_space starting from address
address. The compiler would like to call this function if trying to access a 32-bit sized
object, such as a long or float type.
read_external64
unsigned long long __read_external64(unsigned int address,
unsigned int memory_space)
Read 64 bits from external memory space memory_space starting from address
address. The compiler would like to call this function if trying to access a 64-bit sized
object, such as a long long or long double type.
write_external
void __write_external(unsigned int address,
unsigned int memory_space,
void *buffer,
unsigned int len)
This function is a generic Write function and will be called if one of the next functions
are required but not defined. This function should perform the steps necessary to write
len bytes of memory from the buffer to the external memory named memory_space
starting at address address.
write_external8
void __write_external8(unsigned int address,
unsigned int memory_space,
unsigned char data)
Write 8 bits of data to external memory space memory_space starting from address
address. The compiler would like to call this function if trying to write an 8-bit sized
object.
write_external16
void __write_external16(unsigned int address,
unsigned int memory_space,
unsigned int data)
Write 16 bits of data to external memory space memory_space starting from address
address. The compiler would like to call this function if trying to write an 16-bit sized
object.
write_external32
void __write_external32(unsigned int address,
unsigned int memory_space,
unsigned long data)
Write 32 bits of data to external memory space memory_space starting from address
address. The compiler would like to call this function if trying to write a 32-bit sized
object, such as a long or float type.
write_external64
void __write_external64(unsigned int address,
unsigned int memory_space,
unsigned long long data)
Write 64 bits of data to external memory space memory_space starting from address
address. The compiler would like to call this function if trying to write a 64-bit sized
object, such as a long long or long double type.
Note: Some devices use DSRPAG to represent extended read access to Flash or
the extended data space (EDS).
You may specify a fixed register assignment for a particular C variable. It is not
recommended that this be done.
/* ... */
}
These steps need only be done once. Unless psv page is changed, variables in
EEData space may be read by referring to them as normal C variables, as shown in the
example.
Note: This access model is not compatible with the compiler-managed PSV
(-mconst-in-code) model. You should be careful to prevent conflict.
int main(void) {
int value;
TBLPAG = __builtin_tblpage(&user_data);
eedata_read(user_data,2*sizeof(user_data[0]), value);
if (value) ; /* do something */
int main(void) {
int value;
value = user_data[0];
if (value) ; /* do something */
}
The command-line options apply globally to the modules being compiled. Individual
variables and functions can be declared as near, far or in eds to better control the
code generation. For information on setting individual variable or function attributes,
see Section 8.11 “Variable Attributes.” and Section 13.2.1 “Function Specifiers.”.
void badCode(void)
{
asm (“mov #0, w8”);
WREG9 = 0;
}
The compiler is unable to interpret the meaning of in-line assembly code that is encoun-
tered in C code. Nor does it associate a variable mapped over an SFR to the actual
register itself. Writing to an SFR register using either of these two methods will not flag
the register as having changed and may lead to code failure.
address (addr)
The address attribute specifies an absolute address for the function.
void __attribute__ ((address(0x100))) foo() {
...
}
Alternatively, you may define the address in the function prototype:
void foo() __attribute__ ((address(0x100)));
auto_psv, no_auto_psv
The auto_psv attribute, when combined with the interrupt attribute, will cause the
compiler to generate additional code in the function prologue to set the psv page SFR
to the correct value for accessing space(auto_psv) (or constants in the con-
stants-in-code memory model) variables. Use this option when using 24-bit pointers
and an interrupt may occur while the psv page has been modified and the interrupt rou-
tine, or a function it calls, uses an auto_psv variable. Compare this with no_au-
to_psv.
The no_auto_psv attribute, when combined with the interrupt attribute, will cause
the compiler to not generate additional code for accessing space(auto_psv) (or
constants in the constants-in-code memory model) variables. Use this option if none of
the conditions under auto_psv hold true.
If neither auto_psv nor no_auto_psv option is specified for an interrupt routine, the
compiler will issue a warning and assume auto_psv.
boot
This attribute directs the compiler to allocate a function in the boot segment of program
Flash.
For example, to declare a protected function:
void __attribute__((boot)) func();
An optional argument can be used to specify a protected access entry point within the
boot segment. The argument may be a literal integer in the range 0 to 31 (except 16),
or the word unused. Integer arguments correspond to 32 instruction slots in the seg-
ment access area, which occupies the lowest address range of each secure segment.
The value 16 is excluded because access entry 16 is reserved for the secure segment
interrupt vector. The value unused is used to specify a function for all of the unused
slots in the access area.
Access entry points facilitate the creation of application segments from different ven-
dors that are combined at run time. They can be specified for external functions as well
as locally defined functions.
For example:
/* an external function that we wish to call */
extern void __attribute__((boot(3))) boot_service3();
/* local function callable from other segments */
void __attribute__((secure(4))) secure_service4()
{
boot_service3();
}
Note: In order to allocate functions with the boot or secure attribute, memory
for the boot and/or secure segment must be reserved. This can be accom-
plished by setting configuration words in source code, or by specifying
linker command options. For more information, see Chapter 8.8, “Options
that Specify CodeGuard Security Features,” in the MPLAB® XC16
Assembler, Linker and Utilities User’s Guide (DS50002106).
If attributes boot or secure are used, and memory is not reserved, then a
link error will result.
To specify a secure interrupt handler, use the boot attribute in combination with the
interrupt attribute:
void __attribute__((boot,interrupt)) boot_interrupts();
When an access entry point is specified for an external secure function, that function
need not be included in the project for a successful link. All references to that function
will be resolved to a fixed location in Flash, depending on the security model selected
at link time.
When an access entry point is specified for a locally defined function, the linker will
insert a branch instruction into the secure segment access area. The exception is for
access entry 16, which is represented as a vector (i.e, an instruction address) rather
than an instruction. The actual function definition will be located beyond the access
area; therefore the access area will contain a jump table through which control can be
transferred from another security segment to functions with defined entry points.
Automatic variables are owned by the enclosing function and do not need the boot
attribute. They may be assigned initial values, as shown:
void __attribute__((boot)) chuck_cookies()
{
int hurl;
int them = 55;
char *where = "far";
splat(where);
/* ... */
}
Note that the initial value of where is based on a string literal which is allocated in the
PSV constant section .boot_const. The compiler will set the psv page SFR to the
correct value upon entrance to the function. If necessary, the compiler will also restore
it after the call to splat().
const
Many functions do not examine any values except their arguments, and have no effects
except the return value. Such a function can be subject to common subexpression
elimination and loop optimization just as an arithmetic operator would be. These
functions should be declared with the attribute const. For example:
int square (int) __attribute__ ((const int));
says that the hypothetical function square is safe to call fewer times than the program
states.
Note that a function that has pointer arguments and examines the data pointed to must
not be declared const. Likewise, a function that calls a non-const function usually
must not be const. It does not make sense for a const function to have a void return
type.
deprecated
See Section 8.11 “Variable Attributes.” for information on the deprecated attribute.
far
The far attribute tells the compiler that the function may be located too far away to use
short call instruction.
format_arg (string-index)
The format_arg attribute specifies that a function takes printf or scanf style
arguments, modifies it (for example, to translate it into another language), and passes
it to a printf or scanf style function. For example, consider the declaration:
extern char *
my_dgettext (char *my_domain, const char *my_format)
__attribute__ ((format_arg (2)));
This causes the compiler to check the arguments in calls to my_dgettext, whose
result is passed to a printf, scanf or strftime type function for consistency with
the printf style format string argument my_format.
The parameter string-index specifies which argument is the format string
argument (starting from 1).
keep
The keep attribute will prevent the linker from removing the function with the ELF linker
option --gc-sections, even if it is unused.
in C:
void __attribute__((keep)) foo(void);
in Assembly:
.section *,code,keep
.global _foo
_foo:
return
naked
The naked attribute will prevent the compiler from saving or restoring any registers.
This attribute should be applied with caution as failing to save or restore registers may
cause issues. Consider using this attribute with noreturn for safety - any attempt to
return will cause a reset.
void __attribute__((naked)) func();
near
The near attribute tells the compiler that the function can be called using a more
efficient form of the call instruction.
no_instrument_function
If the command line option -finstrument-function is given, profiling function calls
will be generated at entry and exit of most user-compiled functions. Functions with this
attribute will not be so instrumented.
noload
The noload attribute indicates that space should be allocated for the function, but that
the actual code should not be loaded into memory. This attribute could be useful if an
application is designed to load a function into memory at run time, such as from a serial
EEPROM.
void bar() __attribute__ ((noload)) {
...
}
void
fatal (int i)
{
/* Print error message. */
exit (1);
}
The noreturn keyword tells the compiler to assume that fatal cannot return. It can
then optimize without regard to what would happen if fatal ever did return. This
makes slightly better code. It also helps avoid spurious warnings of uninitialized
variables.
It does not make sense for a noreturn function to have a return type other than void.
A noreturn function will reset if it attempts to return.
optimize
Use the optimize attribute to specify different optimization options for various func-
tions within a source file. Arguments can be either numbers or strings. Numbers are
assumed to be an optimization level. Strings that begin with O are assumed to be an
optimization option. This feature can be used, for example, to have frequently executed
functions compiled with more aggressive optimization options that produce faster and
larger code, while other functions can be called with less aggressive options.
This optimization setting overrides the file or project optimization setting.
int __attribute__((optimize("-O3"))) pandora (void)
{
if (maya > axton) return 1;
return 0;
}
priority(n)
The priority attribute can be applied to a variable to group initializations together.
n must be between 1 and 65535, with 1 being the highest level. All initializations with
the same priority are initialized before moving onto the next priority level. Level 1 vari-
ables are initialized first and variables without a priority level are initialized last. The
attribute can also be applied to void functions (void result and argument types); in
this case the function(s) for level n will be executed immediately after all the
initializations for level n are complete.
round(mode)
The round attribute controls the rounding mode of C language fixed-point support
(_Fract, _Accum variable types) dialect code (-menable-fixed command-line
option) within a function. Specify mode as one of truncation, conventional, or conver-
gent. This attribute overrides the default rounding mode set by -menable-fixed for
C language code within the attributed function, but has no effect on functions that may
be called by that function.
save(list)
Functions declared with the save(list) attribute will direct the compiler to save and
restore the C variables expressed in list.
secure
This attribute directs the compiler to allocate a function in the secure segment of
program Flash.
For example, to declare a protected function:
void __attribute__((secure)) func();
An optional argument can be used to specify a protected access entry point within the
secure segment. The argument may be a literal integer in the range 0 to 31 (except
16), or the word unused. Integer arguments correspond to 32 instruction slots in the
segment access area, which occupies the lowest address range of each secure seg-
ment. The value 16 is excluded because access entry 16 is reserved for the secure
segment interrupt vector. The value unused is used to specify a function for all of the
unused slots in the access area.
Access entry points facilitate the creation of application segments from different ven-
dors that are combined at run time. They can be specified for external functions as well
as locally defined functions. For example:
/* an external function that we wish to call */
extern void __attribute__((boot(3))) boot_service3();
/* local function callable from other segments */
void __attribute__((secure(4))) secure_service4()
{
boot_service3();
}
Note: In order to allocate functions with the boot or secure attribute, memory
for the boot and/or secure segment must be reserved. This can be accom-
plished by setting configuration words in source code, or by specifying
linker command options. For more information, see Chapter 8.8, “Options
that Specify CodeGuard Security Features,” in the linker manual
(DS51317).
If attributes boot or secure are used, and memory is not reserved, then a
link error will result.
To specify a secure interrupt handler, use the secure attribute in combination with the
interrupt attribute:
void __attribute__((secure,interrupt)) secure_interrupts();
When an access entry point is specified for an external secure function, that function
need not be included in the project for a successful link. All references to that function
will be resolved to a fixed location in Flash, depending on the security model selected
at link time.
shadow
The shadow attribute causes the compiler to use the shadow registers rather than the
software stack for saving registers. This attribute is usually used in conjunction with the
interrupt attribute.
void __attribute__ ((interrupt, shadow)) _T1Interrupt (void);
shared
Used with co-resident applications. The function may be used outside of the applica-
tion. A data item will be initialized at startup of any application in the co-resident set.
unsupported("message")
This attribute will display a custom message when the object is used.
int foo __attribute__((unsupported(“This object is unsupported”));
Access to foo will generate a warning message.
unused
This attribute, attached to a function, means that the function is meant to be possibly
unused. The compiler will not produce an unused function warning for this function.
user_init
The user_init attribute may be applied to any non-interrupt function with void
parameter and return types. Applying this attribute will cause default C start-up mod-
ules to call this function before the user main is executed. There is no guarantee of
ordering, so these functions cannot rely on other user_init functions having been
previously run; these functions will be called after PSV and data initialization. A
user_init may still be called by the executing program. For example:
void __attribute__((user_init)) initialize_me(void) {
// perform initalization sequence alpha alpha beta
}
weak
See Section 8.11 “Variable Attributes.” for information on the weak attribute.
Note: Function inlining will only take place when the function’s definition is visible
at the call site (not just the prototype). In order to have a function inlined into
more than one source file, the function definition may be placed into a
header file that is included by each of the source files.
To declare a function inline, use the inline keyword in its declaration, like this:
inline int
inc (int *a)
{
(*a)++;
}
(If you are using the -traditional option or the -ansi option, write __inline__
instead of inline.) You can also make all “simple enough” functions inline with the
command-line option -finline-functions. The compiler heuristically decides
which functions are simple enough to be worth integrating in this way, based on an
estimate of the function’s size.
Certain usages in a function definition can make it unsuitable for inline substitution.
Among these usages are: use of varargs, use of alloca, use of variable-sized data,
use of computed goto and use of nonlocal goto. Using the command-line option
-Winline will warn when a function marked inline could not be substituted, and will
give the reason for the failure.
In compiler syntax, the inline keyword does not affect the linkage of the function.
When a function is both inline and static, if all calls to the function are integrated
into the caller and the function’s address is never used, then the function’s own
assembler code is never referenced. In this case, the compiler does not actually output
assembler code for the function, unless you specify the command-line option
-fkeep-inline-functions. Some calls cannot be integrated for various reasons
(in particular, calls that precede the function’s definition cannot be integrated and
neither can recursive calls within the definition). If there is a non-integrated call, then
the function is compiled to assembler code as usual. The function must also be com-
piled as usual if the program refers to its address, because that can’t be inlined. The
compiler will only eliminate inline functions if they are declared to be static and if the
function definition precedes all uses of the function.
When an inline function is not static, then the compiler must assume that there
may be calls from other source files. Since a global symbol can be defined only once
in any program, the function must not be defined in the other source files, so the calls
therein cannot be integrated. Therefore, a non-static inline function is always
compiled on its own in the usual fashion.
Parameters are placed in the first aligned contiguous register(s) that are available. The
calling function must preserve the parameters, if required. Structures do not have any
alignment restrictions; a structure parameter will occupy registers if there are enough
registers to hold the entire structure. Function results are stored in consecutive
registers, beginning with W0.
void
params1(int i, bar b) {
/*
** W0 i
** W1 b.i
** W5:W2 b.d
*/
Parameters corresponding to the ellipses (...) of a variable-length argument list are not
allocated to registers. Any parameter not allocated to registers is pushed onto the
stack, in right-to-left order.
In the next example, the structure parameter cannot be placed in registers because it
is too large. However, this does not prevent the next parameter from using a register
spot.
void
params2(int i, bar b, int j) {
/*
** W0 i
** stack b
** W1 j
*/
}
Accessing arguments that have been placed onto the stack depends upon whether or
not a Frame Pointer has been created. Generally the compiler will produce a Frame
Pointer (unless told not to do so), as stack-based parameters will be accessed via the
Frame Pointer register (W14). In the preceding example, b will be accessed from
W14-22. The Frame Pointer offset of negative 22 has been calculated (refer to
Figure 10-4) by removing 2 bytes for the previous FP, 4 bytes for the return address,
followed by 16 bytes for b.
When no Frame Pointer is used, the assembly programmer must know how much
stack space has been used since entry to the procedure. If no further stack space is
used, the calculation is similar to Example 13-3. b would be accessed via W15-20; 4
bytes for the return address and 16 bytes to access the start of b.
The interrupt attribute name and the parameter names may be written with a pair
of underscore characters before and after the name. Thus, interrupt and
__interrupt__ are equivalent, as are save and __save__.
The optional save parameter names a list of one or more variables that are to be saved
and restored on entry to and exit from the ISR. The list of names is written inside paren-
theses, with the names separated by commas.
You should arrange to save global variables that may be modified in an ISR if you do
not want the value to be exported. Global variables accessed by an ISR should be
qualified volatile.
The optional irq parameter allows you to place an interrupt vector at a specific
interrupt, with the optional altirq parameter allowing you to place an interrupt vector
at a specified alternate interrupt. Each parameter requires a parenthesized interrupt ID
number. (See Section 14.4 “Specifying the Interrupt Vector.” for a list of interrupt IDs.)
The optional preprologue parameter allows you to insert assembly-language
statements into the generated code immediately before the compiler-generated
function prologue.
When using the interrupt attribute, please specify either auto_psv or
no_auto_psv. If none is specified a warning will be produced and auto_psv will be
assumed.
Note: A device Reset is not handled through the interrupt vector table. Instead,
on device Reset, the program counter is cleared. This causes the processor
to begin execution at address zero. By convention, the linker script
constructs a GOTO instruction at that location which transfers control to the
C run-time startup module.
The alternate vector name is used when the ALTIVT bit is set in the INTCON2 register.
For devices with alternate vector tables which may be disabled and moved, AIVT
support is configured via configuration words, notably:
• AIVTDIS to enable the vector table
• BSLIM to locate the vector table
On these devices, the tool chain will inspect the values of these configuration words to
determine whether or not to allocate space and fill in the value of the alternate vector
tables. Simply specify device appropriate values for these configuration words:
#pragma config AIVTDIS = ON
#pragma config BSLIM = 0x1FFD
and define the alternate vectors in the normal way, i.e.:
void __attribute__((interrupt)) _AltT1Interrupt(void) {}
Each exception vector occupies a program word. For tables of interrupt vectors by
device family, see Section 14.4.2 “Interrupt Vector Tables.”
Note: Traps, such as the address error trap, cannot be disabled. Only IRQs can
be disabled.
Each interrupt source can be individually enabled or disabled. One interrupt enable bit
for each IRQ is allocated in the Interrupt Enable Control registers (IECn). Setting an
interrupt enable bit to one (1) enables the corresponding interrupt; clearing the interrupt
enable bit to zero (0) disables the corresponding interrupt. When the device comes out
of Reset, all interrupt enable bits are cleared to zero.
The safe method of enabling and disabling peripheral interrupts is to use the
__write_to_IEC() macro, which is defined in the device header files. This is helpful
because some devices require one cycle of delay for this to take effect, but some
require two. A different version of __write_to_IEC() will be generated based on
device-specific information.
In addition, the processor has a disable interrupt instruction (DISI) that can disable all
interrupts for a specified number of instruction cycles.The DISI instruction can be used
in a C program through the use of:
__builtin_disi
For example:
__builtin_disi(16);
will emit the specified DISI instruction at the point it appears in the source program. A
disadvantage of using DISI in this way is that the C programmer cannot always be
sure how the C compiler will translate C source to machine instructions, so it may be
difficult to determine the cycle count for the DISI instruction. It is possible to get around
this difficulty by bracketing the code that is to be protected from interrupts by DISI
instructions, the first of which sets the cycle count to the maximum value, and the
second of which sets the cycle count to zero. For example,
__builtin_disi(0x3FFF); /* disable interrupts */
/* ... protected C code ... */
__builtin_disi(0x0000); /* enable interrupts */
An alternative approach is to write directly to the DISICNT register to enable interrupts.
The DISICNT register may be modified only after a DISI instruction has been issued
and if the contents of the DISICNT register are not zero.
__builtin_disi(0x3FFF); /* disable interrupts */
/* ... protected C code ... */
DISICNT = 0x0000; /* enable interrupts */
For some applications, it may be necessary to disable level 7 interrupts as well. These
can only be disabled through the modification of the COROCON IPL field. The provided
support files contain some useful preprocessor macro functions to help you safely
modify the IPL value. These macros are:
SET_CPU_IPL(ipl)
SET_AND_SAVE_CPU_IPL(save_to, ipl)
RESTORE_CPU_IPL(saved_to)
For example, you may wish to protect a section of code from interrupt. The following
code will adjust the current IPL setting and restore the IPL to its previous value.
void foo(void) {
int current_cpu_ipl;
int main(void) {
/* More User Code */
LATGbits.LATG10 ^= 1; /* Potential HAZARD -
First reads LATG into a W reg,
implements XOR operation,
then writes result to LATG */
IPC0bits.T1IP = 5; /* HAZARD -
Assigning a multiple bitfield
can generate a multiple
instruction sequence */
The no_auto_psv attribute is used to indicate that an ISR does not reference the
auto_psv constants section. If neither attribute is specified, the compiler assumes
auto_psv and inserts the necessary instructions to ensure correct operation at run
time. A warning diagnostic message is also issued that alerts the user to the migration
issue, and to the possibility of reducing interrupt latency by specifying the
no_auto_psv attribute.
14.8.3 Latency
There are two elements that affect the number of cycles between the time the interrupt
source occurs and the execution of the first instruction of your ISR code. These factors
are:
• Processor Servicing of Interrupt – the amount of time it takes the processor to
recognize the interrupt and branch to the first address of the interrupt vector. To
determine this value refer to the processor data sheet for the specific processor
and interrupt source being used.
• ISR Code – although an interrupt function may call other functions, whether they
be user-defined functions, library functions or implicitly called functions to imple-
ment a C operation, the compiler cannot know (in general) which resources are
used by the called function. As a result, the compiler will save all the working reg-
isters and RCOUNT, even if they are not all used explicitly in the ISR itself. The
increased latency associated with the call does not lend itself to fast response
times.
.global _main
_main:
call _foo
return
.bss
.global _asmVariable
.align 2
_asmVariable: .space 2
.end
In the C file, ex1.c, external references to symbols declared in an assembly file are
declared using the standard extern keyword; note that asmFunction, or
_asmFunction in the assembly source, is a void function and is declared
accordingly.
In the assembly file, ex1.s, the symbols _asmFunction, _main and _asmVariable
are made globally visible through the use of the .global assembler directive and can
be accessed by any other source file. The symbol _main is only referenced and not
declared; therefore, the assembler takes this to be an external reference.
The following compiler example shows how to call an assembly function with two
parameters. The C function main in call1.c calls the asmFunction in call2.s
with two parameters.
Note: Only a single string can be passed to the simple form of inline
assembly.
In an extended assembler instruction using asm, the operands of the instruction are
specified using C expressions. The extended syntax is:
asm("template" [ : [ "constraint"(output-operand) [ , ... ] ]
[ : [ "constraint"(input-operand) [ , ... ] ]
[ "clobber" [ , ... ] ]
]
]);
You must specify an assembler instruction template, plus an operand constraint
string for each operand. The template specifies the instruction mnemonic and option-
ally placeholders for the operands. The constraint strings specify operand con-
straints, for example, that an operand must either be in a register (the usual case) or
that it must be an immediate value.
This example demonstrates how to use the swap instruction (which the compiler does
not generally use):
asm ("swap %0" : "+r"(var));
Here var is the C expression for the operand, which is both an input and an output
operand. The operand is constrained to be of type r, which denotes a register operand.
The + in +r indicates that the operand is both an input and output operand.
Each operand is described by an operand-constraint string that is followed by the C
expression in parentheses. A colon separates the assembler template from the first
output operand and another separates the last output operand from the first input, if
any. Commas separate output operands and separate inputs.
If there are no output operands, but there are input operands; then there must be two
consecutive colons surrounding the place where the output operands would go. The
compiler requires that the output operand expressions must be L-values. The input
operands need not be L-values. The compiler cannot check whether the operands
have data types that are reasonable for the instruction being executed. It does not
parse the assembler instruction template and does not know what it means, or whether
it is valid assembler input. The extended asm feature is most often used for machine
instructions that the compiler itself does not know exist. If the output expression cannot
be directly addressed (for example, it is a bit-field), the constraint must allow a register.
In that case, the compiler will use the register as the output of the asm, and then store
that register into the output. If output operands are write-only, the compiler will assume
that the values in these operands before the instruction are dead and need not be
generated.
return(c);
}
The intention is to compute the value (a + b) << a. However, as written, the value
computed may or may not be this value. The correct coding informs the compiler that
the operand c is modified before the asm instruction is finished using the input
operands, as follows:
int
exprgood(int a, int b)
{
int c;
return(c);
}
void main(void)
{
double i;
100%
OPTIMIZATION LEVELS
50%
0% Free* PRO
...
while (object.status != 0) {
object.blinky ^= 1;
}
If the compiler has not been able to generate an atomic, uninterruptable sequence to
XOR blinky then this can be a possible source of corruption. Consider the flow where
status is updated but the blinky update is not complete. Writing back the new value
of blinky, which shares a word with status, might over-write the possibly new value
of status causing the generated code to never see when status has been updated.
If your code is similar to the above example, you can see that volatile is not a suf-
ficient solution. Consider coding styles that will prevent this overwrite from occurring,
such as not sharing memory in that way and the use of critical-sections to control
access of shared data. Often it is efficient and clearer to make use of the
object-oriented principal of accessor functions where the access of each object is
tightly controlled in one place. A well-defined gating of shared data can allow the code
to be written without using volatile at all, thus allowing the code to be safe and share
data efficiently.
int bar() {
asm("mov _foo,w7");
asm("inc w7,w0");
asm("return");
}
Though the example could be written in pure C as return foo+1;, the correct way
to write this in inline assembly requires the use of extended Asm syntax:
int bar() {
int result;
Earlier (Section 18.4 “Using Optimizations.”) we mentioned some of the effects of opti-
mizing code. Some of these effects will prevent the debugger from displaying a value
(the variable is not needed and has been optimized away) or placing a breakpoint (the
line of code does not exist).
Sometimes it is more effective to debug in a mixed C-assembly display, or to follow the
C code along with the Program Memory view.
Table 19-12: Compiler automatically SaveS and Restores the Variables var1
and var2
PICC18 No equivalent
C18 #pragma interrupt isr0 save=var1, var2
void isr0(void)
{
/* perform interrupt function here */
}
XC16 void __attribute__((__interrupt__(__save__(var1,var2))))
isr0(void)
{
/* perform interrupt function here */
}
data
General data space. Variables in general data space can be accessed using ordinary
C statements. This is the default allocation.
prog
General program space, which is normally reserved for executable code. Variables in
this program space can not be accessed using ordinary C statements. They must be
explicitly accessed by the programmer, usually using table-access inline assembly
instructions, using the program space visibility window, or by qualifying with
__prog__.
auto_psv
A compiler-managed area in program space, designated for program space visibility
window access. Variables in this space can be read (but not written) using ordinary C
statements and are subject to a maximum of 32K total space allocated.
psv
Program space, designated for program space visibility window access. Variables in
PSV space are not managed by the compiler and can not be accessed using ordinary
C statements. They must be explicitly accessed by the programmer, usually using
table-access inline assembly instructions, or using the program space visibility window.
Variables in PSV space can be accessed using a single setting of the PSVPAG register
or by qualifying with __psv__.
end_page = __builtin_tblpage(&_PROGRAM_END);
end_offset = __builtin_tbloffset(&_PROGRAM_END);
_init_prog_address(big_addr, _PROGRAM_END);
A.2 Translation
Implementation-Defined Behavior for Translation is covered in section G.3.1 of the
ANSI C Standard.
Is each non-empty sequence of white-space characters, other than new line, retained
or is it replaced by one space character? (ISO 5.1.1.2)
It is replaced by one space character.
How is a diagnostic message identified? (ISO 5.1.1.3)
Diagnostic messages are identified by prefixing them with the source file name and line
number corresponding to the message, separated by colon characters (‘:’).
Are there different classes of message? (ISO 5.1.1.3)
Yes.
If yes, what are they? (ISO 5.1.1.3)
Errors, which inhibit production of an output file, and warnings, which do not inhibit
production of an output file.
What is the translator return status code for each class of message? (ISO 5.1.1.3)
The return status code for errors is 1; for warnings it is 0.
Can a level of diagnostic be controlled? (ISO 5.1.1.3)
Yes.
If yes, what form does the control take? (ISO 5.1.1.3)
Compiler command-line options may be used to request or inhibit the generation of
warning messages.
A.3 Environment
Implementation-Defined Behavior for Environment is covered in section G.3.2 of the
ANSI C Standard.
What library facilities are available to a freestanding program? (ISO 5.1.2.1)
All of the facilities of the standard C library are available, provided that a small set of
functions is customized for the environment, as described in the “Run Time Libraries”
section.
Describe program termination in a freestanding environment. (ISO 5.1.2.1)
If the function main returns or the function exit is called, a HALT instruction is executed
in an infinite loop. This behavior is customizable.
Describe the arguments (parameters) passed to the function main? (ISO 5.1.2.2.1)
No parameters are passed to main.
Which of the following is a valid interactive device: (ISO 5.1.2.3)
Asynchronous terminal No
Paired display and keyboard No
Inter program connection No
Other, please describe? None
A.4 Identifiers
Implementation-Defined Behavior for Identifiers is covered in section G.3.3 of the ANSI
C Standard.
How many characters beyond thirty-one (31) are significant in an identifier without
external linkage? (ISO 6.1.2)
All characters are significant.
How many characters beyond six (6) are significant in an identifier with external
linkage? (ISO 6.1.2)
All characters are significant.
Is case significant in an identifier with external linkage? (ISO 6.1.2)
Yes.
A.5 Characters
Implementation-Defined Behavior for Characters is covered in section G.3.4 of the
ANSI C Standard.
Detail any source and execution characters which are not explicitly specified by the
Standard? (ISO 5.2.1)
None.
List escape sequence value produced for listed sequences. (ISO 5.2.2)
A.6 Integers
Implementation-Defined Behavior for Integers is covered in section G.3.5 of the ANSI
C Standard.
The following table describes the amount of storage and range of various types of
integers: (ISO 6.1.2.5)
What is the result of converting an integer to a shorter signed integer, or the result of
converting an unsigned integer to a signed integer of equal length, if the value cannot
be represented? (ISO 6.2.1.2)
There is a loss of significance. No error is signaled.
What are the results of bitwise operations on signed integers? (ISO 6.3)
Shift operators retain the sign. Other operators act as if the operand(s) are unsigned
integers.
What is the sign of the remainder on integer division? (ISO 6.3.5)
+
What is the result of a right shift of a negative-valued signed integral type? (ISO 6.3.7)
The sign is retained.
A.9 Registers
Implementation-Defined Behavior for Registers is covered in section G.3.8 of the ANSI
C Standard.
To what extent does the storage class specifier register actually effect the storage
of objects in registers? (ISO 6.5.1)
If optimization is disabled, an attempt will be made to honor the register storage
class; otherwise, it is ignored.
A.11 Qualifiers
Implementation-Defined Behavior for Qualifiers is covered in section G.3.10 of the
ANSI C Standard.
Describe what action constitutes an access to an object that has volatile-qualified type?
(ISO 6.5.3)
If an object is named in an expression, it has been accessed.
A.12 Declarators
Implementation-Defined Behavior for Declarators is covered in section G.3.11 of the
ANSI C Standard.
What is the maximum number of declarators that may modify an arithmetic, structure,
or union type? (ISO 6.5.4)
No limit.
A.13 Statements
Implementation-Defined Behavior for Statements is covered in section G.3.12 of the
ANSI C Standard.
What is the maximum number of case values in a switch statement? (ISO 6.6.4.2)
No limit.
What are the definitions for __ DATE __ and __ TIME __ respectively, when the date
and time of translation are not available? (ISO 6.8.8)
Not applicable. The compiler is not supported in environments where these functions
are not available.
What values are returned by the mathematics functions after a domain errors?
(ISO 7.5.1)
NaN.
Do the mathematics functions set the integer expression errno to the value of the
macro ERANGE on underflow range errors? (ISO 7.5.1)
Yes.
Do you get a domain error or is zero returned when the fmod function has a second
argument of zero? (ISO 7.5.6.4)
Domain error.
A.16 Signals
What is the set of signals for the signal function? (ISO 7.7.1.1)
Describe the parameters and the usage of each signal recognized by the signal
function. (ISO 7.7.1.1)
Application defined.
Describe the default handling and the handling at program startup for each signal
recognized by the signal function? (ISO 7.7.1.1)
None.
If the equivalent of signal (sig,SIG_DFL) is not executed prior to the call of a signal
handler, what blocking of the signal is performed? (ISO 7.7.1.1)
None.
Is the default handling reset if a SIGILL signal is received by a handler specified to the
signal function? (ISO 7.7.1.1)
No.
A.18 tmpfile
Is an open temporary file removed if the program terminates abnormally? (ISO 7.9.4.3)
Yes.
A.19 errno
What value is the macro errno set to by the fgetpos or ftell function on failure?
(ISO 7.9.9.1, (ISO 7.9.9.4)
Application defined.
What is the format of the messages generated by the perror function? (ISO 7.9.10.4)
The argument to perror, followed by a colon, followed by a text description of the
value of errno.
A.20 Memory
What is the behavior of the calloc, malloc or realloc function if the size requested
is zero? (ISO 7.10.3)
A block of zero length is allocated.
A.21 abort
What happens to open and temporary files when the abort function is called?
(ISO 7.10.4.1)
Nothing.
A.22 exit
What is the status returned by the exit function if the value of the argument is other than
zero, EXIT_SUCCESS, or EXIT_FAILURE? (ISO 7.10.4.3)
The value of the argument.
A.23 getenv
What limitations are there on environment names? (ISO 7.10.4.4)
Application defined.
Describe the method used to alter the environment list obtained by a call to the getenv
function. (ISO 7.10.4.4)
Application defined.
A.24 system
Describe the format of the string that is passed to the system function. (ISO 7.10.4.5)
Application defined.
What mode of execution is performed by the system function? (ISO 7.10.4.5)
Application defined.
A.25 strerror
Describe the format of the error message output by the strerror function.
(ISO 7.11.6.2)
A plain character string.
List the contents of the error message strings returned by a call to the strerror
function. (ISO 7.11.6.2)
Do not confuse the boolean type, bool, and the integer type, bit, implemented by
MPLAB XC8.
1. Not all C99 features have been adopted by all Microchip MPLAB XC compilers.
B.5 Operator
The @ operator may be used with other compilers to indicate the desired memory loca-
tion of an object. As Table B-4 indicates, support for this syntax in MPLAB C is limited
to MPLAB XC8 only.
Any address specified with another device is unlikely to be correct on a new architec-
ture. Review the address in conjunction with the data sheet for your target Microchip
device.
Using @ in a compatibility mode with MPLAB XC8 will work correctly, but will generate
a warning. To prevent this warning from appearing again, use the reviewed address
with the MPLAB C __at() specifier instead.
For MPLAB XC16/32, consider using the address attribute.
Note 1: These intrinsic functions map to macros which disable or enable the global interrupt
enable bit on 8-bit PIC® devices.
The header file <xc.h> must be included for supported functions to operate correctly.
B.8 Pragmas
Pragmas may be used by a compiler to control code generation. Any compiler will
ignore an unknown pragma, but many pragmas implemented by another compiler have
also been implemented by the MPLAB XC compilers in compatibility mode. Table B-7
shows the pragmas and the level of support when using each of the MPLAB XC
compilers.
Many of these pragmas take arguments. Even if a pragma is supported by an MPLAB
XC compiler, this support may not apply to all of the pragma’s arguments. This is
indicated in the following table.
C.2 Errors
Symbols
\x used with no following HEX digits
The escape sequence \x should be followed by hex digits.
‘&’ constraint used with no register class
The asm statement is invalid.
‘%’ constraint used with last operand
The asm statement is invalid.
#elif after #else
In a preprocessor conditional, the #else clause must appear after any #elif clauses.
#elif without #if
In a preprocessor conditional, the #if must be used before using the #elif.
#else after #else
In a preprocessor conditional, the #else clause must appear only once.
#else without #if
In a preprocessor conditional, the #if must be used before using the #else.
A
a parameter list with an ellipsis can’t match an empty parameter name list
declaration
The declaration and definition of a function must be consistent.
“symbol” after #line is not a positive integer
#line is expecting a source line number which must be positive.
aggregate value used where a complex was expected
Do not use aggregate values where complex values are expected.
aggregate value used where a float was expected
Do not use aggregate values where floating-point values are expected.
aggregate value used where an integer was expected
Do not use aggregate values where integer values are expected.
alias arg not a string
The argument to the alias attribute must be a string that names the target for which the
current identifier is an alias.
alignment may not be specified for ‘identifier’
The aligned attribute may only be used with a variable.
‘__alignof’ applied to a bit-field
The ‘__alignof’ operator may not be applied to a bit-field.
alternate interrupt vector is not a constant
The interrupt vector number must be an integer constant.
alternate interrupt vector number n is not valid
A valid interrupt vector number is required.
B
bit-field ‘identifier’ has invalid type
Bit-fields must be of enumerated or integral type.
bit-field ‘identifier’ width not an integer constant
Bit-field widths must be integer constants.
both long and short specified for ‘identifier’
A variable cannot be of type long and of type short.
both signed and unsigned specified for ‘identifier’
A variable cannot be both signed and unsigned.
braced-group within expression allowed only inside a function
It is illegal to have a braced-group within expression outside a function.
break statement not within loop or switch
Break statements must only be used within a loop or switch.
__builtin_longjmp second argument must be 1
__builtin_longjmp requires its second argument to be 1.
C
called object is not a function
Only functions may be called in C.
cannot convert to a pointer type
The expression cannot be converted to a pointer type.
cannot put object with volatile field into register
It is not legal to put an object with a volatile field into a register.
cannot reload integer constant operand in ‘asm’
The asm statement is invalid.
cannot specify both near and far attributes
The attributes near and far are mutually exclusive, only one may be used for a function
or variable.
cannot take address of bit-field ‘identifier’
It is not legal to attempt to take address of a bit-field.
can’t open ‘file’ for writing
The system cannot open the specified ‘file’. Possible causes are not enough disk
space to open the file, the directory does not exist, or there is no write permission in the
destination directory.
can’t set ‘attribute’ attribute after definition
The ‘attribute’ attribute must be used when the symbol is defined.
case label does not reduce to an integer constant
Case labels must be compile-time integer constants.
case label not within a switch statement
Case labels must be within a switch statement.
cast specifies array type
It is not permissible for a cast to specify an array type.
D
data type of ‘name’ isn’t suitable for a register
The data type does not fit into the requested register.
declaration for parameter ‘identifier’ but no such parameter
Only parameters in the parameter list may be declared.
declaration of ‘identifier’ as array of functions
It is not legal to have an array of functions.
declaration of ‘identifier’ as array of voids
It is not legal to have an array of voids.
‘identifier’ declared as function returning a function
Functions may not return functions.
‘identifier’ declared as function returning an array
Functions may not return arrays.
decrement of pointer to unknown structure
Do not decrement a pointer to an unknown structure.
‘default’ label not within a switch statement
Default case labels must be within a switch statement.
‘symbol’ defined both normally and as an alias
A ‘symbol’ can not be used as an alias for another symbol if it has already been
defined.
‘defined’ cannot be used as a macro name
The macro name cannot be called ‘defined’.
dereferencing pointer to incomplete type
A dereferenced pointer must be a pointer to an incomplete type.
E
elements of array ‘identifier’ have incomplete type
Array elements should have complete types.
empty character constant
Empty character constants are not legal.
empty file name in ‘#keyword’
The file name specified as an argument of the specified #keyword is empty.
empty index range in initializer
Do not use empty index ranges in initializers
empty scalar initializer
Scalar initializers must not be empty.
enumerator value for ‘identifier’ not integer constant
Enumerator values must be integer constants.
error closing ‘file’
The system cannot close the specified ‘file’. Possible causes are not enough disk
space to write to the file or the file is too big.
error writing to ‘file’
The system cannot write to the specified ‘file’. Possible causes are not enough disk
space to write to the file or the file is too big.
excess elements in char array initializer
There are more elements in the list than the initializer value states.
excess elements in struct initializer
Do not use excess elements in structure initializers.
expression statement has incomplete type
The type of the expression is incomplete.
extra brace group at end of initializer
Do not place extra brace groups at the end of initializers.
F
‘identifier’ fails to be a typedef or built in type
A data type must be a typedef or built-in type.
field ‘identifier’ declared as a function
Fields may not be declared as functions.
field ‘identifier’ has incomplete type
Fields must have complete types.
first argument to __builtin_choose_expr not a constant
The first argument must be a constant expression that can be determined at compile
time.
flexible array member in otherwise empty struct
A flexible array member must be the last element of a structure with more than one
named member.
flexible array member in union
A flexible array member cannot be used in a union.
flexible array member not at end of struct
A flexible array member must be the last element of a structure.
‘for’ loop initial declaration used outside C99 mode
A ‘for’ loop initial declaration is not valid outside C99 mode.
format string arg follows the args to be formatted
The arguments to the format attribute are inconsistent. The format string argument
index must be less than the index of the first argument to check.
format string arg not a string type
The format string index argument of the format attribute specifies a parameter which is
not a string type.
format string has invalid operand number
The operand number argument of the format attribute must be a compile-time constant.
function definition declared ‘register’
Function definitions may not be declared ‘register’.
function definition declared ‘typedef’
Function definitions may not be declared ‘typedef’.
function does not return string type
The format_arg attribute may only be used with a function which return value is a string
type.
function ‘identifier’ is initialized like a variable
It is not legal to initialize a function like a variable.
function return type cannot be function
The return type of a function cannot be a function.
G
global register variable follows a function definition
Global register variables should precede function definitions.
global register variable has initial value
Do not specify an initial value for a global register variable.
global register variable ‘identifier’ used in nested function
Do not use a global register variable in a nested function.
H
‘identifier’ has an incomplete type
It is not legal to have an incomplete type for the specified ‘identifier’.
‘identifier’ has both ‘extern’ and initializer
A variable declared ‘extern’ cannot be initialized.
hexadecimal floating constants require an exponent
Hexadecimal floating constants must have exponents.
I
implicit declaration of function ‘identifier’
The function identifier is used without a preceding prototype declaration or function
definition.
impossible register constraint in ‘asm’
The asm statement is invalid.
incompatible type for argument n of ‘identifier’
When calling functions in C, ensure that actual argument types match the formal
parameter types.
incompatible type for argument n of indirect function call
When calling functions in C, ensure that actual argument types match the formal
parameter types.
incompatible types in operation
The types used in operation must be compatible.
incomplete ‘name’ option
The option to the command-line parameter name is incomplete.
inconsistent operand constraints in an ‘asm’
The asm statement is invalid.
increment of pointer to unknown structure
Do not increment a pointer to an unknown structure.
initializer element is not computable at load time
Initializer elements must be computable at load time.
initializer element is not constant
Initializer elements must be constant.
initializer fails to determine size of ‘identifier’
An array initializer fails to determine its size.
L
label label referenced outside of any function
Labels may only be referenced inside functions.
label ‘label’ used but not defined
The specified label is used but is not defined.
language ‘name’ not recognized
Permissible languages include: c assembler none.
filename: linker input file unused because linking not done
The specified filename was specified on the command line, and it was taken to be a
linker input file (since it was not recognized as anything else). However, the link step
was not run. Therefore, this file was ignored.
long long long is too long for GCC
The compiler supports integers no longer than long long.
long or short specified with char for ‘identifier’
The long and short qualifiers cannot be used with the char type.
long or short specified with floating type for ‘identifier’
The long and short qualifiers cannot be used with the float type.
long, short, signed or unsigned invalid for ‘identifier’
The long, short and signed qualifiers may only be used with integral types.
M
macro names must be identifiers
Macro names must start with a letter or underscore followed by more letters, numbers
or underscores.
macro parameters must be comma-separated
Commas are required between parameters in a list of parameters.
macro ‘name’ passed x arguments, but takes just y
Too many arguments were passed to macro ‘name’.
N
negative width in bit-field ‘identifier’
Bit-field widths may not be negative.
nested function ‘name’ declared ‘extern’
A nested function cannot be declared ‘extern’.
nested redefinition of ‘identifier’
Nested redefinitions are illegal.
no data type for mode ‘mode’
The argument mode specified for the mode attribute is a recognized GCC machine
mode, but it is not one that is implemented in the compiler.
no include path in which to find ‘name’
Cannot find include file ‘name’.
no macro name given in #‘directive’ directive
A macro name must follow the #define, #undef, #ifdef or #ifndef directives.
nonconstant array index in initializer
Only constant array indices may be used in initializers.
non-prototype definition here
If a function prototype follows a definition without a prototype and the number of
arguments is inconsistent between the two, this message identifies the line number of
the non-prototype definition.
number of arguments doesn’t match prototype
The number of function arguments must match the function’s prototype.
O
operand constraint contains incorrectly positioned ‘+’ or ‘=’
The asm statement is invalid.
operand constraints for ‘asm’ differ in number of alternatives
The asm statement is invalid.
operator “defined” requires an identifier
“defined” is expecting an identifier.
operator ‘symbol’ has no right operand
Preprocessor operator ‘symbol’ requires an operand on the right side.
output number n not directly addressable
The asm statement is invalid.
output operand constraint lacks ‘=’
The asm statement is invalid.
output operand is constant in ‘asm’
The asm statement is invalid.
overflow in enumeration values
Enumeration values must be in the range of ‘int’.
P
parameter ‘identifier’ declared void
Parameters may not be declared void.
parameter ‘identifier’ has incomplete type
Parameters must have complete types.
parameter ‘identifier’ has just a forward declaration
Parameters must have complete types; forward declarations are insufficient.
parameter ‘identifier’ is initialized
It is not legal to initialize parameters.
parameter name missing
The macro was expecting a parameter name. Check for two commas without a name
between.
parameter name missing from parameter list
Parameter names must be included in the parameter list.
parameter name omitted
Parameter names may not be omitted.
param types given both in param list and separately
Parameter types should be given either in the parameter list or separately, but not both.
parse error
The source line cannot be parsed; it contains errors.
pointer value used where a complex value was expected
Do not use pointer values where complex values are expected.
pointer value used where a floating point value was expected
Do not use pointer values where floating-point values are expected.
pointers are not permitted as case values
A case value must be an integer-valued constant or constant expression.
predicate must be an identifier
#assert or #unassert require a single identifier as the predicate.
predicate’s answer is empty
The #assert or #unassert has a predicate and parentheses but no answer inside the
parentheses, which is required.
previous declaration of ‘identifier’
This message identifies the location of a previous declaration of identifier that conflicts
with the current declaration.
identifier previously declared here
This message identifies the location of a previous declaration of identifier that conflicts
with the current declaration.
identifier previously defined here
This message identifies the location of a previous definition of identifier that conflicts
with the current definition.
prototype declaration
Identifies the line number where a function prototype is declared. Used in conjunction
with other error messages.
R
redeclaration of ‘identifier’
The identifier is multiply declared.
redeclaration of ‘enum identifier’
Enums may not be redeclared.
‘identifier’ redeclared as different kind of symbol
Multiple, inconsistent declarations exist for identifier.
redefinition of ‘identifier’
The identifier is multiply defined.
redefinition of ‘struct identifier’
Structs may not be redefined.
redefinition of ‘union identifier’
Unions may not be redefined.
register name given for non-register variable ‘name’
Attempt to map a register to a variable which is not marked as register.
register name not specified for ‘name’
File scope variable ‘name’ declared as a register variable without providing a register.
register specified for ‘name’ isn’t suitable for data type
Alignment or other restrictions prevent using requested register.
request for member ‘identifier’ in something not a structure or union
Only structure or unions have members. It is not legal to reference a member of
anything else, since nothing else has members.
requested alignment is not a constant
The argument to the aligned attribute must be a compile-time constant.
requested alignment is not a power of 2
The argument to the aligned attribute must be a power of two.
requested alignment is too large
The alignment size requested is larger than the linker allows. The size must be 4096
or less and a power of 2.
return type is an incomplete type
Return types must be complete.
S
save variable ‘name’ index not constant
The subscript of the array ‘name’ is not a constant integer.
save variable ‘name’ is not word aligned
The object being saved must be word aligned
save variable ‘name’ size is not even
The object being saved must be evenly sized.
save variable ‘name’ size is not known
The object being saved must have a known size.
T
the only valid combination is ‘long double’
The long qualifier is the only qualifier that may be used with the double type.
this built-in requires a frame pointer
__builtin_return_address requires a frame pointer. Do not use the
-fomit-frame-pointer option.
this is a previous declaration
If a label is duplicated, this message identifies the line number of a preceding
declaration.
too few arguments to function
When calling a function in C, do not specify fewer arguments than the function requires.
Nor should you specify too many.
too few arguments to function ‘identifier’
When calling a function in C, do not specify fewer arguments than the function requires.
Nor should you specify too many.
too many alternatives in ‘asm’
The asm statement is invalid.
too many arguments to function
When calling a function in C, do not specify more arguments than the function requires.
Nor should you specify too few.
too many arguments to function ‘identifier’
When calling a function in C, do not specify more arguments than the function requires.
Nor should you specify too few.
too many decimal points in number
Expecting only one decimal point.
top-level declaration of ‘identifier’ specifies ‘auto’
Auto variables can only be declared inside functions.
two or more data types in declaration of ‘identifier’
Each identifier may have only a single data type.
two types specified in one empty declaration
No more that one type should be specified.
type of formal parameter n is incomplete
Specify a complete type for the indicated parameter.
type mismatch in conditional expression
Types in conditional expressions must not be mismatched.
typedef ‘identifier’ is initialized
It is not legal to initialize typedef’s. Use __typeof__ instead.
U
‘identifier’ undeclared (first use in this function)
The specified identifier must be declared.
‘identifier’ undeclared here (not in a function)
The specified identifier must be declared.
union has no member named ‘identifier’
A union member named ‘identifier’ is referenced, but the referenced union contains no
such member. This is not allowed.
unknown field ‘identifier’ specified in initializer
Do not use unknown fields in initializers.
unknown machine mode ‘mode’
The argument mode specified for the mode attribute is not a recognized machine
mode.
unknown register name ‘name’ in ‘asm’
The asm statement is invalid.
unrecognized format specifier
The argument to the format attribute is invalid.
unrecognized option ‘-option’
The specified command-line option is not recognized.
unrecognized option ‘option’
‘option’ is not a known option.
‘identifier’ used prior to declaration
The identifier is used prior to its declaration.
unterminated #‘name’
#endif is expected to terminate a #if, #ifdef or #ifndef conditional.
unterminated argument list invoking macro ‘name’
Evaluation of a function macro has encountered the end of file before completing the
macro expansion.
unterminated comment
The end of file was reached while scanning for a comment terminator.
V
‘va_start’ used in function with fixed args
‘va_start’ should be used only in functions with variable argument lists.
variable ‘identifier’ has initializer but incomplete type
It is not legal to initialize variables with incomplete types.
variable or field ‘identifier’ declared void
Neither variables nor fields may be declared void.
variable-sized object may not be initialized
It is not legal to initialize a variable-sized object.
virtual memory exhausted
Not enough memory left to write error message.
W
warning: -pipe ignored because -save-temps specified
The -pipe option cannot be used with the -save-temps option.
warning: -pipe ignored because -time specified
The -pipe option cannot be used with the -time option.
warning: ‘-x spec’ after last input file has no effect
The ‘-x’ command line option affects only those files named after its on the command
line; if there are no such files, then this option has no effect.
weak declaration of ‘name’ must be public
Weak symbols must be externally visible.
weak declaration of ‘name’ must precede definition
‘name’ was defined and then declared weak.
wrong number of arguments specified for attribute attribute
There are too few or too many arguments given for the attribute named ‘attribute’.
wrong type argument to bit-complement
Do not use the wrong type of argument to this operator.
wrong type argument to decrement
Do not use the wrong type of argument to this operator.
wrong type argument to increment
Do not use the wrong type of argument to this operator.
wrong type argument to unary exclamation mark
Do not use the wrong type of argument to this operator.
wrong type argument to unary minus
Do not use the wrong type of argument to this operator.
wrong type argument to unary plus
Do not use the wrong type of argument to this operator.
Z
zero width for bit-field ‘identifier’
Bit-fields may not have zero width.
C.3 Warnings
Symbols
‘/*’ within comment
A comment mark was found within a comment.
‘$’ character(s) in identifier or number
Dollar signs in identifier names are an extension to the standard.
#‘directive’ is a GCC extension
#warning, #include_next, #ident, #import, #assert and #unassert directives are GCC
extensions and are not of ISO C89.
#import is obsolete, use an #ifndef wrapper in the header file
The #import directive is obsolete. #import was used to include a file if it hadn’t already
been included. Use the #ifndef directive instead.
#include_next in primary source file
#include_next starts searching the list of header file directories after the directory
in which the current file was found. In this case, there were no previous header files so
it is starting in the primary source file.
#pragma pack (pop) encountered without matching #pragma pack (push, <n>)
The pack(pop) pragma must be paired with a pack(push) pragma, which must precede
it in the source file.
#pragma pack (pop, identifier) encountered without matching #pragma pack
(push, identifier, <n>)
The pack(pop) pragma must be paired with a pack(push) pragma, which must precede
it in the source file.
#warning: message
The directive #warning causes the preprocessor to issue a warning and continue
preprocessing. The tokens following #warning are used as the warning message.
A
absolute address specification ignored
Ignoring the absolute address specification for the code section in the #pragma
statement because it is not supported in the compiler. Addresses must be specified in
the linker script and code sections can be defined with the keyword __attribute__.
address of register variable ‘name’ requested
The register specifier prevents taking the address of a variable.
alignment must be a small power of two, not n
The alignment parameter of the pack pragma must be a small power of two.
anonymous enum declared inside parameter list
An anonymous enum is declared inside a function parameter list. It is usually better
programming practice to declare enums outside parameter lists, since they can never
become complete types when defined inside parameter lists.
anonymous struct declared inside parameter list
An anonymous struct is declared inside a function parameter list. It is usually better
programming practice to declare structs outside parameter lists, since they can never
become complete types when defined inside parameter lists.
B
backslash and newline separated by space
While processing for escape sequences, a backslash and newline were found
separated by a space.
backslash-newline at end of file
While processing for escape sequences, a backslash and newline were found at the
end of the file.
bit-field ‘identifier’ type invalid in ISO C
The type used on the specified identifier is not valid in ISO C.
braces around scalar initializer
A redundant set of braces around an initializer is supplied.
C
C++ style comments are not allowed in ISO C89
Use C style comments ‘/*’ and ‘*/’ instead of C++ style comments ‘//’.
call-clobbered register used for global register variable
Choose a register that is normally saved and restored by function calls (W8-W13), so
that library routines will not clobber it.
cannot inline function ‘main’
The function ‘main’ is declared with the inline attribute. This is not supported, since
main must be called from the C start-up code, which is compiled separately.
can’t inline call to ‘identifier’ called from here
The compiler was unable to inline the call to the specified function.
case value ‘n’ not in enumerated type
The controlling expression of a switch statement is an enumeration type, yet a case
expression has the value n, which does not correspond to any of the enumeration
values.
case value ‘value’ not in enumerated type ‘name’
‘value’ is an extra switch case that is not an element of the enumerated type ‘name’.
cast does not match function type
The return type of a function is cast to a type that does not match the function’s type.
cast from pointer to integer of different size
A pointer is cast to an integer that is not 16 bits wide.
cast increases required alignment of target type
When compiling with the -Wcast-align command-line option, the compiler verifies
that casts do not increase the required alignment of the target type. For example, this
warning message will be given if a pointer to char is cast as a pointer to int, since the
aligned for char (byte alignment) is less than the alignment requirement for int (word
alignment).
character constant too long
Character constants must not be too long.
comma at end of enumerator list
Unnecessary comma at the end of the enumerator list.
comma operator in operand of #if
Not expecting a comma operator in the #if directive.
comparing floating point with == or != is unsafe
Floating-point values can be approximations to infinitely precise real numbers. Instead
of testing for equality, use relational operators to see whether the two values have
ranges that overlap.
comparison between pointer and integer
A pointer type is being compared to an integer type.
D
data definition has no type or storage class
A data definition was detected that lacked a type and storage class.
data qualifier ‘qualifier’ ignored
Data qualifiers, which include ‘access’, ‘shared’ and ‘overlay’, are not used in the com-
piler, but are there for compatibility with the MPLAB C Compiler for PIC18 MCUs.
declaration of ‘identifier’ has ‘extern’ and is initialized
Externs should not be initialized.
declaration of ‘identifier’ shadows a parameter
The specified identifier declaration shadows a parameter, making the parameter
inaccessible.
declaration of ‘identifier’ shadows a symbol from the parameter list
The specified identifier declaration shadows a symbol from the parameter list, making
the symbol inaccessible.
declaration of ‘identifier’ shadows global declaration
The specified identifier declaration shadows a global declaration, making the global
inaccessible.
‘identifier’ declared inline after being called
The specified function was declared inline after it was called.
‘identifier’ declared inline after its definition
The specified function was declared inline after it was defined.
‘identifier’ declared ‘static’ but never defined
The specified function was declared static, but was never defined.
decrement of read-only member ‘name’
The member ‘name’ was declared as const and cannot be modified by decrementing.
decrement of read-only variable ‘name’
‘name’ was declared as const and cannot be modified by decrementing.
‘identifier’ defined but not used
The specified function was defined, but was never used.
deprecated use of label at end of compound statement
A label should not be at the end of a statement. It should be followed by a statement.
dereferencing ‘void *’ pointer
It is not correct to dereference a ‘void *’ pointer. Cast it to a pointer of the appropriate
type before dereferencing the pointer.
division by zero
Compile-time division by zero has been detected.
E
embedded ‘\0’ in format
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the format string contains an embedded ‘\0’ (zero), which can cause early termination
of format string processing.
empty body in an else-statement
An else statement is empty.
empty body in an if-statement
An if statement is empty.
empty declaration
The declaration contains no names to declare.
empty range specified
The range of values in a case range is empty, that is, the value of the low expression
is greater than the value of the high expression. Recall that the syntax for case ranges
is case low ... high:.
‘enum identifier’ declared inside parameter list
The specified enum is declared inside a function parameter list. It is usually better
programming practice to declare enums outside parameter lists, since they can never
become complete types when defined inside parameter lists.
enum defined inside parms
An enum is defined inside a function parameter list.
enumeration value ‘identifier’ not handled in switch
The controlling expression of a switch statement is an enumeration type, yet not all
enumeration values have case expressions.
enumeration values exceed range of largest integer
Enumeration values are represented as integers. The compiler detected that an
enumeration range cannot be represented in any of the compiler integer formats,
including the largest such format.
excess elements in array initializer
There are more elements in the initializer list than the array was declared with.
excess elements in scalar initializer");
There should be only one initializer for a scalar variable.
excess elements in struct initializer
There are more elements in the initializer list than the structure was declared with.
excess elements in union initializer
There are more elements in the initializer list than the union was declared with.
F
-ffunction-sections may affect debugging on some targets
You may have problems with debugging if you specify both the -g option and the
-ffunction-sections option.
first argument of ‘identifier’ should be ‘int’
Expecting declaration of first argument of specified identifier to be of type int.
floating constant exceeds range of ‘double’
A floating-point constant is too large or too small (in magnitude) to be represented as
a ‘double’.
floating constant exceeds range of ‘float’
A floating-point constant is too large or too small (in magnitude) to be represented as
a ‘float’.
floating constant exceeds range of ‘long double’
A floating-point constant is too large or too small (in magnitude) to be represented as
a ‘long double’.
floating point overflow in expression
When folding a floating-point constant expression, the compiler found that the
expression overflowed, that is, it could not be represented as float.
‘type1’ format, ‘type2’ arg (arg ‘num’)
The format is of type ‘type1’, but the argument being passed is of type ‘type2’.
The argument in question is the ‘num’ argument.
format argument is not a pointer (arg n)
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the specified argument number n was not a pointer, san the format specifier indicated
it should be.
format argument is not a pointer to a pointer (arg n)
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the specified argument number n was not a pointer san the format specifier indicated
it should be.
fprefetch-loop-arrays not supported for this target
The option to generate instructions to prefetch memory is not supported for this target.
function call has aggregate value
The return value of a function is an aggregate.
function declaration isn’t a prototype
When compiling with the -Wstrict-prototypes command-line option, the compiler
ensures that function prototypes are specified for all functions. In this case, a function
definition was encountered without a preceding function prototype.
function declared ‘noreturn’ has a ‘return’ statement
A function was declared with the noreturn attribute-indicating that the function does not
return-yet the function contains a return statement. This is inconsistent.
G
GCC does not yet properly implement ‘[*]’ array declarators
Variable length arrays are not currently supported by the compiler.
H
hex escape sequence out of range
The hex sequence must be less than 100 in hex (256 in decimal).
I
ignoring asm-specifier for non-static local variable ‘identifier’
The asm-specifier is ignored when it is used with an ordinary, non-register local
variable.
ignoring invalid multibyte character
When parsing a multibyte character, the compiler determined that it was invalid. The
invalid character is ignored.
ignoring option ‘option’ due to invalid debug level specification
A debug option was used with a debug level that is not a valid debug level.
ignoring #pragma identifier
The specified pragma is not supported by the compiler, and is ignored.
imaginary constants are a GCC extention
ISO C does not allow imaginary numeric constants.
implicit declaration of function ‘identifier’
The specified function has no previous explicit declaration (definition or function
prototype), so the compiler makes assumptions about its return type and parameters.
L
label ‘identifier’ defined but not used
The specified label was defined, but not referenced.
large integer implicitly truncated to unsigned type
An integer constant value appears in the source code without an explicit unsigned
modifier, yet the number cannot be represented as a signed int; therefore, the compiler
automatically treats it as an unsigned int.
left-hand operand of comma expression has no effect
One of the operands of a comparison is a promoted ~unsigned, while the other is
unsigned.
left shift count >= width of type
Shift counts should be less than the number of bits in the type being shifted. Otherwise,
the shift is meaningless, and the result is undefined.
left shift count is negative
Shift counts should be positive. A negative left shift count does not mean shift right;
it is meaningless.
M
‘main’ is usually a function
The identifier main is usually used for the name of the main entry point of an
application. The compiler detected that it was being used in some other way, for
example, as the name of a variable.
‘operation’ makes integer from pointer without a cast
A pointer has been implicitly converted to an integer.
‘operation’ makes pointer from integer without a cast
An integer has been implicitly converted to a pointer.
malformed ‘#pragma pack-ignored’
The syntax of the pack pragma is incorrect.
malformed ‘#pragma pack(pop[,id])-ignored’
The syntax of the pack pragma is incorrect.
malformed ‘#pragma pack(push[,id],<n>)-ignored’
The syntax of the pack pragma is incorrect.
malformed ‘#pragma weak-ignored’
The syntax of the weak pragma is incorrect.
‘identifier’ might be used uninitialized in this function
The compiler detected a control path though a function which might use the specified
identifier before it has been initialized.
missing braces around initializer
A required set of braces around an initializer is missing.
missing initializer
An initializer is missing.
modification by ‘asm’ of read-only variable ‘identifier’
A const variable is the left-hand-side of an assignment in an ‘asm’ statement.
multi-character character constant
A character constant contains more than one character.
N
negative integer implicitly converted to unsigned type
A negative integer constant value appears in the source code, but the number cannot
be represented as a signed int; therefore, the compiler automatically treats it as an
unsigned int.
nested extern declaration of ‘identifier’
There are nested extern definitions of the specified identifier.
no newline at end of file
The last line of the source file is not terminated with a newline character.
no previous declaration for ‘identifier’
When compiling with the -Wmissing-declarations command-line option, the
compiler ensures that functions are declared before they are defined. In this case, a
function definition was encountered without a preceding function declaration.
no previous prototype for ‘identifier’
When compiling with the -Wmissing-prototypes command-line option, the
compiler ensures that function prototypes are specified for all functions. In this case, a
function definition was encountered without a preceding function prototype.
no semicolon at end of struct or union
A semicolon is missing at the end of the structure or union declaration.
non-ISO-standard escape sequence, ‘seq’
‘seq’ is ‘\e’ or ‘\E’ and is an extension to the ISO standard. The sequence can be used
in a string or character constant and stands for the ASCII character <ESC>.
non-static declaration for ‘identifier’ follows static
The specified identifier was declared non-static after it was previously declared as
static.
‘noreturn’ function does return
A function declared with the noreturn attribute returns. This is inconsistent.
‘noreturn’ function returns non-void value
A function declared with the noreturn attribute returns a non-void value. This is
inconsistent.
null format string
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the format string was missing.
O
octal escape sequence out of range
The octal sequence must be less than 400 in octal (256 in decimal).
output constraint ‘constraint’ for operand n is not at the beginning
Output constraints in extended asm should be at the beginning.
overflow in constant expression
The constant expression has exceeded the range of representable values for its type.
overflow in implicit constant conversion
An implicit constant conversion resulted in a number that cannot be represented as a
signed int; therefore, the compiler automatically treats it as an unsigned int.
P
parameter has incomplete type
A function parameter has an incomplete type.
parameter names (without types) in function declaration
The function declaration lists the names of the parameters but not their types.
parameter points to incomplete type
A function parameter points to an incomplete type.
parameter ‘identifier’ points to incomplete type
The specified function parameter points to an incomplete type.
passing arg ‘number’ of ‘name’ as complex rather than floating due to prototype
The prototype declares argument ‘number’ as a complex, but a float value is used so
the compiler converts to a complex to agree with the prototype.
passing arg ‘number’ of ‘name’ as complex rather than integer due to prototype
The prototype declares argument ‘number’ as a complex, but an integer value is used
so the compiler converts to a complex to agree with the prototype.
passing arg ‘number’ of ‘name’ as floating rather than complex due to prototype
The prototype declares argument ‘number’ as a float, but a complex value is used so
the compiler converts to a float to agree with the prototype.
passing arg ‘number’ of ‘name’ as ‘float’ rather than ‘double’ due to prototype
The prototype declares argument ‘number’ as a float, but a double value is used so the
compiler converts to a float to agree with the prototype.
passing arg ‘number’ of ‘name’ as floating rather than integer due to prototype
The prototype declares argument ‘number’ as a float, but an integer value is used so
the compiler converts to a float to agree with the prototype.
passing arg ‘number’ of ‘name’ as integer rather than complex due to prototype
The prototype declares argument ‘number’ as an integer, but a complex value is used
so the compiler converts to an integer to agree with the prototype.
passing arg ‘number’ of ‘name’ as integer rather than floating due to prototype
The prototype declares argument ‘number’ as an integer, but a float value is used so
the compiler converts to an integer to agree with the prototype.
pointer of type ‘void *’ used in arithmetic
A pointer of type ‘void’ has no size and should not be used in arithmetic.
pointer to a function used in arithmetic
A pointer to a function should not be used in arithmetic.
previous declaration of ‘identifier’
This warning message appears in conjunction with another warning message. The
previous message identifies the location of the suspect code. This message identifies
the first declaration or definition of the identifier.
previous implicit declaration of ‘identifier’
This warning message appears in conjunction with the warning message “type
mismatch with previous implicit declaration”. It locates the implicit declaration of the
identifier that conflicts with the explicit declaration.
R
“name” reasserted
The answer for "name" has been duplicated.
“name” redefined
“name” was previously defined and is being redefined now.
redefinition of ‘identifier’
The specified identifier has multiple, incompatible definitions.
redundant redeclaration of ‘identifier’ in same scope
The specified identifier was re-declared in the same scope. This is redundant.
register used for two global register variables
Two global register variables have been defined to use the same register.
repeated ‘flag’ flag in format
When checking the argument list of a call to strftime, the compiler found that there was
a flag in the format string that is repeated.
When checking the argument list of a call to printf, scanf, etc., the compiler found that
one of the flags { ,+,#,0,-} was repeated in the format string.
return-type defaults to ‘int’
In the absence of an explicit function return-type declaration, the compiler assumes
that the function returns an int.
return type of ‘name’ is not ‘int’
The compiler is expecting the return type of ‘name’ to be ‘int’.
‘return’ with a value, in function returning void
The function was declared as void but returned a value.
‘return’ with no value, in function returning non-void
A function declared to return a non-void value contains a return statement with no
value. This is inconsistent.
right shift count >= width of type
Shift counts should be less than the number of bits in the type being shifted. Otherwise,
the shift is meaningless, and the result is undefined.
right shift count is negative
Shift counts should be positive. A negative right shift count does not mean shift left; it
is meaningless.
S
second argument of ‘identifier’ should be ‘char **’
Expecting second argument of specified identifier to be of type ‘char **’.
second parameter of ‘va_start’ not last named argument
The second parameter of ‘va_start’ must be the last named argument.
shadowing built-in function ‘identifier’
The specified function has the same name as a built-in function, and consequently
shadows the built-in function.
shadowing library function ‘identifier’
The specified function has the same name as a library function, and consequently
shadows the library function.
T
‘identifier’ takes only zero or two arguments
Expecting zero or two arguments only.
the meaning of ‘\a’ is different in traditional C
When the -wtraditional option is used, the escape sequence ‘\a’ is not recognized
as a meta-sequence: its value is just ‘a’. In non-traditional compilation, ‘\a’ represents
the ASCII BEL character.
the meaning of ‘\x’ is different in traditional C
When the -wtraditional option is used, the escape sequence ‘\x’ is not recognized
as a meta-sequence: its value is just ‘x’. In non-traditional compilation, ‘\x’ introduces
a hexadecimal escape sequence.
third argument of ‘identifier’ should probably be ‘char **’
Expecting third argument of specified identifier to be of type ‘char **’.
this function may return with or without a value
All exit paths from non-void function should return an appropriate value. The compiler
detected a case where a non-void function terminates, sometimes with and sometimes
without an explicit return value. Therefore, the return value might be unpredictable.
this target machine does not have delayed branches
The -fdelayed-branch option is not supported.
too few arguments for format
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the number of actual arguments was fewer than that required by the format string.
U
undefining ‘defined’
‘defined’ cannot be used as a macro name and should not be undefined.
undefining ‘name’
The #undef directive was used on a previously defined macro name ‘name’.
union cannot be made transparent
The transparent_union attribute was applied to a union, but the specified variable
does not satisfy the requirements of that attribute.
‘union identifier’ declared inside parameter list
The specified union is declared inside a function parameter list. It is usually better
programming practice to declare unions outside parameter lists, since they can never
become complete types when defined inside parameter lists.
V
__VA_ARGS__ can only appear in the expansion of a C99 variadic macro
The predefined macro __VA_ARGS should be used in the substitution part of a macro
definition using ellipses.
value computed is not used
A value computed is not used.
variable ‘name’ declared ‘inline’
The keyword ‘inline’ should be used with functions only.
variable ‘%s’ might be clobbered by ‘longjmp’ or ‘vfork’
A non-volatile automatic variable might be changed by a call to longjmp. These
warnings are possible only in optimizing compilation.
volatile register variables don’t work as you might wish
Passing a variable as an argument could transfer the variable to a different register
(w0-w7) than the one specified (if not w0-w7) for argument transmission. The compiler
may issue an instruction that is not suitable for the specified register and may need to
temporarily move the value to another place. These are only issues if the specified reg-
ister is modified asynchronously (i.e., though an ISR).
W
-Wformat-extra-args ignored without -Wformat
-Wformat must be specified to use -Wformat-extra-args.
-Wformat-nonliteral ignored without -Wformat
-Wformat must be specified to use -Wformat-nonliteral.
-Wformat-security ignored without -Wformat
-Wformat must be specified to use -Wformat-security.
-Wformat-y2k ignored without -Wformat
-Wformat must be specified to use.
-Wid-clash-LEN is no longer supported
The option -Wid-clash-LEN is no longer supported.
-Wmissing-format-attribute ignored without -Wformat
-Wformat must be specified to use -Wmissing-format-attribute.
-Wuninitialized is not supported without -O
Optimization must be on to use the -Wuninitialized option.
‘identifier’ was declared ‘extern’ and later ‘static’
The specified identifier was previously declared ‘extern’ and is now being declared as
static.
‘identifier’ was declared implicitly ‘extern’ and later ‘static’
The specified identifier was previously declared implicitly ‘extern’ and is now being
declared as static.
‘identifier’ was previously implicitly declared to return ‘int’
There is a mismatch against the previous implicit declaration.
Z
zero-length identifier format string
When checking the argument list of a call to printf, scanf, etc., the compiler found that
the format string was empty (“”).
Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
<http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document,
but changing it is not allowed.
D.1 Preamble
The purpose of this License is to make a manual, textbook, or other functional and use-
ful document “free” in the sense of freedom: to assure everyone the effective freedom
to copy and redistribute it, with or without modifying it, either commercially or non-com-
mercially. Secondarily, this License preserves for the author and publisher a way to get
credit for their work, while not being considered responsible for modifications made by
others.
This License is a kind of “copyleft,” which means that derivative works of the document
must themselves be free in the same sense. It complements the GNU General Public
License, which is a copyleft license designed for free software.
We have designed this License in order to use it for manuals for free software, because
free software needs free documentation: a free program should come with manuals
providing the same freedoms that the software does. But this License is not limited to
software manuals; it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License principally for
works whose purpose is instruction or reference.
D.5 Modifications
You may copy and distribute a Modified Version of the Document under the conditions
of sections 2 and 3 above, provided that you release the Modified Version under pre-
cisely this License, with the Modified Version filling the role of the Document, thus
licensing distribution and modification of the Modified Version to whoever possesses a
copy of it. In addition, you must do these things in the Modified Version:
a) Use in the Title Page (and on the covers, if any) a title distinct from that of the
Document, and from those of previous versions (which should, if there were any,
be listed in the History section of the Document). You may use the same title as
a previous version if the original publisher of that version gives permission.
b) List on the Title Page, as authors, one or more persons or entities responsible
for authorship of the modifications in the Modified Version, together with at least
five of the principal authors of the Document (all of its principal authors, if it has
fewer than five), unless they release you from this requirement.
c) State on the Title page, the name of the publisher of the Modified Version, as the
publisher.
d) Preserve all the copyright notices of the Document.
e) Add an appropriate copyright notice for your modifications adjacent to the other
copyright notices.
f) Include, immediately after the copyright notices, a license notice giving the public
permission to use the Modified Version under the terms of this License, in the
form shown in the Addendum below.
g) Preserve in that license notice the full lists of Invariant Sections and required
Cover Texts given in the Document's license notice.
h) Include an unaltered copy of this License.
i) Preserve the section entitled “History,” as well as its Title, and add an item stating
at least the title, year, new authors, and publisher of the Modified Version as
given on the Title Page. If there is no section entitled “History” in the Document,
create one stating the title, year, authors, and publisher of the Document as given
on its Title Page, then add an item describing the Modified Version as stated in
the previous sentence.
j) Preserve the network location, if any, given in the Document for public access to
a Transparent copy of the Document, and likewise the network locations given in
the Document for previous versions it was based on. These may be placed in the
“History” section. You may omit a network location for a work that was published
at least four years before the Document itself, or if the original publisher of the
version it refers to gives permission.
k) For any section entitled “Acknowledgments” or “Dedications,” preserve the Title
of the section, and preserve in the section all the substance and tone of each of
the contributor acknowledgments and/or dedications given therein.
l) Preserve all the Invariant Sections of the Document, unaltered in their text and
in their titles. Section numbers or the equivalent are not considered part of the
section titles.
m) Delete any section entitled “Endorsements.” Such a section may not be included
in the Modified Version.
n) Do not retitle any existing section to be entitled “Endorsements” or to conflict in
title with any Invariant Section. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or appendices that qualify as
Secondary Sections and contain no material copied from the Document, you may at
your option designate some or all of these sections as invariant. To do this, add their
titles to the list of Invariant Sections in the Modified Version's license notice. These
titles must be distinct from any other section titles.
D.9 Translation
Translation is considered a kind of modification, so you may distribute translations of
the Document under the terms of section 4. Replacing Invariant Sections with transla-
tions requires special permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the original versions of these
Invariant Sections. You may include a translation of this License, and all the license
notices in the Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions of those notices
and disclaimers. In case of a disagreement between the translation and the original
version of this License or a notice or disclaimer, the original version will prevail.
If a section in the Document is entitled “Acknowledgments,” “Dedications,” or “History,”
the requirement (section 4) to Preserve its Title (section 1) will typically require chang-
ing the actual title.
D.10 Termination
You may not copy, modify, sublicense, or distribute the Document except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense, or dis-
tribute it is void, and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your license from a particular
copyright holder is reinstated (a) provisionally, unless and until the copyright holder
explicitly and finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means prior to 60 days
after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if
the copyright holder notifies you of the violation by some reasonable means, this is the
first time you have received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after your receipt of the
notice.
Termination of your rights under this section does not terminate the licenses of parties
who have received copies or rights from you under this License. If your rights have
been terminated and not permanently reinstated, receipt of a copy of some or all of the
same material does not give you any rights to use it.
D.12 Relicensing
“Massive Multi-author Collaboration Site” (or “MMC Site”) means any World Wide Web
server that publishes copyrightable works and also provides prominent facilities for
anybody to edit those works. A public wiki that anybody can edit is an example of such
a server. A “Massive Multi-author Collaboration” (or “MMC”) contained in the site
means any set of copyrightable works thus published on the MMC site.
“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license pub-
lished by Creative Commons Corporation, a not-for-profit corporation with a principal
place of business in San Francisco, California, as well as future copyleft versions of
that license published by that same organization.
“Incorporate” means to publish or republish a Document, in whole or in part, as part of
another Document.
An MMC is “eligible for relicensing” if it is licensed under this License and if all works
that were first published under this License somewhere other than this MMC, and sub-
sequently incorporated in whole or in part into the MMC, (1) had no cover texts or
invariant sections, and (2) were thus incorporated prior to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the site under
CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is
eligible for relicensing.
Hex 0 1 2 3 4 5 6 7
1 SOH DC1 ! 1 A Q a q
3 ETX DC3 # 3 C S c s
4 EOT DC4 $ 4 D T d t
5 ENQ NAK % 5 E U e u
9 HT EM ) 9 I Y i y
A LF SUB * : J Z j z
B VT ESC + ; K [ k {
C FF FS , < L \ l |
D CR GS - = M ] m }
E SO RS . > N ^ n ~
F SI US / ? O _ o DEL
The ELF-specific version of the compiler defines the following preprocessing symbols.
For the most current information, see Section 19.4 “Predefined Macro Names”.
Note: Using too many registers, in particular register W0, may impair the ability of
the 16-bit compiler to compile. It is not recommended that registers be
placed into fixed registers.
You can also specify the register in which an ordinary register variable should be
allocated.
• Global register variables reserve registers throughout the program. This may be
useful in programs such as programming language interpreters which have a
couple of global variables that are accessed very often.
• Local register variables in specific registers do not reserve the registers. The
compiler’s data flow analysis is capable of determining where the specified
registers contain live values, and where they are available for other uses. Stores
into local register variables may be deleted when they appear to be unused.
References to local register variables may be deleted, moved or simplified.
These local variables are sometimes convenient for use with the extended inline
assembly (see Chapter 16. “Mixing C and Assembly Code”), if you want to write one
output of the assembler instruction directly into a particular register. (This will work, pro-
vided that the register you specify fits the constraints specified for that operand in the
inline assembly statement).
Configuration Settings macros are provided that can be used to set Configuration bits.
For example, to set the FOSC bit using a macro, the following line of code can be
inserted before the beginning of your C source code:
_FOSC(CSW_FSCM_ON & EC_PLL16);
This would enable the external clock, with the PLL set to 16x, and enable clock
switching and fail-safe clock monitoring.
Similarly, to set the FBORPOR bit:
_FBORPOR(PBOR_ON & BORV_27 & PWRT_ON_64 & MCLR_DIS);
This would enable Brown-out Reset at 2.7V, and initialize the Power-up timer to 64 ms,
and configure the use of the MCLR pin for I/O.
Configuration Settings macros are defined in compiler header files for each device.
Please refer to your device’s header files for a complete listing of related macros.
Header files are located, by default, in:
<MPLAB XC16 Installation folder>/vx.xx/support/device/h
where vx.xx is the compiler version and device is your 16-bit device family.
__builtin_add
Description: Add value to the accumulator specified by result with a shift specified by literal shift. For
example:
volatile register int result asm("A");
int value;
result = __builtin_add(result,value,0);
If value is held in w0, the following will be generated:
add w0, #0, A
Prototype: int __builtin_add(int Accum,int value,
const int shift);
Argument: Accum Accumulator to add.
value Integer number to add to accumulator value.
shift Amount to shift resultant accumulator value.
Return Value: Returns the shifted addition result to an accumulator.
Assembler Operator/ add
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• argument 0 is not an accumulator
• the shift value is not a literal within range
__builtin_addab
Description: Add accumulators A and B with the result written back to the specified accumulator. For
example:
volatile register int result asm("A");
volatile register int B asm("B");
result = __builtin_addab(result,B);
will generate:
add A
Prototype: int __builtin_addab(int Accum_a, int Accum_b);
Argument: Accum_a First accumulator to add.
Accum_b Second accumulator to add.
Return Value: Returns the addition result to an accumulator.
Assembler Operator/ add
Machine Instruction:
Error Messages An error message will be displayed if the result is not an accumulator register.
__builtin_btg
Description: This function will generate a btg machine instruction.
Some examples include:
struct foo {
int bit1:1;
} barbits;
int bar;
void some_bittoggles() {
register int j asm("w9");
int k;
k = i;
__builtin_btg(&i,1);
__builtin_btg(&j,3);
__builtin_btg(&k,4);
__builtin_btg(&l,11);
return j+k;
}
Note that taking the address of a variable in a register will produce warning by the compiler
and cause the register to be saved onto the stack (so that its address may be taken); this
form is not recommended. This caution only applies to variables explicitly placed in registers
by the programmer.
Prototype: void __builtin_btg(unsigned int *, unsigned int 0xn);
Argument: * A pointer to the data item for which a bit should be toggled.
0xn A literal value in the range of 0 to 15.
Return Value: Returns a btg machine instruction.
Assembler Operator/ btg
Machine Instruction:
Error Messages An error message will be displayed if the parameter values are not within range.
__builtin_clr
Description: Clear the specified accumulator.
For example:
volatile register int result asm("A");
result = __builtin_clr();
will generate:
clr A
Prototype: int __builtin_clr(void);
Argument: None
Return Value: Returns the cleared value result to an accumulator.
Assembler Operator/ clr
Machine Instruction:
Error Messages An error message will be displayed if the result is not an accumulator register.
__builtin_clr_prefetch
Description: Clear an accumulator and prefetch data ready for a future MAC operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
If AWB is non null, the other accumulator will be written back into the referenced variable.
For example:
volatile register int result asm("A");
volatile register int B asm("B");
int x_memory_buffer[256]
__attribute__((space(xmemory)));
int y_memory_buffer[256]
__attribute__((space(ymemory)));
int *xmemory;
int *ymemory;
int awb;
int xVal, yVal;
xmemory = x_memory_buffer;
ymemory = y_memory_buffer;
result = __builtin_clr(&xmemory, &xVal, 2,
&ymemory, &yVal, 2, &awb, B);
might generate:
clr A, [w8]+=2, w4, [w10]+=2, w5, w13
The compiler may need to spill w13 to ensure that it is available for the write-back. It may be
recommended to users that the register be claimed for this purpose.
After this instruction:
• result will be cleared
• xVal will contain x_memory_buffer[0]
• yVal will contain y_memory_buffer[0]
• xmemory and ymemory will be incremented by 2, ready for the next mac operation
Prototype: int __builtin_clr_prefetch(
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr, int *AWB,
int AWB_accum);
__builtin_clr_prefetch (Continued)
Argument: xptr Integer pointer to x prefetch
xval Integer value of x prefetch
xincr Integer increment value of x prefetch
yptr Integer pointer to y prefetch
yval Integer value of y prefetch
yincr Integer increment value of y prefetch
AWB Accumulator write back location
AWB_accum Accumulator to write back
Return Value: Returns the cleared value result to an accumulator.
Assembler Operator/ clr
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
• AWB_accum is not an accumulator and AWB is not null
__builtin_clrwdt
Description: Clear watchdog timer.
Prototype: void __builtin_clrwdt(void);
Argument: None
Return Value: None
Assembler Operator/ clrwdt
Machine Instruction:
Error Messages None
__builtin_dataflashoffset
Description: Disable the specified interrupts.
Prototype: int __builtin_dataflashoffset(unsigned int &var);
Argument: &var = address of pointer to a dataflash variable.
Return Value: Offset value as an integer.
Assembler Operator/
Machine Instruction:
Error Messages None
__builtin_disable_interrupts
Description: Disable the specified interrupts.
Prototype: void __builtin_disable_interrupts(void);
Argument: None
Return Value: None
Assembler Operator/
Machine Instruction:
Error Messages None
__builtin_disi
Description: Disable all interrupts for a specified number of instruction cycles.
See Section 14.7 “Enabling/Disabling Interrupts”.
Will emit the specified DISI instruction at the point it appears in the source program: disi
#<disi_count>
Prototype: void __builtin_disi(int disi_count);
Argument: disi_count instruction cycle count. Must be a literal integer between 0 and 16383.
Return Value: N/A
Assembler Operator/ disi.f
Machine Instruction:
__builtin_divf
Description: Computes the quotient num / den. A math error exception occurs if den is zero. Function
arguments are signed, as is the function result.
Prototype: signed int __builtin_divf(signed int num,
signed int den);
Argument: num numerator
den denominator
Return Value: Returns the signed integer value of the quotient num / den.
Assembler Operator/ div.f
Machine Instruction:
__builtin_divmodsd
Description: Issues the 16-bit architecture’s native signed divide support with the same restrictions given
in the “dsPIC30F/33F Programmer’s Reference Manual” (DS70157). Notably, if the quotient
does not fit into a 16-bit result, the results (including remainder) are unexpected. This form
of the built-in function will capture both the quotient and remainder.
Prototype: signed int __builtin_divmodsd(
signed long dividend, signed int divisor,
signed int *remainder);
Argument: dividend number to be divided
divisor number to divide by
remainder pointer to remainder
Return Value: Quotient and remainder.
Assembler Operator/ divmodsd
Machine Instruction:
Error Messages None
__builtin_divmodud
Description: Issues the 16-bit architecture’s native unsigned divide support with the same restrictions
given in the “dsPIC30F/33F Programmer’s Reference Manual” (DS70157). Notably, if the
quotient does not fit into a 16-bit result, the results (including remainder) are unexpected.
This form of the built-in function will capture both the quotient and remainder.
Prototype: unsigned int __builtin_divmodud(
unsigned long dividend, unsigned int divisor,
unsigned int *remainder);
Argument: dividend number to be divided
divisor number to divide by
remainder pointer to remainder
Return Value: Quotient and remainder.
Assembler Operator/ divmodud
Machine Instruction:
Error Messages None
__builtin_divsd
Description: Computes the quotient num / den. A math error exception occurs if den is zero. Function
arguments are signed, as is the function result. The command-line option -Wconversions
can be used to detect unexpected sign conversions.
Prototype: int __builtin_divsd(const long num, const int den);
Argument: num numerator
den denominator
Return Value: Returns the signed integer value of the quotient num / den.
Assembler Operator/ div.sd
Machine Instruction:
__builtin_divud
Description: Computes the quotient num / den. A math error exception occurs if den is zero. Function
arguments are unsigned, as is the function result. The command-line option -Wconver-
sions can be used to detect unexpected sign conversions.
Prototype: unsigned int __builtin_divud(const unsigned
long num, const unsigned int den);
Argument: num numerator
den denominator
Return Value: Returns the unsigned integer value of the quotient num / den.
Assembler Operator/ div.ud
Machine Instruction:
__builtin_dmaoffset
Description: Obtains the offset of a symbol within DMA memory.
For example:
unsigned int result;
char buffer[256] __attribute__((space(dma)));
result = __builtin_dmaoffset(&buffer);
Might generate:
mov #dmaoffset(buffer), w0
Prototype: unsigned int __builtin_dmaoffset(const void *p);
Argument: *p pointer to DMA address value
Return Value: Returns the offset to a variable located in DMA memory.
Assembler Operator/ dmaoffset
Machine Instruction:
Error Messages An error message will be displayed if the parameter is not the address of a global symbol.
__builtin_dmapage
Description: Obtains the page number of a symbol within DMA memory.
For example:
unsigned int result;
char buffer[256] __attribute__((space(dma)));
result = __builtin_dmapage(&buffer);
Might generate:
mov #dmapage(buffer), w0
Prototype: unsigned int __builtin_dmapage(const void *p);
Argument: *p pointer to DMA address value
Return Value: Returns the page number of a variable located in DMA memory.
Assembler Operator/ dmapage
Machine Instruction:
Error Messages An error message will be displayed if the parameter is not the address of a global symbol.
__builtin_ed
Description: Squares sqr, returning it as the result. Also prefetches data for future square operation by
computing **xptr - **yptr and storing the result in *distance.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
For example:
volatile register int result asm("A");
int *xmemory, *ymemory;
int distance;
result = __builtin_ed(distance,
&xmemory, 2,
&ymemory, 2,
&distance);
might generate:
ed w4*w4, A, [w8]+=2, [W10]+=2, w4
Prototype: int __builtin_ed(int sqr, int **xptr, int xincr,
int **yptr, int yincr, int *distance);
__builtin_ed
Argument: sqr Integer squared value.
xptr Integer pointer to pointer to x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yincr Integer increment value of y prefetch.
distance Integer pointer to distance.
Return Value: Returns the squared result to an accumulator.
Assembler Operator/ ed
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• xptr is null
• yptr is null
• distance is null
__builtin_edac
Description: Squares sqr and sums with the nominated accumulator register, returning it as the result.
Also prefetches data for future square operation by computing **xptr - **yptr and stor-
ing the result in *distance.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
For example:
volatile register int result asm("A");
int *xmemory, *ymemory;
int distance;
might generate:
edac w4*w4, A, [w8]+=2, [W10]+=2, w4
Prototype: int __builtin_edac(int Accum, int sqr,
int **xptr, int xincr, int **yptr, int yincr,
int *distance);
Argument: Accum Accumulator to sum.
sqr Integer squared value.
xptr Integer pointer to pointer to x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yincr Integer increment value of y prefetch.
distance Integer pointer to distance.
Return Value: Returns the squared result to specified accumulator.
Assembler Operator/ edac
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• Accum is not an accumulator register
• xptr is null
• yptr is null
• distance is null
__builtin_edsoffset
Description: Returns the eds page offset of the object whose address is given as a parameter. The argu-
ment p must be the address of an object in an Extended Data Space (EDS); otherwise an
error message is produced and the compilation fails. See the space attribute in
Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_edsoffset(const void *p);
Argument: p object address
Return Value: Returns the eds page number offset of the object whose address is given as a parameter.
Assembler Operator/ edsoffset
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_edsoffset() is not the address of an object in extended data
space.”
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_edsoffset(&obj);
__builtin_edspage
Description: Returns the eds page number of the object whose address is given as a parameter. The
argument p must be the address of an object in an Extended Data Space (EDS); otherwise
an error message is produced and the compilation fails. See the space attribute in
Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_edspage(const void *p);
Argument: p object address
Return Value: Returns the eds page number of the object whose address is given as a parameter.
Assembler Operator/ edspage
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_edspage() is not the address of an object in extended data
space.”
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_edspage(&obj);
__builtin_enable_interrupts
Description: Enable the specified interrupts.
Prototype: void __builtin_enable_interrupts(void);
Argument: None
Return Value: None
Assembler Operator/
Machine Instruction:
Error Messages None
__builtin_fbcl
Description: Finds the first bit change from left in value. This is useful for dynamic scaling of fixed-point
data. For example:
int result, value;
result = __builtin_fbcl(value);
might generate:
fbcl w4, w5
Prototype: int __builtin_fbcl(int value);
Argument: value Integer number to check for change.
Return Value: Returns a literal value sign extended to represent the number of bits to shift left.
Assembler Operator/ fbcl
Machine Instruction:
Error Messages None
__builtin_flim
Description: Force (Signed) Data Range Limit. Simultaneously compares a 16-bit signed data value to a
maximum signed limit value and a minimum signed limit value.
If the data value is greater than the maximum, the data value is set to the maximum value.
If the data value is less than the minimum, the data value is set to the minimum value.
If the data value is within the maximum-minimum values, the data value is not changed.
Prototype: int __builtin_flim(int value, int high, int low);
Argument: value Data value
high Maximum limit value
low Minimum limit value
Return Value: Returns value clamped between high and low.
Assembler Operator/ flim
Machine Instruction:
Error Messages None
__builtin_flim_excess
Description: Force (Signed) Data Range Limit with Limit Excess Result. Simultaneously compares a
16-bit signed data value to a maximum signed limit value and a minimum signed limit value.
Return the sign of the excess value.
Prototype: int __builtin_flim_excess(int value, int high, int low,
int *excess);
Argument: value Data value
high Maximum limit value
low Minimum limit value
excess excess over limit
Return Value: Return the direction of the excess (-1,0,1 ).
Assembler Operator/ flim.v (when used with __builtin_flimv_excess)
Machine Instruction:
Error Messages None
__builtin_flimv_excess
Description: Force (Signed) Data Range Limit with Limit Excess Result. Simultaneously compares a
16-bit signed data value to a maximum signed limit value and a minimum signed limit value.
Return the amount of the excess value.
Prototype: int __builtin_flimv_excess(int value, int high, int low,
int *excess);
Argument: value Data value
high Maximum limit value
low Minimum limit value
excess excess over limit
Return Value: Returns the value of the excess.
Assembler Operator/ flim.v (when used with __builtin_flim_excess)
Machine Instruction:
Error Messages None
__builtin_get_isr_state
Description: Determine the current CPU interrupt state.
Prototype: unsigned int __builtin_get_isr_state(void);
Argument: None
Return Value: Returns an integer value specifying the current CPU interrupt state.
Assembler Operator/ get_isr_state
Machine Instruction:
Error Messages None
__builtin_lac
Description: Shifts value by shift (a literal between -8 and 7) and returns the value to be stored into the
accumulator register. For example:
volatile register int result asm("A");
int value;
result = __builtin_lac(value,3);
Might generate:
lac w4, #3, A
Prototype: int __builtin_lac(int value, int shift);
Argument: value Integer number to be shifted.
shift Literal amount to shift.
Return Value: Returns the shifted result to an accumulator.
Assembler Operator/ lac
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• the shift value is not a literal within range
__builtin_lacd
Description: Shifts a value by shift (a literal between -8 and 7) and returns the value to be stored into
the accumulator register. For example:
volatile register int result asm("A");
long value;
result = __builtin_lacd(value,3);
Prototype: int __builtin_lacd(long value, unsigned int shift);
Argument: value Long integer number to be shifted.
shift Literal amount to shift between -16 and 15.
Return Value: Returns the shifted result to an accumulator.
Assembler Operator/ None
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• the shift value is not a literal within range
__builtin_mac
Description: Computes a x b and sums with accumulator; also prefetches data ready for a future MAC
operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
If AWB is non null, the other accumulator will be written back into the referenced variable.
For example:
volatile register int result asm("A");
volatile register int B asm("B");
int *xmemory;
int *ymemory;
int xVal, yVal;
might generate:
mac w4*w5, A, [w8]+=2, w4, [w10]+=2, w5
Prototype: int __builtin_mac(int Accum, int a, int b,
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr,
int *AWB, int AWB_accum);
Argument: Accum Accumulator to sum.
a Integer multiplicand.
b Integer multiplier.
xptr Integer pointer to pointer to x prefetch.
xval Integer pointer to value of x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yval Integer pointer to value of y prefetch.
yincr Integer increment value of y prefetch.
AWB Accumulator write back location.
AWB_accum Accumulator to write back.
__builtin_mac (Continued)
Return Value: Returns the value of accumulator plus the result of a x b.
Assembler Operator/ mac
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• Accum is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
• AWB_accum is not an accumulator register and AWB is not null
__builtin_modsd
Description: Issues the 16-bit architecture’s native signed divide support with the same restrictions given
in the “dsPIC30F/33F Programmer’s Reference Manual” (DS70157). Notably, if the quotient
does not fit into a 16-bit result, the results (including remainder) are unexpected. This form
of the built-in function will capture only the remainder.
Prototype: signed int __builtin_modsd(signed long dividend,
signed int divisor);
Argument: dividend number to be divided
divisor number to divide by
Return Value: Remainder.
Assembler Operator/ modsd
Machine Instruction:
Error Messages None
__builtin_modud
Description: Issues the 16-bit architecture’s native unsigned divide support with the same restrictions
given in the “dsPIC30F/33F Programmer’s Reference Manual” (DS70157). Notably, if the
quotient does not fit into a 16-bit result, the results (including remainder) are unexpected.
This form of the built-in function will capture only the remainder.
Prototype: unsigned int __builtin_modud(unsigned long dividend,
unsigned int divisor);
Argument: dividend number to be divided
divisor number to divide by
Return Value: Remainder.
Assembler Operator/ modud
Machine Instruction:
Error Messages None
__builtin_movsac
Description: Computes nothing, but prefetches data ready for a future MAC operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
If AWB is non null, the other accumulator will be written back into the referenced variable.
For example:
volatile register int result asm("A");
int *xmemory;
int *ymemory;
int xVal, yVal;
__builtin_movsac(&xmemory, &xVal, 2,
&ymemory, &yVal, 2, 0, 0);
might generate:
movsac A, [w8]+=2, w4, [w10]+=2, w5
Prototype: void __builtin_movsac(
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr, int *AWB
int AWB_accum);
Argument: xptr Integer pointer to pointer to x prefetch.
xval Integer pointer to value of x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yval Integer pointer to value of y prefetch.
yincr Integer increment value of y prefetch.
AWB Accumulator write back location.
AWB_accum Accumulator to write back.
Return Value: None
Assembler Operator/ movsac
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
• AWB_accum is not an accumulator register and AWB is not null
__builtin_mpy
Description: Computes a x b ; also prefetches data ready for a future MAC operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
For example:
volatile register int result asm("A");
int *xmemory;
int *ymemory;
int xVal, yVal;
might generate:
mpy w4*w5, A, [w8]+=2, w4, [w10]+=2, w5
Prototype: int __builtin_mpy(int a, int b,
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr);
Argument: a Integer multiplicand.
b Integer multiplier.
xptr Integer pointer to pointer to x prefetch.
xval Integer pointer to value of x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yval Integer pointer to value of y prefetch.
yincr Integer increment value of y prefetch.
AWB Integer pointer to accumulator selection.
Return Value: Returns the value of a x b.
Assembler Operator/ mpy
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
__builtin_mpyn
Description: Computes -a x b ; also prefetches data ready for a future MAC operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
For example:
volatile register int result asm("A");
int *xmemory;
int *ymemory;
int xVal, yVal;
might generate:
mpy.n w4*w5, A, [w8]+=2, w4, [w10]+=2, w5
Prototype: int __builtin_mpyn(int a, int b,
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr);
Argument: a Integer multiplicand.
b Integer multiplier.
xptr Integer pointer to pointer to x prefetch.
xval Integer pointer to value of x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yval Integer pointer to value of y prefetch.
yincr Integer increment value of y prefetch.
AWB Integer pointer to accumulator selection.
Return Value: Returns the value of -a x b.
Assembler Operator/ mpyn
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
__builtin_msc
Description: Computes a x b and subtracts from accumulator; also prefetches data ready for a future
MAC operation.
xptr may be null to signify no X prefetch to be performed, in which case the values of
xincr and xval are ignored, but required.
yptr may be null to signify no Y prefetch to be performed, in which case the values of
yincr and yval are ignored, but required.
xval and yval nominate the address of a C variable where the prefetched value will be
stored.
xincr and yincr may be the literal values: -6, -4, -2, 0, 2, 4, 6 or an integer value.
If AWB is non null, the other accumulator will be written back into the referenced variable.
For example:
volatile register int result asm("A");
int *xmemory;
int *ymemory;
int xVal, yVal;
might generate:
msc w4*w5, A, [w8]+=2, w4, [w10]+=2, w5
Prototype: int __builtin_msc(int Accum, int a, int b,
int **xptr, int *xval, int xincr,
int **yptr, int *yval, int yincr, int *AWB,
int AWB_accum);
Argument: Accum Accumulator to subtract.
a Integer multiplicand.
b Integer multiplier.
xptr Integer pointer to pointer to x prefetch.
xval Integer pointer to value of x prefetch.
xincr Integer increment value of x prefetch.
yptr Integer pointer to pointer to y prefetch.
yval Integer pointer to value of y prefetch.
yincr Integer increment value of y prefetch.
AWB Accumulator write back location.
AWB_accum Accumulator to write back.
Return Value: Returns the value of accumulator minus the result of a x b.
Assembler Operator/ msc
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• Accum is not an accumulator register
• xval is a null value but xptr is not null
• yval is a null value but yptr is not null
• AWB_accum is not an accumulator register and AWB is not null
__builtin_mulss
Description: Computes the product p0 x p1. Function arguments are signed integers, and the function
result is a signed long integer. The command-line option -Wconversions can be used to
detect unexpected sign conversions.
For example:
volatile register int a asm("A");
signed long result;
const signed int p0, p1;
const unsigned int p2, p3;
result = __builtin_mulss(p0,p1);
a = __builtin_mulss(p0,p1);
Prototype: signed long __builtin_mulss(const signed int p0, const signed int
p1);
Argument: p0 multiplicand
p1 multiplier
Return Value: Returns the signed long integer value of the product p0 x p1. The value can either be
returned into a variable of type signed long or directly into an accumulator register.
Assembler Operator/ mul.ss
Machine Instruction:
__builtin_mulsu
Description: Computes the product p0 x p1. Function arguments are integers with mixed signs, and the
function result is a signed long integer. The command-line option -Wconversions can be
used to detect unexpected sign conversions. This function supports the full range of
addressing modes of the instruction, including immediate mode for operand p1.
For example:
volatile register int a asm("A");
signed long result;
const signed int p0, p1;
const unsigned int p2, p3;
result = __builtin_mulsu(p0,p2);
a = __builtin_mulsu(p0,p2);
Prototype: signed long __builtin_mulsu(const signed int p0, const unsigned int
p1);
Argument: p0 multiplicand
p1 multiplier
Return Value: Returns the signed long integer value of the product p0 x p1. The value can either be
returned into a variable of type signed long or directly into an accumulator register.
Assembler Operator/ mul.su
Machine Instruction:
__builtin_mulus
Description: Computes the product p0 x p1. Function arguments are integers with mixed signs, and the
function result is a signed long integer. The command-line option -Wconversions can be
used to detect unexpected sign conversions. This function supports the full range of
addressing modes of the instruction.
For example:
volatile register int a asm("A");
signed long result;
const signed int p0, p1;
const unsigned int p2, p3;
result = __builtin_mulus(p2,p0);
a = __builtin_mulus(p2,p0);
Prototype: signed long __builtin_mulus(const unsigned int p0, const signed int
p1);
Argument: p0 multiplicand
p1 multiplier
Return Value: Returns the signed long integer value of the product p0 x p1. The value can either be
returned into a variable of type signed long or directly into an accumulator register.
Assembler Operator/ mul.us
Machine Instruction:
__builtin_muluu
Description: Computes the product p0 x p1. Function arguments are unsigned integers, and the function
result is an unsigned long integer. The command-line option -Wconversions can be used
to detect unexpected sign conversions. This function supports the full range of addressing
modes of the instruction, including immediate mode for operand p1.
For example:
volatile register int a asm("A");
unsigned long result;
const signed int p0, p1;
const unsigned int p2, p3;
result = __builtin_muluu(p2,p3);
a = __builtin_muluu(p2,p3);
Prototype: unsigned long __builtin_muluu(const unsigned int p0, const unsigned
int p1);
Argument: p0 multiplicand
p1 multiplier
Return Value: Returns the signed long integer value of the product p0 x p1. The value can either be
returned into a variable of type unsigned long or directly into an accumulator register.
Assembler Operator/ mul.uu
Machine Instruction:
__builtin_nop
Description: Generates a nop instruction.
Prototype: void __builtin_nop(void);
Argument: None
Return Value: Returns a no operation (nop).
Assembler Operator/ nop
Machine Instruction:
__builtin_popcount
Description: Count the number of 1’s (set bits) in an integer.
Prototype: int __builtin_popcount(unsigned int num);
Argument: num integer number
Return Value: Returns the number of 1’s found..
Assembler Operator/ N/A
Machine Instruction:
__builtin_popcountl
Description: Count the number of 1’s (set bits) in a long integer.
Prototype: int __builtin_popcountl(unsigned long num);
Argument: num long integer number
Return Value: Returns the number of 1’s found.
Assembler Operator/ N/A
Machine Instruction:
__builtin_psvoffset
Description: Returns the psv page offset of the object whose address is given as a parameter. The argu-
ment p must be the address of an object in an EE data, PSV or executable memory space;
otherwise an error message is produced and the compilation fails. See the space attribute
in Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_psvoffset(const void *p);
Argument: p object address
Return Value: Returns the psv page number offset of the object whose address is given as a parameter.
Assembler Operator/ psvoffset
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_psvoffset() is not the address of an object in code, psv, or
eedata section”.
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_psvoffset(&obj);
__builtin_psvpage
Description: Returns the psv page number of the object whose address is given as a parameter. The
argument p must be the address of an object in an EE data, PSV or executable memory
space; otherwise an error message is produced and the compilation fails. See the space
attribute in Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_psvpage(const void *p);
Argument: p object address
Return Value: Returns the psv page number of the object whose address is given as a parameter.
Assembler Operator/ psvpage
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_psvpage() is not the address of an object in code, psv, or
eedata section”.
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_psvpage(&obj);
__builtin_pwrsav
Description: Enables/disables PIC32 MCU power saving modes.
Prototype: void __builtin_pwrsav(unsigned int p);
Argument: p 1 = enable, 0 = disable
Return Value: None
Assembler Operator/ pwrsav
Machine Instruction:
Error Messages None
__builtin_readsfr
Description: Reads the Special Function Register (SFR).
Prototype: unsigned int __builtin_readsfr(const void *p);
Argument: p object address
Return Value: Returns the SFR value.
Assembler Operator/ readsfr
Machine Instruction:
Error Messages If the object address is not in the range of SFR memory space, an error will be produced.
Consult your device data sheet for the memory range.
__builtin_return_address
Description: Returns the return address of the current function, or of one of its callers. For the level
argument, a value of 0 yields the return address of the current function, a value of 1 yields
the return address of the caller of the current function, and so forth. When level exceeds the
current stack depth, 0 will be returned. This function should only be used with a non-zero
argument for debugging purposes.
Prototype: int __builtin_return_address (const int level);
Argument: level Number of frames to scan up the call stack.
Return Value: Returns the return address of the current function, or of one of its callers.
Assembler Operator/ return_address
Machine Instruction:
__builtin_sac
Description: Shifts a value by shift and returns the value. For example:
volatile register int value asm("A");
long result;
result = __builtin_sac(value,3);
Prototype: long __builtin_sac(int value, int shift);
Argument: value Integer number to be shifted.
shift Literal amount to shift between -8 and 7
Return Value: Returns the shifted result.
Assembler Operator/ None
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• the shift value is not a literal within range
__builtin_sacd
Description: Shifts value by shift (a literal between -8 and 7) and returns the value. For example:
volatile register int value asm("A");
int result;
result = __builtin_sacd(value,3);
Might generate:
sacd A, #3, w0
Prototype: int __builtin_sacd(int value, int shift);
Argument: value Integer number to be shifted.
shift Literal amount to shift between -16 and 15
Return Value: Returns the shifted result.
Assembler Operator/ sacd
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• the shift value is not a literal within range
__builtin_sacr
Description: Shifts value by shift and returns the value which is rounded using the rounding mode
determined by the CORCONbits.RND control bit.
For example:
volatile register int value asm("A");
int result;
result = __builtin_sacr(value,3);
Might generate:
sac.r A, #3, w0
Prototype: int __builtin_sacr(int value, int shift);
Argument: value Integer number to be shifted.
shift Literal amount to shift between -8 and 7
Return Value: Returns the shifted result to CORCON register.
Assembler Operator/ sacr
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• the shift value is not a literal within range
__builtin_section_begin, __builtin_section_end
Description: Get run-time information about a section beginning or ending address.
Prototype: unsigned long __builtin_section_begin("section_name");
unsigned long __builtin_section_end("section_name");
Argument: section_name name of the section
Return Value: Returns the beginning or ending address of the named section.
Assembler Operator/ section_begin
Machine Instruction: section_end
Error Messages An error message will be displayed if the named section cannot be found.
__builtin_section_size
Description: Get run-time information about a section’s size.
Prototype: unsigned long __builtin_section_size("section_name");
Argument: section_name name of the section
Return Value: Returns the size of the named section.
Assembler Operator/ section_size
Machine Instruction:
Error Messages An error message will be displayed if the named section cannot be found.
__builtin_set_isr_state
Description: Set the current CPU interrupt state.
Prototype: void __builtin_get_isr_state(unsigned int state);
Argument: state Integer value specifying the current CPU interrupt state.
Return Value: None
Assembler Operator/ set_isr_state
Machine Instruction:
Error Messages None
__builtin_sftac
Description: Shifts accumulator by shift. The valid shift range is -16 to 16.
For example:
volatile register int result asm("A");
int i;
result = __builtin_sftac(result,i);
Might generate:
sftac A, w0
Prototype: int __builtin_sftac(int Accum, int shift);
Argument: Accum Accumulator to shift.
shift Amount to shift.
Return Value: Returns the shifted result to an accumulator.
Assembler Operator/ sftac
Machine Instruction:
Error Messages An error message will be displayed if:
• the result is not an accumulator register
• Accum is not an accumulator register
• the shift value is not a literal within range
__builtin_software_breakpoint
Description: Provides for a software breakpoint. If a debugger is attached, the IDE will halt. If no
debugger is attached, the device will reset.
Prototype: void __builtin_software_breakpoint(void);
Argument: None
Return Value: None
Assembler Operator/ software_breakpoint
Machine Instruction:
Error Messages None
__builtin_subab
Description: Subtracts accumulators A and B with the result written back to the specified accumulator.
For example:
volatile register int result asm("A");
volatile register int B asm("B");
result = __builtin_subab(result,B);
will generate:
sub A
Prototype: int __builtin_subab(int Accum_a, int Accum_b);
Argument: Accum_a Accumulator from which to subtract.
Accum_b Accumulator to subtract.
Return Value: Returns the subtraction result to an accumulator.
Assembler Operator/ sub
Machine Instruction:
Error Messages An error message will be displayed if the result is not an accumulator register.
__builtin_swap
Description: For a 16-bit word, swap the bytes in the word; 0x1234 -> 0x3412.
Prototype: uint16_t __builtin_swap(uint16_t word);
Argument: word 16-bit word
Return Value: Returns the swapped value.
Assembler Operator/ swap
Machine Instruction:
Error Messages None.
__builtin_swap_byte
Description: For a byte, swap the nibbles in the byte; 0x12 -> 0x21.
Prototype: uint8_t __builtin_swap(uint8_t byte);
Argument: byte byte
Return Value: Returns the swapped value.
Assembler Operator/ swap.b
Machine Instruction:
Error Messages None.
__builtin_tbladdress
Description: Returns a value that represents the address of an object in program memory. The argument
p must be the address of an object in an EE data, PSV or executable memory space; other-
wise an error message is produced and the compilation fails. See the space attribute in
Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned long __builtin_tbladdress(const void *p);
Argument: p object address
Return Value: Returns an unsigned long value that represents the address of an object in program
memory.
Assembler Operator/ tbladdress
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_tbladdress() is not the address of an object in code, psv, or
eedata section”.
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned long page = __builtin_tbladdress(&obj);
__builtin_tbloffset
Description: Returns the table page offset of the object whose address is given as a parameter. The
argument p must be the address of an object in an EE data, PSV or executable memory
space; otherwise an error message is produced and the compilation fails. See the space
attribute in Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_tbloffset(const void *p);
Argument: p object address
Return Value: Returns the table page number offset of the object whose address is given as a parameter.
Assembler Operator/ tbloffset
Machine Instruction:
__builtin_tbloffset
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_tbloffset() is not the address of an object in code, psv, or
eedata section.”
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_tbloffset(&obj);
__builtin_tblpage
Description: Returns the table page number of the object whose address is given as a parameter. The
argument p must be the address of an object in an EE data, PSV or executable memory
space; otherwise an error message is produced and the compilation fails. See the space
attribute in Section 2.3.1 “Specifying Attributes of Variables.”
Prototype: unsigned int __builtin_tblpage(const void *p);
Argument: p object address
Return Value: Returns the table page number of the object whose address is given as a parameter.
Assembler Operator/ tblpage
Machine Instruction:
Error Messages The following error message is produced when this function is used incorrectly:
“Argument to __builtin_tblpage() is not the address of an object in code, psv, or
eedata section.”
The argument must be an explicit object address.
For example, if obj is object in an executable or read-only section, the following syntax is
valid:
unsigned page = __builtin_tblpage(&obj);
__builtin_tblrdh
Description: Issues the tblrdh.w instruction to read a word from Flash or EEData memory. You must
set up the TBLPAG to point to the appropriate page. To do this, you may make use of
__builtin_tbloffset() and __builtin_tblpage().
Please refer to your device data sheet or Family Reference Manual (FRM) for complete
details regarding reading and writing program Flash.
Prototype: unsigned int __builtin_tblrdh(unsigned int offset);
Argument: offset desired memory offset
Return Value: Contents of the memory address in Flash or EEData memory.
Assembler Operator/ tblrdh
Machine Instruction:
Error Messages None
__builtin_tblrdl
Description: Issues the tblrdl.w instruction to read a word from Flash or EEData memory. You must
set up the TBLPAG to point to the appropriate page. To do this, you may make use of
__builtin_tbloffset() and__builtin_tblpage().
Please refer to your device data sheet or Family Reference Manual (FRM) for complete
details regarding reading and writing program Flash.
Prototype: unsigned int __builtin_tblrdl(unsigned int offset);
Argument: offset desired memory offset
Return Value: Contents of the memory address in Flash or EEData memory.
__builtin_tblrdl
Assembler Operator/ tblrdl
Machine Instruction:
Error Messages None
__builtin_tblwth
Description: Issues the tblwth.w instruction to write a word to Flash or EEData memory. You must set
up the TBLPAG to point to the appropriate page. To do this, you may make use of
__builtin_tbloffset() and __builtin_tblpage().
Please refer to your device data sheet or Family Reference Manual (FRM) for complete
details regarding reading and writing program Flash.
Prototype: void __builtin_tblwth(unsigned int offset
unsigned int data);
Argument: offset desired memory offset
data data to be written
Return Value: None
Assembler Operator/ tblwth
Machine Instruction:
Error Messages None
__builtin_tblwtl
Description: Issues the tblrdl.w instruction to write a word to Flash or EEData memory. You must set
up the TBLPAG to point to the appropriate page. To do this, you may make use of
__builtin_tbloffset() and __builtin_tblpage().
Please refer to your device data sheet or Family Reference Manual (FRM) or complete
details regarding reading and writing program Flash.
Prototype: void __builtin_tblwtl(unsigned int offset
unsigned int data);
Argument: offset desired memory offset
data data to be written
Return Value: None
Assembler Operator/ tblwtl
Machine Instruction:
Error Messages None
__builtin_write_CRYOTP
Description: Initiates a write to the Crypto OTP by issuing the correct unlock sequence and setting the
CRYWR bit.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more
information.
Prototype: void __builtin_write_CRYOTP(void);
Argument: None
Return Value: None
__builtin_write_CRYOTP
Assembler Operator/ mov #0x55, Wn
Machine Instruction: mov Wn, _CRYKEY
mov #0xAA, Wn
mov Wn, _CRYKEY
bset _CRYCON, #0
nop
nop
Error Messages None
__builtin_write_DISICNT
Description: Enables the Flash for writing by issuing the correct unlock sequence and enabling the Write
bit of the DISICNT register.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_DISICNT(DISI_save);
Argument: DISI_save - Specified value to save to DISICNT register
Return Value: None
Assembler Operator/
Machine Instruction:
Error Messages None
__builtin_write_NVM
Description: Enables the Flash for writing by issuing the correct unlock sequence and enabling the Write
bit of the NVMCON register.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_NVM(void);
Argument: None
Return Value: None
Assembler Operator/ mov #0x55, Wn
Machine Instruction: mov Wn, _NVMKEY
mov #0xAA, Wn
mov Wn, _NVMKEY
bset _NVMCON, #15
nop
nop
Error Messages None
__builtin_write_NVM_secure
Description: Enables the Flash for writing by issuing an unlock sequence specified by two keys and
enabling the Write bit of the NVMCON register. After completion, the two keys are cleared to
zero.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_NVM_secure(unsigned int key1,
unsigned int key2);
Argument: key1 first key in the NVM unlock sequence
key2 second key in the NVM unlock sequence
Return Value: None
Assembler Operator/ Depending on the location of the keys:
Machine Instruction: mov W0, Wn
mov Wn, _NVMKEY
mov W1, Wn
mov Wn, _NVMKEY
bset _NVMCON, #15
nop
nop
Error Messages None
__builtin_write_OSCCONH
Description: Unlocks and writes its argument to OSCCONH.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_OSCCONH(unsigned char value);
Argument: value character to be written
Return Value: None
Assembler Operator/ mov #0x78, w0
Machine Instruction*: mov #0x9A, w1
mov #_OSCCON+1, w2
mov.b w0, [w2]
mov.b w1, [w2]
mov.b value, [w2]
Error Messages None
* The exact sequence may be different.
__builtin_write_OSCCONL
Description: Unlocks and writes its argument to OSCCONL.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_OSCCONL(unsigned char value);
Argument: value character to be written
Return Value: None
Assembler Operator/ mov #0x46, w0
Machine Instruction*: mov #0x57, w1
mov #_OSCCON, w2
mov.b w0, [w2]
mov.b w1, [w2]
mov.b value, [w2]
Error Messages None
* The exact sequence may be different.
__builtin_write_PWMSFR
Description: Writes the PWM unlock sequence to the SFR pointed to by PWM_KEY and then writes
value to the SFR pointed to by PWM_sfr.
Prototype: void __builtin_write_PWMSFR(volatile unsigned int *PWM_sfr,
unsigned int value, volatile unsigned int *PWM_KEY);
Argument: PWM_sfr register to be written
value value to write
PWM_KEY hardware unlock key location
Return Value: None
Assembler Operator/ mov #<it>PWM_KEY</it>, w3
Machine Instruction: mov #<it>value</it>, w2
mov #0x4321, w1
mov #0xABCD, w0
mov w1,[w3]
mov w0,[w3]
mov w2,[w3]
Error Messages None
Examples Example 1:
__builtin_write_PWMSFR(&PWM1CON1, 0x123, &PWM1KEY);
Example 2:
__builtin_write_PWMSFR(&P1FLTACON, 0x123, &PWMKEY);
__builtin_write_RPCON
Description: Initiates a write to RPCON register by issuing the correct unlock sequence and setting the
RPCON register. Interrupts may need to be disabled for proper operation.
Prototype: void __builtin_write_RPCON(unsigned int value);
Argument: value Specified value to save to RPCON register
Return Value: None
Assembler Operator/ mov #0x55, Wn
Machine Instruction: mov Wn, _NVMKEY
mov #0xAA, Wn
mov Wn, _NVMKEY
mov value, _RPCON
Error Messages None
__builtin_write_RTCWEN
Description: Used to write to the RTCC Timer by implementing the unlock sequence by writing the cor-
rect unlock values to NVMKEY, and then setting the RTCWREN bit of RCFGCAL SFR.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_RTCWEN(void);
Argument: None
Return Value: None
Assembler Operator/ mov #0x55,w0
Machine Instruction: mov w0,_NVMKEY
mov #0xAA,w0
mov w0,_NVMKEY
bset _RCFGCAL,#13
nop
nop
Error Messages None
__builtin_write_RTCC_WRLOCK
Description: Used to write to the RTCC Timer by implementing the unlock sequence by writing the cor-
rect unlock values to NVMKEY, and then setting the RTCWREN bit of RCFGCAL SFR.
Interrupts may need to be disabled for proper operation.
This builtin function can be used as a part of a complex sequence discussed in your
device data sheet or Family Reference Manual (FRM). See these documents for more infor-
mation.
Prototype: void __builtin_write_RTCC_WRLOCK(void);
Argument: None
Return Value: None
Assembler Operator/ mov #0x55,w0
Machine Instruction: mov w0,_NVMKEY
mov #0xAA,w0
mov w0,_NVMKEY
bclr _RTCCON1L,#11
nop
nop
Error Messages None
Microchip Forums
Forums: https://www.microchip.com/forums
Microchip provides additional online support via our web forums. Currently available
forums are:
• Development Tools
• 8-bit PIC MCUs
• 16-bit PIC MCUs
• 32-bit PIC MCUs
Customer Support
Users of Microchip products can receive assistance through several channels:
• Distributor or Representative
• Local Sales Office
• Field Application Engineer (FAE)
• Technical Support
Customers should contact their distributor, representative or field application engineer
(FAE) for support. Local sales offices are also available to help customers. A listing of
sales offices and locations is included in the back of this document. See our web site
for a complete, up-to-date listing of sales offices.
Technical Support: https://support.microchip.com
Documentation errors or comments may be emailed to docerrors@microchip.com.
E
EEPROM
Electrically Erasable Programmable Read Only Memory. A special type of PROM that
can be erased electrically. Data is written or erased one byte at a time. EEPROM
retains its contents even when power is turned off.
ELF
Executable and Linking Format. An object file of this format contains machine code.
Debugging and other information is specified in with DWARF. ELF/DWARF provide bet-
ter debugging of optimized code than COFF.
Emulation/Emulator
See ICE/ICD.
Endianness
The ordering of bytes in a multi-byte object.
Environment
MPLAB PM3 – A folder containing files on how to program a device. This folder can be
transferred to a SD/MMC card.
Epilogue
A portion of compiler-generated code that is responsible for deallocating stack space,
restoring registers and performing any other machine-specific requirement specified in
the runtime model. This code executes after any user code for a given function,
immediately prior to the function return.
EPROM
Erasable Programmable Read Only Memory. A programmable read-only memory that
can be erased usually by exposure to ultraviolet radiation.
Error/Error File
An error reports a problem that makes it impossible to continue processing your pro-
gram. When possible, an error identifies the source file name and line number where
the problem is apparent. An error file contains error messages and diagnostics gener-
ated by a language tool.
Event
A description of a bus cycle which may include address, data, pass count, external
input, cycle type (fetch, R/W), and time stamp. Events are used to describe triggers,
breakpoints and interrupts.
Executable Code
Software that is ready to be loaded for execution.
Export
Send data out of the MPLAB IDE/MPLAB X IDE in a standardized format.
Expressions
Combinations of constants and/or symbols separated by arithmetic or logical
operators.
Extended Microcontroller Mode
In extended microcontroller mode, on-chip program memory as well as external mem-
ory is available. Execution automatically switches to external if the program memory
address is greater than the internal memory space of the PIC18 device.
T
Target
Refers to user hardware.
Target Application
Software residing on the target board.
Target Board
The circuitry and programmable device that makes up the target application.
Target Processor
The microcontroller device on the target application board.
Template
Lines of text that you build for inserting into your files at a later time. The MPLAB Editor
stores templates in template files.
Tool Bar
A row or column of icons that you can click on to execute MPLAB IDE/MPLAB X IDE
functions.
Trace
An emulator or simulator function that logs program execution. The emulator logs pro-
gram execution into its trace buffer which is uploaded to the MPLAB IDE/MPLAB X IDE
trace window.
Trace Memory
Trace memory contained within the emulator. Trace memory is sometimes called the
trace buffer.
Trace Macro
A macro that will provide trace information from emulator data. Since this is a software
trace, the macro must be added to code, the code must be recompiled or reassembled,
and the target device must be programmed with this code before trace will work.
Trigger Output
Trigger output refers to an emulator output signal that can be generated at any address
or address range, and is independent of the trace and breakpoint settings. Any number
of trigger output points can be set.
Trigraphs
Three-character sequences, all starting with ??, that are defined by ISO C as
replacements for single characters.
U
Unassigned Section
A section which has not been assigned to a specific target memory block in the linker
command file. The linker must find a target memory block in which to allocate an
unassigned section.
Uninitialized Data
Data which is defined without an initial value. In C,
int myVar;
defines a variable which will reside in an uninitialized data section.
Upload
The Upload function transfers data from a tool, such as an emulator or programmer, to
the host PC or from the target board to the emulator.