From: maartenbrock Date: Sun, 25 Sep 2005 10:39:17 +0000 (+0000) Subject: * src/SDCC.y: added tokens GETABIT, GETBYTE, GETWORD X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=411a4bf70f7e46852d1ff250a7512c504ea71810;p=fw%2Fsdcc * src/SDCC.y: added tokens GETABIT, GETBYTE, GETWORD * src/SDCCast.c (optimizeGetHbit): updated to also accept bool=expr&(1<>(8*n), (optimizeGetWord): new, to get a word from a long int: expr>>(8*n), (isConformingBody): also check GETABIT, GETBYTE, GETWORD, (decorateType): '&': also try GETABIT, GETBYTE, GETWORD optimization, RIGHT_OP: also try GETBYTE, GETWORD optimization, GETABIT, GETBYTE, GETWORD: decorate them, (isShiftRightLitVal, isBitAndPowOf2): new helper functions, (ast_print): added GETABIT, GETBYTE, GETWORD * src/SDCCcse.c (isSignedOp): added GETABIT, GETBYTE, GETWORD * src/SDCCicode.c (codeTable): added GETABIT, GETBYTE, GETWORD, (geniCodeBinary): new generic binary icode, (ast2iCode): added GETABIT, GETBYTE, GETWORD * src/port.h: updated comment for PORT.hasExtBitOp * src/mcs51/gen.c (genGetAbit): new, to get any single bit, (genGetByte): new, to get a single byte, (genGetWord): new, to get a word from a long, (gen51Code): added GETABIT, GETBYTE, GETWORD * src/mcs51/main.c (hasExtBitOp): added GETABIT, GETBYTE, GETWORD git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3898 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index 8b62e96f..1745eb5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2005-09-25 Maarten Brock + + * src/SDCC.y: added tokens GETABIT, GETBYTE, GETWORD + * src/SDCCast.c (optimizeGetHbit): updated to also accept bool=expr&(1<>(8*n), + (optimizeGetWord): new, to get a word from a long int: expr>>(8*n), + (isConformingBody): also check GETABIT, GETBYTE, GETWORD, + (decorateType): '&': also try GETABIT, GETBYTE, GETWORD optimization, + RIGHT_OP: also try GETBYTE, GETWORD optimization, + GETABIT, GETBYTE, GETWORD: decorate them, + (isShiftRightLitVal, isBitAndPowOf2): new helper functions, + (ast_print): added GETABIT, GETBYTE, GETWORD + * src/SDCCcse.c (isSignedOp): added GETABIT, GETBYTE, GETWORD + * src/SDCCicode.c (codeTable): added GETABIT, GETBYTE, GETWORD, + (geniCodeBinary): new generic binary icode, + (ast2iCode): added GETABIT, GETBYTE, GETWORD + * src/port.h: updated comment for PORT.hasExtBitOp + * src/mcs51/gen.c (genGetAbit): new, to get any single bit, + (genGetByte): new, to get a single byte, + (genGetWord): new, to get a word from a long, + (gen51Code): added GETABIT, GETBYTE, GETWORD + * src/mcs51/main.c (hasExtBitOp): added GETABIT, GETBYTE, GETWORD + 2005-09-23 Raphael Neider * configure.in, configure: have device/lib/pic configured diff --git a/src/SDCC.y b/src/SDCC.y index 6d8229fe..4a38510e 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -95,7 +95,7 @@ bool uselessDecl = TRUE; %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN %token NAKED JAVANATIVE OVERLAY %token INLINEASM -%token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT +%token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT GETABIT GETBYTE GETWORD %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE %token RRC RLC %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT diff --git a/src/SDCCast.c b/src/SDCCast.c index 1d65bc7d..7f94a700 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -55,7 +55,10 @@ static ast *createIvalCharPtr (ast *, sym_link *, ast *); static ast *optimizeCompare (ast *); ast *optimizeRRCRLC (ast *); ast *optimizeSWAP (ast *); -ast *optimizeGetHbit (ast *); +ast *optimizeGetHbit (ast *, RESULT_TYPE); +ast *optimizeGetAbit (ast *, RESULT_TYPE); +ast *optimizeGetByte (ast *, RESULT_TYPE); +ast *optimizeGetWord (ast *, RESULT_TYPE); ast *backPatchLabels (ast *, symbol *, symbol *); void PA(ast *t); int inInitMode = 0; @@ -1756,6 +1759,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body) case '%': case LEFT_OP: case RIGHT_OP: + case GETABIT: + case GETBYTE: + case GETWORD: if (IS_AST_SYM_VALUE (pbody->left) && isSymbolEqual (AST_SYMBOL (pbody->left), sym)) @@ -2600,7 +2606,34 @@ decorateType (ast * tree, RESULT_TYPE resultType) /* see if this is a GETHBIT operation if yes then return that */ { - ast *otree = optimizeGetHbit (tree); + ast *otree = optimizeGetHbit (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETABIT operation if yes + then return that */ + { + ast *otree = optimizeGetAbit (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETBYTE operation if yes + then return that */ + { + ast *otree = optimizeGetByte (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETWORD operation if yes + then return that */ + { + ast *otree = optimizeGetWord (tree, resultType); if (otree != tree) return decorateType (otree, RESULT_TYPE_NONE); @@ -3420,9 +3453,18 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; case GETHBIT: + case GETABIT: TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink(); return tree; + case GETBYTE: + TTYPE (tree) = TETYPE (tree) = newCharLink(); + return tree; + + case GETWORD: + TTYPE (tree) = TETYPE (tree) = newIntLink(); + return tree; + case LEFT_OP: case RIGHT_OP: if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype)) @@ -3454,6 +3496,24 @@ decorateType (ast * tree, RESULT_TYPE resultType) return tree; } + /* see if this is a GETBYTE operation if yes + then return that */ + { + ast *otree = optimizeGetByte (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + + /* see if this is a GETWORD operation if yes + then return that */ + { + ast *otree = optimizeGetWord (tree, resultType); + + if (otree != tree) + return decorateType (otree, RESULT_TYPE_NONE); + } + LRVAL (tree) = RRVAL (tree) = 1; if (tree->opval.op == LEFT_OP) { @@ -4870,41 +4930,202 @@ createWhile (symbol * trueLabel, symbol * continueLabel, } /*-----------------------------------------------------------------*/ -/* optimizeGetHbit - get highest order bit of the expression */ +/* isShiftRightLitVal _BitAndLitVal - helper function */ /*-----------------------------------------------------------------*/ -ast * -optimizeGetHbit (ast * tree) +static ast * +isShiftRightLitVal_BitAndLitVal (ast * tree) { - int i, j; /* if this is not a bit and */ if (!IS_BITAND (tree)) - return tree; + return NULL; /* will look for tree of the form - ( expr >> ((sizeof expr) -1) ) & 1 */ + ( expr >> litval2) & litval1 */ if (!IS_AST_LIT_VALUE (tree->right)) + return NULL; + + if (!IS_RIGHT_OP (tree->left)) + return NULL; + + if (!IS_AST_LIT_VALUE (tree->left->right)) + return NULL; + + return tree->left->left; +} + +/*-----------------------------------------------------------------*/ +/* isBitAndPowOf2 - helper function */ +/*-----------------------------------------------------------------*/ +static int +isBitAndPow2 (ast * tree) +{ + int p2; + + /* if this is not a bit and */ + if (!IS_BITAND (tree)) + return -1; + + /* will look for tree of the form + ( expr & (1 << litval) */ + if (!IS_AST_LIT_VALUE (tree->right)) + return -1; + + if (AST_LIT_VALUE (tree->right) == 1) + return 0; + p2 = powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right)); + if (!p2) + return -1; + + return p2; +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetHbit - get highest order bit of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetHbit (ast * tree, RESULT_TYPE resultType) +{ + int i, j; + ast * expr; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + if ((AST_LIT_VALUE (tree->right) != 1) || + ((i = (int) AST_LIT_VALUE (tree->left->right)) != + (j = (getSize (TTYPE (expr)) * 8 - 1)))) + expr = NULL; + } + if (!expr && (resultType == RESULT_TYPE_BIT)) + { + expr = tree->left; + if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1) + expr = NULL; + } + if (!expr) return tree; - if (AST_LIT_VALUE (tree->right) != 1) + /* make sure the port supports GETHBIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr)))) return tree; - if (!IS_RIGHT_OP (tree->left)) + return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE); +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetAbit - get a single bit of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetAbit (ast * tree, RESULT_TYPE resultType) +{ + ast * expr; + ast * count = NULL; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + if (AST_LIT_VALUE (tree->right) != 1) + expr = NULL; + count = tree->left->right; + } + if (!expr && (resultType == RESULT_TYPE_BIT)) + { + int p2 = isBitAndPow2 (tree); + if (p2 >= 0) + { + expr = tree->left; + count = newAst_VALUE (valueFromLit (p2)); + } + } + if (!expr) return tree; - if (!IS_AST_LIT_VALUE (tree->left->right)) + /* make sure the port supports GETABIT */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr)))) return tree; - if ((i = (int) AST_LIT_VALUE (tree->left->right)) != - (j = (getSize (TTYPE (tree->left->left)) * 8 - 1))) + return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE); + +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetByte - get a byte of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetByte (ast * tree, RESULT_TYPE resultType) +{ + unsigned int i = 0; + ast * expr; + ast * count = NULL; + + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + i = (unsigned int) AST_LIT_VALUE (tree->left->right); + count = tree->left->right; + if (AST_LIT_VALUE (tree->right) != 0xFF) + expr = NULL; + } + if (!expr && resultType == RESULT_TYPE_CHAR) + { + /* if this is a right shift over a multiple of 8 */ + if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right)) + { + i = (unsigned int) AST_LIT_VALUE (tree->right); + count = tree->right; + expr = tree->left; + } + } + if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8)) return tree; - /* make sure the port supports GETHBIT */ + /* make sure the port supports GETBYTE */ if (port->hasExtBitOp - && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) + && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr)))) return tree; - return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_TYPE_NONE); + return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE); +} + +/*-----------------------------------------------------------------*/ +/* optimizeGetWord - get two bytes of the expression */ +/*-----------------------------------------------------------------*/ +ast * +optimizeGetWord (ast * tree, RESULT_TYPE resultType) +{ + unsigned int i; + ast * expr; + ast * count = NULL; + expr = isShiftRightLitVal_BitAndLitVal(tree); + if (expr) + { + i = (unsigned int) AST_LIT_VALUE (tree->left->right); + count = tree->left->right; + if (AST_LIT_VALUE (tree->right) != 0xFFFF) + expr = NULL; + } + if (!expr && resultType == RESULT_TYPE_INT) + { + /* if this is a right shift over a multiple of 8 */ + if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right)) + { + i = (unsigned int) AST_LIT_VALUE (tree->right); + count = tree->right; + expr = tree->left; + } + } + if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8)) + return tree; + + /* make sure the port supports GETWORD */ + if (port->hasExtBitOp + && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr)))) + return tree; + + return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE); } /*-----------------------------------------------------------------*/ @@ -5130,7 +5351,7 @@ optimizeSWAP (ast * root) } /*-----------------------------------------------------------------*/ -/* optimizeCompare - otimizes compares for bit variables */ +/* optimizeCompare - optimizes compares for bit variables */ /*-----------------------------------------------------------------*/ static ast * optimizeCompare (ast * root) @@ -5831,6 +6052,27 @@ void ast_print (ast * tree, FILE *outfile, int indent) fprintf(outfile,")\n"); ast_print(tree->left,outfile,indent+2); return ; + case GETABIT: + fprintf(outfile,"GETABIT (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + ast_print(tree->right,outfile,indent+2); + return ; + case GETBYTE: + fprintf(outfile,"GETBYTE (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + ast_print(tree->right,outfile,indent+2); + return ; + case GETWORD: + fprintf(outfile,"GETWORD (%p) type (",tree); + printTypeChain(tree->ftype,outfile); + fprintf(outfile,")\n"); + ast_print(tree->left,outfile,indent+2); + ast_print(tree->right,outfile,indent+2); + return ; case LEFT_OP: fprintf(outfile,"LEFT_SHIFT (%p) type (",tree); printTypeChain(tree->ftype,outfile); diff --git a/src/SDCCcse.c b/src/SDCCcse.c index c64866f2..a2cc6ef0 100644 --- a/src/SDCCcse.c +++ b/src/SDCCcse.c @@ -1752,6 +1752,9 @@ static int isSignedOp (iCode *ic) case RRC: case RLC: case GETHBIT: + case GETABIT: + case GETBYTE: + case GETWORD: case RIGHT_OP: case CAST: case ARRAYINIT: diff --git a/src/SDCCicode.c b/src/SDCCicode.c index ee4783cd..f9e22e60 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -80,6 +80,9 @@ iCodeTable codeTable[] = {RRC, "rrc", picGenericOne, NULL}, {RLC, "rlc", picGenericOne, NULL}, {GETHBIT, "ghbit", picGenericOne, NULL}, + {GETABIT, "gabit", picGenericOne, NULL}, + {GETBYTE, "gbyte", picGenericOne, NULL}, + {GETWORD, "gword", picGenericOne, NULL}, {UNARYMINUS, "-", picGenericOne, NULL}, {IPUSH, "push", picGenericOne, NULL}, {IPOP, "pop", picGenericOne, NULL}, @@ -3122,6 +3125,19 @@ geniCodeUnary (operand * op, int oper) return IC_RESULT (ic); } +/*-----------------------------------------------------------------*/ +/* geniCodeBinary - for a generic binary operation */ +/*-----------------------------------------------------------------*/ +operand * +geniCodeBinary (operand * left, operand * right, int oper) +{ + iCode *ic = newiCode (oper, left, right); + + IC_RESULT (ic) = newiTempOperand (operandType (left), 0); + ADDTOCHAIN (ic); + return IC_RESULT (ic); +} + /*-----------------------------------------------------------------*/ /* geniCodeConditional - geniCode for '?' ':' operation */ /*-----------------------------------------------------------------*/ @@ -4241,6 +4257,16 @@ ast2iCode (ast * tree,int lvl) setOperandType (op, UCHARTYPE); return op; } + case GETABIT: + case GETBYTE: + case GETWORD: + { + operand *op = geniCodeBinary (geniCodeRValue (left, FALSE), + geniCodeRValue (right, FALSE), + tree->opval.op); + setOperandType (op, (tree->opval.op == GETWORD) ? UINTTYPE : UCHARTYPE); + return op; + } case AND_OP: case OR_OP: return geniCodeLogicAndOr (tree, lvl); diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 317a4b16..085333af 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -7297,6 +7297,140 @@ genGetHbit (iCode * ic) freeAsmop (result, NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genGetAbit - generates code get a single bit */ +/*-----------------------------------------------------------------*/ +static void +genGetAbit (iCode * ic) +{ + operand *left, *right, *result; + int shCount; + + D(emitcode ("; genGetAbit","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); + + /* get the needed byte into a */ + MOVA (aopGet (left, shCount / 8, FALSE, FALSE)); + shCount %= 8; + if (AOP_TYPE (result) == AOP_CRY) + { + if ((shCount) == 7) + emitcode ("rlc", "a"); + else if ((shCount) == 0) + emitcode ("rrc", "a"); + else + emitcode ("mov", "c,acc[%d]", shCount); + outBitC (result); + } + else + { + switch (shCount) + { + case 2: + emitcode ("rr", "a"); + //fallthrough + case 1: + emitcode ("rr", "a"); + //fallthrough + case 0: + emitcode ("anl", "a,#0x01"); + break; + case 3: + case 5: + emitcode ("mov", "c,acc[%d]", shCount); + emitcode ("clr", "a"); + emitcode ("rlc", "a"); + break; + case 4: + emitcode ("swap", "a"); + emitcode ("anl", "a,#0x01"); + break; + case 6: + emitcode ("rl", "a"); + //fallthrough + case 7: + emitcode ("rl", "a"); + emitcode ("anl", "a,#0x01"); + break; + } + outAcc (result); + } + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGetByte - generates code get a single byte */ +/*-----------------------------------------------------------------*/ +static void +genGetByte (iCode * ic) +{ + operand *left, *right, *result; + int offset; + + D(emitcode ("; genGetByte","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8; + aopPut (result, + aopGet (left, offset, FALSE, FALSE), + 0, + isOperandVolatile (result, FALSE)); + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + +/*-----------------------------------------------------------------*/ +/* genGetWord - generates code get two bytes */ +/*-----------------------------------------------------------------*/ +static void +genGetWord (iCode * ic) +{ + operand *left, *right, *result; + int offset; + + D(emitcode ("; genGetWord","")); + + left = IC_LEFT (ic); + right = IC_RIGHT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE); + aopOp (right, ic, FALSE); + aopOp (result, ic, FALSE); + + offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8; + aopPut (result, + aopGet (left, offset, FALSE, FALSE), + 0, + isOperandVolatile (result, FALSE)); + aopPut (result, + aopGet (left, offset+1, FALSE, FALSE), + 1, + isOperandVolatile (result, FALSE)); + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (right, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + /*-----------------------------------------------------------------*/ /* genSwap - generates code to swap nibbles or bytes */ /*-----------------------------------------------------------------*/ @@ -11142,6 +11276,18 @@ gen51Code (iCode * lic) genGetHbit (ic); break; + case GETABIT: + genGetAbit (ic); + break; + + case GETBYTE: + genGetByte (ic); + break; + + case GETWORD: + genGetWord (ic); + break; + case LEFT_OP: genLeftShift (ic); break; diff --git a/src/mcs51/main.c b/src/mcs51/main.c index 402993d8..e8295e81 100644 --- a/src/mcs51/main.c +++ b/src/mcs51/main.c @@ -264,6 +264,9 @@ hasExtBitOp (int op, int size) if (op == RRC || op == RLC || op == GETHBIT + || op == GETABIT + || op == GETBYTE + || op == GETWORD || (op == SWAP && size <= 2) ) return TRUE; diff --git a/src/port.h b/src/port.h index fa127a4e..d5bcf342 100644 --- a/src/port.h +++ b/src/port.h @@ -294,7 +294,7 @@ typedef struct bool (*hasNativeMulFor) (iCode *ic, sym_link *left, sym_link *right); /** Returns true if the port has implemented certain bit - manipulation iCodes (RRC, RLC, SWAP, GETHBIT) + manipulation iCodes (RRC, RLC, SWAP, GETHBIT, GETABIT, GETBYTE, GETWORD) */ bool (*hasExtBitOp) (int op, int size);