+2003-08-13 Bernhard Held <bernhard@bernhardheld.de>
+
+ * src/SDCCcse.c (algebraicOpts): fix bug converting op from value to type
+ * src/SDCCicode.c (operandOperation): rewritten some ops
+ (*, ==, unary_minus) to fix possible overflows and to accord with ANSI
+ * src/SDCCsymt.c (computeType): literals are handled the same way as any
+ other type
+ * src/SDCCval.c (cheapestVal): removed, it doesn't accord with ANSI (can
+ be re-activated by defining REDUCE_LITERALS)
+ * src/SDCCval.c (constVal): fixed; hex and octal constants can be
+ unsigned, but are signed by default
+ * src/SDCCval.c (constVal): rearranged
+ * src/SDCCval.c (valMod): preliminary fix
+ * src/SDCCval.c (valCastLiteral): use TYPE_* types
+ * support/regression/literalop.c: added, work in progress
+
2003-08-12 Erik Petrich <epetrich@ivorytower.norman.ok.us>
Generate warnings for useless declarations like "char data;"
2003-08-09 Bernhard Held <bernhard@bernhardheld.de>
- * src/SDCCval.c (valMult): fixex overflow detection of negativ int
+ * src/SDCCval.c (valMult): fix overflow detection of negative int
2003-08-07 Erik Petrich <epetrich@ivorytower.norman.ok.us>
void ReplaceOpWithCheaperOp(operand **op, operand *cop) {
#ifdef RANGEHUNT
- printf ("ReplaceOpWithCheaperOp %s with %s: ",
- IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM",
+ printf ("ReplaceOpWithCheaperOp %s with %s: ",
+ IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM",
IS_SYMOP(cop) ? OP_SYMBOL(cop)->name : "!SYM");
// if op is a register equivalent
if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) {
/* replaceAllSymBySym - replaces all operands by operand in an */
/* instruction chain */
/*-----------------------------------------------------------------*/
-void
+void
replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset)
{
iCode *lic;
IS_ITEMP (IC_RESULT (cdp->diCode)))
*opp = IC_RESULT (cdp->diCode);
- if ((*opp) &&
- (isOperandLiteral(*opp) || !checkSign ||
+ if ((*opp) &&
+ (isOperandLiteral(*opp) || !checkSign ||
(checkSign &&
IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
(SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) &&
*opp = operandFromOperand (*opp);
(*opp)->isaddr = cop->isaddr;
}
-
+
if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) &&
SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp)))
{
- // special case: we can make an unsigned char literal
+ // special case: we can make an unsigned char literal
// into an int literal with no cost.
if (isOperandLiteral(*opp)
&& SPEC_NOUN(operandType(*opp)) == V_CHAR
*opp = NULL;
return 0;
}
-
+
}
-
+
return 1;
}
/*-----------------------------------------------------------------*/
/* ifDefSymIs - if a definition is found in the set */
/*-----------------------------------------------------------------*/
-int
+int
ifDefSymIs (set * cseSet, operand * sym)
{
cseDef *loop;
/*-----------------------------------------------------------------*/
/* ifDiCodeIs - returns truw if diCode is same */
/*-----------------------------------------------------------------*/
-int
+int
ifDiCodeIs (set * cseSet, iCode * ic)
{
cseDef *loop;
{
ic->op = CAST;
IC_LEFT (ic)->type = TYPE;
+ IC_LEFT (ic)->isLiteral = 0;
setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
}
return;
IC_RIGHT (ic) = IC_LEFT (ic);
IC_LEFT (ic) = op;
IC_LEFT (ic)->type = TYPE;
+ IC_LEFT (ic)->isLiteral = 0;
setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic)));
}
return;
/* update the spill location for this */
updateSpillLocation (ic,0);
- if (POINTER_SET (ic) &&
+ if (POINTER_SET (ic) &&
!(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype)))
{
pdop = NULL;
change = 1;
}
}
-
+
/* if left or right changed then do algebraic */
if (!computeOnly && change)
{
if (pdic && compareType (operandType (IC_RESULT (pdic)),
operandType (IC_RESULT (ic))) != 1)
pdic = NULL;
- if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0)
+ if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0)
pdic = NULL;
}
/* Alternate code */
if (pdic && IS_ITEMP(IC_RESULT(ic))) {
if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) {
- /* Mmm, found an equivalent pointer get at a lower level.
- This could be a loop however with the same pointer set
+ /* Mmm, found an equivalent pointer get at a lower level.
+ This could be a loop however with the same pointer set
later on */
} else {
/* if previous definition found change this to an assignment */
IC_LEFT(ic) = NULL;
IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic));
SET_ISADDR(IC_RESULT(ic),0);
- SET_ISADDR(IC_RIGHT (ic),0);
+ SET_ISADDR(IC_RIGHT (ic),0);
}
}
/* checkConstantRange: check a constant against the type */
/*-----------------------------------------------------------------*/
+
/* pedantic=0: allmost anything is allowed as long as the absolute
value is within the bit range of the type, and -1 is treated as
0xf..f for unsigned types (e.g. in assign)
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
-double
+double
operandLitValue (operand * op)
{
assert (isOperandLiteral (op));
}
/*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands */
+/* operandOperation - performs operations on operands */
/*-----------------------------------------------------------------*/
operand *
operandOperation (operand * left, operand * right,
operandLitValue (right)));
break;
case '*':
+ /*
retval = operandFromValue (valCastLiteral (type,
operandLitValue (left) *
operandLitValue (right)));
- if (!options.lessPedantic &&
- !IS_FLOAT (OP_VALUE(retval)->type) &&
- !SPEC_LONG (OP_VALUE(retval)->type))
- ; /* TODO: werror (W_INT_OVL) */
+ This could be all we've to do, but with gcc we've to take care about
+ overflows. Two examples:
+ ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+ significant bits are lost (52 in fraction, 63 bits would be
+ necessary to keep full precision).
+ If the resulting double value is greater than ULONG_MAX (resp.
+ USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+ */
+
+ /* if it is not a specifier then we can assume that */
+ /* it will be an unsigned long */
+ if (IS_INT (type) ||
+ !IS_SPEC (type))
+ {
+ /* long is handled here, because it can overflow with double */
+ if (SPEC_LONG (type) ||
+ !IS_SPEC (type))
+ /* signed and unsigned mul are the same, as long as the precision
+ of the result isn't bigger than the precision of the operands. */
+ retval = operandFromValue (valCastLiteral (type,
+ (TYPE_UDWORD) operandLitValue (left) *
+ (TYPE_UDWORD) operandLitValue (right)));
+ else if (SPEC_USIGN (type)) /* unsigned int */
+ {
+ /* unsigned int is handled here in order to detect overflow */
+ TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+ (TYPE_UWORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+ if (!options.lessPedantic &&
+ ul != (TYPE_UWORD) ul)
+ werror (W_INT_OVL);
+ }
+ else /* int */
+ {
+ /* int is handled here in order to detect overflow */
+ TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+ (TYPE_WORD) operandLitValue (right);
+
+ retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+ if (!options.lessPedantic &&
+ l != (TYPE_WORD) l)
+ werror (W_INT_OVL);
+ }
+ }
+ else
+ /* all others go here: */
+ retval = operandFromValue (valCastLiteral (type,
+ operandLitValue (left) *
+ operandLitValue (right)));
break;
case '/':
if ((TYPE_UDWORD) operandLitValue (right) == 0)
retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
(TYPE_UDWORD) operandLitValue (right));
break;
- case RIGHT_OP: {
+ case RIGHT_OP:
/* The number of right shifts is always unsigned. Signed doesn't make
sense here. Shifting by a negative number is impossible. */
if (SPEC_USIGN(let))
retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
(TYPE_UDWORD) operandLitValue (right));
break;
- }
case EQ_OP:
- retval = operandFromLit (operandLitValue (left) ==
- operandLitValue (right));
+ /* this op doesn't care about signedness */
+ {
+ TYPE_UDWORD l, r;
+
+ l = (TYPE_UDWORD) operandLitValue (left);
+ if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
+ l &= 0xff;
+ else if (!SPEC_LONG (OP_VALUE(left)->type))
+ l &= 0xffff;
+ r = (TYPE_UDWORD) operandLitValue (right);
+ if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
+ r &= 0xff;
+ else if (!SPEC_LONG (OP_VALUE(right)->type))
+ r &= 0xffff;
+ retval = operandFromLit (l == r);
+ }
break;
case '<':
retval = operandFromLit (operandLitValue (left) <
break;
case UNARYMINUS:
- retval = operandFromLit (-1 * operandLitValue (left));
+ retval = operandFromValue (valCastLiteral (type,
+ -1 * operandLitValue (left)));
break;
case '~':
/*-----------------------------------------------------------------*/
/* isOperandEqual - compares two operand & return 1 if they r = */
/*-----------------------------------------------------------------*/
-int
+int
isOperandEqual (operand * left, operand * right)
{
/* if the pointers are equal then they are equal */
/* if the right is a literal & power of 2 */
/* then make it a left shift */
- /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
- efficient in most cases than 2 bytes result = 2 bytes << literal
+ /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
+ efficient in most cases than 2 bytes result = 2 bytes << literal
if port has 1 byte muldiv */
if (p2 && !IS_FLOAT (letype) &&
- !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
+ !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
(port->support.muldiv == 1)))
{
if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
check if the literal value is within bounds */
if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
{
- checkConstantRange(ltype,
+ checkConstantRange(ltype,
OP_VALUE(right), "compare operation", 1);
}
/*-----------------------------------------------------------------*/
/* geniCodeSwitch - changes a switch to a if statement */
/*-----------------------------------------------------------------*/
-void
+void
geniCodeSwitch (ast * tree,int lvl)
{
iCode *ic;
reType = getSpec (rType);
/* if either of them unsigned but not val then make this unsigned */
- if (((!IS_LITERAL(type1) && SPEC_USIGN (etype1)) ||
- (!IS_LITERAL(type2) && SPEC_USIGN (etype2))) &&
+ if (((/*!IS_LITERAL(type1) &&*/ SPEC_USIGN (etype1)) ||
+ (/*!IS_LITERAL(type2) &&*/ SPEC_USIGN (etype2))) &&
!IS_FLOAT (reType))
SPEC_USIGN (reType) = 1;
else
SPEC_USIGN (reType) = 0;
-
+
/* if result is a literal then make not so */
if (IS_LITERAL (reType))
SPEC_SCLS (reType) = S_REGISTER;
/*--------------------------------------------------------------------*/
/* compareType - will do type check return 1 if match, -1 if castable */
/*--------------------------------------------------------------------*/
-int
+int
compareType (sym_link * dest, sym_link * src)
{
if (!dest && !src)
/*------------------------------------------------------------------*/
/* list2int - converts the first element of the list to value */
/*------------------------------------------------------------------*/
-double
+double
list2int (initList * val)
{
initList *i = val;
return val;
}
+#if defined(REDUCE_LITERALS)
/*--------------------------------------------------------------------*/
/* cheapestVal - convert a val to the cheapest as possible value */
/*--------------------------------------------------------------------*/
}
return val;
}
+#endif
/*-----------------------------------------------------------------*/
/* valueFromLit - creates a value from a literal */
unsigned long sval;
sscanf (s, scanFmt, &sval);
dval=sval;
- SPEC_USIGN (val->type) = 1;
} else {
sscanf (s, scanFmt, &dval);
}
SPEC_NOUN (val->type) = V_INT;
}
else if (dval>0x7f && !SPEC_USIGN (val->type)) { // check if we have to promote to int
- SPEC_NOUN (val->type) = V_INT;
+ if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */
+ dval<=0xff) {
+ SPEC_USIGN (val->type) = 1;
+ } else {
+ SPEC_NOUN (val->type) = V_INT;
+ }
}
if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long
SPEC_LONG (val->type) = 1;
}
else if (dval>0x7fff && !SPEC_USIGN (val->type)) { // check if we have to promote to long int
- SPEC_LONG (val->type) = 1;
+ if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */
+ dval<=0xffff) {
+ SPEC_USIGN (val->type) = 1;
+ } else {
+ SPEC_LONG (val->type) = 1;
+ if (dval>0x7fffffff) {
+ SPEC_USIGN (val->type) = 1;
+ }
+ }
}
}
{
char *s ;
unsigned long value ;
-
+
(*src)++ ; /* Skip over the 'x' */
s = *src ; /* Save for error detection */
/*------------------------------------------------------------------*/
/* floatFromVal - value to double float conversion */
/*------------------------------------------------------------------*/
-double
+double
floatFromVal (value * val)
{
if (!val)
else
return (double) SPEC_CVAL (val->etype).v_long;
}
-
+
if (SPEC_NOUN (val->etype) == V_INT) {
if (SPEC_USIGN (val->etype))
return (double) SPEC_CVAL (val->etype).v_uint;
return 0;
}
-
/*------------------------------------------------------------------*/
/* valUnaryPM - does the unary +/- operation on a constant */
/*------------------------------------------------------------------*/
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval);
- else
- {
/* signed and unsigned mul are the same, as long as the precision of the
result isn't bigger than the precision of the operands. */
- if (SPEC_LONG (val->type))
- SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) *
- (TYPE_UDWORD) floatFromVal (rval);
- else /* int */
- {
- TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) *
- (TYPE_UWORD) floatFromVal (rval);
-
- SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul;
- if (!options.lessPedantic)
- {
- if (SPEC_USIGN (val->type))
- {
- if (ul != SPEC_CVAL (val->type).v_uint)
- werror (W_INT_OVL);
- }
- else /* signed result */
- {
- TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) *
- (TYPE_WORD) floatFromVal (rval);
-
- if (l != SPEC_CVAL (val->type).v_int)
- werror (W_INT_OVL);
- }
- }
- }
+ else if (SPEC_LONG (val->type))
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) *
+ (TYPE_UDWORD) floatFromVal (rval);
+ else if (SPEC_USIGN (val->type)) /* unsigned */
+ {
+ TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) *
+ (TYPE_UWORD) floatFromVal (rval);
+
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul;
+ if (!options.lessPedantic &&
+ ul != SPEC_CVAL (val->type).v_uint)
+ werror (W_INT_OVL);
+ }
+ else /* int */
+ {
+ TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) *
+ (TYPE_WORD) floatFromVal (rval);
+
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) l;
+ if (!options.lessPedantic &&
+ l != SPEC_CVAL (val->type).v_int)
+ werror (W_INT_OVL);
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->etype) = S_LITERAL;
SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
- SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
+ SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
if (IS_FLOAT (val->type))
SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
if (SPEC_LONG (val->type))
{
if (SPEC_USIGN (val->type))
- SPEC_CVAL (val->type).v_ulong =
- (unsigned long) floatFromVal (lval) /
- (unsigned long) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) /
+ (TYPE_UDWORD) floatFromVal (rval);
else
- SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) /
- (long) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) /
+ (TYPE_DWORD) floatFromVal (rval);
}
else
{
if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) /
- (unsigned) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) /
+ (TYPE_UWORD) floatFromVal (rval);
} else {
- SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) /
- (int) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) /
+ (TYPE_WORD) floatFromVal (rval);
}
}
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
SPEC_NOUN (val->type) = V_INT; /* type is int */
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype));
- SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
+ SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype));
if (SPEC_LONG (val->type))
{
if (SPEC_USIGN (val->type))
- SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) %
- (unsigned long) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) %
+ (TYPE_UDWORD) floatFromVal (rval);
else
- SPEC_CVAL (val->type).v_long = (unsigned long) floatFromVal (lval) %
- (unsigned long) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) %
+ (TYPE_DWORD) floatFromVal (rval);
}
else
{
if (SPEC_USIGN (val->type)) {
- SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) %
- (unsigned) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) %
+ (TYPE_UWORD) floatFromVal (rval);
} else {
- SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) %
- (unsigned) floatFromVal (rval);
+ SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) %
+ (TYPE_WORD) floatFromVal (rval);
}
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) ||
IS_FLOAT (rval->etype) ? V_FLOAT : V_INT);
SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */
- SPEC_USIGN (val->type) =
+ SPEC_USIGN (val->type) =
SPEC_USIGN (lval->etype) &&
SPEC_USIGN (rval->etype) &&
(floatFromVal(lval)+floatFromVal(rval))>=0;
-
+
SPEC_LONG (val->type) = 1;
if (IS_FLOAT (val->type))
(long) floatFromVal (rval);
}
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
}
}
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
(long) floatFromVal (lval) >> (long) floatFromVal (rval);
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
break;
}
+#ifdef REDUCE_LITERALS
return cheapestVal(val);
+#else
+ return val;
+#endif
}
/*------------------------------------------------------------------*/
val = newValue ();
val->etype = getSpec (val->type = copyLinkChain (dtype));
SPEC_SCLS (val->etype) = S_LITERAL;
+ TYPE_UDWORD l = (TYPE_UDWORD)fval;
+
/* if it is not a specifier then we can assume that */
/* it will be an unsigned long */
if (!IS_SPEC (val->type)) {
- SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval;
+ SPEC_CVAL (val->etype).v_ulong = l;
return val;
}
if (SPEC_NOUN (val->etype) == V_FLOAT)
SPEC_CVAL (val->etype).v_float = fval;
- else {
- unsigned long l = (unsigned long)fval;
+ else if (SPEC_NOUN (val->etype) == V_CHAR) {
+ if (SPEC_USIGN (val->etype))
+ SPEC_CVAL (val->etype).v_uint= (TYPE_UBYTE) l;
+ else
+ SPEC_CVAL (val->etype).v_int = (TYPE_BYTE) l;
+ } else {
if (SPEC_LONG (val->etype)) {
if (SPEC_USIGN (val->etype))
- SPEC_CVAL (val->etype).v_ulong = (unsigned long) l;
+ SPEC_CVAL (val->etype).v_ulong = (TYPE_UDWORD) l;
else
- SPEC_CVAL (val->etype).v_long = (long) l;
+ SPEC_CVAL (val->etype).v_long = (TYPE_DWORD) l;
} else {
if (SPEC_USIGN (val->etype))
- SPEC_CVAL (val->etype).v_uint = (unsigned short)l;
+ SPEC_CVAL (val->etype).v_uint = (TYPE_UWORD)l;
else
- SPEC_CVAL (val->etype).v_int = (short)l;
+ SPEC_CVAL (val->etype).v_int = (TYPE_WORD)l;
}
}
return val;
/*------------------------------------------------------------------*/
/* getNelements - determines # of elements from init list */
/*------------------------------------------------------------------*/
-int
+int
getNelements (sym_link * type, initList * ilist)
{
int i;
--- /dev/null
+/* Test operandOperation() in SDCCicode.c
+
+ type: char, short, long
+ */
+#include <testfwk.h>
+
+typedef signed {type} stype;
+typedef unsigned {type} utype;
+
+#define _{type}
+
+#if defined(PORT_HOST) || defined(SDCC_z80) || defined(SDCC_gbz80)
+# define idata
+# define code
+#endif
+
+volatile char is8 = 8;
+
+signed char sc;
+signed short ss;
+signed long sl;
+unsigned char uc;
+unsigned short us;
+unsigned long ul;
+volatile signed char vsc;
+volatile signed short vss;
+volatile signed long vsl;
+volatile unsigned char vuc;
+volatile unsigned short vus;
+volatile unsigned long vul;
+stype s;
+volatile stype vs;
+utype u;
+volatile utype vu;
+
+unsigned long t1, t2;
+
+void
+testOpOp(void)
+{
+ /* mul ast */
+ ASSERT((stype) -3 * (stype) -1 == (stype) 3);
+ ASSERT((stype) -3 * (stype) 1 == (stype) -3);
+ ASSERT((stype) 3 * (stype) -1 == (stype) -3);
+
+ ASSERT((stype) 1 * (utype) 0xfffffff7 == (utype) 0xfffffff7);
+
+ ASSERT((unsigned char ) 0xfffffff8 * (unsigned char ) 0xfffffff7 == 0xef48);
+ ASSERT((unsigned short) 0xfffffff8 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 0x0048 : 0xffef0048));
+ ASSERT((unsigned long ) 0xfffffff8 * (unsigned long ) 0xfffffff7 == 0x0048);
+
+ ASSERT((stype ) 0xfffffff8 * (stype ) 0xfffffff7 == 72);
+
+ ASSERT((signed char ) -1 * (unsigned char ) 0xfffffff7 == (sizeof(int) == 2 ? 0xff09 : 0xffffff09));
+ ASSERT((signed short) -1 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 9u : 0xffff0009));
+ ASSERT((signed long ) -1 * (unsigned long ) 0xfffffff7 == 9u);
+
+ ASSERT((signed char ) -2 * (unsigned char ) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffffff8));
+ ASSERT((signed short) -2 * (unsigned short) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffefff8));
+ ASSERT((signed long ) -2 * (unsigned long ) 0x8004 == 0xfffefff8);
+
+ ASSERT(-1 * 0xfff7 == (sizeof(int) == 2 ? 9 : 0xffff0009)); // 0xfff7 is stored in 'unsigned int'
+ // but:
+ ASSERT(-1 * 65527 == -65527); // 65527 (== 0xfff7) is stored in 'signed long'
+ ASSERT(-1 * 33000 == -33000);
+
+ ASSERT(1 * 10000 * is8 == (sizeof(int) == 2 ? 14464 : 80000)); /* int */
+ ASSERT(1 * 10000l * is8 == 80000); /* long */
+ ASSERT(1 * 40000u * is8 == (sizeof(int) == 2 ? 57856u : 320000)); /* unsigned */
+ ASSERT(1 * 40000 * is8 == 320000); /* long */
+ ASSERT(1 * 0x4000 * is8 == (sizeof(int) == 2 ? 0 : 0x20000)); /* unsigned */
+
+ ASSERT(-1 * 1 < 0);
+ ASSERT(-1 * 1u > 0);
+
+
+ /* mul icode */
+ s = -3;
+ ASSERT(s * (stype) -1 == (stype) 3);
+ ASSERT(s * (stype) 1 == (stype) -3);
+ s = 3;
+ ASSERT(s * (stype) -1 == (stype) -3);
+
+ s = 1;
+ ASSERT(s * (utype) 0xfffffff7 == (utype) 0xfffffff7);
+ uc = (unsigned char ) 0xfffffff8;
+ ASSERT(uc * (unsigned char ) 0xfffffff7 == 0xef48);
+ us = (unsigned short) 0xfffffff8;
+ ASSERT(us * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 0x0048 : 0xffef0048));
+ ul = (unsigned long ) 0xfffffff8;
+ ASSERT(ul * (unsigned long ) 0xfffffff7 == 0x0048);
+ ul = (unsigned long ) 0xfffffff8;
+
+ ASSERT((stype ) 0xfffffff8 * (stype ) 0xfffffff7 == 72);
+
+ ASSERT((signed char ) -1 * (unsigned char ) 0xfffffff7 == (sizeof(int) == 2 ? 0xff09 : 0xffffff09));
+ ASSERT((signed short) -1 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 9u : 0xffff0009));
+ ASSERT((signed long ) -1 * (unsigned long ) 0xfffffff7 == 9u);
+
+ ASSERT((signed char ) -2 * (unsigned char ) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffffff8));
+ ASSERT((signed short) -2 * (unsigned short) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffefff8));
+ ASSERT((signed long ) -2 * (unsigned long ) 0x8004 == 0xfffefff8);
+
+
+
+ ASSERT((stype) -12 / (stype) -3 == (stype) 4);
+ ASSERT((stype) -12 / (stype) 3 == (stype) -4);
+ ASSERT((stype) 12 / (stype) -3 == (stype) -4);
+
+// ASSERT((stype) -12 / (utype) -3 == (stype) 4);
+// ASSERT((utype) -12 / (stype) -3 == (stype) 4);
+// ASSERT((utype) -12 / (utype) -3 == (stype) 4);
+
+
+ ASSERT(12u / 3 * 10000 == 40000);
+
+ ASSERT(-1 / 1 < 0);
+
+
+
+ ASSERT((stype) -14 % (stype) -3 == (stype) -2);
+ ASSERT((stype) -14 % (stype) 3 == (stype) -2);
+ ASSERT((stype) 14 % (stype) -3 == (stype) 2);
+
+ ASSERT(-3 % 2 < 0);
+}