static bool matchLine (char *, char *, hTab **);
-#define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *head, \
- const char *cmdLine)
+#define FBYNAME(x) int x (hTab *vars, lineNode *currPl, lineNode *endPl, \
+ lineNode *head, const char *cmdLine)
-#if !OPT_DISABLE_PIC
+#if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
void peepRules2pCode(peepRule *);
#endif
/*-----------------------------------------------------------------*/
/* 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)
{
char buff[MAX_PATTERN_LEN];
int dist = 0;
- sprintf (buff, "%s:", lbl);
+ SNPRINTF (buff, sizeof(buff), "%s:", lbl);
while (pl)
{
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;
return (options.xram_movc && (strcmp(port->target,"mcs51") == 0));
}
+
+
+
+
+
/*-----------------------------------------------------------------*/
/* labelInRange - will check to see if label %5 is within range */
/*-----------------------------------------------------------------*/
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;
}
+/*-----------------------------------------------------------------*/
+/* labelIsReturnOnly - Check if label %5 is followed by RET */
+/*-----------------------------------------------------------------*/
+FBYNAME (labelIsReturnOnly)
+{
+ /* assumes that %5 pattern variable has the label name */
+ const char *label, *p;
+ const lineNode *pl;
+ int len;
+
+ label = hTabItemWithKey (vars, 5);
+ if (!label) return FALSE;
+ len = strlen(label);
+
+ for(pl = currPl; pl; pl = pl->next) {
+ if (pl->line && !pl->isDebug &&
+ pl->line[strlen(pl->line)-1] == ':') {
+ if (strncmp(pl->line, label, len) == 0) break; /* Found Label */
+ if (strlen(pl->line) != 7 || !isdigit(*(pl->line)) ||
+ !isdigit(*(pl->line+1)) || !isdigit(*(pl->line+2)) ||
+ !isdigit(*(pl->line+3)) || !isdigit(*(pl->line+4)) ||
+ *(pl->line+5) != '$') {
+ return FALSE; /* non-local label encountered */
+ }
+ }
+ }
+ if (!pl) return FALSE; /* did not find the label */
+ pl = pl->next;
+ if (!pl || !pl->line || pl->isDebug) return FALSE; /* next line not valid */
+ p = pl->line;
+ for (p = pl->line; *p && isspace(*p); p++)
+ ;
+ if (strcmp(p, "ret") == 0) return TRUE;
+ return FALSE;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* okToRemoveSLOC - Check if label %1 is a SLOC and not other */
+/* usage of it in the code depends on a value from this section */
+/*-----------------------------------------------------------------*/
+FBYNAME (okToRemoveSLOC)
+{
+ const lineNode *pl;
+ const char *sloc, *p;
+ int dummy1, dummy2, dummy3;
+
+ /* assumes that %1 as the SLOC name */
+ sloc = hTabItemWithKey (vars, 1);
+ if (sloc == NULL) return FALSE;
+ p = strstr(sloc, "sloc");
+ if (p == NULL) return FALSE;
+ p += 4;
+ if (sscanf(p, "%d_%d_%d", &dummy1, &dummy2, &dummy3) != 3) return FALSE;
+ /*TODO: ultra-paranoid: get funtion name from "head" and check that */
+ /* the sloc name begins with that. Probably not really necessary */
+
+ /* Look for any occurance of this SLOC before the peephole match */
+ for (pl = currPl->prev; pl; pl = pl->prev) {
+ if (pl->line && !pl->isDebug && !pl->isComment
+ && *pl->line != ';' && strstr(pl->line, sloc))
+ return FALSE;
+ }
+ /* Look for any occurance of this SLOC after the peephole match */
+ for (pl = endPl->next; pl; pl = pl->next) {
+ if (pl->line && !pl->isDebug && !pl->isComment
+ && *pl->line != ';' && strstr(pl->line, sloc))
+ return FALSE;
+ }
+ return TRUE; /* safe for a peephole to remove it :) */
+}
+
+
/*-----------------------------------------------------------------*/
/* operandsNotSame - check if %1 & %2 are the same */
/*-----------------------------------------------------------------*/
callFuncByName (char *fname,
hTab * vars,
lineNode * currPl,
+ lineNode * endPl,
lineNode * head)
{
struct ftab
{
char *fname;
- int (*func) (hTab *, lineNode *, lineNode *, const char *);
+ int (*func) (hTab *, lineNode *, lineNode *, lineNode *, const char *);
}
ftab[] =
{
{
"operandsNotSame8", operandsNotSame8
}
- ,
+ ,
{
"24bitMode", flat24bitMode
}
{
"portIsDS390", portIsDS390
},
+ {
+ "labelIsReturnOnly", labelIsReturnOnly
+ },
+ {
+ "okToRemoveSLOC", okToRemoveSLOC
+ },
{
"24bitModeAndPortDS390", flat24bitModeAndPortDS390
}
};
- int i;
+ int i;
+ char *cmdCopy, *funcName, *funcArgs;
+ int rc = -1;
+
+ /* Isolate the function name part (we are passed the full condition
+ * string including arguments)
+ */
+ cmdCopy = Safe_strdup(fname);
+ funcName = strtok(cmdCopy, " \t");
+ funcArgs = strtok(NULL, "");
- for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
- if (strncmp (ftab[i].fname, fname, strlen (ftab[i].fname)) == 0)
- {
- return (*ftab[i].func) (vars, currPl, head,
- fname + strlen (ftab[i].fname));
- }
- fprintf (stderr, "could not find named function in function table\n");
- return TRUE;
+ for (i = 0; i < ((sizeof (ftab)) / (sizeof (struct ftab))); i++)
+ {
+ if (strcmp (ftab[i].fname, funcName) == 0)
+ {
+ rc = (*ftab[i].func) (vars, currPl, endPl, head,
+ funcArgs);
+ }
+ }
+
+ Safe_free(cmdCopy);
+
+ if (rc == -1)
+ {
+ fprintf (stderr,
+ "could not find named function \"%s\" in "
+ "peephole function table\n",
+ funcName);
+ // If the function couldn't be found, let's assume it's
+ // a bad rule and refuse it.
+ rc = FALSE;
+ }
+
+ return rc;
}
/*-----------------------------------------------------------------*/
if (cond && *cond)
{
- pr->cond = Safe_alloc ( strlen (cond) + 1);
- strcpy (pr->cond, cond);
+ pr->cond = Safe_strdup (cond);
}
else
pr->cond = NULL;
lineNode *pl;
pl = Safe_alloc ( sizeof (lineNode));
- pl->line = Safe_alloc ( strlen (line) + 1);
- strcpy (pl->line, line);
+ pl->line = Safe_strdup (line);
return pl;
}
*s = vvx;
*vv = '\0';
/* got value */
- vvx = traceAlloc (&_G.values, Safe_alloc(strlen (vval) + 1));
- strcpy (vvx, vval);
+ vvx = traceAlloc (&_G.values, Safe_strdup(vval));
hTabAddItem (vtab, key, vvx);
}
/* if this rule has additional conditions */
if (pr->cond)
{
- if (callFuncByName (pr->cond, pr->vars, pl, head))
+ if (callFuncByName (pr->cond, pr->vars, pl, spl, head))
{
*mtail = spl;
return TRUE;
lineNode *mtail = NULL;
bool restart;
-#if !OPT_DISABLE_PIC
+#if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
/* The PIC port uses a different peep hole optimizer based on "pCode" */
- if (TARGET_IS_PIC)
+ if (TARGET_IS_PIC || TARGET_IS_PIC16)
return;
#endif
if (rs)
{
rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
- strcat (rs, lb);
+ strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
}
else
{
- rs = Safe_alloc ( strlen (lb) + 1);
- strcpy (rs, lb);
+ rs = Safe_strdup (lb);
}
nch = 0;
}
if (rs)
{
rs = Safe_realloc (rs, strlen (rs) + strlen (lb) + 1);
- strcat (rs, lb);
+ strncatz (rs, lb, strlen (rs) + strlen (lb) + 1);
}
else
{
- rs = Safe_alloc ( strlen (lb) + 1);
- strcpy (rs, lb);
+ rs = Safe_strdup (lb);
}
}
return rs;
}
-#if !OPT_DISABLE_PIC
+#if !OPT_DISABLE_PIC || !OPT_DISABLE_PIC16
/* Convert the peep rules into pcode.
NOTE: this is only support in the PIC port (at the moment)
*/
- if (TARGET_IS_PIC) {
+ if (TARGET_IS_PIC || TARGET_IS_PIC16) {
peepRules2pCode(rootRules);
}
#endif