* src/SDCCast.c (optimizeGetHbit): updated to also accept bool=expr&(1<<n),
(optimizeGetAbit): new, to get any bit, not only the high bit,
(optimizeGetByte): new, to get a byte from a (long) int: expr>>(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
+2005-09-25 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ * src/SDCC.y: added tokens GETABIT, GETBYTE, GETWORD
+ * src/SDCCast.c (optimizeGetHbit): updated to also accept bool=expr&(1<<n),
+ (optimizeGetAbit): new, to get any bit, not only the high bit,
+ (optimizeGetByte): new, to get a byte from a (long) int: expr>>(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 <rneider AT web.de>
* configure.in, configure: have device/lib/pic configured
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%token NAKED JAVANATIVE OVERLAY
%token <yyinline> 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
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;
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))
/* 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);
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))
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)
{
}
/*-----------------------------------------------------------------*/
-/* 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);
}
/*-----------------------------------------------------------------*/
}
/*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables */
+/* optimizeCompare - optimizes compares for bit variables */
/*-----------------------------------------------------------------*/
static ast *
optimizeCompare (ast * root)
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);
case RRC:
case RLC:
case GETHBIT:
+ case GETABIT:
+ case GETBYTE:
+ case GETWORD:
case RIGHT_OP:
case CAST:
case ARRAYINIT:
{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},
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 */
/*-----------------------------------------------------------------*/
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);
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 */
/*-----------------------------------------------------------------*/
genGetHbit (ic);
break;
+ case GETABIT:
+ genGetAbit (ic);
+ break;
+
+ case GETBYTE:
+ genGetByte (ic);
+ break;
+
+ case GETWORD:
+ genGetWord (ic);
+ break;
+
case LEFT_OP:
genLeftShift (ic);
break;
if (op == RRC
|| op == RLC
|| op == GETHBIT
+ || op == GETABIT
+ || op == GETBYTE
+ || op == GETWORD
|| (op == SWAP && size <= 2)
)
return TRUE;
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);