+2008-10-05 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ * src/ds390/main.c (_ds390_genInitStartup): added
+ * src/SDCCpeeph.c (getPatternVar): new, added,
+ (labelInRange): fixed bug 2115959
+ * src/mcs51/peeph.def (rules 193.x to 198.x): check for labelInRange
+ * src/SDCCicode.h: added newiTempOperand
+ * src/SDCCcse.c (algebraicOpts): fixed bug for x*-1,
+ added optimizations for 0/x and x/-1, see also patch 2142900
+ * support/regression/tests/onebyte.c (testMul): added test cases
+
2008-09-20 Borut Razem <borut.razem AT siol.net>
* src/pic16/glue.c:
}
if (rightValue == -1.0)
{
+ /* '*' can have two unsigned chars as operands */
+ /* and an unsigned int as result. */
+ if (IS_INTEGRAL (operandType (IC_LEFT (ic))))
+ {
+ if ((getSize (operandType (IC_LEFT (ic))) < (unsigned int) INTSIZE) &&
+ (getSize (operandType (IC_LEFT (ic))) < getSize (operandType (IC_RESULT (ic)))))
+ {
+ operand * op;
+ iCode * newic;
+ /* Widen to int. */
+ op = operandFromOperand (IC_RESULT (ic));
+ op->type = TYPE;
+ setOperandType (op, INTTYPE);
+ newic = newiCode (CAST, op, IC_LEFT (ic));
+ IC_RESULT (newic) = newiTempOperand (INTTYPE, TRUE);
+ addiCodeToeBBlock (ebp, newic, ic);
+ IC_LEFT (ic) = IC_RESULT (newic);
+ }
+ }
/* convert x * -1 to -x */
ic->op = UNARYMINUS;
IC_RIGHT (ic) = NULL;
IC_LEFT (ic) = NULL;
IC_RESULT (ic) = operandFromOperand (IC_RESULT (ic));
IC_RESULT (ic)->isaddr = 0;
- break;
+ return;
}
- /* if this is a division then check if right */
- /* is one then change it to an assignment */
- if (IS_OP_LITERAL (IC_RIGHT (ic)) &&
- operandLitValue (IC_RIGHT (ic)) == 1.0)
+ /* if this is a division then check if left is zero */
+ /* and right is not then change it to an assignment */
+ if (IS_OP_LITERAL (IC_LEFT (ic)) && IS_OP_LITERAL (IC_RIGHT (ic)) &&
+ (operandLitValue (IC_LEFT (ic)) == 0.0) && (operandLitValue (IC_RIGHT (ic)) != 0.0))
{
-
ic->op = '=';
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = NULL;
SET_RESULT_RIGHT (ic);
return;
}
+ /* if this is a division then check if right */
+ /* is one then change it to an assignment */
+ if (IS_OP_LITERAL (IC_RIGHT (ic)))
+ {
+ double rightValue = operandLitValue (IC_RIGHT (ic));
+ if (rightValue == 1.0)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = IC_LEFT (ic);
+ IC_LEFT (ic) = NULL;
+ SET_RESULT_RIGHT (ic);
+ return;
+ }
+ if (rightValue == -1.0)
+ {
+ /* '/' can have two unsigned chars as operands */
+ /* and an unsigned int as result. */
+ if (IS_INTEGRAL (operandType (IC_LEFT (ic))))
+ {
+ if ((getSize (operandType (IC_LEFT (ic))) < (unsigned int) INTSIZE) &&
+ (getSize (operandType (IC_LEFT (ic))) < getSize (operandType (IC_RESULT (ic)))))
+ {
+ operand * op;
+ iCode * newic;
+ /* Widen to int. */
+ op = operandFromOperand (IC_RESULT (ic));
+ op->type = TYPE;
+ setOperandType (op, INTTYPE);
+ newic = newiCode (CAST, op, IC_LEFT (ic));
+ IC_RESULT (newic) = newiTempOperand (INTTYPE, TRUE);
+ addiCodeToeBBlock (ebp, newic, ic);
+ IC_LEFT (ic) = IC_RESULT (newic);
+ }
+ }
+ /* convert x / -1 to -x */
+ ic->op = UNARYMINUS;
+ IC_RIGHT (ic) = NULL;
+ return;
+ }
+ }
break;
/* if both are the same for an comparison operators */
case EQ_OP:
mine and type is a pointer then delete
pointerGets to take care of aliasing */
if (ASSIGNMENT (ic) &&
- IS_SYMOP (IC_RESULT (ic)) &&
+ IS_SYMOP (IC_RESULT (ic)) &&
OTHERS_PARM (OP_SYMBOL (IC_RESULT (ic))) &&
IS_PTR (operandType (IC_RESULT (ic))))
{
bool isOperandInCodeSpace (operand *);
operand *opFromOpWithDU (operand *, bitVect *, bitVect *);
iCode *copyiCode (iCode *);
+operand *newiTempOperand (sym_link *, char);
operand *newiTempFromOp (operand *);
iCode *getBuiltinParms (iCode *,int *, operand **);
int isiCodeInFunctionCall (iCode *);
void pic16_peepRules2pCode(peepRule *);
#endif
+/*-----------------------------------------------------------------*/
+/* getPatternVar - finds a pattern variable */
+/*-----------------------------------------------------------------*/
+
+static char*
+getPatternVar (hTab *vars, char **cmdLine)
+{
+ int varNumber;
+ char *digitend;
+
+ if (!cmdLine || !*cmdLine || !**cmdLine)
+ return NULL; /* no parameters given */
+
+ while (**cmdLine && ISCHARSPACE(**cmdLine))
+ (*cmdLine)++; /* skip whitespace */
+
+ if (**cmdLine != '%')
+ goto error;
+ (*cmdLine)++;
+ if (!ISCHARDIGIT (**cmdLine))
+ goto error;
+ varNumber = strtol (*cmdLine, &digitend, 10);
+ *cmdLine = digitend;
+ return hTabItemWithKey (vars, varNumber);
+
+error:
+ fprintf (stderr,
+ "*** internal error: peephole restriction malformed: %s\n", *cmdLine);
+ return NULL;
+}
+
/*-----------------------------------------------------------------*/
/* pcDistance - finds a label backward or forward */
/*-----------------------------------------------------------------*/
}
/*-----------------------------------------------------------------*/
-/* labelInRange - will check to see if label %5 is within range */
+/* labelInRange - will check to see if label is within range */
/*-----------------------------------------------------------------*/
FBYNAME (labelInRange)
{
- /* assumes that %5 pattern variable has the label name */
- char *lbl = hTabItemWithKey (vars, 5);
int dist = 0;
+ char *lbl = getPatternVar (vars, &cmdLine);
if (!lbl)
- return FALSE;
+ {
+ /* If no parameters given, assume that %5 pattern variable
+ has the label name for backward compatibility */
+ lbl = hTabItemWithKey (vars, 5);
+ }
- /* Don't optimize jumps in a jump table; a more generic test */
- if (currPl->ic && currPl->ic->op == JUMPTABLE)
+ if (!lbl)
return FALSE;
- /* if the previous two instructions are "ljmp"s then don't
- do it since it can be part of a jump table */
- if (currPl->prev && currPl->prev->prev &&
- strstr (currPl->prev->line, "ljmp") &&
- strstr (currPl->prev->prev->line, "ljmp"))
- return FALSE;
+ do
+ {
+ /* Don't optimize jumps in a jump table; a more generic test */
+ if (currPl->ic && currPl->ic->op == JUMPTABLE)
+ return FALSE;
- /* calculate the label distance : the jump for reladdr can be
- +/- 127 bytes, here I am assuming that an average 8051
- instruction is 2 bytes long, so if the label is more than
- 63 intructions away, the label is considered out of range
- for a relative jump. we could get more precise this will
- suffice for now since it catches > 90% cases */
- dist = (pcDistance (currPl, lbl, TRUE) +
- pcDistance (currPl, lbl, FALSE));
-
-/* changed to 127, now that pcDistance return actual number of bytes */
- if (!dist || dist > 127)
- return FALSE;
+ /* if the previous two instructions are "ljmp"s then don't
+ do it since it can be part of a jump table */
+ if (currPl->prev && currPl->prev->prev &&
+ strstr (currPl->prev->line, "ljmp") &&
+ strstr (currPl->prev->prev->line, "ljmp"))
+ return FALSE;
+
+ /* calculate the label distance : the jump for reladdr can be
+ +/- 127 bytes, here I am assuming that an average 8051
+ instruction is 2 bytes long, so if the label is more than
+ 63 intructions away, the label is considered out of range
+ for a relative jump. we could get more precise this will
+ suffice for now since it catches > 90% cases */
+ dist = (pcDistance (currPl, lbl, TRUE) +
+ pcDistance (currPl, lbl, FALSE));
+
+ /* changed to 127, now that pcDistance return actual number of bytes */
+ if (!dist || dist > 127)
+ return FALSE;
+
+ lbl = getPatternVar (vars, &cmdLine);
+ }
+ while (lbl);
return TRUE;
}
static bool
matchLine (char *s, char *d, hTab ** vars)
{
-
if (!s || !(*s))
return FALSE;
while (*s && *d)
{
-
/* skip white space in both */
while (ISCHARSPACE (*s))
s++;
}
}
- /* if some charaters left over */
+ /* if some characters left over */
if (nch)
{
lb[nch] = '\0';
return TRUE;
}
+static void
+_ds390_genInitStartup (FILE *of)
+{
+ fprintf (of, "__sdcc_gsinit_startup:\n");
+ /* if external stack is specified then the
+ higher order byte of the xdatalocation is
+ going into P2 and the lower order going into
+ spx */
+ if (options.useXstack)
+ {
+ fprintf (of, "\tmov\tP2,#0x%02x\n",
+ (((unsigned int) options.xdata_loc) >> 8) & 0xff);
+ fprintf (of, "\tmov\t_spx,#0x%02x\n",
+ (unsigned int) options.xdata_loc & 0xff);
+ }
+
+ // This should probably be a port option, but I'm being lazy.
+ // on the 400, the firmware boot loader gives us a valid stack
+ // (see '400 data sheet pg. 85 (TINI400 ROM Initialization code)
+ if (!TARGET_IS_DS400)
+ {
+ /* initialise the stack pointer. JCF: aslink takes care of the location */
+ fprintf (of, "\tmov\tsp,#__start__stack - 1\n"); /* MOF */
+ }
+
+ fprintf (of, "\tlcall\t__sdcc_external_startup\n");
+ fprintf (of, "\tmov\ta,dpl\n");
+ fprintf (of, "\tjz\t__sdcc_init_data\n");
+ fprintf (of, "\tljmp\t__sdcc_program_startup\n");
+ fprintf (of, "__sdcc_init_data:\n");
+
+ // if the port can copy the XINIT segment to XISEG
+ if (port->genXINIT)
+ {
+ port->genXINIT(of);
+ }
+}
+
/* Generate code to copy XINIT to XISEG */
static void _ds390_genXINIT (FILE * of) {
fprintf (of, "; _ds390_genXINIT() start\n");
NULL, /* no genAssemblerEnd */
_ds390_genIVT,
_ds390_genXINIT,
- NULL, /* genInitStartup */
+ _ds390_genInitStartup,
_ds390_reset_regparm,
_ds390_regparm,
NULL,
_tininative_genAssemblerEnd,
_tininative_genIVT,
NULL,
- NULL, /* genInitStartup */
+ _ds390_genInitStartup,
_ds390_reset_regparm,
_ds390_regparm,
NULL,
NULL, /* no genAssemblerEnd */
_ds400_genIVT,
_ds390_genXINIT,
- NULL, /* genInitStartup */
+ _ds390_genInitStartup,
_ds390_reset_regparm,
_ds390_regparm,
NULL,
cjne %13,%14,%8
sjmp %7
%3:
-} if labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
+} if labelInRange(%8), labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
replace {
cjne %1,%2,%3
cjne %13,%14,%8
sjmp %7
%3:
-} if labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
+} if labelInRange(%8), labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
replace {
cjne @%1,%2,%3
cjne @%1,%14,%8
sjmp %7
%3:
-} if labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
+} if labelInRange(%8), labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
replace {
cjne %1,%2,%3
cjne %13,%14,%8
sjmp %7
%3:
-} if labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
+} if labelInRange(%8), labelRefCount(%3 4), labelRefCountChange(%3 -4), labelRefCountChange(%8 3)
replace {
jnz %3
cjne %10,%11,%8
sjmp %7
%3:
-} if labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
+} if labelInRange(%8), labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
replace {
cjne %1,%2,%3
cjne %10,%11,%8
sjmp %7
%3:
-} if labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
+} if labelInRange(%8), labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
replace {
cjne @%1,%2,%3
cjne @%1,%11,%8
sjmp %7
%3:
-} if labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
+} if labelInRange(%8), labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
replace {
cjne %1,%2,%3
cjne %10,%11,%8
sjmp %7
%3:
-} if labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
+} if labelInRange(%8), labelRefCount(%3 3), labelRefCountChange(%3 -3), labelRefCountChange(%8 2)
replace {
jnz %3
cjne %5,%6,%8
sjmp %7
%3:
-} if labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
+} if labelInRange(%8), labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
replace {
cjne %1,%2,%3
cjne %5,%6,%8
sjmp %7
%3:
-} if labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
+} if labelInRange(%8), labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
replace {
cjne @%1,%2,%3
cjne @%1,%6,%8
sjmp %7
%3:
-} if labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
+} if labelInRange(%8), labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
replace {
cjne %1,%2,%3
cjne %5,%6,%8
sjmp %7
%3:
-} if labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
+} if labelInRange(%8), labelRefCount(%3 2), labelRefCountChange(%3 -2), labelRefCountChange(%8 1)
replace {
cjne %1,%2,%3
cjne %1,%2,%5
sjmp %4
%3:
-} if labelRefCount(%3 1), labelRefCountChange(%3 -1)
+} if labelInRange(%5), labelRefCount(%3 1), labelRefCountChange(%3 -1)
replace {
sjmp %1
ucL = 128; cR = 1; ur8 = ucL * cR; ur8b = cR * ucL; ASSERT (ur8 == 128); ASSERT (ur8b == 128);
ucL = 128; ucR = 5; r16 = ucL * ucR; r16b = ucR * ucL; ASSERT (r16 == 640); ASSERT (r16b == 640);
ucL = 128; ucR = 1; ur8 = ucL * ucR; ur8b = ucR * ucL; ASSERT (ur8 == 128); ASSERT (ur8b == 128);
+
+ ucL = 254; cR = -1; r16 = ucL * cR; ASSERT (r16 == -254);
+ cL = -128; cR = -1; r16 = cL * cR; ASSERT (r16 == 128);
}
void