+2004-10-20 Vangelis Rokas <vrokas AT otenet.gr>
+
+ * device/lib/pic16/libsdcc/Makefile: added lregs directory in
+ makefile targets,
+ * device/lib/pic16/libsdcc/lregs/{Makefile,lrst.c,lrrest.c}: NEW
+ support functions to replace long sequences of MOVFF's from access
+ bank registers to stack and vice versa,
+ * src/pic16/device.h: added new field opt_flags, where optimization
+ flags can be set to enable certain features,
+ * src/pic16/gen.c (pic16_emitpinfo): NEW to add PC_INFO pCode in
+ * pBlock, (genFunction, genEndFunction): surroung loop for
+ saving/loading used registers in stack with PC_INFO pCodes,
+ INF_LREGS. Code in between can then be optimized by pCode optimizer
+ to support function calls,
+ * (genDataPointerSet): fixed bug which loaded float fields in
+ structures with corrupt data,
+ * src/pic16/genutils.c (debugf, _debugf): macro/function which emits
+ in a standard way debug info on stderr. Feature used for developing
+ and debugging only,
+ * src/pic16/glue.c (pic16glue): reformatted, deleted some old and
+ obsolete chunks of code,
+ * if optimization flag OF_LR_SUPPORT was set, call pic16_OptimizeLocalRegs,
+ * src/pic16/main.c (_pic16_parseOptions): added handler for --flr-support,
+ * pic16/src/pcode.c (pic16_newpCodeInfo,
+ * (pic16_newpCodeOpLocalRegs),
+ * (pic16_convertLocalRegs2Support): NEW, to support new optimization
+ feature,
+ * (pic16_pCodeConstString): printing of the initial value of a
+ symbol as a comment is inhibited since parsing was already done by
+ copyStr and output is corrupt,
+ * (pic16_pCode2str, genericPrint): handle PC_INFO pCode,
+
2004-10-20 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
* src/mcs51/ralloc.c (packRegisters): fixed bug #1044601
int \
long \
float \
- gptr
+ gptr \
+ lregs
LIB = libsdcc.lib
include ../Makefile.rules
-CFLAGS += -I$(LIBC_INC_DIR)
-
-
all: build-library
build-library: $(LIB)
--- /dev/null
+#
+# Makefile - Makefile to build pic16 local register store/restore
+# support library
+#
+# This file is part of the GNU PIC Library.
+#
+# January, 2004
+# The GNU PIC Library is maintained by,
+# Vangelis Rokas <vrokas@otenet.gr>
+#
+# $Id$
+#
+#
+
+
+SRCS = lrst \
+ lrrest
+
+
+include ../Makefile.rules
+
+
+all: build-library
+
+build-library: $(OFILES)
--- /dev/null
+/*-------------------------------------------------------------------------
+
+ lrrest.c :- restore local registers in stack upon function exit
+
+ Written for pic16 port by Vangelis Rokas, 2004 (vrokas@otenet.gr)
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+/*
+** $Id$
+*/
+
+/* FSR0 points to last register to store, WREG holds the register count
+ */
+
+extern PREINC1;
+extern POSTDEC0;
+extern WREG;
+
+void _lr_restore(void) _naked
+{
+ _asm
+loop:
+ movff _PREINC1, _POSTDEC0
+ decfsz _WREG, f
+ bra loop
+
+ return
+ _endasm;
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+
+ lrst.c :- store local registers in stack upon function entry
+
+ Written for pic16 port by Vangelis Rokas, 2004 (vrokas@otenet.gr)
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+/*
+** $Id$
+*/
+
+/* FSR0 points to first register to store, WREG holds the register count
+ */
+
+extern POSTDEC1;
+extern POSTINC0;
+extern WREG;
+
+void _lr_store(void) _naked
+{
+ _asm
+loop:
+ movff _POSTINC0, _POSTDEC1
+ decfsz _WREG, f
+ bra loop
+
+ return
+ _endasm;
+}
/* Given a pointer to a register, this macro returns the bank that it is in */
#define REG_ADDR(r) ((r)->isBitField ? (((r)->address)>>3) : (r)->address)
+#define OF_LR_SUPPORT 0x00000001
+
typedef struct {
int no_banksel;
char *crt_name;
int no_crt;
int ip_stack;
+ unsigned long opt_flags;
} pic16_options_t;
#define STACK_MODEL_SMALL (pic16_options.stack_model == 0)
pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
else
DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
-
-// fprintf(stderr, "%s\n", pcop->name);
}
+void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
+{
+ if(pcop)
+ pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
+ else
+ DEBUGpic16_emitcode(";","%s ignoring NULL pcop",__FUNCTION__);
+}
+
void pic16_emitpcodeNULLop(PIC_OPCODE poc)
{
if (sym->regsUsed) {
/* save the registers used */
DEBUGpic16_emitcode("; **", "Saving used registers in stack");
+ pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
for ( i = 0 ; i < sym->regsUsed->size ; i++) {
if (bitVectBitValue(sym->regsUsed,i)) {
pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
}
}
}
+ pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
}
}
if (sym->regsUsed) {
int i;
+ pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
/* restore registers used */
DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
for ( i = sym->regsUsed->size; i >= 0; i--) {
_G.nRegsSaved--;
}
}
+ pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
+
}
if(strcmp(sym->name, "main")) {
while (size--) {
if (AOP_TYPE(right) == AOP_LIT) {
- unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
-
- lit = lit >> (8*offset);
- if(lit&0xff) {
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
- } else {
- pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
- }
- } else {
- mov2w(AOP(right), offset);
- pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
- }
+ unsigned int lit;
+
+ if(!IS_FLOAT(operandType( right )))
+ lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+ else {
+ union {
+ unsigned long lit_int;
+ float lit_float;
+ } info;
+
+ /* take care if literal is a float */
+ info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+ lit = info.lit_int;
+ }
+
+ lit = lit >> (8*offset);
+ if(lit&0xff) {
+ pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
+ } else {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
+ }
+ } else {
+ mov2w(AOP(right), offset);
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
+ }
offset++;
resoffset++;
}
}
+//#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
+
+void _debugf(char *f, int l, char *frm, ...)
+{
+ va_list ap;
+
+ va_start(ap, frm);
+ fprintf(stderr, "%s:%d ", f, l);
+ vfprintf(stderr, frm, ap);
+ va_end(ap);
+}
+
+
void gpsimio2_pcop(pCodeOp *pcop)
{
void gpsimDebug_StackDump(char *fname, int line, char *info);
+#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
+void _debugf(char *f, int l, char *frm, ...);
+
#endif /* __GENUTILS_H__ */
pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
extern void pic16_pCodeConstString(char *name, char *value);
+#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
+extern void _debugf(char *f, int l, char *frm, ...);
+
/*-----------------------------------------------------------------*/
/* aopLiteral - string from a literal value */
/*-----------------------------------------------------------------*/
fprintf(stderr, "%s\n",__FUNCTION__);
#endif
- if (!s)
- {
-
- val = list2val (ilist);
- /* if the value is a character string */
- if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
- {
- if (!DCL_ELEM (type))
- DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
-
- for(remain=0; remain<DCL_ELEM(type); remain++)
- pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
-
- if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
- while (remain--) {
- pic16_emitDB(0x00, ptype, p);
- }
- }
- return 1;
- }
- else
- return 0;
- }
- else {
+ if(!s) {
+ val = list2val (ilist);
+ /* if the value is a character string */
+ if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
+ if(!DCL_ELEM (type))
+ DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
+
+ for(remain=0; remain<strlen(SPEC_CVAL(val->etype).v_char)+1; remain++)
+ pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
+
+ if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
+ while(remain--) {
+ pic16_emitDB(0x00, ptype, p);
+ }
+ }
+ return 1;
+ } else return 0;
+ } else {
for(remain=0; remain<strlen(s); remain++) {
pic16_emitDB(s[remain], ptype, p);
}
if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
SPEC_CVAL (sym->etype).v_char) {
-// fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
+// fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
} else {
void
pic16glue ()
{
-
FILE *vFile;
FILE *asmFile;
FILE *ovrFile = tempfile();
+ mainf = newSymbol ("main", 0);
+ mainf->block = 0;
- mainf = newSymbol ("main", 0);
- mainf->block = 0;
+ mainf = findSymWithLevel(SymbolTab, mainf);
- mainf = findSymWithLevel(SymbolTab, mainf);
-#if 0
- /* only if the main function exists */
- if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
- if (!options.cc_only)
- werror (E_NO_MAIN);
- return;
- }
-#endif
-
-// fprintf(stderr, "main function= %p (%s)\thas body= %d\n", mainf, (mainf?mainf->name:NULL), mainf?IFFUNC_HASBODY(mainf->type):-1);
-
- addSetHead(&tmpfileSet,ovrFile);
- pic16_pCodeInitRegisters();
+ addSetHead(&tmpfileSet,ovrFile);
+ pic16_pCodeInitRegisters();
+ if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
+ pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
- if (pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
- pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
+ pic16_addpBlock(pb);
- pic16_addpBlock(pb);
+ /* entry point @ start of CSEG */
+ pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
- /* entry point @ start of CSEG */
- pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
-
- if(initsfpnt) {
- pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
- pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
- pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
- pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
- }
+ if(initsfpnt) {
+ pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
+ pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
+ pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
+ pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
+ }
- /* put in the call to main */
- pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
+ /* put in the call to main */
+ pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
- if (options.mainreturn) {
- pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
- pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
- } else {
- pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
- pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
- }
- }
+ if (options.mainreturn) {
+ pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
+ pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
+ } else {
+ pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
+ pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
+ }
+ }
- /* At this point we've got all the code in the form of pCode structures */
- /* Now it needs to be rearranged into the order it should be placed in the */
- /* code space */
+ /* At this point we've got all the code in the form of pCode structures */
+ /* Now it needs to be rearranged into the order it should be placed in the */
+ /* code space */
- pic16_movepBlock2Head('P'); // Last
- pic16_movepBlock2Head(code->dbName);
- pic16_movepBlock2Head('X');
- pic16_movepBlock2Head(statsg->dbName); // First
+ pic16_movepBlock2Head('P'); // Last
+ pic16_movepBlock2Head(code->dbName);
+ pic16_movepBlock2Head('X');
+ pic16_movepBlock2Head(statsg->dbName); // First
- /* print the global struct definitions */
-// if (options.debug)
-// cdbStructBlock (0); //,cdbFile);
+ /* print the global struct definitions */
- vFile = tempfile();
- /* PENDING: this isnt the best place but it will do */
- if (port->general.glue_up_main) {
- /* create the interrupt vector table */
- pic16createInterruptVect (vFile);
- }
+ vFile = tempfile();
+ /* PENDING: this isnt the best place but it will do */
+ if (port->general.glue_up_main) {
+ /* create the interrupt vector table */
+ pic16createInterruptVect (vFile);
+ }
- addSetHead(&tmpfileSet,vFile);
+ addSetHead(&tmpfileSet,vFile);
- /* emit code for the all the variables declared */
- pic16emitMaps ();
- /* do the overlay segments */
- pic16emitOverlay(ovrFile);
- pic16_AnalyzepCode('*');
+ /* emit code for the all the variables declared */
+ pic16emitMaps ();
+
+ /* do the overlay segments */
+ pic16emitOverlay(ovrFile);
+ pic16_AnalyzepCode('*');
#if 1
- if(pic16_options.dumpcalltree) {
- FILE *cFile;
- sprintf(buffer, dstFileName);
- strcat(buffer, ".calltree");
- cFile = fopen(buffer, "w");
- pic16_printCallTree( cFile );
- fclose(cFile);
- }
+ if(pic16_options.dumpcalltree) {
+ FILE *cFile;
+
+ sprintf(buffer, dstFileName);
+ strcat(buffer, ".calltree");
+ cFile = fopen(buffer, "w");
+ pic16_printCallTree( cFile );
+ fclose(cFile);
+ }
#endif
- pic16_InlinepCode();
- pic16_AnalyzepCode('*');
+ pic16_InlinepCode();
+ pic16_AnalyzepCode('*');
- if(pic16_debug_verbose)
- pic16_pcode_test();
- /* now put it all together into the assembler file */
- /* create the assembler file name */
- if ((noAssemble || options.c1mode) && fullDstFileName) {
- sprintf (buffer, fullDstFileName);
- } else {
- sprintf (buffer, dstFileName);
- strcat (buffer, ".asm");
- }
+ if(pic16_debug_verbose)
+ pic16_pcode_test();
- if (!(asmFile = fopen (buffer, "w"))) {
- werror (E_FILE_OPEN_ERR, buffer);
- exit (1);
- }
+ /* now put it all together into the assembler file */
+ /* create the assembler file name */
+ if((noAssemble || options.c1mode) && fullDstFileName) {
+ sprintf (buffer, fullDstFileName);
+ } else {
+ sprintf (buffer, dstFileName);
+ strcat (buffer, ".asm");
+ }
+
+ if(!(asmFile = fopen (buffer, "w"))) {
+ werror (E_FILE_OPEN_ERR, buffer);
+ exit (1);
+ }
- /* initial comments */
- pic16initialComments (asmFile);
+ /* initial comments */
+ pic16initialComments (asmFile);
- /* print module name */
- if(options.debug)
- fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
+ /* print module name */
+ if(options.debug)
+ fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
- /* Let the port generate any global directives, etc. */
- if (port->genAssemblerPreamble) {
- port->genAssemblerPreamble(asmFile);
- }
-
- /* print the extern variables to this module */
- pic16_printExterns(asmFile);
+ /* Let the port generate any global directives, etc. */
+ if(port->genAssemblerPreamble) {
+ port->genAssemblerPreamble(asmFile);
+ }
- /* print the global variables in this module */
- pic16printPublics (asmFile);
+ /* Put all variables into a cblock */
+ pic16_AnalyzeBanking();
-#if 0
- /* copy the sfr segment */
- fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile, "; special function registers\n");
- fprintf (asmFile, "%s", iComments2);
- copyFile (asmFile, sfr->oFile);
-#endif
+ if(pic16_options.opt_flags & OF_LR_SUPPORT) {
+ pic16_OptimizeLocalRegs();
+ }
- /* Put all variables into a cblock */
- pic16_AnalyzeBanking();
- pic16_writeUsedRegs(asmFile);
+ /* print the extern variables to this module */
+ pic16_printExterns(asmFile);
+
+ /* print the global variables in this module */
+ pic16printPublics (asmFile);
+
+ pic16_writeUsedRegs(asmFile);
#if 0
- /* no xdata in pic */
- /* if external stack then reserve space of it */
- if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
- fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile, "; external stack \n");
- fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
- fprintf (asmFile,";\t.ds 256\n");
- }
+ /* no xdata in pic */
+ /* if external stack then reserve space of it */
+ if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; external stack \n");
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
+ fprintf (asmFile,";\t.ds 256\n");
+ }
#endif
#if 0
- /* no xdata in pic */
- /* copy xtern ram data */
- fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile, "; external ram data\n");
- fprintf (asmFile, "%s", iComments2);
- copyFile (asmFile, xdata->oFile);
+ /* no xdata in pic */
+ /* copy xtern ram data */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; external ram data\n");
+ fprintf (asmFile, "%s", iComments2);
+ copyFile (asmFile, xdata->oFile);
#endif
#if 0
- /* copy the bit segment */
- fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile, "; bit data\n");
- fprintf (asmFile, "%s", iComments2);
- copyFile (asmFile, bit->oFile);
+ /* copy the bit segment */
+ fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "; bit data\n");
+ fprintf (asmFile, "%s", iComments2);
+ copyFile (asmFile, bit->oFile);
#endif
- /* copy the interrupt vector table */
- if(mainf && IFFUNC_HASBODY(mainf->type)) {
- fprintf (asmFile, "\n%s", iComments2);
- fprintf (asmFile, "; interrupt vector \n");
- fprintf (asmFile, "%s", iComments2);
- copyFile (asmFile, vFile);
- }
+ /* copy the interrupt vector table */
+ if(mainf && IFFUNC_HASBODY(mainf->type)) {
+ fprintf (asmFile, "\n%s", iComments2);
+ fprintf (asmFile, "; interrupt vector \n");
+ fprintf (asmFile, "%s", iComments2);
+ copyFile (asmFile, vFile);
+ }
- /* copy global & static initialisations */
- fprintf (asmFile, "\n%s", iComments2);
- fprintf (asmFile, "; global & static initialisations\n");
- fprintf (asmFile, "%s", iComments2);
+ /* copy global & static initialisations */
+ fprintf (asmFile, "\n%s", iComments2);
+ fprintf (asmFile, "; global & static initialisations\n");
+ fprintf (asmFile, "%s", iComments2);
- if(pic16_debug_verbose)
- fprintf(asmFile, "; A code from now on!\n");
- pic16_copypCode(asmFile, 'A');
-
-
- if(pic16_options.no_crt) {
- if(mainf && IFFUNC_HASBODY(mainf->type)) {
- fprintf(asmFile, "\tcode\n");
- fprintf(asmFile,"__sdcc_gsinit_startup:\n");
- }
- }
+ if(pic16_debug_verbose)
+ fprintf(asmFile, "; A code from now on!\n");
+
+ pic16_copypCode(asmFile, 'A');
-// copyFile (stderr, code->oFile);
+ if(pic16_options.no_crt) {
+ if(mainf && IFFUNC_HASBODY(mainf->type)) {
+ fprintf(asmFile, "\tcode\n");
+ fprintf(asmFile,"__sdcc_gsinit_startup:\n");
+ }
+ }
- fprintf(asmFile, "; I code from now on!\n");
- pic16_copypCode(asmFile, 'I');
+// copyFile (stderr, code->oFile);
- if(pic16_debug_verbose)
- fprintf(asmFile, "; dbName from now on!\n");
- pic16_copypCode(asmFile, statsg->dbName);
+ fprintf(asmFile, "; I code from now on!\n");
+ pic16_copypCode(asmFile, 'I');
+ if(pic16_debug_verbose)
+ fprintf(asmFile, "; dbName from now on!\n");
+
+ pic16_copypCode(asmFile, statsg->dbName);
- if(pic16_options.no_crt) {
- if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
- fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
- }
- }
+ if(pic16_options.no_crt) {
+ if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
+ fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
+ }
+ }
+ if(pic16_debug_verbose)
+ fprintf(asmFile, "; X code from now on!\n");
- if(pic16_debug_verbose)
- fprintf(asmFile, "; X code from now on!\n");
- pic16_copypCode(asmFile, 'X');
+ pic16_copypCode(asmFile, 'X');
- if(pic16_debug_verbose)
- fprintf(asmFile, "; M code from now on!\n");
- pic16_copypCode(asmFile, 'M');
+ if(pic16_debug_verbose)
+ fprintf(asmFile, "; M code from now on!\n");
+ pic16_copypCode(asmFile, 'M');
- pic16_copypCode(asmFile, code->dbName);
-
- pic16_copypCode(asmFile, 'P');
-
- fprintf (asmFile,"\tend\n");
- fclose (asmFile);
+ pic16_copypCode(asmFile, code->dbName);
+
+ pic16_copypCode(asmFile, 'P');
- rm_tmpfiles();
+ fprintf (asmFile,"\tend\n");
+ fclose (asmFile);
+
+ rm_tmpfiles();
}
#define NL_OPT "--nl="
#define USE_CRT "--use-crt="
+#define OFMSG_LRSUPPORT "--flr-support"
+
+
char *alt_asm=NULL;
char *alt_link=NULL;
{ 0, NL_OPT, NULL, "new line, \"lf\" or \"crlf\""},
{ 0, USE_CRT, NULL, "use <crt-o> run-time initialization module"},
{ 0, "--no-crt", &pic16_options.no_crt, "do not link any default run-time initialization module"},
+ { 0, OFMSG_LRSUPPORT, NULL, "use support functions for local register store/restore"},
{ 0, NULL, NULL, NULL}
};
/* TODO: allow port-specific command line options to specify
* segment names here.
*/
- /* check for arguments that have associated an integer variable */
- while(pic16_optionsTable[j].pparameter) {
- if(ISOPT( pic16_optionsTable[j].longOpt )) {
- (*pic16_optionsTable[j].pparameter)++;
- return TRUE;
- }
- j++;
- }
-
+
+ /* check for arguments that have associated an integer variable */
+ while(pic16_optionsTable[j].pparameter) {
+ if(ISOPT( pic16_optionsTable[j].longOpt )) {
+ (*pic16_optionsTable[j].pparameter)++;
+ return TRUE;
+ }
+ j++;
+ }
- if(ISOPT(STACK_MODEL)) {
- stkmodel = getStringArg(STACK_MODEL, argv, i, *pargc);
- if(!STRCASECMP(stkmodel, "small"))pic16_options.stack_model = 0;
- else if(!STRCASECMP(stkmodel, "large"))pic16_options.stack_model = 1;
- else {
- fprintf(stderr, "Unknown stack model: %s", stkmodel);
- exit(-1);
- }
- return TRUE;
- }
+ if(ISOPT(STACK_MODEL)) {
+ stkmodel = getStringArg(STACK_MODEL, argv, i, *pargc);
+ if(!STRCASECMP(stkmodel, "small"))pic16_options.stack_model = 0;
+ else if(!STRCASECMP(stkmodel, "large"))pic16_options.stack_model = 1;
+ else {
+ fprintf(stderr, "Unknown stack model: %s", stkmodel);
+ exit(-1);
+ }
+ return TRUE;
+ }
- if(ISOPT(OPT_BANKSEL)) {
- pic16_options.opt_banksel = getIntArg(OPT_BANKSEL, argv, i, *pargc);
- return TRUE;
- }
+ if(ISOPT(OPT_BANKSEL)) {
+ pic16_options.opt_banksel = getIntArg(OPT_BANKSEL, argv, i, *pargc);
+ return TRUE;
+ }
- if(ISOPT(REP_UDATA)) {
- pic16_sectioninfo.at_udata = Safe_strdup(getStringArg(REP_UDATA, argv, i, *pargc));
- return TRUE;
- }
+ if(ISOPT(REP_UDATA)) {
+ pic16_sectioninfo.at_udata = Safe_strdup(getStringArg(REP_UDATA, argv, i, *pargc));
+ return TRUE;
+ }
- if(ISOPT(ALT_ASM)) {
- alt_asm = Safe_strdup(getStringArg(ALT_ASM, argv, i, *pargc));
- return TRUE;
- }
+ if(ISOPT(ALT_ASM)) {
+ alt_asm = Safe_strdup(getStringArg(ALT_ASM, argv, i, *pargc));
+ return TRUE;
+ }
- if(ISOPT(ALT_LINK)) {
- alt_link = Safe_strdup(getStringArg(ALT_LINK, argv, i, *pargc));
- return TRUE;
- }
+ if(ISOPT(ALT_LINK)) {
+ alt_link = Safe_strdup(getStringArg(ALT_LINK, argv, i, *pargc));
+ return TRUE;
+ }
- if(ISOPT(IVT_LOC)) {
- pic16_options.ivt_loc = getIntArg(IVT_LOC, argv, i, *pargc);
- return TRUE;
- }
+ if(ISOPT(IVT_LOC)) {
+ pic16_options.ivt_loc = getIntArg(IVT_LOC, argv, i, *pargc);
+ return TRUE;
+ }
- if(ISOPT(NL_OPT)) {
- char *tmp;
+ if(ISOPT(NL_OPT)) {
+ char *tmp;
- tmp = Safe_strdup( getStringArg(NL_OPT, argv, i, *pargc) );
- if(!STRCASECMP(tmp, "lf"))pic16_nl = 0;
- else if(!STRCASECMP(tmp, "crlf"))pic16_nl = 1;
- else {
- fprintf(stderr, "invalid termination character id\n");
- exit(-1);
- }
- return TRUE;
+ tmp = Safe_strdup( getStringArg(NL_OPT, argv, i, *pargc) );
+ if(!STRCASECMP(tmp, "lf"))pic16_nl = 0;
+ else if(!STRCASECMP(tmp, "crlf"))pic16_nl = 1;
+ else {
+ fprintf(stderr, "invalid termination character id\n");
+ exit(-1);
}
+ return TRUE;
+ }
- if(ISOPT(USE_CRT)) {
- pic16_options.no_crt = 0;
- pic16_options.crt_name = Safe_strdup( getStringArg(USE_CRT, argv, i, *pargc) );
+ if(ISOPT(USE_CRT)) {
+ pic16_options.no_crt = 0;
+ pic16_options.crt_name = Safe_strdup( getStringArg(USE_CRT, argv, i, *pargc) );
- return TRUE;
- }
+ return TRUE;
+ }
+
+ if(ISOPT(OFMSG_LRSUPPORT)) {
+ pic16_options.opt_flags |= OF_LR_SUPPORT;
+ return TRUE;
+ }
return FALSE;
}
pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
+char *OPT_TYPE_STR[] = { "begin", "end" };
+char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
+
static int mnemonics_initialized = 0;
extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
void pic16_pCodeRegMapLiveRanges(pBlock *pb);
+void OptimizeLocalRegs(void);
char *dumpPicOptype(PIC_OPTYPE type);
+pCodeOp *pic16_popGetLit2(int, pCodeOp *);
+pCodeOp *pic16_popGetLit(int);
+pCodeOp *pic16_popGetWithString(char *);
+
+
/****************************************************************/
/* PIC Instructions */
/****************************************************************/
return ( (pCode *)pcl );
}
-#if 0
pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
{
+ pCodeInfo *pci;
+ pci = Safe_calloc(1, sizeof(pCodeInfo));
+ pci->pci.pc.type = PC_INFO;
+ pci->pci.pc.prev = pci->pci.pc.next = NULL;
+ pci->pci.pc.pb = NULL;
+ pci->pci.label = NULL;
+
+ pci->pci.pc.destruct = genericDestruct;
+ pci->pci.pc.print = genericPrint;
+
+ pci->type = type;
+ pci->oper1 = pcop;
+
+ return ((pCode *)pci);
}
-#endif
/*-----------------------------------------------------------------*/
return (PCOP(pcop));
}
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
+{
+ pCodeOpLocalReg *pcop;
+
+ pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
+
+ pcop->type = type;
+
+ return (PCOP(pcop));
+}
+
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
pic16_addpBlock(pb);
- sprintf(buffer,"; %s = %s",name,value);
-
- pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
+// sprintf(buffer,"; %s = ", name);
+// strcat(buffer, value);
+// fputs(buffer, stderr);
+
+// pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
do {
SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
break;
+ case PC_INFO:
+ SAFE_snprintf(&s,&size,"; info ==>");
+ switch(((pCodeInfo *)pc)->type) {
+ case INF_OPTIMIZATION:
+ SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
+ break;
+ case INF_LOCALREGS:
+ SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
+ break;
+ }; break;
+
case PC_INLINE:
/* assuming that inline code ends with a \n */
SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
case PC_BAD:
SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
break;
-
- case PC_INFO:
- SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
- break;
}
return str;
switch(pc->type) {
case PC_COMMENT:
- fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
+// fputs(((pCodeComment *)pc)->comment, of);
+ fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
break;
+ case PC_INFO:
+ {
+ pBranch *pbl = PCI(pc)->label;
+ while(pbl && pbl->pc) {
+ if(pbl->pc->type == PC_LABEL)
+ pCodePrintLabel(of, pbl->pc);
+ pbl = pbl->next;
+ }
+ }
+
+ fprintf(of, "; info ==>");
+ switch(((pCodeInfo *)pc)->type) {
+ case INF_OPTIMIZATION:
+ fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
+ break;
+ case INF_LOCALREGS:
+ fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
+ break;
+ }; break;
+
case PC_INLINE:
fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
break;
} while(changes && (i++ < MAX_PASSES));
+
buildCallTree();
}
+
+/* convert a series of movff's of local regs to stack, with a single call to
+ * a support functions which does the same thing via loop */
+static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
+{
+ pBranch *pbr;
+ pCode *pc, *pct;
+ char *fname[]={"__lr_store", "__lr_restore"};
+
+// pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
+
+ pct = pic16_findNextInstruction(pcstart->next);
+ do {
+ pc = pct;
+ pct = pc->next; //pic16_findNextInstruction(pc->next);
+// pc->print(stderr, pc);
+ if(isPCI(pc) && PCI(pc)->label) {
+ pbr = PCI(pc)->label;
+ while(pbr && pbr->pc) {
+ PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
+ pbr = pbr->next;
+ }
+
+// pc->print(stderr, pc);
+ /* unlink pCode */
+ pc->prev->next = pct;
+ pct->prev = pc->prev;
+// pc->next = NULL;
+// pc->prev = NULL;
+ }
+ } while ((pc) && (pc != pcend));
+
+ /* unlink movff instructions */
+ pcstart->next = pcend;
+ pcend->prev = pcstart;
+
+ pic16_pCodeInsertAfter(pcstart, (pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name))))); pc = pct;
+ pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
+ pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] )));
+
+ {
+ symbol *sym;
+
+ sym = newSymbol( fname[ entry?0:1 ], 0 );
+ strcpy(sym->rname, fname[ entry?0:1 ]);
+ checkAddSym(&externs, sym);
+
+// fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
+ }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
+/* local registers to a support function call */
+/*-----------------------------------------------------------------*/
+void pic16_OptimizeLocalRegs(void)
+{
+ pBlock *pb;
+ pCode *pc;
+ pCodeInfo *pci;
+ pCodeOpLocalReg *pclr;
+ int regCount=0;
+ int inRegCount=0;
+ regs *r, *lastr=NULL, *firstr=NULL;
+ pCode *pcstart=NULL, *pcend=NULL;
+ int inEntry=0;
+
+ /* Overview:
+ * local_regs begin mark
+ * MOVFF r0x01, POSTDEC1
+ * MOVFF r0x02, POSTDEC1
+ * ...
+ * ...
+ * MOVFF r0x0n, POSTDEC1
+ * local_regs end mark
+ *
+ * convert the above to the below:
+ * MOVLW starting_register_index
+ * MOVWF PRODL
+ * MOVLW register_count
+ * call __save_registers_in_stack
+ */
+
+ if(!the_pFile)
+ return;
+
+ for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+ inRegCount = regCount = 0;
+ firstr = lastr = NULL;
+ for(pc = pb->pcHead; pc; pc = pc->next) {
+ if(pc && (pc->type == PC_INFO)) {
+ pci = PCINF(pc);
+
+ if(pci->type == INF_LOCALREGS) {
+ pclr = PCOLR(pci->oper1);
+
+ if((pclr->type == LR_ENTRY_BEGIN)
+ || (pclr->type == LR_ENTRY_END))inEntry = 1;
+ else inEntry = 0;
+
+ switch(pclr->type) {
+ case LR_ENTRY_BEGIN:
+ case LR_EXIT_BEGIN:
+ inRegCount = 1; regCount = 0;
+ pcstart = pc; //pic16_findNextInstruction(pc->next);
+ firstr = lastr = NULL;
+ break;
+
+ case LR_ENTRY_END:
+ case LR_EXIT_END:
+ inRegCount = -1;
+ pcend = pc; //pic16_findPrevInstruction(pc->prev);
+
+#if 1
+ if(regCount>2) {
+ pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
+ firstr, inEntry);
+ }
+#endif
+ firstr = lastr = NULL;
+ break;
+ }
+
+ if(inRegCount == -1) {
+// fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
+ regCount = 0;
+ inRegCount = 0;
+ }
+ }
+ } else {
+ if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
+ if(inEntry)
+ r = pic16_getRegFromInstruction(pc);
+ else
+ r = pic16_getRegFromInstruction2(pc);
+ if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
+ if(!firstr)firstr = r;
+ regCount++;
+// fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+
+
+
/*-----------------------------------------------------------------*/
/* ispCodeFunction - returns true if *pc is the pCode of a */
/* function */
typedef enum
{
INF_OPTIMIZATION, /* structure contains optimization information */
+ INF_LOCALREGS /* structure contains local register information */
} INFO_TYPE;
OPT_END, /* mark ending of optimization block */
} OPT_TYPE;
+/***********************************************************************
+ * LR_TYPE - optimization node types
+ ***********************************************************************/
+
+typedef enum
+{
+ LR_ENTRY_BEGIN, /* mark beginning of optimization block */
+ LR_ENTRY_END, /* mark ending of optimization block */
+ LR_EXIT_BEGIN,
+ LR_EXIT_END
+} LR_TYPE;
/************************************************/
char *key; /* key by which a block is identified */
} pCodeOpOpt;
-
+typedef struct pCodeOpLocalReg
+{
+ pCodeOp pcop;
+
+ LR_TYPE type;
+} pCodeOpLocalReg;
/*************************************************
pCode
Here are stored generic informaton
*************************************************/
-typedef struct pInfo
+typedef struct pCodeInfo
{
- pCode pc;
+ pCodeInstruction pci;
INFO_TYPE type; /* info node type */
pCodeOp *oper1; /* info node arguments */
-} pInfo;
+} pCodeInfo;
/*************************************************
#define PCW(x) ((pCodeWild *)(x))
#define PCCS(x) ((pCodeCSource *)(x))
#define PCAD(x) ((pCodeAsmDir *)(x))
+#define PCINF(x) ((pCodeInfo *)(x))
#define PCOP(x) ((pCodeOp *)(x))
//#define PCOB(x) ((pCodeOpBit *)(x))
#define PCOR2(x) ((pCodeOpReg2 *)(x))
#define PCORB(x) ((pCodeOpRegBit *)(x))
#define PCOO(x) ((pCodeOpOpt *)(x))
+#define PCOLR(x) ((pCodeOpLocalReg *)(x))
#define PCOW(x) ((pCodeOpWild *)(x))
#define PCOW2(x) (PCOW(PCOW(x)->pcop2))
#define PBR(x) ((pBranch *)(x))
void pic16_copypCode(FILE *of, char dbName); // Write all pBlocks with dbName to *of
void pic16_movepBlock2Head(char dbName); // move pBlocks around
void pic16_AnalyzepCode(char dbName);
+void pic16_OptimizeLocalRegs(void);
void pic16_AssignRegBanks(void);
void pic16_printCallTree(FILE *of);
void pCodePeepInit(void);
pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE p);
pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop);
+pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop);
+pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key);
+pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type);
+
pCode * pic16_findNextInstruction(pCode *pci);
pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct);
int pic16_isPCinFlow(pCode *pc, pCode *pcflow);