left = IC_LEFT (ic);
right = IC_RIGHT (ic);
- switch (ic->op)
- {
- case '+':
- func = __fsadd;
- break;
- case '-':
- func = __fssub;
- break;
- case '/':
- func = __fsdiv;
- break;
- case '*':
- func = __fsmul;
- break;
- case EQ_OP:
- func = __fseq;
- break;
- case NE_OP:
- func = __fsneq;
- break;
- case '<':
- func = __fslt;
- break;
- case '>':
- func = __fsgt;
- break;
- case LE_OP:
- func = __fslteq;
- break;
- case GE_OP:
- func = __fsgteq;
- break;
- }
+ if(IS_FLOAT(operandType( IC_RIGHT( ic ) ))) {
+ switch (ic->op)
+ {
+ case '+':
+ func = __fsadd;
+ break;
+ case '-':
+ func = __fssub;
+ break;
+ case '/':
+ func = __fsdiv;
+ break;
+ case '*':
+ func = __fsmul;
+ break;
+ case EQ_OP:
+ func = __fseq;
+ break;
+ case NE_OP:
+ func = __fsneq;
+ break;
+ case '<':
+ func = __fslt;
+ break;
+ case '>':
+ func = __fsgt;
+ break;
+ case LE_OP:
+ func = __fslteq;
+ break;
+ case GE_OP:
+ func = __fsgteq;
+ break;
+ }
+ } else
+ if(IS_FIXED16X16 (operandType (IC_RIGHT(ic)))) {
+ switch (ic->op)
+ {
+ case '+':
+ func = __fps16x16_add;
+ break;
+ case '-':
+ func = __fps16x16_sub;
+ break;
+ case '/':
+ func = __fps16x16_div;
+ break;
+ case '*':
+ func = __fps16x16_mul;
+ break;
+ case EQ_OP:
+ func = __fps16x16_eq;
+ break;
+ case NE_OP:
+ func = __fps16x16_neq;
+ break;
+ case '<':
+ func = __fps16x16_lt;
+ break;
+ case '>':
+ func = __fps16x16_gt;
+ break;
+ case LE_OP:
+ func = __fps16x16_lteq;
+ break;
+ case GE_OP:
+ func = __fps16x16_gteq;
+ break;
+ }
+ }
+
/* if float support routines NOT compiled as reentrant */
if (!options.float_rent)
}
}
}
+
+ if(compareType (type, fixed16x16Type) == 1) {
+ func = __fp16x16conv[0][3][0];
+ goto found;
+ }
+
+ assert (0);
+found:
+
+ /* if float support routines NOT compiled as reentrant */
+ if (!options.float_rent)
+ {
+ /* first one */
+ if (IS_REGPARM (FUNC_ARGS(func->type)->etype))
+ {
+ newic = newiCode (SEND, IC_RIGHT (ic), NULL);
+ newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
+ }
+ else
+ {
+ newic = newiCode ('=', NULL, IC_RIGHT (ic));
+ IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
+ }
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = linenno;
+
+ }
+ else
+ {
+ /* push the left */
+ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
+ newic = newiCode (SEND, IC_RIGHT (ic), NULL);
+ newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
+ }
+ else
+ {
+ newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
+ newic->parmPush = 1;
+ bytesPushed += getSize(operandType(IC_RIGHT(ic)));
+ }
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = linenno;
+
+ }
+
+ /* make the call */
+ newic = newiCode (CALL, operandFromSymbol (func), NULL);
+ IC_RESULT (newic) = IC_RESULT (ic);
+ newic->parmBytes+=bytesPushed;
+ ebp->hasFcall = 1;
+ if (currFunc)
+ FUNC_HASFCALL (currFunc->type) = 1;
+
+ if(TARGET_IS_PIC16) {
+ /* normally these functions aren't marked external, so we can use their
+ * _extern field to marked as already added to symbol table */
+
+ if(!SPEC_EXTR(func->etype)) {
+ memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+
+ SPEC_EXTR(func->etype) = 1;
+ seg = SPEC_OCLS( func->etype );
+ addSet(&seg->syms, func);
+ }
+ }
+
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = linenno;
+}
+
+/*----------------------------------------------------------------------*/
+/* cnvToFixed16x16Cast - converts casts to fixed16x16 to function calls */
+/*----------------------------------------------------------------------*/
+static void
+cnvToFixed16x16Cast (iCode * ic, eBBlock * ebp)
+{
+ iCode *ip, *newic;
+ symbol *func = NULL;
+ sym_link *type = operandType (IC_RIGHT (ic));
+ int linenno = ic->lineno;
+ int bwd, su;
+ int bytesPushed=0;
+
+ ip = ic->next;
+ /* remove it from the iCode */
+ remiCodeFromeBBlock (ebp, ic);
+ /* depending on the type */
+ for (bwd = 0; bwd < 3; bwd++)
+ {
+ for (su = 0; su < 2; su++)
+ {
+ if (compareType (type, __multypes[bwd][su]) == 1)
+ {
+ func = __fp16x16conv[0][bwd][su];
+ goto found;
+ }
+ }
+ }
assert (0);
found:
newic->lineno = lineno;
}
+/*--------------------------------------------------------------------------*/
+/* cnvFromFixed16x16Cast - converts casts from fixed16x16 to function calls */
+/*--------------------------------------------------------------------------*/
+static void
+cnvFromFixed16x16Cast (iCode * ic, eBBlock * ebp)
+{
+ iCode *ip, *newic;
+ symbol *func = NULL;
+ sym_link *type = operandType (IC_LEFT (ic));
+ int lineno = ic->lineno;
+ int bwd, su;
+ int bytesPushed=0;
+
+ ip = ic->next;
+ /* remove it from the iCode */
+ remiCodeFromeBBlock (ebp, ic);
+
+ /* depending on the type */
+ for (bwd = 0; bwd < 3; bwd++)
+ {
+ for (su = 0; su < 2; su++)
+ {
+ if (compareType (type, __multypes[bwd][su]) == 1)
+ {
+ func = __fp16x16conv[1][bwd][su];
+ goto found;
+ }
+ }
+ }
+
+ if (compareType (type, floatType) == 1)
+ {
+ func = __fp16x16conv[1][3][0];
+ goto found;
+ }
+
+ assert (0);
+found:
+
+ /* if float support routines NOT compiled as reentrant */
+ if (!options.float_rent)
+ {
+ /* first one */
+ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
+ newic = newiCode (SEND, IC_RIGHT (ic), NULL);
+ newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
+ }
+ else
+ {
+ newic = newiCode ('=', NULL, IC_RIGHT (ic));
+ IC_RESULT (newic) = operandFromValue (FUNC_ARGS(func->type));
+ }
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = lineno;
+
+ }
+ else
+ {
+
+ /* push the left */
+ if (IS_REGPARM (FUNC_ARGS(func->type)->etype)) {
+ newic = newiCode (SEND, IC_RIGHT (ic), NULL);
+ newic->argreg = SPEC_ARGREG(FUNC_ARGS(func->type)->etype);
+ }
+ else
+ {
+ newic = newiCode (IPUSH, IC_RIGHT (ic), NULL);
+ newic->parmPush = 1;
+ bytesPushed += getSize(operandType(IC_RIGHT(ic)));
+ }
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = lineno;
+
+ }
+
+ /* make the call */
+ newic = newiCode (CALL, operandFromSymbol (func), NULL);
+ IC_RESULT (newic) = IC_RESULT (ic);
+ newic->parmBytes+=bytesPushed;
+ ebp->hasFcall = 1;
+ if (currFunc)
+ FUNC_HASFCALL (currFunc->type) = 1;
+
+ if(TARGET_IS_PIC16) {
+ /* normally these functions aren't marked external, so we can use their
+ * _extern field to marked as already added to symbol table */
+
+ if(!SPEC_EXTR(func->etype)) {
+ memmap *seg = SPEC_OCLS(OP_SYMBOL(IC_LEFT(newic))->etype);
+
+ SPEC_EXTR(func->etype) = 1;
+ seg = SPEC_OCLS( func->etype );
+ addSet(&seg->syms, func);
+ }
+ }
+
+ addiCodeToeBBlock (ebp, newic, ip);
+ newic->lineno = lineno;
+}
+
extern operand *geniCodeRValue (operand *, bool);
/*-----------------------------------------------------------------*/
converted to function calls */
if ((IS_CONDITIONAL (ic) ||
IS_ARITHMETIC_OP (ic)) &&
- (IS_FLOAT (operandType (IC_RIGHT (ic)))))
+ (IS_FLOAT (operandType (IC_RIGHT (ic)))
+ || IS_FIXED( operandType (IC_RIGHT (ic)))))
{
cnvToFcall (ic, ebbs[i]);
cnvFromFloatCast (ic, ebbs[i]);
else if (IS_FLOAT (operandType (IC_LEFT (ic))))
cnvToFloatCast (ic, ebbs[i]);
+ if (IS_FIXED16X16 (operandType (IC_RIGHT (ic))))
+ cnvFromFixed16x16Cast (ic, ebbs[i]);
+ else if (IS_FIXED16X16 (operandType (IC_LEFT (ic))))
+ cnvToFixed16x16Cast (ic, ebbs[i]);
}
// Easy special case which avoids function call: modulo by a literal power
if (ic->op == '%' && isOperandLiteral(IC_RIGHT(ic)) &&
IS_UNSIGNED(operandType(IC_LEFT(ic))))
{
- unsigned litVal = abs(operandLitValue(IC_RIGHT(ic)));
+ unsigned litVal = fabs(operandLitValue(IC_RIGHT(ic)));
+ /* modulo by 1: no remainder */
+ if (litVal == 1)
+ {
+ ic->op = '=';
+ IC_RIGHT (ic) = operandFromLit(0);
+ IC_LEFT (ic) = NULL;
+ continue;
+ }
// See if literal value is a power of 2.
while (litVal && !(litVal & 1))
{
/* replaceRegEqv - replace all local variables with their reqv */
/*-----------------------------------------------------------------*/
static void
-replaceRegEqv (eBBlock ** ebbs, int count)
+replaceRegEqv (ebbIndex * ebbi)
{
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
int i;
/* Update the symbols' def bitvector so we know if there is */
/* a defining iCode or not. Only replace a local variable */
/* with its register equivalent if there is a defining iCode; */
/* otherwise, the port's register allocater may choke. */
- cseAllBlocks (ebbs, count, TRUE);
+ cseAllBlocks (ebbi, TRUE);
for (i = 0; i < count; i++)
{
/* killDeadCode - eliminates dead assignments */
/*-----------------------------------------------------------------*/
int
-killDeadCode (eBBlock ** ebbs, int count)
+killDeadCode (ebbIndex * ebbi)
{
+ eBBlock ** ebbs = ebbi->dfOrder;
+ int count = ebbi->count;
int change = 1;
int gchange = 0;
int i = 0;
if (IC_RESULT (ic) && isOperandVolatile (IC_RESULT (ic), FALSE))
continue;
- /* We also cannot remove the iCode, when an operand is volatile. */
- /* Even read access can cause side effects on some hardware registers! */
-
- /* if the left operand is volatile then continue */
- if (IC_LEFT(ic) && isOperandVolatile (IC_LEFT (ic), TRUE))
- continue;
-
- /* if the right operand is volatile then continue */
- if (IC_RIGHT(ic) && isOperandVolatile (IC_RIGHT (ic), TRUE))
- continue;
-
-
/* if the result is a temp & isaddr then skip */
if (IC_RESULT (ic) && POINTER_SET (ic))
continue;
/* a dead address-of operation should die, even if volatile */
if (ic->op == ADDRESS_OF)
volLeft = FALSE;
-
+
if (ic->next && ic->seqPoint == ic->next->seqPoint
&& (ic->next->op == '+' || ic->next->op == '-'))
{
}
continue;
}
-
+
change = 1;
gchange++;
symbol * resultsym = OP_SYMBOL (IC_RESULT (ic));
symbol * prereqv = resultsym->prereqv;
- if (OP_SYMBOL (prereqv->reqv) == resultsym)
+ if (prereqv && prereqv->reqv && (OP_SYMBOL (prereqv->reqv) == resultsym))
{
operand * newreqv;
} /* end of all instructions */
if (!ebbs[i]->sch && !ebbs[i]->noPath)
- disconBBlock (ebbs[i], ebbs, count);
+ disconBBlock (ebbs[i], ebbi);
} /* end of for all blocks */
eBBlock **
eBBlockFromiCode (iCode * ic)
{
- eBBlock **ebbs = NULL;
- int count = 0;
- int saveCount = 0;
+ ebbIndex *ebbi = NULL;
int change = 1;
int lchange = 0;
int kchange = 0;
if (!ic)
return NULL;
- count = 0;
eBBNum = 0;
/* optimize the chain for labels & gotos
ic = iCodeLabelOptimize (ic);
/* break it down into basic blocks */
- ebbs = iCodeBreakDown (ic, &count);
- saveCount = count;
-
+ ebbi = iCodeBreakDown (ic);
+
/* hash the iCode keys so that we can quickly index */
/* them in the rest of the optimization steps */
setToNull ((void *) &iCodehTab);
iCodehTab = newHashTable (iCodeKey);
- hashiCodeKeys (ebbs, count);
+ hashiCodeKeys (ebbi->bbOrder, ebbi->count);
/* compute the control flow */
- computeControlFlow (ebbs, count, 0);
+ computeControlFlow (ebbi);
/* dumpraw if asked for */
if (options.dump_raw)
- dumpEbbsToFileExt (DUMP_RAW0, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RAW0, ebbi);
/* replace the local variables with their
register equivalents : the liveRange computation
along with the register allocation will determine
if it finally stays in the registers */
- replaceRegEqv (ebbs, count);
+ replaceRegEqv (ebbi);
/* create loop regions */
- loops = createLoopRegions (ebbs, count);
+ loops = createLoopRegions (ebbi);
/* dumpraw if asked for */
if (options.dump_raw)
- dumpEbbsToFileExt (DUMP_RAW1, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RAW1, ebbi);
- optimizeCastCast (ebbs, saveCount);
+ optimizeCastCast (ebbi->bbOrder, ebbi->count);
/* do common subexpression elimination for each block */
- change = cseAllBlocks (ebbs, saveCount, FALSE);
+ change = cseAllBlocks (ebbi, FALSE);
/* dumpraw if asked for */
if (options.dump_raw)
- dumpEbbsToFileExt (DUMP_CSE, ebbs, count);
+ dumpEbbsToFileExt (DUMP_CSE, ebbi);
/* compute the data flow */
- computeDataFlow (ebbs, saveCount);
+ computeDataFlow (ebbi);
/* dumpraw if asked for */
if (options.dump_raw)
- dumpEbbsToFileExt (DUMP_DFLOW, ebbs, count);
+ dumpEbbsToFileExt (DUMP_DFLOW, ebbi);
/* global common subexpression elimination */
if (optimize.global_cse)
{
- change += cseAllBlocks (ebbs, saveCount, FALSE);
+ change += cseAllBlocks (ebbi, FALSE);
if (options.dump_gcse)
- dumpEbbsToFileExt (DUMP_GCSE, ebbs, saveCount);
+ dumpEbbsToFileExt (DUMP_GCSE, ebbi);
}
else
{
// compute the dataflow only
- assert(cseAllBlocks (ebbs, saveCount, TRUE)==0);
+ assert(cseAllBlocks (ebbi, TRUE)==0);
}
/* kill dead code */
- kchange = killDeadCode (ebbs, saveCount);
+ kchange = killDeadCode (ebbi);
if (options.dump_kill)
- dumpEbbsToFileExt (DUMP_DEADCODE, ebbs, count);
+ dumpEbbsToFileExt (DUMP_DEADCODE, ebbi);
/* do loop optimizations */
- change += (lchange = loopOptimizations (loops, ebbs, count));
+ change += (lchange = loopOptimizations (loops, ebbi));
if (options.dump_loop)
- dumpEbbsToFileExt (DUMP_LOOP, ebbs, count);
+ dumpEbbsToFileExt (DUMP_LOOP, ebbi);
/* recompute the data flow and apply global cse again
if loops optimizations or dead code caused a change:
subexpression once more */
if (lchange || kchange)
{
- computeDataFlow (ebbs, saveCount);
- change += cseAllBlocks (ebbs, saveCount, FALSE);
+ computeDataFlow (ebbi);
+ change += cseAllBlocks (ebbi, FALSE);
if (options.dump_loop)
- dumpEbbsToFileExt (DUMP_LOOPG, ebbs, count);
+ dumpEbbsToFileExt (DUMP_LOOPG, ebbi);
/* if loop optimizations caused a change then do
dead code elimination once more : this will
get rid of the extra assignments to the induction
variables created during loop optimizations */
- killDeadCode (ebbs, saveCount);
+ killDeadCode (ebbi);
if (options.dump_loop)
- dumpEbbsToFileExt (DUMP_LOOPD, ebbs, count);
+ dumpEbbsToFileExt (DUMP_LOOPD, ebbi);
}
/* sort it back by block number */
- qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
+ //qsort (ebbs, saveCount, sizeof (eBBlock *), bbNumCompare);
if (!options.lessPedantic) {
// this is a good place to check missing return values
&& !FUNC_ISNAKED(currFunc->type)) {
eBBlock *bp;
// make sure all predecessors of the last block end in a return
- for (bp=setFirstItem(ebbs[saveCount-1]->predList);
+ for (bp=setFirstItem(ebbi->bbOrder[ebbi->count-1]->predList);
bp;
- bp=setNextItem(ebbs[saveCount-1]->predList)) {
+ bp=setNextItem(ebbi->bbOrder[ebbi->count-1]->predList)) {
if (bp->ech->op != RETURN) {
werrorfl (bp->ech->filename, bp->ech->lineno,
W_VOID_FUNC, currFunc->name);
/* if cyclomatic info requested then print it */
if (options.cyclomatic)
- printCyclomatic (ebbs, saveCount);
+ printCyclomatic (ebbi->bbOrder, ebbi->count);
/* convert operations with support routines
written in C to function calls : Iam doing
this at this point since I want all the
operations to be as they are for optimzations */
- convertToFcall (ebbs, count);
+ convertToFcall (ebbi->bbOrder, ebbi->count);
/* compute the live ranges */
- computeLiveRanges (ebbs, count);
+ computeLiveRanges (ebbi->bbOrder, ebbi->count);
if (options.dump_range)
- dumpEbbsToFileExt (DUMP_RANGE, ebbs, count);
+ dumpEbbsToFileExt (DUMP_RANGE, ebbi);
/* Now that we have the live ranges, discard parameter
* receives for unused parameters.
*/
- discardDeadParamReceives (ebbs, count);
+ discardDeadParamReceives (ebbi->bbOrder, ebbi->count);
/* allocate registers & generate code */
- port->assignRegisters (ebbs, count);
+ port->assignRegisters (ebbi);
/* throw away blocks */
setToNull ((void *) &graphEdges);
- ebbs = NULL;
return NULL;
}