PRINTFUNC (picInline);
PRINTFUNC (picReceive);
PRINTFUNC (picDummyRead);
+PRINTFUNC (picCritical);
+PRINTFUNC (picEndCritical);
iCodeTable codeTable[] =
{
{RECEIVE, "recv", picReceive, NULL},
{SEND, "send", picGenericOne, NULL},
{ARRAYINIT, "arrayInit", picGenericOne, NULL},
- {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
+ {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL},
+ {CRITICAL, "critical_start", picCritical, NULL},
+ {ENDCRITICAL, "critical_end", picEndCritical, NULL}
};
/*-----------------------------------------------------------------*/
fprintf (of, "\n");
}
+PRINTFUNC (picCritical)
+{
+ fprintf (of, "\t");
+ if (IC_RESULT (ic))
+ printOperand (IC_RESULT (ic), of);
+ else
+ fprintf (of, "(stack)");
+ fprintf (of, " = %s ", s);
+ fprintf (of, "\n");
+}
+
+PRINTFUNC (picEndCritical)
+{
+ fprintf (of, "\t");
+ fprintf (of, "%s = ", s);
+ if (IC_RIGHT (ic))
+ printOperand (IC_RIGHT (ic), of);
+ else
+ fprintf (of, "(stack)");
+ fprintf (of, "\n");
+}
+
/*-----------------------------------------------------------------*/
/* piCode - prints one iCode */
/*-----------------------------------------------------------------*/
return FALSE;
}
+/*-----------------------------------------------------------------*/
+/* isOclsExpensive - will return true if accesses to an output */
+/* storage class are expensive */
+/*-----------------------------------------------------------------*/
+bool
+isOclsExpensive (struct memmap *oclass)
+{
+ if (port->oclsExpense)
+ return port->oclsExpense (oclass) > 0;
+
+ /* In the absence of port specific guidance, assume only */
+ /* farspace is expensive. */
+ return IN_FARSPACE (oclass);
+}
+
/*-----------------------------------------------------------------*/
/* operandLitValue - literal value of an operand */
/*-----------------------------------------------------------------*/
(TYPE_UWORD) operandLitValue (right);
retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
- if (!options.lessPedantic &&
- ul != (TYPE_UWORD) ul)
+ if (ul != (TYPE_UWORD) ul)
werror (W_INT_OVL);
}
else /* signed int */
(TYPE_WORD) operandLitValue (right);
retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
- if (!options.lessPedantic &&
- l != (TYPE_WORD) l)
+ if (l != (TYPE_WORD) l)
werror (W_INT_OVL);
}
}
register equivalent for a local symbol */
if (sym->level && sym->etype && SPEC_OCLS (sym->etype) &&
(IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ !TARGET_IS_HC08 &&
(!(options.model == MODEL_FLAT24)) ) &&
options.stackAuto == 0)
ok = 0;
/* if this is not a temp symbol then */
if (!IS_ITEMP (op) &&
!force &&
- !IN_FARSPACE (SPEC_OCLS (etype)))
+ !(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08))
{
op = operandFromOperand (op);
op->isaddr = 0;
if (IS_SPEC (type) &&
IS_TRUE_SYMOP (op) &&
- (!IN_FARSPACE (SPEC_OCLS (etype)) ||
+ (!(IN_FARSPACE (SPEC_OCLS (etype)) && !TARGET_IS_HC08) ||
(options.model == MODEL_FLAT24) ))
{
op = operandFromOperand (op);
if (IS_VOID(ltype->next) || IS_VOID(rtype->next)) {
return result;
}
-
+
// should we really do this? is this ANSI?
return geniCodeDivision (result,
operandFromLit (getSize (ltype->next)));
/* if the right side is LITERAL zero */
/* return the left side */
- if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
+ if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (rtype)))
return left;
/* if left is literal zero return right */
- if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (letype)))
+ if (IS_LITERAL (letype) && left->isLiteral && !floatFromVal (valFromType (ltype)))
return right;
/* if left is a pointer then size */
/* 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)));
+ return operandFromValue (valPlus (valFromType (ltype),
+ valFromType (rtype)));
ic = newiCode ('+', left, right);
{
iCode *ic;
sym_link *ltype = operandType (left);
-
+
if (IS_PTR (ltype))
{
if (IS_PTR (ltype->next) && left->isaddr)
{
left = geniCodeRValue (left, FALSE);
}
+
return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
}
IC_RESULT (ic)->isaddr = (!IS_AGGREGATE (ltype->next));
ADDTOCHAIN (ic);
+
return IC_RESULT (ic);
}
/* geniCodePreInc - generate code for preIncrement */
/*-----------------------------------------------------------------*/
operand *
-geniCodePreInc (operand * op)
+geniCodePreInc (operand * op, bool lvalue)
{
iCode *ic;
sym_link *optype = operandType (op);
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
-
- return geniCodeAssign (op, result, 0);
+ (void) geniCodeAssign (op, result, 0);
+ if (lvalue || IS_TRUE_SYMOP (op))
+ return op;
+ else
+ return result;
}
/*-----------------------------------------------------------------*/
/* geniCodePreDec - generate code for pre decrement */
/*-----------------------------------------------------------------*/
operand *
-geniCodePreDec (operand * op)
+geniCodePreDec (operand * op, bool lvalue)
{
iCode *ic;
sym_link *optype = operandType (op);
IC_RESULT (ic) = result = newiTempOperand (roptype, 0);
ADDTOCHAIN (ic);
-
- return geniCodeAssign (op, result, 0);
+ (void) geniCodeAssign (op, result, 0);
+ if (lvalue || IS_TRUE_SYMOP (op))
+ return op;
+ else
+ return result;
}
sym_link *optype = operandType (op);
sym_link *opetype = getSpec (optype);
+ if (IS_ITEMP (op) && op->isaddr && IS_PTR (optype))
+ {
+ op = operandFromOperand (op);
+ op->isaddr = 0;
+ return op;
+ }
+
/* lvalue check already done in decorateType */
/* this must be a lvalue */
/* if (!op->isaddr && !IS_AGGREGATE(optype)) { */
else if (compareType (ltype, rtype) < 0)
right = geniCodeCast (ltype, right, TRUE);
- /* if left is a true symbol & ! volatile
+ /* If left is a true symbol & ! volatile
create an assignment to temporary for
the right & then assign this temporary
- to the symbol this is SSA . isn't it simple
- and folks have published mountains of paper on it */
+ to the symbol. This is SSA (static single
+ assignment). Isn't it simple and folks have
+ published mountains of paper on it */
if (IS_TRUE_SYMOP (left) &&
!isOperandVolatile (left, FALSE) &&
isOperandGlobal (left))
return left;
}
+/*-----------------------------------------------------------------*/
+/* geniCodeDummyRead - generate code for dummy read */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeDummyRead (operand * op)
+{
+ iCode *ic;
+ sym_link *type = operandType (op);
+
+ if (!IS_VOLATILE(type))
+ return;
+
+ ic = newiCode (DUMMY_READ_VOLATILE, NULL, op);
+ ADDTOCHAIN (ic);
+
+ ic->nosupdate = 1;
+}
+
/*-----------------------------------------------------------------*/
/* geniCodeSEParms - generate code for side effecting fcalls */
/*-----------------------------------------------------------------*/
if (!IS_FUNC(OP_SYMBOL(left)->type) &&
!IS_CODEPTR(OP_SYMBOL(left)->type)) {
werror (E_FUNCTION_EXPECTED);
- return NULL;
+ return operandFromValue(valueFromLit(0));
}
/* take care of parameters with side-effecting
if (!sym->addrtaken && !IS_VOLATILE (sym->etype))
{
- if (IN_FARSPACE (SPEC_OCLS (sym->etype)) &&
+ if ((IN_FARSPACE (SPEC_OCLS (sym->etype)) && !TARGET_IS_HC08) &&
options.stackAuto == 0 &&
(!(options.model == MODEL_FLAT24)) )
{
}
ADDTOCHAIN (ic);
}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeCritical - intermediate code for a critical statement */
+/*-----------------------------------------------------------------*/
+static void
+geniCodeCritical (ast *tree, int lvl)
+{
+ iCode *ic;
+ operand *op = NULL;
+
+ /* If op is NULL, the original interrupt state will saved on */
+ /* the stack. Otherwise, it will be saved in op. */
+
+ /* Generate a save of the current interrupt state & disabled */
+ ic = newiCode (CRITICAL, NULL, NULL);
+ IC_RESULT (ic) = op;
+ ADDTOCHAIN (ic);
+
+ /* Generate the critical code sequence */
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+
+ /* Generate a restore of the original interrupt state */
+ ic = newiCode (ENDCRITICAL, NULL, op);
+ ADDTOCHAIN (ic);
+}
/*-----------------------------------------------------------------*/
/* Stuff used in ast2iCode to modify geniCodeDerefPtr in some */
(tree->opval.op == NULLOP ||
tree->opval.op == BLOCK))
{
- ast2iCode (tree->left,lvl+1);
- ast2iCode (tree->right,lvl+1);
+ if (tree->left && tree->left->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->left,lvl+1));
+ else
+ ast2iCode (tree->left,lvl+1);
+ if (tree->right && tree->right->type == EX_VALUE)
+ geniCodeDummyRead (ast2iCode (tree->right,lvl+1));
+ else
+ ast2iCode (tree->right,lvl+1);
return NULL;
}
tree->opval.op != GOTO &&
tree->opval.op != SWITCH &&
tree->opval.op != FUNCTION &&
- tree->opval.op != INLINEASM)
+ tree->opval.op != INLINEASM &&
+ tree->opval.op != CRITICAL)
{
if (IS_ASSIGN_OP (tree->opval.op) ||
if (left)
return geniCodePostInc (left);
else
- return geniCodePreInc (right);
+ return geniCodePreInc (right, tree->lvalue);
case DEC_OP: /* decrement operator */
if (left)
return geniCodePostDec (left);
else
- return geniCodePreDec (right);
+ return geniCodePreDec (right, tree->lvalue);
case '&': /* bitwise and or address of operator */
if (right)
return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
case '-':
- if (right)
+ if (right)
return geniCodeSubtract (geniCodeRValue (left, FALSE),
geniCodeRValue (right, FALSE));
else
case '~':
case RRC:
case RLC:
+ case SWAP:
return geniCodeUnary (geniCodeRValue (left, FALSE), tree->opval.op);
case '!':
case ARRAYINIT:
geniCodeArrayInit(tree, ast2iCode (tree->left,lvl+1));
return NULL;
+
+ case CRITICAL:
+ geniCodeCritical (tree, lvl);
}
return NULL;