]> git.sur5r.net Git - cc65/commitdiff
Added the optional C keyword "volatile" to the __asm__ statement grammar. 285/head
authorGreg King <gregdk@users.sf.net>
Fri, 22 Apr 2016 15:33:52 +0000 (11:33 -0400)
committerGreg King <gregdk@users.sf.net>
Fri, 22 Apr 2016 15:33:52 +0000 (11:33 -0400)
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).

doc/cc65.sgml
src/cc65/asmstmt.c

index 9198d6982d1bc6b5ff91d1009195079c2fee4c84..8346bac6b37ac9f9d38916f116141a0f97cf0739 100644 (file)
@@ -2,8 +2,9 @@
 
 <article>
 <title>cc65 Users Guide
-<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">
-<date>2015-05-26
+<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
+<url url="mailto:gregdk@users.sf.net" name="Greg King">
+<date>2016-04-22
 
 <abstract>
 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 -->
 
-
 <sect>Overview<p>
 
 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
        user-written, cdecl functions (the calling conventions are incompatible).
        <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
         possible to keep values in registers anyway.
        <p>
@@ -586,14 +586,14 @@ This cc65 version has some extensions to the ISO C standard.
        file. The syntax is
 
        <tscreen><verb>
-       asm (&lt;string literal&gt;[, optional parameters]) ;
+       asm [optional volatile] (&lt;string literal&gt;[, optional parameters]) ;
        </verb></tscreen>
        or
        <tscreen><verb>
-               __asm__ (&lt;string literal&gt;[, optional parameters]) ;
+        __asm__ [optional volatile] (&lt;string literal&gt;[, optional parameters]) ;
        </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.
 
        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>
 
 
+
 <sect>Predefined macros<p>
 
 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
 
 <tscreen><verb>
-       asm (&lt;string literal&gt;[, optional parameters]) ;
+        asm [optional volatile] (&lt;string literal&gt;[, optional parameters]) ;
 </verb></tscreen>
 or
 <tscreen><verb>
-               __asm__ (&lt;string literal&gt;[, optional parameters]) ;
+        __asm__ [optional volatile] (&lt;string literal&gt;[, optional parameters]) ;
 </verb></tscreen>
 <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/.
 
-The asm statement may be used inside a function and on global file level. An
-inline assembler statement is a primary expression, so it may also be used as
-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 <tt/asm/ statement can be used only inside a function.  Please note that
+the result of an inline assembler expression is always of type <tt/void/.
 
-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
-the backend and especially the optimizer. For this reason, the compiler does
-only allow regular 6502 opcodes to be used with the inline assembler. Pseudo
-instructions (like <tt/.import/, <tt/.byte/ and so on) are <em/not/ allowed,
+The contents of the string literal are preparsed by the compiler; and, inserted
+into the generated assembly output, so that it can be processed further by
+the backend -- and, especially the optimizer. For that reason, the compiler does
+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,
 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
-the full blown macro assembler which comes with the compiler.
+code) would accept them. The built-in inline assembler is not a replacement for
+the full-blown macro assembler which comes with the compiler.
 
 Note: Inline assembler statements are subject to all optimizations done by the
-compiler. There is currently no way to protect an inline assembler statement
-from being moved or removed completely by the optimizer. If in doubt, check
-the generated assembler output, or disable optimizations.
+compiler. There currently is no way to protect an inline assembler statement
+-- alone -- from being moved or removed completely by the optimizer. If in
+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
 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>
   <item><tt/%b/ - Numerical 8-bit value
@@ -1269,33 +1275,33 @@ the format specifier before passing the assembly code line to the backend.
   <item><tt/%%/ - The % sign itself
 </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
-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>
-       #define OFFS  23
-               __asm__ ("ldy #%b", OFFS);
+        #define OFFS  23
+        __asm__ ("ldy #%b", OFFS);
 </verb></tscreen>
 
 Or, to access a struct member of a static variable:
 
 <tscreen><verb>
-       typedef struct {
-           unsigned char x;
-           unsigned char y;
-           unsigned char color;
-       } pixel_t;
-       static pixel_t pixel;
-               __asm__ ("ldy #%b", offsetof(pixel_t, color));
-       __asm__ ("lda %v,y", pixel);
+        typedef struct {
+            unsigned char x;
+            unsigned char y;
+            unsigned char color;
+        } pixel_t;
+        static pixel_t pixel;
+        __asm__ ("ldy #%b", offsetof(pixel_t, color));
+        __asm__ ("lda %v,y", pixel);
 </verb></tscreen>
 <p>
 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>
-        unsigned char globalSubA, globalSubB, globalSubResult;
+        static unsigned char globalSubA, globalSubB, globalSubResult;
 
         /* return a-b, return 255 if b>a */
         unsigned char sub (unsigned char a, unsigned char b)
@@ -1314,19 +1320,19 @@ an assembler and how to handle assembler jumps:
 </verb></tscreen>
 <p>
 
-Arrays can also be accessed:
+Arrays also can be accessed:
 
 <tscreen><verb>
-        unsigned char globalSquareTable[] = {
+        static const unsigned char globalSquareTable[] = {
             0, 1, 4, 9, 16, 25, 36, 49, 64, 81,
             100, 121, 144, 169, 196, 225
         };
-        unsigned char globalSquareA, globalSquareResult;
+        static unsigned char globalSquareA, globalSquareResult;
 
         /* return a*a for a<16, else 255 */
         unsigned char square (unsigned char a)
         {
-            if (a>15){
+            if (a > 15) {
                 return 255;
             }
             globalSquareA = a;
@@ -1339,28 +1345,30 @@ Arrays can also be accessed:
 <p>
 
 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>
         int foo;
-        int bar () { return 1; }
-               __asm__ ("lda _foo");           /* DON'T DO THAT! */
+        int bar (void) { return 1; }
+        ...
+        __asm__ ("lda _foo");           /* DON'T DO THAT! */
         ...
         __asm__ ("jsr _bar");           /* DON'T DO THAT EITHER! */
 </verb></tscreen>
 <p>
 
-may stop working if the way, the compiler generates these names is changed in
-a future version. Instead use the format specifiers from the table above:
+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:
 
 <tscreen><verb>
-               __asm__ ("lda %v", foo);        /* OK */
+        __asm__ ("lda %v", foo);        /* OK */
         ...
         __asm__ ("jsr %v", bar);        /* OK */
 </verb></tscreen>
 <p>
 
 
+
 <sect>Implementation-defined behavior<p>
 
 This section describes the behavior of cc65 when the standard describes the
@@ -1434,4 +1442,3 @@ freely, subject to the following restrictions:
 </enum>
 
 </article>
-
index 59c1332ffedf1663447ca7522edce6c0d7becd0f..4dd6628c44a4e719dda499e4fd7742e3e3d568be 100644 (file)
 /* cc65 */
 #include "asmlabel.h"
 #include "codegen.h"
+#include "codeseg.h"
 #include "datatype.h"
 #include "error.h"
 #include "expr.h"
 #include "function.h"
 #include "litpool.h"
 #include "scanner.h"
+#include "segments.h"
 #include "stackptr.h"
 #include "symtab.h"
 #include "asmstmt.h"
@@ -422,6 +424,15 @@ void AsmStatement (void)
     /* Skip the ASM */
     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 */
     if (!ConsumeLParen ()) {
         return;