Extended the semantics of the critical keyword to include
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 22 Oct 2003 07:17:24 +0000 (07:17 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 22 Oct 2003 07:17:24 +0000 (07:17 +0000)
individual statements. See RFE #827755 and #799831
* src/SDCC.y
* src/SDCCicode.c
* src/SDCCopt.c
* src/SDCCast.c
* support/Util/SDCCerr.c
* support/Util/SDCCerr.h
* src/mcs51/gen.c
* src/ds390/gen.c
* src/hc08/gen.c

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2956 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/SDCC.y
src/SDCCast.c
src/SDCCicode.c
src/SDCCopt.c
src/ds390/gen.c
src/hc08/gen.c
src/mcs51/gen.c
support/Util/SDCCerr.c
support/Util/SDCCerr.h

index 58549105f8bf2d9bc9c6fc7194024c475d27a5cb..02f70a12aff4a09086bd4da891e608e98fefee65 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2003-10-22 Erik Petrich <epetrich@ivorytower.norman.ok.us>
+
+       Extended the semantics of the critical keyword to include
+       individual statements. See RFE #827755 and #799831
+       * src/SDCC.y
+       * src/SDCCicode.c
+       * src/SDCCopt.c
+       * src/SDCCast.c
+       * support/Util/SDCCerr.c
+       * support/Util/SDCCerr.h
+       * src/mcs51/gen.c
+       * src/ds390/gen.c
+       * src/hc08/gen.c
+
 2003-10-19  Borut Razem <borut.razem@siol.net>
 
        * src/SDCC.lex: fixed bug #825944 - defined yytext_ptr to make it compile with flex 2.5.31
index 2ef823c93c0e07a1a29af9226af9f376b788dc58..96fbfb1030bdd2a274005a90f2e63a2c86ab3cc6 100644 (file)
@@ -44,6 +44,7 @@ int xstackPtr = 0 ;     /* xstack pointer          */
 int reentrant = 0 ; 
 int blockNo   = 0 ;     /* sequential block number  */
 int currBlockno=0 ;
+int inCritical= 0 ;
 extern int yylex();
 int yyparse(void);
 extern int noLineno ;
@@ -93,7 +94,7 @@ bool uselessDecl = TRUE;
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
 %token RRC RLC 
 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
-%token DUMMY_READ_VOLATILE
+%token DUMMY_READ_VOLATILE ENDCRITICAL
 
 %type <yyint>  Interrupt_storage
 %type <sym> identifier  declarator  declarator2 enumerator_list enumerator
@@ -101,7 +102,7 @@ bool uselessDecl = TRUE;
 %type <sym> struct_declarator_list  struct_declaration   struct_declaration_list
 %type <sym> declaration init_declarator_list init_declarator
 %type <sym> declaration_list identifier_list parameter_identifier_list
-%type <sym> declarator2_function_attributes while do for
+%type <sym> declarator2_function_attributes while do for critical
 %type <lnk> pointer type_specifier_list type_specifier type_name
 %type <lnk> storage_class_specifier struct_or_union_specifier
 %type <lnk> declaration_specifiers  sfr_reg_bit type_specifier2
@@ -118,6 +119,7 @@ bool uselessDecl = TRUE;
 %type <asts> statement_list statement labeled_statement compound_statement
 %type <asts> expression_statement selection_statement iteration_statement
 %type <asts> jump_statement function_body else_statement string_literal
+%type <asts> critical_statement
 %type <ilist> initializer initializer_list
 %type <yyint> unary_operator  assignment_operator struct_or_union
 
@@ -1247,6 +1249,7 @@ statement
    | selection_statement
    | iteration_statement
    | jump_statement
+   | critical_statement
    | INLINEASM  ';'      {
                             ast *ex = newNode(INLINEASM,NULL,NULL);
                            ex->values.inlineasm = strdup($1);
@@ -1254,6 +1257,24 @@ statement
                          } 
    ;
 
+critical
+   : CRITICAL   {
+                  inCritical++;
+                  STACK_PUSH(continueStack,NULL);
+                  STACK_PUSH(breakStack,NULL);
+                   $$ = NULL;
+                }
+   ;
+   
+critical_statement
+   : critical statement  {
+                  STACK_POP(breakStack);
+                  STACK_POP(continueStack);
+                  inCritical--;
+                  $$ = newNode(CRITICAL,$2,NULL);
+                }
+   ;
+      
 labeled_statement
 //   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
    : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
@@ -1482,8 +1503,22 @@ jump_statement
           STACK_PEEK(breakStack)->isref = 1;
        }
    }
-   | RETURN ';'            { $$ = newNode(RETURN,NULL,NULL)    ; }
-   | RETURN expr ';'       { $$ = newNode(RETURN,NULL,$2) ; } 
+   | RETURN ';'            {
+       if (inCritical) {
+          werror(E_INVALID_CRITICAL);
+          $$ = NULL;
+       } else {
+          $$ = newNode(RETURN,NULL,NULL);
+       }
+   }
+   | RETURN expr ';'       {
+       if (inCritical) {
+          werror(E_INVALID_CRITICAL);
+          $$ = NULL;
+       } else {
+          $$ = newNode(RETURN,NULL,$2);
+       }
+   }
    ;
 
 identifier
index 0c160a1bc7c0eb2d167eab9fd92813b7f144002d..7db25f4f605307e2121778c99db5acee13d8b065 100644 (file)
@@ -5505,6 +5505,9 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                fprintf(outfile,"FOR LOOP BODY \n");
                ast_print(tree->left,outfile,indent+2);
                return ;
+       case CRITICAL:
+               fprintf(outfile,"CRITICAL (%p) \n",tree);
+               ast_print(tree->left,outfile,indent+2);
        default:
            return ;
        }
index 99996df959a873dbac74630a6e1debb1f9c9d63c..82199b508d676ffe84bfa90c71380d42533915c0 100644 (file)
@@ -69,6 +69,8 @@ PRINTFUNC (picJumpTable);
 PRINTFUNC (picInline);
 PRINTFUNC (picReceive);
 PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
 
 iCodeTable codeTable[] =
 {
@@ -115,7 +117,9 @@ iCodeTable codeTable[] =
   {RECEIVE, "recv", picReceive, NULL},
   {SEND, "send", picGenericOne, NULL},
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
-  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+  {CRITICAL, "critical_start", picCritical, NULL},
+  {ENDCRITICAL, "critical_end", picEndCritical, NULL}
 };
 
 /*-----------------------------------------------------------------*/
@@ -473,6 +477,28 @@ PRINTFUNC (picDummyRead)
   fprintf (of, "\n");
 }
 
+PRINTFUNC (picCritical)
+{
+  fprintf (of, "\t");
+  if (IC_RESULT (ic))
+    printOperand (IC_RESULT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, " = %s ", s);
+  fprintf (of, "\n");
+}
+
+PRINTFUNC (picEndCritical)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s = ", s);
+  if (IC_RIGHT (ic))
+    printOperand (IC_RIGHT (ic), of);
+  else
+    fprintf (of, "(stack)");
+  fprintf (of, "\n");
+}
+
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
@@ -3431,6 +3457,34 @@ geniCodeArrayInit (ast * tree, operand *array)
   }
   ADDTOCHAIN (ic);
 }
+       
+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement   */
+/*-----------------------------------------------------------------*/
+static void 
+geniCodeCritical (ast *tree, int lvl)
+{
+  iCode *ic;
+  operand *op = NULL;
+
+  /* If op is NULL, the original interrupt state will saved on */
+  /* the stack. Otherwise, it will be saved in op. */
+  
+  /* Generate a save of the current interrupt state & disabled */
+  ic = newiCode (CRITICAL, NULL, NULL);
+  IC_RESULT (ic) = op;
+  ADDTOCHAIN (ic);
+  
+  /* Generate the critical code sequence */
+  if (tree->left && tree->left->type == EX_VALUE)
+    geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+  else
+    ast2iCode (tree->left,lvl+1);
+  
+  /* Generate a restore of the original interrupt state */
+  ic = newiCode (ENDCRITICAL, NULL, op);
+  ADDTOCHAIN (ic);
+}
 
 /*-----------------------------------------------------------------*/
 /* Stuff used in ast2iCode to modify geniCodeDerefPtr in some      */
@@ -3546,7 +3600,8 @@ ast2iCode (ast * tree,int lvl)
       tree->opval.op != GOTO &&
       tree->opval.op != SWITCH &&
       tree->opval.op != FUNCTION &&
-      tree->opval.op != INLINEASM)
+      tree->opval.op != INLINEASM &&
+      tree->opval.op != CRITICAL)
     {
 
         if (IS_ASSIGN_OP (tree->opval.op) ||
@@ -3880,6 +3935,9 @@ ast2iCode (ast * tree,int lvl)
     case ARRAYINIT:
        geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
        return NULL;
+    
+    case CRITICAL:
+       geniCodeCritical (tree, lvl);    
     }
 
   return NULL;
index 116c5f0fada20a2a572c5980f0a760a2ba7755e5..aea6e373f457f7cc6d4a1ce57d2f68fee469e244 100644 (file)
@@ -680,7 +680,9 @@ killDeadCode (eBBlock ** ebbs, int count)
              if (SKIP_IC (ic) ||
                  ic->op == IFX ||
                  ic->op == RETURN ||
-                  ic->op == DUMMY_READ_VOLATILE)
+                  ic->op == DUMMY_READ_VOLATILE ||
+                  ic->op == CRITICAL ||
+                  ic->op == ENDCRITICAL)
                continue;
 
              /* if the result is volatile then continue */
index a171483f20c3518f9b925ab63ccfc55fc602ff74..a6b6702454eb6b3c6a71e20069fda817e18e7113 100644 (file)
@@ -3194,9 +3194,12 @@ genFunction (iCode * ic)
   /* if critical function then turn interrupts off */
   if (IFFUNC_ISCRITICAL (ftype))
     {
-      emitcode ("mov", "c,ea");
+      symbol *tlbl = newiTempLabel (NULL);
+      emitcode ("setb", "c");
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      emitcode ("clr", "c");
+      emitcode ("", "%05d$:", (tlbl->key + 100));
       emitcode ("push", "psw"); /* save old ea via c in psw */
-      emitcode ("clr", "ea");
     }
 
 }
@@ -12673,6 +12676,66 @@ release:
   freeAsmop (right, NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  D(emitcode(";     genCritical",""));
+  
+  if (IC_RESULT (ic))
+    aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
+
+  emitcode ("setb", "c");
+  emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+  emitcode ("clr", "c");
+  emitcode ("", "%05d$:", (tlbl->key + 100));
+
+  if (IC_RESULT (ic))
+    outBitC (IC_RESULT (ic)); /* save old ea in an operand */
+  else
+    emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
+
+  if (IC_RESULT (ic))
+    freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  D(emitcode(";     genEndCritical",""));
+  
+  if (IC_RIGHT (ic))
+    {
+      aopOp (IC_RIGHT (ic), ic, FALSE, FALSE);
+      if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+        {
+         emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
+          emitcode ("mov", "ea,c");
+        }
+      else
+        {
+          MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE));
+          emitcode ("rrc", "a");
+          emitcode ("mov", "ea,c");
+        }
+      freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+    }
+  else
+    {
+      emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
+      emitcode ("mov", "ea,c");
+    }
+}
+
+
+
 /*-----------------------------------------------------------------*/
 /* genBuiltIn - calls the appropriate function to  generating code */
 /* for a built in function                                        */
@@ -13046,6 +13109,14 @@ gen390Code (iCode * lic)
          genDummyRead (ic);
          break;
 
+       case CRITICAL:
+         genCritical (ic);
+         break;
+
+       case ENDCRITICAL:
+         genEndCritical (ic);
+         break;
+          
 #if 0 // obsolete, and buggy for != xdata
        case ARRAYINIT:
            genArrayInit(ic);
index 25e62e95040a05f7af6bf9085ed62b7c655cccdf..2bcb3ca5087fb83f28c1e898100e36cd3b8b8cac 100644 (file)
@@ -7306,6 +7306,85 @@ genReceive (iCode * ic)
   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles        */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+  operand *right;
+  int size, offset;
+
+  D(emitcode(";     genDummyRead",""));
+
+  right = IC_RIGHT (ic);
+
+  aopOp (right, ic, FALSE);
+
+  /* bit variables done */
+  /* general case */
+  size = AOP_SIZE (right);
+  offset = 0;
+
+  while (size--)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (right), offset);
+      hc08_freeReg (hc08_reg_a);
+      offset++;
+    }
+
+  freeAsmop (right, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  D(emitcode(";     genCritical",""));
+  
+  if (IC_RESULT (ic))
+    aopOp (IC_RESULT (ic), ic, TRUE);
+
+  emitcode ("tpa", "");
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  emitcode ("sei", "");
+
+  if (IC_RESULT (ic))
+    storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
+  else
+    pushReg (hc08_reg_a, FALSE);
+
+  hc08_freeReg (hc08_reg_a);
+  if (IC_RESULT (ic))
+    freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  D(emitcode(";     genEndCritical",""));
+  
+  if (IC_RIGHT (ic))
+    {
+      aopOp (IC_RIGHT (ic), ic, FALSE);
+      loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
+      emitcode ("tap", "");
+      hc08_freeReg (hc08_reg_a);
+      freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+    }
+  else
+    {
+      pullReg (hc08_reg_a);
+      emitcode ("tap", "");
+    }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* genhc08Code - generate code for HC08 based controllers          */
 /*-----------------------------------------------------------------*/
@@ -7617,6 +7696,18 @@ genhc08Code (iCode * lic)
          addSet (&_G.sendSet, ic);
          break;
 
+       case DUMMY_READ_VOLATILE:
+         genDummyRead (ic);
+         break;
+
+       case CRITICAL:
+         genCritical (ic);
+         break;
+
+       case ENDCRITICAL:
+         genEndCritical (ic);
+         break;
+
        default:
          ic = ic;
        }
index aa19b83b1edb3c142e04288ab6b43c00ee5bf1d2..34c178c00454d23ecfe80712a442eb4c09829d61 100644 (file)
@@ -2604,9 +2604,12 @@ genFunction (iCode * ic)
   /* if critical function then turn interrupts off */
   if (IFFUNC_ISCRITICAL (ftype))
     {
-      emitcode ("mov", "c,ea");
+      symbol *tlbl = newiTempLabel (NULL);
+      emitcode ("setb", "c");
+      emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+      emitcode ("clr", "c");
+      emitcode ("", "%05d$:", (tlbl->key + 100));
       emitcode ("push", "psw"); /* save old ea via c in psw */
-      emitcode ("clr", "ea");
     }
 }
 
@@ -9004,6 +9007,65 @@ release:
   freeAsmop (right, NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* genCritical - generate code for start of a critical sequence    */
+/*-----------------------------------------------------------------*/
+static void
+genCritical (iCode *ic)
+{
+  symbol *tlbl = newiTempLabel (NULL);
+
+  D(emitcode(";     genCritical",""));
+  
+  if (IC_RESULT (ic))
+    aopOp (IC_RESULT (ic), ic, TRUE);
+
+  emitcode ("setb", "c");
+  emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
+  emitcode ("clr", "c");
+  emitcode ("", "%05d$:", (tlbl->key + 100));
+
+  if (IC_RESULT (ic))
+    outBitC (IC_RESULT (ic)); /* save old ea in an operand */
+  else
+    emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
+
+  if (IC_RESULT (ic))
+    freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndCritical - generate code for end of a critical sequence   */
+/*-----------------------------------------------------------------*/
+static void
+genEndCritical (iCode *ic)
+{
+  D(emitcode(";     genEndCritical",""));
+  
+  if (IC_RIGHT (ic))
+    {
+      aopOp (IC_RIGHT (ic), ic, FALSE);
+      if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
+        {
+         emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
+          emitcode ("mov", "ea,c");
+        }
+      else
+        {
+          MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
+          emitcode ("rrc", "a");
+          emitcode ("mov", "ea,c");
+        }
+      freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+    }
+  else
+    {
+      emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
+      emitcode ("mov", "ea,c");
+    }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* gen51Code - generate code for 8051 based controllers            */
 /*-----------------------------------------------------------------*/
@@ -9262,6 +9324,14 @@ gen51Code (iCode * lic)
          genDummyRead (ic);
          break;
 
+       case CRITICAL:
+         genCritical (ic);
+         break;
+
+       case ENDCRITICAL:
+         genEndCritical (ic);
+         break;
+
        default:
          ic = ic;
        }
index af987ae31b3eed4f67f67bdd3239f61e1331dd99..0770abd44d27eca9f6d9141445ddcc8a022635f7 100644 (file)
@@ -397,6 +397,8 @@ struct
     "function attribute following non-function declaration"},
 { W_SAVE_RESTORE, ERROR_LEVEL_PEDANTIC,
     "unmatched #pragma SAVE and #pragma RESTORE" },
+{ E_INVALID_CRITICAL, ERROR_LEVEL_ERROR,
+    "not allowed in a critical section" },
 };
 
 /*
index ffc7bb2794f214c57f2b827f882f71d2da231e94..d461f3816b012744f51babf6d58942b47f7a397f 100644 (file)
@@ -186,6 +186,7 @@ SDCCERR - SDCC Standard error handler
 #define W_BITFLD_NAMED 168          /* declarator used with 0 length bitfield */
 #define E_FUNC_ATTR 169             /* function attribute without function */
 #define W_SAVE_RESTORE 170          /* unmatched #pragma SAVE and #pragma RESTORE */
+#define E_INVALID_CRITICAL 171     /* operation invalid in critical sequence */
 
 /** Describes the maximum error level that will be logged.  Any level
  *  includes all of the levels listed after it.