From 9998aea306b1018e7c6880e990b3d723f716a021 Mon Sep 17 00:00:00 2001 From: epetrich Date: Wed, 22 Oct 2003 07:17:24 +0000 Subject: [PATCH] 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 git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2956 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 14 +++++++ src/SDCC.y | 43 ++++++++++++++++++-- src/SDCCast.c | 3 ++ src/SDCCicode.c | 62 +++++++++++++++++++++++++++- src/SDCCopt.c | 4 +- src/ds390/gen.c | 75 +++++++++++++++++++++++++++++++++- src/hc08/gen.c | 91 ++++++++++++++++++++++++++++++++++++++++++ src/mcs51/gen.c | 74 +++++++++++++++++++++++++++++++++- support/Util/SDCCerr.c | 2 + support/Util/SDCCerr.h | 1 + 10 files changed, 358 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 58549105..02f70a12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2003-10-22 Erik Petrich + + 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 * src/SDCC.lex: fixed bug #825944 - defined yytext_ptr to make it compile with flex 2.5.31 diff --git a/src/SDCC.y b/src/SDCC.y index 2ef823c9..96fbfb10 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -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 Interrupt_storage %type identifier declarator declarator2 enumerator_list enumerator @@ -101,7 +102,7 @@ bool uselessDecl = TRUE; %type struct_declarator_list struct_declaration struct_declaration_list %type declaration init_declarator_list init_declarator %type declaration_list identifier_list parameter_identifier_list -%type declarator2_function_attributes while do for +%type declarator2_function_attributes while do for critical %type pointer type_specifier_list type_specifier type_name %type storage_class_specifier struct_or_union_specifier %type declaration_specifiers sfr_reg_bit type_specifier2 @@ -118,6 +119,7 @@ bool uselessDecl = TRUE; %type statement_list statement labeled_statement compound_statement %type expression_statement selection_statement iteration_statement %type jump_statement function_body else_statement string_literal +%type critical_statement %type initializer initializer_list %type 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 diff --git a/src/SDCCast.c b/src/SDCCast.c index 0c160a1b..7db25f4f 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -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 ; } diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 99996df9..82199b50 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -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; diff --git a/src/SDCCopt.c b/src/SDCCopt.c index 116c5f0f..aea6e373 100644 --- a/src/SDCCopt.c +++ b/src/SDCCopt.c @@ -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 */ diff --git a/src/ds390/gen.c b/src/ds390/gen.c index a171483f..a6b67024 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -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); diff --git a/src/hc08/gen.c b/src/hc08/gen.c index 25e62e95..2bcb3ca5 100644 --- a/src/hc08/gen.c +++ b/src/hc08/gen.c @@ -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; } diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index aa19b83b..34c178c0 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -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; } diff --git a/support/Util/SDCCerr.c b/support/Util/SDCCerr.c index af987ae3..0770abd4 100644 --- a/support/Util/SDCCerr.c +++ b/support/Util/SDCCerr.c @@ -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" }, }; /* diff --git a/support/Util/SDCCerr.h b/support/Util/SDCCerr.h index ffc7bb27..d461f381 100644 --- a/support/Util/SDCCerr.h +++ b/support/Util/SDCCerr.h @@ -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. -- 2.30.2