X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fmcs51%2Fpeep.c;h=c0dcb01652fd568c2e3ab369eb94839690878cfe;hb=5a1d5e778e85664f4e6657019348b4756b16eacb;hp=872dded4c587274b8ad5e31274e45c073aaad6cb;hpb=084dd312234f8d66846225c1ec5c49f32a61fb91;p=fw%2Fsdcc diff --git a/src/mcs51/peep.c b/src/mcs51/peep.c index 872dded4..c0dcb016 100644 --- a/src/mcs51/peep.c +++ b/src/mcs51/peep.c @@ -26,7 +26,7 @@ #include "ralloc.h" #define D(x) x -#define DEADMOVEERROR "SDCC internal error: deadmove in " __FILE__" line %d\n", __LINE__ +#define DEADMOVEERROR() do {werror(E_INTERNAL_ERROR, __FILE__, __LINE__, "error in deadmove");} while(0) typedef enum { @@ -37,7 +37,8 @@ typedef enum S4O_RD_OP, S4O_TERM, S4O_VISITED, - S4O_ABORT + S4O_ABORT, + S4O_CONTINUE } S4O_RET; static struct @@ -176,7 +177,7 @@ findLabel (const lineNode *pl) /* sanity check */ if (p == pl->line) { - D(fprintf (stderr, DEADMOVEERROR);) + DEADMOVEERROR(); return NULL; } @@ -215,17 +216,34 @@ isFunc (const lineNode *pl) } /*-----------------------------------------------------------------*/ -/* isCallerSaveFunc - returns TRUE if it's a 'normal' function */ -/* call and it's a 'caller save' (not 'callee save') */ +/* termScanAtFunc - returns S4O_TERM if it's a 'normal' function */ +/* call and it's a 'caller save'. returns S4O_CONTINUE if it's */ +/* 'callee save' or 'naked'. returns S4O_ABORT if it's 'banked' */ +/* uses the register for the destination. */ /*-----------------------------------------------------------------*/ -static bool -isCallerSaveFunc (const lineNode *pl) +static S4O_RET +termScanAtFunc (const lineNode *pl, int rIdx) { + sym_link *ftype; + if (!isFunc (pl)) - return FALSE; - if (FUNC_CALLEESAVES(OP_SYM_TYPE(IC_LEFT(pl->ic)))) - return FALSE; - return TRUE; + return S4O_CONTINUE; + // let's assume calls to literally given locations use the default + // most notably : (*(void (*)()) 0) (); see bug 1749275 + if (IS_VALOP (IC_LEFT (pl->ic))) + return !options.all_callee_saves; + + ftype = OP_SYM_TYPE(IC_LEFT(pl->ic)); + if (IS_FUNCPTR (ftype)) + ftype = ftype->next; + if (FUNC_CALLEESAVES(ftype)) + return S4O_CONTINUE; + if (FUNC_ISNAKED(ftype)) + return S4O_CONTINUE; + if (FUNC_BANKED(ftype) && + ((rIdx == R0_IDX) || (rIdx == R1_IDX) || (rIdx == R2_IDX))) + return S4O_ABORT; + return S4O_TERM; } /*-----------------------------------------------------------------*/ @@ -273,10 +291,24 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, char *p; int len; bool isConditionalJump; + int rIdx; + S4O_RET ret; /* pReg points to e.g. "ar0"..."ar7" */ len = strlen (pReg); + /* get index into pReg table */ + for (rIdx = 0; rIdx < mcs51_nRegs; ++rIdx) + if (strcmp (regs8051[rIdx].name, pReg + 1) == 0) + break; + + /* sanity check */ + if (rIdx >= mcs51_nRegs) + { + DEADMOVEERROR(); + return S4O_ABORT; + } + for (; *pl; *pl = (*pl)->next) { if (!(*pl)->line || (*pl)->isDebug || (*pl)->isComment) @@ -316,20 +348,6 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, { /* ok, let's have a closer look */ - /* get index into pReg table */ - int rIdx; - - for (rIdx = 0; rIdx < mcs51_nRegs; ++rIdx) - if (strcmp (regs8051[rIdx].name, pReg + 1) == 0) - break; - - /* sanity check */ - if (rIdx >= mcs51_nRegs) - { - D(fprintf (stderr, DEADMOVEERROR);) - return S4O_ABORT; - } - /* does opcode read from pReg? */ if (bitVectBitValue (port->peep.getRegsRead ((*pl)), rIdx)) return S4O_RD_OP; @@ -356,7 +374,7 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, /* register passing this label */ if (!setLabelRefPassedLabel (label)) { - D(fprintf (stderr, DEADMOVEERROR);) + DEADMOVEERROR(); return S4O_ABORT; } continue; @@ -370,8 +388,9 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, if (strncmp ("acall", (*pl)->line, 5) == 0) { /* for comments see 'lcall' */ - if (isCallerSaveFunc (*pl)) - return S4O_TERM; + ret = termScanAtFunc (*pl, rIdx); + if (ret != S4O_CONTINUE) + return ret; break; } if (strncmp ("ajmp", (*pl)->line, 4) == 0) @@ -418,20 +437,21 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, case 'l': if (strncmp ("lcall", (*pl)->line, 5) == 0) { - if (isCallerSaveFunc (*pl)) - { - /* If it's a 'normal' 'caller save' function call, all - registers have been saved until the 'lcall'. The - 'life range' of all registers end at the lcall, - and we can terminate our search. - */ - return S4O_TERM; - } - /* If it's a 'callee save' function call, registers are saved + ret = termScanAtFunc (*pl, rIdx); + /* If it's a 'normal' 'caller save' function call, all + registers have been saved until the 'lcall'. The + 'life range' of all registers end at the lcall, + and we can terminate our search. + * If the function is 'banked', the registers r0, r1 and r2 + are used to tell the trampoline the destination. After + that their 'life range' ends just like the other registers. + * If it's a 'callee save' function call, registers are saved by the callee. We've got no information, if the register might live beyond the lcall. Therefore we've to continue the search. */ + if (ret != S4O_CONTINUE) + return ret; break; } if (strncmp ("ljmp", (*pl)->line, 4) == 0) @@ -456,8 +476,9 @@ scan4op (lineNode **pl, const char *pReg, const char *untilOp, if (isFunc (*pl)) { /* for comments see 'lcall' */ - if (isCallerSaveFunc (*pl)) - return S4O_TERM; + ret = termScanAtFunc (*pl, rIdx); + if (ret != S4O_CONTINUE) + return ret; break; } @@ -508,7 +529,7 @@ doPushScan (lineNode **pl, const char *pReg) case S4O_VISITED: if (!pushPl) { - D(fprintf (stderr, DEADMOVEERROR);) + DEADMOVEERROR(); return FALSE; } *pl = pushPl;