+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)) */
+ (options.model == MODEL_FLAT24) ))
+ {
+ 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); */
+
+ 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;
+ int errors=0;
+
+ /* 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 (compareType (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/from pointers, do some checking */
+ if (IS_PTR(type)) { // to a pointer
+ if (!IS_PTR(optype) && !IS_FUNC(optype) && !IS_AGGREGATE(optype)) { // from a non pointer
+ if (IS_INTEGRAL(optype)) {
+ // maybe this is NULL, than it's ok.
+ if (!(IS_LITERAL(optype) && (SPEC_CVAL(optype).v_ulong ==0))) {
+ if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80 && IS_GENPTR(type)) {
+ // no way to set the storage
+ if (IS_LITERAL(optype)) {
+ werror(E_LITERAL_GENERIC);
+ errors++;
+ } else {
+ werror(E_NONPTR2_GENPTR);
+ errors++;
+ }
+ } else if (implicit) {
+ werror(W_INTEGRAL2PTR_NOCAST);
+ errors++;
+ }
+ }
+ } else {
+ // shouldn't do that with float, array or structure unless to void
+ if (!IS_VOID(getSpec(type)) &&
+ !(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
+ }
+ } else { // from a pointer to a pointer
+ if (!TARGET_IS_Z80 && !TARGET_IS_GBZ80) {
+ // if not a pointer to a function
+ if (!(IS_CODEPTR(type) && IS_FUNC(type->next) && IS_FUNC(optype))) {
+ if (implicit) { // if not to generic, they have to match
+ if ((!IS_GENPTR(type) && (DCL_TYPE(optype) != DCL_TYPE(type)))) {
+ werror(E_INCOMPAT_PTYPES);
+ errors++;
+ }
+ }
+ }
+ }
+ }
+ } else { // to a non pointer
+ if (IS_PTR(optype)) { // from a pointer
+ if (implicit) { // sneaky
+ if (IS_INTEGRAL(type)) {
+ werror(W_PTR2INTEGRAL_NOCAST);
+ errors++;
+ } else { // shouldn't do that with float, array or structure
+ werror(E_INCOMPAT_TYPES);
+ errors++;
+ }
+ }
+ }
+ }
+ if (errors) {
+ printFromToType (optype, type);
+ }
+
+ /* 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;
+ 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 (IS_LITERAL(retype)) {
+ p2 = powof2 ((unsigned long) floatFromVal (right->operand.valOperand));
+ }
+
+ resType = usualBinaryConversions (&left, &right);
+#if 1
+ rtype = operandType (right);
+ retype = getSpec (rtype);
+ ltype = operandType (left);
+ letype = getSpec (ltype);
+#endif
+ if (resultIsInt)
+ {
+ SPEC_NOUN(getSpec(resType))=V_INT;
+ }
+
+ /* 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 has 1 byte muldiv */
+ if (p2 && !IS_FLOAT (letype) &&
+ !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
+ (port->support.muldiv == 1)))
+ {
+ 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);