From: pjs Date: Thu, 27 Mar 2003 21:18:38 +0000 (+0000) Subject: Accurate byte measurement for pcDistance (peephole LJMP -> SJMP) X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=858ccfbd6129f94e03203c955adeca65062a7b96;p=fw%2Fsdcc Accurate byte measurement for pcDistance (peephole LJMP -> SJMP) git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2422 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/ChangeLog b/ChangeLog index b433a159..722dc3df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2003-03-27 Paul Stoffregen + + * src/SDCCpeeph.c (pcDistance): accurate byte distance for mcs51 + 2003-03-26 * src/mcs51/gen.c (saveRegisters): catched symbol abuse diff --git a/src/SDCCpeeph.c b/src/SDCCpeeph.c index 37e349c6..13eadb79 100644 --- a/src/SDCCpeeph.c +++ b/src/SDCCpeeph.c @@ -59,6 +59,115 @@ void peepRules2pCode(peepRule *); /*-----------------------------------------------------------------*/ /* pcDistance - afinds a label back ward or forward */ /*-----------------------------------------------------------------*/ +int +mcs51_instruction_size(const char *inst) +{ + char *op, op1[256], op2[256]; + int opsize; + const char *p; + + while (*inst && isspace(*inst)) inst++; + + #define ISINST(s) (strncmp(inst, (s), sizeof(s)-1) == 0) + if (ISINST("lcall")) return 3; + if (ISINST("ret")) return 1; + if (ISINST("ljmp")) return 3; + if (ISINST("sjmp")) return 2; + if (ISINST("rlc")) return 1; + if (ISINST("rrc")) return 1; + if (ISINST("rl")) return 1; + if (ISINST("rr")) return 1; + if (ISINST("swap")) return 1; + if (ISINST("movx")) return 1; + if (ISINST("movc")) return 1; + if (ISINST("push")) return 2; + if (ISINST("pop")) return 2; + if (ISINST("jc")) return 2; + if (ISINST("jnc")) return 2; + if (ISINST("jb")) return 3; + if (ISINST("jnb")) return 3; + if (ISINST("jbc")) return 3; + if (ISINST("jmp")) return 1; // always jmp @a+dptr + if (ISINST("jz")) return 2; + if (ISINST("jnz")) return 2; + if (ISINST("cjne")) return 3; + if (ISINST("mul")) return 1; + if (ISINST("div")) return 1; + if (ISINST("da")) return 1; + if (ISINST("xchd")) return 1; + if (ISINST("reti")) return 1; + if (ISINST("nop")) return 1; + if (ISINST("acall")) return 1; + if (ISINST("ajmp")) return 2; + + p = inst; + while (*p && isalnum(*p)) p++; + for (op = op1, opsize=0; *p && *p != ',' && opsize < sizeof(op1); p++) { + if (!isspace(*p)) *op++ = *p, opsize++; + } + *op = '\0'; + if (*p == ',') p++; + for (op = op2, opsize=0; *p && *p != ',' && opsize < sizeof(op2); p++) { + if (!isspace(*p)) *op++ = *p, opsize++; + } + *op = '\0'; + + #define IS_A(s) (*(s) == 'a' && *(s+1) == '\0') + #define IS_C(s) (*(s) == 'c' && *(s+1) == '\0') + #define IS_Rn(s) (*(s) == 'r' && *(s+1) >= '0' && *(s+1) <= '7') + #define IS_atRi(s) (*(s) == '@' && *(s+1) == 'r') + + if (ISINST("mov")) { + if (IS_C(op1) || IS_C(op2)) return 2; + if (IS_A(op1)) { + if (IS_Rn(op2) || IS_atRi(op2)) return 1; + return 2; + } + if (IS_Rn(op1) || IS_atRi(op1)) { + if (IS_A(op2)) return 1; + return 2; + } + if (strcmp(op1, "dptr") == 0) return 3; + if (IS_A(op2) || IS_Rn(op2) || IS_atRi(op2)) return 2; + return 3; + } + if (ISINST("add") || ISINST("addc") || ISINST("subb") || ISINST("xch")) { + if (IS_Rn(op2) || IS_atRi(op2)) return 1; + return 2; + } + if (ISINST("inc") || ISINST("dec")) { + if (IS_A(op1) || IS_Rn(op1) || IS_atRi(op1)) return 1; + if (strcmp(op1, "dptr") == 0) return 1; + return 2; + } + if (ISINST("anl") || ISINST("orl") || ISINST("xrl")) { + if (IS_C(op1)) return 2; + if (IS_A(op1)) { + if (IS_Rn(op2) || IS_atRi(op2)) return 1; + return 2; + } else { + if (IS_A(op2)) return 2; + return 3; + } + } + if (ISINST("clr") || ISINST("setb") || ISINST("cpl")) { + if (IS_A(op1) || IS_C(op1)) return 1; + return 2; + } + if (ISINST("djnz")) { + if (IS_Rn(op1)) return 2; + return 3; + } + + if (*inst == 'a' && *(inst+1) == 'r' && *(inst+2) >= '0' && *(inst+2) <= '7' && op1[0] == '=') { + /* ignore ar0 = 0x00 type definitions */ + return 0; + } + + fprintf(stderr, "Warning, peephole unrecognized instruction: %s\n", inst); + return 3; +} + int pcDistance (lineNode * cpos, char *lbl, bool back) { @@ -73,9 +182,13 @@ pcDistance (lineNode * cpos, char *lbl, bool back) if (pl->line && *pl->line != ';' && pl->line[strlen (pl->line) - 1] != ':' && - !pl->isDebug) - - dist++; + !pl->isDebug) { + if (strcmp(port->target,"mcs51") == 0) { + dist += mcs51_instruction_size(pl->line); + } else { + dist += 3; + } + } if (strncmp (pl->line, buff, strlen (buff)) == 0) return dist; @@ -122,6 +235,11 @@ FBYNAME (xramMovcOption) return (options.xram_movc && (strcmp(port->target,"mcs51") == 0)); } + + + + + /*-----------------------------------------------------------------*/ /* labelInRange - will check to see if label %5 is within range */ /*-----------------------------------------------------------------*/ @@ -150,12 +268,8 @@ FBYNAME (labelInRange) dist = (pcDistance (currPl, lbl, TRUE) + pcDistance (currPl, lbl, FALSE)); -/* if (!dist || dist > 45) has produced wrong sjmp */ - /* 07-Sep-2000 Michael Schmitt */ - /* FIX for Peephole 132 */ - /* switch with lots of case can lead to a sjmp with a distance */ - /* out of the range for sjmp */ - if (!dist || dist > 43) +/* changed to 127, now that pcDistance return actual number of bytes */ + if (!dist || dist > 127) return FALSE; return TRUE;