+ if (IS_FLOAT (operandType (*op1)) || IS_FLOAT (operandType (*op2)))
+ {
+ return newFloatLink ();
+ }
+
+ if (!IS_INTEGRAL (operandType (*op1)) || !IS_INTEGRAL (operandType (*op2)))
+ {
+ /* if either is not an integer type, we're done. */
+ return copyLinkChain (operandType (*op1)); /* Punt! we should never get here. */
+ }
+
+ /* If either is an unsigned long, make sure both are. */
+ if (SPEC_USIGN (operandType (*op1)) && IS_LONG (operandType (*op1)))
+ {
+ if (!SPEC_USIGN (operandType (*op2)) || !IS_LONG (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (ULONGTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (SPEC_USIGN (operandType (*op2)) && IS_LONG (operandType (*op2)))
+ {
+ if (!SPEC_USIGN (operandType (*op1)) || !IS_LONG (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (ULONGTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* Next, if one is long and the other is int (signed or un),
+ * cast both to long.
+ *
+ * Note that because in our environment a long can hold all
+ * the values of an unsigned int, the "long/unsigned int" pair
+ * in the ANSI conversion table is unnecessary; this test
+ * handles that case implicitly.
+ */
+ if (IS_LONG (operandType (*op1)))
+ {
+ /* NB: because of the unary conversions, op2 cannot
+ * be smaller than int. Therefore, if it is not
+ * long, it is a regular int.
+ */
+ if (!IS_LONG (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (LONGTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (IS_LONG (operandType (*op2)))
+ {
+ /* NB: because of the unary conversions, op2 cannot
+ * be smaller than int. Therefore, if it is not
+ * long, it is a regular int.
+ */
+ if (!IS_LONG (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (LONGTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* All right, neither is long; they must both be integers.
+
+ * Only remaining issue is signed vs. unsigned; if one is unsigned
+ * and the other isn't, convert both to unsigned.
+ */
+ if (SPEC_USIGN (operandType (*op1)))
+ {
+ if (!SPEC_USIGN (operandType (*op2)))
+ {
+ *op2 = geniCodeCast (UINTTYPE, *op2, TRUE);
+ }
+ return copyLinkChain (operandType (*op1));
+ }
+
+ if (SPEC_USIGN (operandType (*op2)))
+ {
+ if (!SPEC_USIGN (operandType (*op1)))
+ {
+ *op1 = geniCodeCast (UINTTYPE, *op1, TRUE);
+ }
+ return copyLinkChain (operandType (*op2));
+ }
+
+ /* Done! */
+ return copyLinkChain (operandType (*op1));
+}
+
+
+/*-----------------------------------------------------------------*/
+/* geniCodeValueAtAddress - generate intermeditate code for value */
+/* at address */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeRValue (operand * op, bool force)
+{
+ iCode *ic;
+ sym_link *type = operandType (op);
+ sym_link *etype = getSpec (type);
+
+ /* if this is an array & already */
+ /* an address then return this */
+ if (IS_AGGREGATE (type) ||
+ (IS_PTR (type) && !force && !op->isaddr))
+ return operandFromOperand (op);
+
+ /* if this is not an address then must be */
+ /* rvalue already so return this one */
+ if (!op->isaddr)
+ return op;
+
+ /* if this is not a temp symbol then */
+ if (!IS_ITEMP (op) &&
+ !force &&
+ !IN_FARSPACE (SPEC_OCLS (etype)))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
+ if (IS_SPEC (type) &&
+ IS_TRUE_SYMOP (op) &&
+ (!IN_FARSPACE (SPEC_OCLS (etype)) || TARGET_IS_DS390))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
+ ic = newiCode (GET_VALUE_AT_ADDRESS, op, NULL);
+ if (IS_PTR (type) && op->isaddr && force)
+ type = type->next;
+
+ type = copyLinkChain (type);
+
+ IC_RESULT (ic) = newiTempOperand (type, 1);
+ IC_RESULT (ic)->isaddr = 0;
+
+/* ic->supportRtn = ((IS_GENPTR(type) | op->isGptr) & op->isaddr); */
+
+ /* if the right is a symbol */
+ if (op->type == SYMBOL)
+ IC_RESULT (ic)->operand.symOperand->args =
+ op->operand.symOperand->args;
+ ADDTOCHAIN (ic);
+
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeCast - changes the value from one type to another */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeCast (sym_link * type, operand * op, bool implicit)
+{
+ iCode *ic;
+ sym_link *optype;
+ sym_link *opetype = getSpec (optype = operandType (op));
+ sym_link *restype;
+
+ /* one of them has size zero then error */
+ if (IS_VOID (optype))
+ {
+ werror (E_CAST_ZERO);
+ return op;
+ }
+
+ /* if the operand is already the desired type then do nothing */
+ if (checkType (type, optype) == 1)
+ return op;
+
+ /* if this is a literal then just change the type & return */
+ if (IS_LITERAL (opetype) && op->type == VALUE && !IS_PTR (type) && !IS_PTR (optype))
+ return operandFromValue (valCastLiteral (type,
+ operandLitValue (op)));
+
+ /* if casting to some pointer type &&
+ the destination is not a generic pointer
+ then give a warning : (only for implicit casts) */
+ if (IS_PTR (optype) && implicit &&
+ (DCL_TYPE (optype) != DCL_TYPE (type)) &&
+ !IS_GENPTR (type))
+ {
+ werror (E_INCOMPAT_CAST);
+ werror (E_CONTINUE, "from type '");
+ printTypeChain (optype, stderr);
+ fprintf (stderr, "' to type '");
+ printTypeChain (type, stderr);
+ fprintf (stderr, "'\n");
+ }
+
+ /* if they are the same size create an assignment */
+ if (getSize (type) == getSize (optype) &&
+ !IS_BITFIELD (type) &&
+ !IS_FLOAT (type) &&
+ !IS_FLOAT (optype) &&
+ ((IS_SPEC (type) && IS_SPEC (optype)) ||
+ (!IS_SPEC (type) && !IS_SPEC (optype))))
+ {
+
+ ic = newiCode ('=', NULL, op);
+ IC_RESULT (ic) = newiTempOperand (type, 0);
+ SPIL_LOC (IC_RESULT (ic)) =
+ (IS_TRUE_SYMOP (op) ? OP_SYMBOL (op) : NULL);
+ IC_RESULT (ic)->isaddr = 0;
+ }
+ else
+ {
+ ic = newiCode (CAST, operandFromLink (type),
+ geniCodeRValue (op, FALSE));
+
+ IC_RESULT (ic) = newiTempOperand (type, 0);
+ }
+
+ /* preserve the storage class & output class */
+ /* of the original variable */
+ restype = getSpec (operandType (IC_RESULT (ic)));
+ SPEC_SCLS (restype) = SPEC_SCLS (opetype);
+ SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeLabel - will create a Label */
+/*-----------------------------------------------------------------*/
+void
+geniCodeLabel (symbol * label)
+{
+ iCode *ic;
+
+ ic = newiCodeLabelGoto (LABEL, label);
+ ADDTOCHAIN (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeGoto - will create a Goto */
+/*-----------------------------------------------------------------*/
+void
+geniCodeGoto (symbol * label)
+{
+ iCode *ic;
+
+ ic = newiCodeLabelGoto (GOTO, label);
+ ADDTOCHAIN (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeMultiply - gen intermediate code for multiplication */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeMultiply (operand * left, operand * right,int resultIsInt)
+{
+ iCode *ic;
+ int p2 = 0;
+ int saveOption=0;
+ sym_link *resType;
+ LRTYPE;
+
+ /* if they are both literal then we know the result */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype))
+ return operandFromValue (valMult (left->operand.valOperand,
+ right->operand.valOperand));
+
+ if (resultIsInt)
+ {
+ saveOption = options.ANSIint;
+ options.ANSIint = 0;
+ }
+ resType = usualBinaryConversions (&left, &right);
+ if (resultIsInt)
+ {
+ options.ANSIint = saveOption;
+ SPEC_NOUN(getSpec(resType))=V_INT;
+ SPEC_SHORT(getSpec(resType))=0;
+ }
+
+ /* 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 if port as 1 byte muldiv */
+ if (IS_LITERAL (retype) && !IS_FLOAT (letype) &&
+ !((resultIsInt) && (getSize (resType) != getSize (ltype)) && (1 == port->muldiv.native_below)) &&
+ (p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand))))
+ {
+ if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
+ {
+ /* LEFT_OP need same size for left and result, */
+ left = geniCodeCast (resType, left, TRUE);
+ ltype = operandType (left);
+ }
+ ic = newiCode (LEFT_OP, left, operandFromLit (p2)); /* left shift */
+ }
+ else
+ {
+ ic = newiCode ('*', left, right); /* normal multiplication */
+ /* if the size left or right > 1 then support routine */
+ if (getSize (ltype) > 1 || getSize (rtype) > 1)
+ ic->supportRtn = 1;
+
+ }
+ IC_RESULT (ic) = newiTempOperand (resType, 1);
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeDivision - gen intermediate code for division */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeDivision (operand * left, operand * right)
+{
+ iCode *ic;
+ int p2 = 0;
+ sym_link *resType;
+ sym_link *rtype = operandType (right);
+ sym_link *retype = getSpec (rtype);
+ sym_link *ltype = operandType (left);
+ sym_link *letype = getSpec (ltype);
+
+ resType = usualBinaryConversions (&left, &right);
+
+ /* if the right is a literal & power of 2 */
+ /* then make it a right shift */
+ if (IS_LITERAL (retype) &&
+ !IS_FLOAT (letype) &&
+ (p2 = powof2 ((unsigned long)
+ floatFromVal (right->operand.valOperand))))
+ ic = newiCode (RIGHT_OP, left, operandFromLit (p2)); /* right shift */
+ else
+ {
+ ic = newiCode ('/', left, right); /* normal division */
+ /* if the size left or right > 1 then support routine */
+ if (getSize (ltype) > 1 || getSize (rtype) > 1)
+ ic->supportRtn = 1;
+ }
+ IC_RESULT (ic) = newiTempOperand (resType, 0);
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+/*-----------------------------------------------------------------*/
+/* geniCodeModulus - gen intermediate code for modulus */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeModulus (operand * left, operand * right)
+{
+ iCode *ic;
+ sym_link *resType;
+ LRTYPE;
+
+ /* if they are both literal then we know the result */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype))
+ return operandFromValue (valMod (left->operand.valOperand,
+ right->operand.valOperand));
+
+ resType = usualBinaryConversions (&left, &right);
+
+ /* now they are the same size */
+ ic = newiCode ('%', left, right);
+
+ /* if the size left or right > 1 then support routine */
+ if (getSize (ltype) > 1 || getSize (rtype) > 1)
+ ic->supportRtn = 1;
+ IC_RESULT (ic) = newiTempOperand (resType, 0);
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodePtrPtrSubtract - subtracts pointer from pointer */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodePtrPtrSubtract (operand * left, operand * right)
+{
+ iCode *ic;
+ operand *result;
+ LRTYPE;
+
+ /* if they are both literals then */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype))
+ {
+ result = operandFromValue (valMinus (left->operand.valOperand,
+ right->operand.valOperand));
+ goto subtractExit;
+ }
+
+ ic = newiCode ('-', left, right);
+
+ IC_RESULT (ic) = result = newiTempOperand (newIntLink (), 1);
+ ADDTOCHAIN (ic);
+
+subtractExit:
+ return geniCodeDivision (result,
+ operandFromLit (getSize (ltype->next)));
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeSubtract - generates code for subtraction */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeSubtract (operand * left, operand * right)
+{
+ iCode *ic;
+ int isarray = 0;
+ sym_link *resType;
+ LRTYPE;
+
+ /* if they both pointers then */
+ if ((IS_PTR (ltype) || IS_ARRAY (ltype)) &&
+ (IS_PTR (rtype) || IS_ARRAY (rtype)))
+ return geniCodePtrPtrSubtract (left, right);
+
+ /* if they are both literal then we know the result */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype)
+ && left->isLiteral && right->isLiteral)
+ return operandFromValue (valMinus (left->operand.valOperand,
+ right->operand.valOperand));
+
+ /* if left is an array or pointer */
+ if (IS_PTR (ltype) || IS_ARRAY (ltype))
+ {
+ isarray = left->isaddr;
+ right = geniCodeMultiply (right,
+ operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+ resType = copyLinkChain (IS_ARRAY (ltype) ? ltype->next : ltype);
+ }
+ else
+ { /* make them the same size */
+ resType = usualBinaryConversions (&left, &right);
+ }
+
+ ic = newiCode ('-', left, right);
+
+ IC_RESULT (ic) = newiTempOperand (resType, 1);
+ IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
+
+ /* if left or right is a float */
+ if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+ ic->supportRtn = 1;
+
+ ADDTOCHAIN (ic);
+ return IC_RESULT (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeAdd - generates iCode for addition */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeAdd (operand * left, operand * right)
+{
+ iCode *ic;
+ sym_link *resType;
+ operand *size;
+ int isarray = 0;
+ LRTYPE;
+
+ /* if left is an array then array access */
+ if (IS_ARRAY (ltype))
+ return geniCodeArray (left, right);
+
+ /* if the right side is LITERAL zero */
+ /* return the left side */
+ if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
+ return left;
+
+ /* if left is literal zero return right */
+ if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
+ return right;
+
+ /* if left is an array or pointer then size */
+ if (IS_PTR (ltype))
+ {
+ isarray = left->isaddr;
+ // there is no need to multiply with 1
+ if (getSize(ltype->next)!=1) {
+ size = operandFromLit (getSize (ltype->next));
+ right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
+ }
+ resType = copyLinkChain (ltype);
+ }
+ else
+ { /* make them the same size */
+ resType = usualBinaryConversions (&left, &right);
+ }
+
+ /* if they are both literals then we know */
+ if (IS_LITERAL (letype) && IS_LITERAL (retype)
+ && left->isLiteral && right->isLiteral)
+ return operandFromValue (valPlus (valFromType (letype),
+ valFromType (retype)));
+
+ ic = newiCode ('+', left, right);
+
+ IC_RESULT (ic) = newiTempOperand (resType, 1);
+ IC_RESULT (ic)->isaddr = (isarray ? 1 : 0);
+
+ /* if left or right is a float then support
+ routine */
+ if (IS_FLOAT (ltype) || IS_FLOAT (rtype))
+ ic->supportRtn = 1;
+
+ ADDTOCHAIN (ic);
+
+ return IC_RESULT (ic);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* aggrToPtr - changes an aggregate to pointer to an aggregate */
+/*-----------------------------------------------------------------*/
+sym_link *
+aggrToPtr (sym_link * type, bool force)
+{
+ sym_link *etype;
+ sym_link *ptype;
+
+
+ if (IS_PTR (type) && !force)
+ return type;
+
+ etype = getSpec (type);
+ ptype = newLink ();
+
+ ptype->next = type;
+ /* if the output class is generic */
+ if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
+ DCL_PTR_CONST (ptype) = port->mem.code_ro;
+
+ /* if the variable was declared a constant */
+ /* then the pointer points to a constant */
+ if (IS_CONSTANT (etype))
+ DCL_PTR_CONST (ptype) = 1;
+
+ /* the variable was volatile then pointer to volatile */
+ if (IS_VOLATILE (etype))
+ DCL_PTR_VOLATILE (ptype) = 1;
+ return ptype;
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeArray2Ptr - array to pointer */
+/*-----------------------------------------------------------------*/
+operand *
+geniCodeArray2Ptr (operand * op)
+{
+ sym_link *optype = operandType (op);
+ sym_link *opetype = getSpec (optype);
+
+ /* set the pointer depending on the storage class */
+ if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
+ DCL_PTR_CONST (optype) = port->mem.code_ro;
+
+
+ /* if the variable was declared a constant */
+ /* then the pointer points to a constant */
+ if (IS_CONSTANT (opetype))
+ DCL_PTR_CONST (optype) = 1;
+
+ /* the variable was volatile then pointer to volatile */
+ if (IS_VOLATILE (opetype))
+ DCL_PTR_VOLATILE (optype) = 1;
+ op->isaddr = 0;
+ return op;
+}