From 6f196a83a3a37f87375757099cb66ade405f4cd3 Mon Sep 17 00:00:00 2001 From: tecodev Date: Tue, 30 Jan 2007 23:52:00 +0000 Subject: [PATCH] * 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 git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4608 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 16 ++++++++++++- src/pic/glue.c | 63 ++++++++++++++++++++++++++++++++++++++++--------- src/pic/pcode.c | 57 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 115 insertions(+), 21 deletions(-) diff --git a/ChangeLog b/ChangeLog index d86d958d..a9303c65 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2007-01-31 Raphael Neider + + * 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 * 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 diff --git a/src/pic/glue.c b/src/pic/glue.c index b48f1c35..563bd7fd 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -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; } diff --git a/src/pic/pcode.c b/src/pic/pcode.c index 1e7b0fa0..a17c4ebf 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -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(®->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; } /*-----------------------------------------------------------------*/ -- 2.30.2