mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 19:29:37 +00:00
Added the optional C keyword "volatile" to the __asm__ statement grammar.
It prevents the statement's Assembly code from being optimized (e.g., moved or removed). Optimization is disabled for that statement's entire function (other functions aren't affected).
This commit is contained in:
parent
62c2177599
commit
2c7ccca210
@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
<article>
|
<article>
|
||||||
<title>cc65 Users Guide
|
<title>cc65 Users Guide
|
||||||
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
|
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
|
||||||
<date>2015-05-26
|
<url url="mailto:gregdk@users.sf.net" name="Greg King">
|
||||||
|
<date>2016-04-22
|
||||||
|
|
||||||
<abstract>
|
<abstract>
|
||||||
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
cc65 is a C compiler for 6502 targets. It supports several 6502 based home
|
||||||
@ -15,7 +16,6 @@ computers like the Commodore and Atari machines, but it is easily retargetable.
|
|||||||
|
|
||||||
<!-- Begin the document -->
|
<!-- Begin the document -->
|
||||||
|
|
||||||
|
|
||||||
<sect>Overview<p>
|
<sect>Overview<p>
|
||||||
|
|
||||||
cc65 was originally a C compiler for the Atari 8-bit machines written by
|
cc65 was originally a C compiler for the Atari 8-bit machines written by
|
||||||
@ -564,7 +564,7 @@ and the one defined by the ISO standard:
|
|||||||
that you must not mix pointers to those functions with pointers to
|
that you must not mix pointers to those functions with pointers to
|
||||||
user-written, cdecl functions (the calling conventions are incompatible).
|
user-written, cdecl functions (the calling conventions are incompatible).
|
||||||
<p>
|
<p>
|
||||||
<item> The <tt/volatile/ keyword doesn't have an effect. This is not as bad
|
<item> The <tt/volatile/ keyword has almost no effect. That is not as bad
|
||||||
as it sounds, since the 6502 has so few registers that it isn't
|
as it sounds, since the 6502 has so few registers that it isn't
|
||||||
possible to keep values in registers anyway.
|
possible to keep values in registers anyway.
|
||||||
<p>
|
<p>
|
||||||
@ -586,14 +586,14 @@ This cc65 version has some extensions to the ISO C standard.
|
|||||||
file. The syntax is
|
file. The syntax is
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
asm (<string literal>[, optional parameters]) ;
|
asm [optional volatile] (<string literal>[, optional parameters]) ;
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
or
|
or
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
__asm__ (<string literal>[, optional parameters]) ;
|
__asm__ [optional volatile] (<string literal>[, optional parameters]) ;
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
|
|
||||||
The first form is in the user namespace and is disabled if the <tt/-A/
|
The first form is in the user namespace; and, is disabled if the <tt/-A/
|
||||||
switch is given.
|
switch is given.
|
||||||
|
|
||||||
There is a whole section covering inline assembler statements,
|
There is a whole section covering inline assembler statements,
|
||||||
@ -735,6 +735,7 @@ This cc65 version has some extensions to the ISO C standard.
|
|||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<sect>Predefined macros<p>
|
<sect>Predefined macros<p>
|
||||||
|
|
||||||
The compiler defines several macros at startup:
|
The compiler defines several macros at startup:
|
||||||
@ -1224,39 +1225,44 @@ The compiler allows to insert assembler statements into the output file. The
|
|||||||
syntax is
|
syntax is
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
asm (<string literal>[, optional parameters]) ;
|
asm [optional volatile] (<string literal>[, optional parameters]) ;
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
or
|
or
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
__asm__ (<string literal>[, optional parameters]) ;
|
__asm__ [optional volatile] (<string literal>[, optional parameters]) ;
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
The first form is in the user namespace and is disabled by <tt><ref
|
The first form is in the user namespace; and, is disabled by <tt><ref
|
||||||
id="option--standard" name="--standard"></tt> if the argument is not <tt/cc65/.
|
id="option--standard" name="--standard"></tt> if the argument is not <tt/cc65/.
|
||||||
|
|
||||||
The asm statement may be used inside a function and on global file level. An
|
The <tt/asm/ statement can be used only inside a function. Please note that
|
||||||
inline assembler statement is a primary expression, so it may also be used as
|
the result of an inline assembler expression is always of type <tt/void/.
|
||||||
part of an expression. Please note however that the result of an expression
|
|
||||||
containing just an inline assembler statement is always of type <tt/void/.
|
|
||||||
|
|
||||||
The contents of the string literal are preparsed by the compiler and inserted
|
The contents of the string literal are preparsed by the compiler; and, inserted
|
||||||
into the generated assembly output, so that the can be further processed by
|
into the generated assembly output, so that it can be processed further by
|
||||||
the backend and especially the optimizer. For this reason, the compiler does
|
the backend -- and, especially the optimizer. For that reason, the compiler does
|
||||||
only allow regular 6502 opcodes to be used with the inline assembler. Pseudo
|
allow only regular 6502 opcodes to be used with the inline assembler. Pseudo
|
||||||
instructions (like <tt/.import/, <tt/.byte/ and so on) are <em/not/ allowed,
|
instructions (like <tt/.import/, <tt/.byte/, and so on) are <em/not/ allowed,
|
||||||
even if the ca65 assembler (which is used to translate the generated assembler
|
even if the ca65 assembler (which is used to translate the generated assembler
|
||||||
code) would accept them. The builtin inline assembler is not a replacement for
|
code) would accept them. The built-in inline assembler is not a replacement for
|
||||||
the full blown macro assembler which comes with the compiler.
|
the full-blown macro assembler which comes with the compiler.
|
||||||
|
|
||||||
Note: Inline assembler statements are subject to all optimizations done by the
|
Note: Inline assembler statements are subject to all optimizations done by the
|
||||||
compiler. There is currently no way to protect an inline assembler statement
|
compiler. There currently is no way to protect an inline assembler statement
|
||||||
from being moved or removed completely by the optimizer. If in doubt, check
|
-- alone -- from being moved or removed completely by the optimizer. If in
|
||||||
the generated assembler output, or disable optimizations.
|
doubt, check the generated assembler output; or, disable optimizations (for
|
||||||
|
that function).
|
||||||
|
|
||||||
|
As a shortcut, you can put the <tt/volatile/ qualifier in your <tt/asm/
|
||||||
|
statements. It will disable optimization for the functions in which those
|
||||||
|
<tt/asm volatile/ statements sit. The effect is the same as though you put
|
||||||
|
</#pragma optimize(push, off)/ above those functions, and </#pragma
|
||||||
|
optimize(pop)/ below those functions.
|
||||||
|
|
||||||
The string literal may contain format specifiers from the following list. For
|
The string literal may contain format specifiers from the following list. For
|
||||||
each format specifier, an argument is expected which is inserted instead of
|
each format specifier, an argument is expected which is inserted instead of
|
||||||
the format specifier before passing the assembly code line to the backend.
|
the format specifier, before passing the assembly code line to the backend.
|
||||||
|
|
||||||
<itemize>
|
<itemize>
|
||||||
<item><tt/%b/ - Numerical 8-bit value
|
<item><tt/%b/ - Numerical 8-bit value
|
||||||
@ -1269,9 +1275,9 @@ the format specifier before passing the assembly code line to the backend.
|
|||||||
<item><tt/%%/ - The % sign itself
|
<item><tt/%%/ - The % sign itself
|
||||||
</itemize><p>
|
</itemize><p>
|
||||||
|
|
||||||
Using these format specifiers, you can access C <tt/#defines/, variables or
|
Using those format specifiers, you can access C <tt/#defines/, variables, or
|
||||||
similar stuff from the inline assembler. For example, to load the value of
|
similar stuff from the inline assembler. For example, to load the value of
|
||||||
a C <tt/#define/ into the Y register, one would use
|
a C <tt/#define/ into the Y index register, one would use
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
#define OFFS 23
|
#define OFFS 23
|
||||||
@ -1292,10 +1298,10 @@ Or, to access a struct member of a static variable:
|
|||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
<p>
|
<p>
|
||||||
The next example shows how to use global variables to exchange data between C
|
The next example shows how to use global variables to exchange data between C
|
||||||
an assembler and how to handle assembler jumps:
|
and assembler; and, how to handle assembler jumps:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
unsigned char globalSubA, globalSubB, globalSubResult;
|
static unsigned char globalSubA, globalSubB, globalSubResult;
|
||||||
|
|
||||||
/* return a-b, return 255 if b>a */
|
/* return a-b, return 255 if b>a */
|
||||||
unsigned char sub (unsigned char a, unsigned char b)
|
unsigned char sub (unsigned char a, unsigned char b)
|
||||||
@ -1314,14 +1320,14 @@ an assembler and how to handle assembler jumps:
|
|||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
Arrays can also be accessed:
|
Arrays also can be accessed:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
unsigned char globalSquareTable[] = {
|
static const unsigned char globalSquareTable[] = {
|
||||||
0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
|
0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
|
||||||
100, 121, 144, 169, 196, 225
|
100, 121, 144, 169, 196, 225
|
||||||
};
|
};
|
||||||
unsigned char globalSquareA, globalSquareResult;
|
static unsigned char globalSquareA, globalSquareResult;
|
||||||
|
|
||||||
/* return a*a for a<16, else 255 */
|
/* return a*a for a<16, else 255 */
|
||||||
unsigned char square (unsigned char a)
|
unsigned char square (unsigned char a)
|
||||||
@ -1339,19 +1345,20 @@ Arrays can also be accessed:
|
|||||||
<p>
|
<p>
|
||||||
|
|
||||||
Note: Do not embed the assembler labels that are used as names of global
|
Note: Do not embed the assembler labels that are used as names of global
|
||||||
variables or functions into your asm statements. Code like this
|
variables or functions into your <tt/asm/ statements. Code such as this:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
int foo;
|
int foo;
|
||||||
int bar () { return 1; }
|
int bar (void) { return 1; }
|
||||||
|
...
|
||||||
__asm__ ("lda _foo"); /* DON'T DO THAT! */
|
__asm__ ("lda _foo"); /* DON'T DO THAT! */
|
||||||
...
|
...
|
||||||
__asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */
|
__asm__ ("jsr _bar"); /* DON'T DO THAT EITHER! */
|
||||||
</verb></tscreen>
|
</verb></tscreen>
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
may stop working if the way, the compiler generates these names is changed in
|
might stop working if the way that the compiler generates those names is changed in
|
||||||
a future version. Instead use the format specifiers from the table above:
|
a future version. Instead, use the format specifiers from the table above:
|
||||||
|
|
||||||
<tscreen><verb>
|
<tscreen><verb>
|
||||||
__asm__ ("lda %v", foo); /* OK */
|
__asm__ ("lda %v", foo); /* OK */
|
||||||
@ -1361,6 +1368,7 @@ a future version. Instead use the format specifiers from the table above:
|
|||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<sect>Implementation-defined behavior<p>
|
<sect>Implementation-defined behavior<p>
|
||||||
|
|
||||||
This section describes the behavior of cc65 when the standard describes the
|
This section describes the behavior of cc65 when the standard describes the
|
||||||
@ -1434,4 +1442,3 @@ freely, subject to the following restrictions:
|
|||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
|
@ -41,12 +41,14 @@
|
|||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "asmlabel.h"
|
#include "asmlabel.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
#include "codeseg.h"
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
|
#include "segments.h"
|
||||||
#include "stackptr.h"
|
#include "stackptr.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "asmstmt.h"
|
#include "asmstmt.h"
|
||||||
@ -422,6 +424,15 @@ void AsmStatement (void)
|
|||||||
/* Skip the ASM */
|
/* Skip the ASM */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
|
/* An optional volatile qualifier disables optimization for
|
||||||
|
** the entire function [same as #pragma optimize(push, off)].
|
||||||
|
*/
|
||||||
|
if (CurTok.Tok == TOK_VOLATILE) {
|
||||||
|
/* Don't optimize the Current code Segment */
|
||||||
|
CS->Code->Optimize = 0;
|
||||||
|
NextToken ();
|
||||||
|
}
|
||||||
|
|
||||||
/* Need left parenthesis */
|
/* Need left parenthesis */
|
||||||
if (!ConsumeLParen ()) {
|
if (!ConsumeLParen ()) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user