SPRU513Y August 2001 – June 2022 SM320F28335-EP
Share C Headers Between C and Assembly Code
Single Line:
.cdecls [options ,] " filename "[, " filename2 "[,...]]
Multiple Lines:
.cdecls [options]
%{
/*---------------------------------------------------------------------------------*/
/* C/C++ code - Typically a list of #includes and a few defines */
/*---------------------------------------------------------------------------------*/
%}
The .cdecls directive allows programmers in mixed assembly and C/C++ environments to share C headers containing declarations and prototypes between the C and assembly code. Any legal C/C++ can be used in a .cdecls block and the C/C++ declarations cause suitable assembly to be generated automatically, allowing you to reference the C/C++ constructs in assembly code; such as calling functions, allocating space, and accessing structure members; using the equivalent assembly mechanisms. While function and variable definitions are ignored, most common C/C++ elements are converted to assembly, for instance: enumerations, (non-function-like) macros, function and variable prototypes, structures, and unions.
The .cdecls options control whether the code is treated as C or C++ code; and how the .cdecls block and converted code are presented. Options must be separated by commas; they can appear in any order:
C | Treat the code in the .cdecls block as C source code (default). | |
CPP | Treat the code in the .cdecls block as C++ source code. This is the opposite of the C option. | |
NOLIST | Do not include the converted assembly code in any listing file generated for the containing assembly file (default). | |
LIST | Include the converted assembly code in any listing file generated for the containing assembly file. This is the opposite of the NOLIST option. | |
NOWARN | Do not emit warnings on STDERR about C/C++ constructs that cannot be converted while parsing the .cdecls source block (default). | |
WARN | Generate warnings on STDERR about C/C++ constructs that cannot be converted while parsing the .cdecls source block. This is the opposite of the NOWARN option. |
In the single-line format, the options are followed by one or more filenames to include. The filenames and options are separated by commas. Each file listed acts as if #include "filename" was specified in the multiple-line format.
In the multiple-line format, the line following .cdecls must contain the opening .cdecls block indicator %{. Everything after the %{, up to the closing block indicator %}, is treated as C/C++ source and processed. Ordinary assembler processing then resumes on the line following the closing %}.
The text within %{ and %} is passed to the C/C++ compiler to be converted into assembly language. Much of C language syntax, including function and variable definitions as well as function-like macros, is not supported and is ignored during the conversion. However, all of what traditionally appears in C header files is supported, including function and variable prototypes; structure and union declarations; non-function-like macros; enumerations; and #defines.
The resulting assembly language is included in the assembly file at the point of the .cdecls directive. If the LIST option is used, the converted assembly statements are printed in the listing file.
The assembly resulting from the .cdecls directive is treated similarly to a .include file. Therefore the .cdecls directive can be nested within a file being copied or included. The assembler limits nesting to ten levels; the host operating system may set additional restrictions. The assembler precedes the line numbers of copied files with a letter code to identify the level of copying. An A indicates the first copied file, B indicates a second copied file, etc.
The .cdecls directive can appear anywhere in an assembly source file, and can occur multiple times within a file. However, the C/C++ environment created by one .cdecls is not inherited by a later .cdecls; the C/C++ environment starts new for each .cdecls.
See Chapter 14 for more information on setting up and using the .cdecls directive with C header files.
In this example, the .cdecls directive is used call the C header.h file.
C header file:
#define WANT_ID 10
#define NAME "John\n"
extern int a_variable;
extern float cvt_integer(int src);
struct myCstruct { int member_a; float member_b; };
enum status_enum { OK = 1, FAILED = 256, RUNNING = 0 };
Source file:
.cdecls C,LIST,"myheader.h"
size: .int $sizeof(myCstruct)
aoffset: .int myCstruct.member_a
boffset: .int myCstruct.member_b
okvalue: .int status_enum.OK
failval: .int status_enum.FAILED
.if $defined(WANT_ID)
id .cstring NAME
.endif
Listing File:
1 .cdecls C,LIST,"myheader.h"
A 1 ; ------------------------------------------
A 2 ; Assembly Generated from C/C++ Source Code
A 3 ; =========== MACRO DEFINITIONS ===========
A 4 .define "1",_OPTIMIZE_FOR_SPACE
A 5 .define "1",__ASM_HEADER__
A 6 .define "1",__edg_front_end__
A 7 .define "5001000",__COMPILER_VERSION__
A 8 .define "0",__TI_STRICT_ANSI_MODE__
A 9 .define """14:53:42""",__TIME__
A 10 .define """I""",__TI_COMPILER_VERSION_QUAL__
A 11 .define "unsigned long",__SIZE_T_TYPE__
A 12 .define "long",__PTRDIFF_T_TYPE__
A 13 .define "1",__TMS320C2000__
A 14 .define "1",_TMS320C28X
A 15 .define "1",_TMS320C2000
A 16 .define "1",__TMS320C28X__
A 17 .define "1",__STDC__
A 18 .define "1",__signed_chars__
A 19 .define "0",__GNUC_MINOR__
A 20 .define "1",_TMS320C28XX
A 21 .define "5001000",__TI_COMPILER_VERSION__
A 22 .define "1",__TMS320C28XX__
A 23 .define "1",__little_endian__
A 24 .define "199409L",__STDC_VERSION__
A 25 .define """EDG gcc 3.0 mode""",__VERSION__
A 26 .define """John\n""",NAME
A 27 .define "unsigned int",__WCHAR_T_TYPE__
A 28 .define "1",__TI_RUNTIME_RTS__
A 29 .define "3",__GNUC__
A 30 .define "10",WANT_ID
A 31 .define """Sep 7 2007""",__DATE__
A 32 .define "7250",__TI_COMPILER_VERSION_QUAL_ID__
A 33
A 34 ; =========== TYPE DEFINITIONS ===========
A 35 status_enum .enum
A 36 0001 OK .emember 1
A 37 0100 FAILED .emember 256
A 38 0000 RUNNING .emember 0
A 39 .endenum
A 40
A 41 myCstruct .struct 0,2 ; size=4 bytes|64 bits, align=2
A 42 0000 member_a .field 16 ; int- offset 0, size 1 byte
A 43 0001 .field 16 ; padding
A 44 0002 member_b .field 32 ; float- offset 2 byte,size 2 byte
A 45 0004 .endstruct ; final size=(4 bytes|64 bits)
A 46
A 47 ; =========== EXTERNAL FUNCTIONS ===========
A 48 .global _cvt_integer
A 49
A 50 ; =========== EXTERNAL VARIABLES ===========
A 51 .global _a_variable
2 00000000 0004 size: .int $sizeof(myCstruct)
3 00000001 0000 aoffset: .int myCstruct.member_a
4 00000002 0002 boffset: .int myCstruct.member_b
5 00000003 0001 okvalue: .int status_enum.OK
6 00000004 0100 failval: .int status_enum.FAILED
7 .if $defined(WANT_ID)
8 00000005 004A id .cstring NAME
00000006 006F
00000007 0068
00000008 006E
00000009 000A
0000000a 0000
9 .endif