* src/pic/pcode.c (isValidIdChar,bankCompare): fuzzy matching of
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 30 Jan 2007 23:52:00 +0000 (23:52 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Tue, 30 Jan 2007 23:52:00 +0000 (23:52 +0000)
    operand names, handles name and (name + n) for all n,
  (sameBank): restructured, also check bank allocation policy,
* src/pic/glue.c (emitPseudoStack): fixed printf arguments,
  (pic14_operandsAllocatedInSameBank): check whether to operands
    will be allocated into the same bank (i.e., section) to reduce
    BANKSEL overhead, queried from pcode.c:sameBank,
  (pic14printLocals): reintroduced clustering registers into a single
    section: all compiler generated symbols will now reside in one
    bank (per file), reducing BANKSEL overhead and code size,
  (showAllMemmaps): use local dbuf where possible

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4608 4a8a32a2-be11-0410-ad9d-d568d2c75423

ChangeLog
src/pic/glue.c
src/pic/pcode.c

index d86d958d97e3385b1122f8d933d69de625d888f7..a9303c65baa6b3b639e0ffd7d005afef078610d2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2007-01-31 Raphael Neider <rneider AT web.de>
+
+       * src/pic/pcode.c (isValidIdChar,bankCompare): fuzzy matching of
+           operand names, handles name and (name + n) for all n,
+         (sameBank): restructured, also check bank allocation policy,
+       * src/pic/glue.c (emitPseudoStack): fixed printf arguments,
+         (pic14_operandsAllocatedInSameBank): check whether to operands
+           will be allocated into the same bank (i.e., section) to reduce
+           BANKSEL overhead, queried from pcode.c:sameBank,
+         (pic14printLocals): reintroduced clustering registers into a single
+           section: all compiler generated symbols will now reside in one
+           bank (per file), reducing BANKSEL overhead and code size,
+         (showAllMemmaps): use local dbuf where possible
+
 2007-01-29 Raphael Neider <rneider AT web.de>
 
        * src/pic/gen.c (popGetExternal): simplified, mark symbol as used,
@@ -11,7 +25,7 @@
            of string literals (still incomplete),
          (picglue): removed symbol emission, moved into showAllMemmaps,
          (emitSymbolSet): new workhorse for symbol output,
-         (pic14emitMaps,pic14printPublics,pic14printExterns): commented out,
+         (pic14emitMaps,pic14printPublics,pic14printExterns): commented out
 
 2007-01-29 Borut Razem <borut.razem AT siol.net>
 
index b48f1c356942e6dfae1398dc6ddbbfba701db205..563bd7fd7360737ebeddcb4ad8a6259cf51fec68 100644 (file)
@@ -78,7 +78,7 @@ int pic14_hasInterrupt = 0;           // Indicates whether to emit interrupt handler or n
 
 /* dbufs for initialized data (idata and code sections),
  * extern, and global declarations */
-struct dbuf_s *ivalBuf, *ivalCodeBuf, *extBuf, *gloBuf, *gloDefBuf, *locBuf;
+struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
 
 static set *emitted = NULL;
 int pic14_stringInSet(const char *str, set **world, int autoAdd);
@@ -163,7 +163,7 @@ emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
        for (i = size - 4; i >= 0; i--) {
            dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
        } // for i
-       dbuf_printf (oBuf, "\n", i);
+       dbuf_printf (oBuf, "\n");
 
        // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
        // banks, sigh...
@@ -195,7 +195,7 @@ emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
            pic14_stringInSet(&buffer[0], &emitted, 1);
        } // for i
     }
-    dbuf_printf (oBuf, "\n", i);
+    dbuf_printf (oBuf, "\n");
 }
 
 static int
@@ -1143,13 +1143,41 @@ pic14printPublics (FILE * afile)
 }
 #endif
 
+/*
+ * Interface to BANKSEL generation.
+ * This function should return != 0 iff str1 and str2 denote operands that
+ * are known to be allocated into the same bank. Consequently, there will
+ * be no BANKSEL emitted if str2 is accessed while str1 has been used to
+ * select the current bank just previously.
+ *
+ * If in doubt, return 0.
+ */
+int
+pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
+    // see pic14printLocals
+    
+    if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
+       // no clustering applied, each register resides in its own bank
+    } else {
+       // check whether BOTH names are local registers
+       // XXX: This is some kind of shortcut, should be safe...
+       // In this model, all r0xXXXX are allocated into a single section
+       // per file, so no BANKSEL required if accessing a r0xXXXX after a
+       // (different) r0xXXXX. Works great for multi-byte operands.
+       if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
+    } // if
+
+    // assume operands in different banks
+    return (0);
+}
+
 static void
 pic14printLocals (struct dbuf_s *oBuf)
 {
     set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
        dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
     regs *reg;
-    int i;
+    int i, is_first = 1;
     static unsigned sectionNr = 0;
 
     /* emit all registers from all possible sets */
@@ -1163,11 +1191,23 @@ pic14printLocals (struct dbuf_s *oBuf)
                if (!pic14_stringInSet(reg->name, &emitted, 1)) {
                    if (reg->isFixed) {
                        // Should not happen, really...
+                       assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
                        dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
                                moduleName, sectionNr++, reg->address, reg->name, reg->size);
                    } else {
-                       dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
-                               moduleName, sectionNr++, reg->name, reg->size);
+                       if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
+                           // assign each local register into its own section
+                           dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
+                                   moduleName, sectionNr++, reg->name, reg->size);
+                       } else {
+                           // group all local registers into a single section
+                           // This should greatly improve BANKSEL generation...
+                           if (is_first) {
+                               dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
+                               is_first = 0;
+                           }
+                           dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
+                       }
                    }
                }
            }
@@ -2077,6 +2117,7 @@ emitSymbolSet(set *s, int type)
 static void
 showAllMemmaps(FILE *of)
 {
+    struct dbuf_s locBuf;
     memmap *maps[] = {
        xstack, istack, code, data, pdata, xdata, xidata, xinit,
        idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
@@ -2089,13 +2130,13 @@ showAllMemmaps(FILE *of)
     if (!gloBuf) gloBuf = dbuf_new(1024);
     if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
     if (!ivalBuf) ivalBuf = dbuf_new(1024);
-    if (!locBuf) locBuf = dbuf_new(1024);
+    dbuf_init(&locBuf, 1024);
 
     dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
     dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
     dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
     dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
-    dbuf_printf (locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
+    dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
 
     for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
        map = maps[i];
@@ -2118,14 +2159,14 @@ showAllMemmaps(FILE *of)
     emitPseudoStack(gloBuf, extBuf);
     pic14_constructAbsMap(gloDefBuf, gloBuf);
 
-    pic14printLocals (locBuf);
+    pic14printLocals (&locBuf);
 
     dbuf_write_and_destroy(extBuf, of);
     dbuf_write_and_destroy(gloBuf, of);
     dbuf_write_and_destroy(gloDefBuf, of);
-    dbuf_write_and_destroy(locBuf, of);
+    dbuf_write_and_destroy(&locBuf, of);
     dbuf_write_and_destroy(ivalBuf, of);
 
-    extBuf = gloBuf = gloDefBuf = locBuf = ivalBuf = NULL;
+    extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;
 }
 
index 1e7b0fa06c4e3c35dc380d5e4476ae883f2f0940..a17c4ebfa5b99e19cc32c28982483d76a8caa5ec 100644 (file)
@@ -4621,24 +4621,63 @@ static void insertBankSel(pCodeInstruction  *pci, const char *name)
        insertPCodeInstruction(pci, PCI(new_pc));
 }
 
+/*
+ * isValidIdChar - check if c may be present in an identifier
+ */
+static int isValidIdChar (char c)
+{
+    if (c >= 'a' && c <= 'z') return 1;
+    if (c >= 'A' && c <= 'Z') return 1;
+    if (c >= '0' && c <= '9') return 1;
+    if (c == '_') return 1;
+    return 0;
+}
+
+/*
+ * bankcompare - check if two operand string refer to the same register
+ * This functions handles NAME and (NAME + x) in both operands.
+ * Returns 1 on same register, 0 on different (or unknown) registers.
+ */
+static int bankCompare(const char *op1, const char *op2)
+{
+    int i;
+
+    if (!op1 && !op2) return 0; // both unknown, might be different though!
+    if (!op1 || !op2) return 0;
+
+    // find start of operand name
+    while (op1[0] == '(' || op1[0] == ' ') op1++;
+    while (op2[0] == '(' || op2[0] == ' ') op2++;
+
+    // compare till first non-identifier character
+    for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
+    if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
+
+    // play safe---assume different operands
+    return 0;
+}
+
 /*-----------------------------------------------------------------*/
 /*-----------------------------------------------------------------*/
+extern int pic14_operandsAllocatedInSameBank(const char *str1, const char *str2);
 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
 {
     if (!cur_bank) return 0;
 
-    // identify '(regname + X)' and 'regname'
-    if (reg && reg->name && reg->name[0] == '(' && !strncmp(&reg->name[1], cur_bank, strlen(cur_bank))) return 1;
-    if (new_bank && new_bank[0] == '(' && !strncmp(&new_bank[1], cur_bank, strlen(cur_bank))) return 1;
-    if (cur_bank[0] == '(' && reg && reg->name && !strncmp(reg->name, &cur_bank[1], strlen(reg->name))) return 1;
-    if (cur_bank[0] == '(' && new_bank && !strncmp(new_bank, &cur_bank[1], strlen(new_bank))) return 1;
-    
     if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask)))     // only if exists 
       return 1;  // if we have address info, we use it for banksel optimization
 
-    // XXX: identify '(regname + X)' and '(regname + Y)'
-    
-    return ((reg && reg->name && !strcmp(reg->name, cur_bank)) || (new_bank && !strcmp(new_bank, cur_bank)));
+    // regard '(regname + X)' and '(regname + Y)' as equal
+    if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
+    if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
+
+    // check allocation policy from glue.c
+    if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
+    if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
+
+    // seems to be a different operand--might be a different bank
+    //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
+    return 0;
 }
     
 /*-----------------------------------------------------------------*/