1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
30 #if defined(__BORLANDC__) || defined(_MSC_VER)
31 #define STRCASECMP stricmp
33 #define STRCASECMP strcasecmp
36 // Eventually this will go into device dependent files:
37 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,NULL};
38 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,NULL};
39 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,NULL};
41 static int mnemonics_initialized = 0;
44 //static char *PIC_mnemonics[] = {
45 static char *scpADDLW = "ADDLW";
46 static char *scpADDWF = "ADDWF";
47 static char *scpANDLW = "ANDLW";
48 static char *scpANDWF = "ANDWF";
49 static char *scpBCF = "BCF";
50 static char *scpBSF = "BSF";
51 static char *scpBTFSC = "BTFSC";
52 static char *scpBTFSS = "BTFSS";
53 static char *scpCALL = "CALL";
54 static char *scpCOMF = "COMF";
55 static char *scpCLRF = "CLRF";
56 static char *scpCLRW = "CLRW";
57 static char *scpDECF = "DECF";
58 static char *scpDECFSZ = "DECFSZ";
59 static char *scpGOTO = "GOTO";
60 static char *scpINCF = "INCF";
61 static char *scpINCFSZ = "INCFSZ";
62 static char *scpIORLW = "IORLW";
63 static char *scpIORWF = "IORWF";
64 static char *scpMOVF = "MOVF";
65 static char *scpMOVLW = "MOVLW";
66 static char *scpMOVWF = "MOVWF";
67 static char *scpNEGF = "NEGF";
68 static char *scpRETLW = "RETLW";
69 static char *scpRETURN = "RETURN";
70 static char *scpSUBLW = "SUBLW";
71 static char *scpSUBWF = "SUBWF";
72 static char *scpTRIS = "TRIS";
73 static char *scpXORLW = "XORLW";
74 static char *scpXORWF = "XORWF";
77 static hTab *pic14MnemonicsHash = NULL;
81 static pFile *the_pFile = NULL;
82 static int peepOptimizing = 1;
83 static int GpCodeSequenceNumber = 1;
85 /****************************************************************/
86 /* Forward declarations */
87 /****************************************************************/
89 static void unlinkPC(pCode *pc);
90 static void genericAnalyze(pCode *pc);
91 static void AnalyzeGOTO(pCode *pc);
92 static void AnalyzeSKIP(pCode *pc);
93 static void AnalyzeRETURN(pCode *pc);
95 static void genericDestruct(pCode *pc);
96 static void genericPrint(FILE *of,pCode *pc);
98 static void pCodePrintLabel(FILE *of, pCode *pc);
99 static void pCodePrintFunction(FILE *of, pCode *pc);
100 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
101 static char *get_op( pCodeInstruction *pcc);
102 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
103 int pCodePeepMatchRule(pCode *pc);
106 pCodeInstruction pciADDWF = {
107 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
115 1,0, // dest, bit instruction
116 (PCC_W | PCC_REGISTER), // inCond
117 (PCC_REGISTER | PCC_Z) // outCond
120 pCodeInstruction pciADDFW = {
121 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
129 0,0, // dest, bit instruction
130 (PCC_W | PCC_REGISTER), // inCond
131 (PCC_W | PCC_Z) // outCond
134 pCodeInstruction pciADDLW = {
135 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
143 0,0, // dest, bit instruction
145 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
148 pCodeInstruction pciANDLW = {
149 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
157 0,0, // dest, bit instruction
159 (PCC_W | PCC_Z) // outCond
162 pCodeInstruction pciANDWF = {
163 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
171 1,0, // dest, bit instruction
172 (PCC_W | PCC_REGISTER), // inCond
173 (PCC_REGISTER | PCC_Z) // outCond
176 pCodeInstruction pciANDFW = {
177 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
185 0,0, // dest, bit instruction
186 (PCC_W | PCC_REGISTER), // inCond
187 (PCC_W | PCC_Z) // outCond
190 pCodeInstruction pciBCF = {
191 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
199 0,1, // dest, bit instruction
201 PCC_EXAMINE_PCOP // outCond
204 pCodeInstruction pciBSF = {
205 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
213 0,1, // dest, bit instruction
215 PCC_EXAMINE_PCOP // outCond
218 pCodeInstruction pciBTFSC = {
219 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
227 0,1, // dest, bit instruction
228 PCC_EXAMINE_PCOP, // inCond
232 pCodeInstruction pciBTFSS = {
233 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
241 0,1, // dest, bit instruction
242 PCC_EXAMINE_PCOP, // inCond
246 pCodeInstruction pciCALL = {
247 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
255 0,0, // dest, bit instruction
260 //fixme - need a COMFW instruction.
261 pCodeInstruction pciCOMF = {
262 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
270 0,0, // dest, bit instruction
275 pCodeInstruction pciCLRF = {
276 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
284 0,0, // dest, bit instruction
285 PCC_REGISTER, // inCond
286 PCC_REGISTER // outCond
289 pCodeInstruction pciCLRW = {
290 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
298 0,0, // dest, bit instruction
303 pCodeInstruction pciDECF = {
304 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
312 1,0, // dest, bit instruction
313 PCC_REGISTER, // inCond
314 PCC_REGISTER // outCond
317 pCodeInstruction pciDECFW = {
318 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
326 0,0, // dest, bit instruction
327 PCC_REGISTER, // inCond
331 pCodeInstruction pciDECFSZ = {
332 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
340 1,0, // dest, bit instruction
341 PCC_REGISTER, // inCond
342 PCC_REGISTER // outCond
345 pCodeInstruction pciDECFSZW = {
346 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
354 0,0, // dest, bit instruction
355 PCC_REGISTER, // inCond
359 pCodeInstruction pciGOTO = {
360 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
368 0,0, // dest, bit instruction
374 pCodeInstruction pciINCF = {
375 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
383 1,0, // dest, bit instruction
384 PCC_REGISTER, // inCond
385 PCC_REGISTER // outCond
388 pCodeInstruction pciINCFW = {
389 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
397 0,0, // dest, bit instruction
398 PCC_REGISTER, // inCond
402 pCodeInstruction pciINCFSZ = {
403 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
411 1,0, // dest, bit instruction
412 PCC_REGISTER, // inCond
413 PCC_REGISTER // outCond
416 pCodeInstruction pciINCFSZW = {
417 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
425 0,0, // dest, bit instruction
426 PCC_REGISTER, // inCond
430 pCodeInstruction pciIORWF = {
431 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
439 1,0, // dest, bit instruction
440 (PCC_W | PCC_REGISTER), // inCond
441 (PCC_REGISTER | PCC_Z) // outCond
444 pCodeInstruction pciIORFW = {
445 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
453 0,0, // dest, bit instruction
454 (PCC_W | PCC_REGISTER), // inCond
455 (PCC_W | PCC_Z) // outCond
458 pCodeInstruction pciIORLW = {
459 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
467 0,0, // dest, bit instruction
469 (PCC_W | PCC_Z) // outCond
472 pCodeInstruction pciMOVF = {
473 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
481 1,0, // dest, bit instruction
482 PCC_REGISTER, // inCond
486 pCodeInstruction pciMOVFW = {
487 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
495 0,0, // dest, bit instruction
496 PCC_REGISTER, // inCond
497 (PCC_W | PCC_Z) // outCond
500 pCodeInstruction pciMOVWF = {
501 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
509 0,0, // dest, bit instruction
514 pCodeInstruction pciMOVLW = {
515 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
523 0,0, // dest, bit instruction
528 pCodeInstruction pciNEGF = {
529 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
537 0,0, // dest, bit instruction
538 PCC_REGISTER, // inCond
543 pCodeInstruction pciRETLW = {
544 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
552 0,0, // dest, bit instruction
557 pCodeInstruction pciRETURN = {
558 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
566 0,0, // dest, bit instruction
572 pCodeInstruction pciSUBWF = {
573 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
581 1,0, // dest, bit instruction
582 (PCC_W | PCC_REGISTER), // inCond
583 (PCC_REGISTER | PCC_Z) // outCond
586 pCodeInstruction pciSUBFW = {
587 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
595 0,0, // dest, bit instruction
596 (PCC_W | PCC_REGISTER), // inCond
597 (PCC_W | PCC_Z) // outCond
600 pCodeInstruction pciSUBLW = {
601 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
609 0,0, // dest, bit instruction
611 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
614 pCodeInstruction pciTRIS = {
615 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
623 0,0, // dest, bit instruction
629 pCodeInstruction pciXORWF = {
630 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
638 1,0, // dest, bit instruction
639 (PCC_W | PCC_REGISTER), // inCond
640 (PCC_REGISTER | PCC_Z) // outCond
643 pCodeInstruction pciXORFW = {
644 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
652 0,0, // dest, bit instruction
653 (PCC_W | PCC_REGISTER), // inCond
654 (PCC_W | PCC_Z) // outCond
657 pCodeInstruction pciXORLW = {
658 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
666 0,0, // dest, bit instruction
668 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
672 #define MAX_PIC14MNEMONICS 100
673 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
675 char *Safe_strdup(char *str)
684 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
693 /*-----------------------------------------------------------------*/
694 /* SAFE_snprintf - like snprintf except the string pointer is */
695 /* after the string has been printed to. This is */
696 /* useful for printing to string as though if it */
698 /*-----------------------------------------------------------------*/
699 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
707 va_start(val, format);
709 // Alas, vsnprintf is not ANSI standard, and does not exist
710 // on Solaris (and probably other non-Gnu flavored Unixes).
711 vsnprintf(*str, *size, format, val);
713 // This, of course, is *not* safe, despite the name.
714 vsprintf(*str, format, val);
725 void pCodeInitRegisters(void)
729 pc_fsr.r = pic14_regWithIdx(4);
733 /*-----------------------------------------------------------------*/
734 /* mnem2key - convert a pic mnemonic into a hash key */
735 /* (BTW - this spreads the mnemonics quite well) */
737 /*-----------------------------------------------------------------*/
739 int mnem2key(char const *mnem)
748 key += toupper(*mnem++) +1;
756 void pic14initMnemonics(void)
761 pCodeInstruction *pci;
763 if(mnemonics_initialized)
766 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
767 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
768 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
769 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
770 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
771 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
772 pic14Mnemonics[POC_BCF] = &pciBCF;
773 pic14Mnemonics[POC_BSF] = &pciBSF;
774 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
775 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
776 pic14Mnemonics[POC_CALL] = &pciCALL;
777 pic14Mnemonics[POC_COMF] = &pciCOMF;
778 pic14Mnemonics[POC_CLRF] = &pciCLRF;
779 pic14Mnemonics[POC_CLRW] = &pciCLRW;
780 pic14Mnemonics[POC_DECF] = &pciDECF;
781 pic14Mnemonics[POC_DECFW] = &pciDECFW;
782 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
783 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
784 pic14Mnemonics[POC_GOTO] = &pciGOTO;
785 pic14Mnemonics[POC_INCF] = &pciINCF;
786 pic14Mnemonics[POC_INCFW] = &pciINCFW;
787 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
788 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
789 pic14Mnemonics[POC_IORLW] = &pciIORLW;
790 pic14Mnemonics[POC_IORWF] = &pciIORWF;
791 pic14Mnemonics[POC_IORFW] = &pciIORFW;
792 pic14Mnemonics[POC_MOVF] = &pciMOVF;
793 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
794 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
795 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
796 pic14Mnemonics[POC_NEGF] = &pciNEGF;
797 pic14Mnemonics[POC_RETLW] = &pciRETLW;
798 pic14Mnemonics[POC_RETURN] = &pciRETURN;
799 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
800 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
801 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
802 pic14Mnemonics[POC_TRIS] = &pciTRIS;
803 pic14Mnemonics[POC_XORLW] = &pciXORLW;
804 pic14Mnemonics[POC_XORWF] = &pciXORWF;
805 pic14Mnemonics[POC_XORFW] = &pciXORFW;
807 for(i=0; i<MAX_PIC14MNEMONICS; i++)
808 if(pic14Mnemonics[i])
809 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
810 pci = hTabFirstItem(pic14MnemonicsHash, &key);
813 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
814 pci = hTabNextItem(pic14MnemonicsHash, &key);
817 mnemonics_initialized = 1;
820 int getpCode(char *mnem,unsigned dest)
823 pCodeInstruction *pci;
824 int key = mnem2key(mnem);
826 if(!mnemonics_initialized)
827 pic14initMnemonics();
829 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
833 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
834 if((pci->num_ops <= 1) || (pci->dest == dest))
838 pci = hTabNextItemWK (pic14MnemonicsHash);
845 char getpBlock_dbName(pBlock *pb)
851 return pb->cmemmap->dbName;
855 /*-----------------------------------------------------------------*/
856 /* movepBlock2Head - given the dbname of a pBlock, move all */
857 /* instances to the front of the doubly linked */
858 /* list of pBlocks */
859 /*-----------------------------------------------------------------*/
861 void movepBlock2Head(char dbName)
865 pb = the_pFile->pbHead;
869 if(getpBlock_dbName(pb) == dbName) {
870 pBlock *pbn = pb->next;
871 pb->next = the_pFile->pbHead;
872 the_pFile->pbHead->prev = pb;
873 the_pFile->pbHead = pb;
876 pb->prev->next = pbn;
878 // If the pBlock that we just moved was the last
879 // one in the link of all of the pBlocks, then we
880 // need to point the tail to the block just before
882 // Note: if pb->next is NULL, then pb must have
883 // been the last pBlock in the chain.
886 pbn->prev = pb->prev;
888 the_pFile->pbTail = pb->prev;
899 void copypCode(FILE *of, char dbName)
903 if(!of || !the_pFile)
906 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
907 if(getpBlock_dbName(pb) == dbName)
912 void pcode_test(void)
915 printf("pcode is alive!\n");
925 /* create the file name */
926 strcpy(buffer,srcFileName);
929 if( !(pFile = fopen(buffer, "w" ))) {
930 werror(E_FILE_OPEN_ERR,buffer);
934 fprintf(pFile,"pcode dump\n\n");
936 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
937 fprintf(pFile,"\n\tNew pBlock\n\n");
939 fprintf(pFile,"%s",pb->cmemmap->sname);
941 fprintf(pFile,"internal pblock");
943 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
944 printpBlock(pFile,pb);
948 static int RegCond(pCodeOp *pcop)
954 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
955 switch(PCOB(pcop)->bit) {
969 /*-----------------------------------------------------------------*/
970 /* newpCode - create and return a newly initialized pCode */
972 /* fixme - rename this */
974 /* The purpose of this routine is to create a new Instruction */
975 /* pCode. This is called by gen.c while the assembly code is being */
979 /* PIC_OPCODE op - the assembly instruction we wish to create. */
980 /* (note that the op is analogous to but not the */
981 /* same thing as the opcode of the instruction.) */
982 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
985 /* a pointer to the new malloc'd pCode is returned. */
989 /*-----------------------------------------------------------------*/
990 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
992 pCodeInstruction *pci ;
994 if(!mnemonics_initialized)
995 pic14initMnemonics();
997 pci = Safe_calloc(1, sizeof(pCodeInstruction));
999 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1000 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1003 if(pci->inCond == PCC_EXAMINE_PCOP)
1004 pci->inCond = RegCond(pcop);
1006 if(pci->outCond == PCC_EXAMINE_PCOP)
1007 pci->outCond = RegCond(pcop);
1009 return (pCode *)pci;
1012 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1018 /*-----------------------------------------------------------------*/
1019 /* newpCodeWild - create a "wild" as in wild card pCode */
1021 /* Wild pcodes are used during the peep hole optimizer to serve */
1022 /* as place holders for any instruction. When a snippet of code is */
1023 /* compared to a peep hole rule, the wild card opcode will match */
1024 /* any instruction. However, the optional operand and label are */
1025 /* additional qualifiers that must also be matched before the */
1026 /* line (of assembly code) is declared matched. Note that the */
1027 /* operand may be wild too. */
1029 /* Note, a wild instruction is specified just like a wild var: */
1030 /* %4 ; A wild instruction, */
1031 /* See the peeph.def file for additional examples */
1033 /*-----------------------------------------------------------------*/
1035 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1040 pcw = Safe_calloc(1,sizeof(pCodeWild));
1042 pcw->pc.type = PC_WILD;
1043 pcw->pc.prev = pcw->pc.next = NULL;
1044 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1047 pcw->pc.analyze = genericAnalyze;
1048 pcw->pc.destruct = genericDestruct;
1049 pcw->pc.print = genericPrint;
1051 pcw->id = pCodeID; // this is the 'n' in %n
1052 pcw->operand = optional_operand;
1053 pcw->label = optional_label;
1055 return ( (pCode *)pcw);
1059 /*-----------------------------------------------------------------*/
1060 /* newPcodeCharP - create a new pCode from a char string */
1061 /*-----------------------------------------------------------------*/
1063 pCode *newpCodeCharP(char *cP)
1068 pcc = Safe_calloc(1,sizeof(pCodeComment));
1070 pcc->pc.type = PC_COMMENT;
1071 pcc->pc.prev = pcc->pc.next = NULL;
1072 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1075 pcc->pc.analyze = genericAnalyze;
1076 pcc->pc.destruct = genericDestruct;
1077 pcc->pc.print = genericPrint;
1079 pcc->comment = Safe_strdup(cP);
1081 return ( (pCode *)pcc);
1085 /*-----------------------------------------------------------------*/
1086 /* newpCodeGLabel - create a new global label */
1087 /*-----------------------------------------------------------------*/
1090 pCode *newpCodeFunction(char *mod,char *f)
1094 _ALLOC(pcf,sizeof(pCodeFunction));
1096 pcf->pc.type = PC_FUNCTION;
1097 pcf->pc.prev = pcf->pc.next = NULL;
1098 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1101 pcf->pc.analyze = genericAnalyze;
1102 pcf->pc.destruct = genericDestruct;
1103 pcf->pc.print = pCodePrintFunction;
1106 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1107 strcpy(pcf->modname,mod);
1109 pcf->modname = NULL;
1112 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1113 strcpy(pcf->fname,f);
1117 return ( (pCode *)pcf);
1121 static void pCodeLabelDestruct(pCode *pc)
1130 free(PCL(pc)->label);
1136 pCode *newpCodeLabel(int key)
1142 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1144 pcl->pc.type = PC_LABEL;
1145 pcl->pc.prev = pcl->pc.next = NULL;
1146 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1149 pcl->pc.analyze = genericAnalyze;
1150 pcl->pc.destruct = pCodeLabelDestruct;
1151 pcl->pc.print = pCodePrintLabel;
1156 sprintf(s,"_%05d_DS_",key);
1157 pcl->label = Safe_strdup(s);
1161 return ( (pCode *)pcl);
1164 pCode *newpCodeLabelStr(char *str)
1166 pCode *pc = newpCodeLabel(-1);
1168 PCL(pc)->label = Safe_strdup(str);
1173 /*-----------------------------------------------------------------*/
1174 /* newpBlock - create and return a pointer to a new pBlock */
1175 /*-----------------------------------------------------------------*/
1176 pBlock *newpBlock(void)
1181 PpB = Safe_calloc(1,sizeof(pBlock) );
1182 PpB->next = PpB->prev = NULL;
1184 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1185 PpB->registers = NULL;
1192 /*-----------------------------------------------------------------*/
1193 /* newpCodeChai0n - create a new chain of pCodes */
1194 /*-----------------------------------------------------------------*
1196 * This function will create a new pBlock and the pointer to the
1197 * pCode that is passed in will be the first pCode in the block.
1198 *-----------------------------------------------------------------*/
1201 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1204 pBlock *pB = newpBlock();
1206 pB->pcHead = pB->pcTail = pc;
1213 /*-----------------------------------------------------------------*/
1214 /* newpCodeOpLabel - Create a new label given the key */
1215 /* Note, a negative key means that the label is part of wild card */
1216 /* (and hence a wild card label) used in the pCodePeep */
1217 /* optimizations). */
1218 /*-----------------------------------------------------------------*/
1220 pCodeOp *newpCodeOpLabel(int key)
1225 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1226 pcop->type = PO_LABEL;
1229 sprintf(s,"_%05d_DS_",key);
1230 pcop->name = Safe_strdup(s);
1234 ((pCodeOpLabel *)pcop)->key = key;
1239 pCodeOp *newpCodeOpLit(int lit)
1245 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1246 pcop->type = PO_LITERAL;
1248 sprintf(s,"0x%02x",lit);
1249 pcop->name = Safe_strdup(s);
1253 ((pCodeOpLit *)pcop)->lit = lit;
1258 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1264 if(!pcp || !subtype) {
1265 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1269 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1270 pcop->type = PO_WILD;
1271 sprintf(s,"%%%d",id);
1272 pcop->name = Safe_strdup(s);
1274 PCOW(pcop)->id = id;
1275 PCOW(pcop)->pcp = pcp;
1276 PCOW(pcop)->subtype = subtype;
1277 PCOW(pcop)->matched = NULL;
1282 pCodeOp *newpCodeOpBit(char *s, int bit)
1286 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1287 pcop->type = PO_BIT;
1288 pcop->name = Safe_strdup(s);
1290 PCOB(pcop)->bit = bit;
1292 PCOB(pcop)->inBitSpace = 1;
1294 PCOB(pcop)->inBitSpace = 0;
1299 /*-----------------------------------------------------------------*/
1300 /*-----------------------------------------------------------------*/
1302 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1308 pcop = newpCodeOpBit(name, -1);
1312 pcop = newpCodeOpLit(-1);
1316 pcop = newpCodeOpLabel(-1);
1320 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1322 pcop->name = Safe_strdup(name);
1328 /*-----------------------------------------------------------------*/
1329 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1330 /*-----------------------------------------------------------------*/
1331 void addpCode2pBlock(pBlock *pb, pCode *pc)
1334 /* If this is the first pcode to be added to a block that
1335 * was initialized with a NULL pcode, then go ahead and
1336 * make this pcode the head and tail */
1337 pb->pcHead = pb->pcTail = pc;
1339 pb->pcTail->next = pc;
1340 pc->prev = pb->pcTail;
1347 /*-----------------------------------------------------------------*/
1348 /* addpBlock - place a pBlock into the pFile */
1349 /*-----------------------------------------------------------------*/
1350 void addpBlock(pBlock *pb)
1354 /* First time called, we'll pass through here. */
1355 _ALLOC(the_pFile,sizeof(the_pFile));
1356 the_pFile->pbHead = the_pFile->pbTail = pb;
1357 the_pFile->functions = NULL;
1361 the_pFile->pbTail->next = pb;
1362 pb->prev = the_pFile->pbTail;
1364 the_pFile->pbTail = pb;
1367 /*-----------------------------------------------------------------*/
1368 /* printpCode - write the contents of a pCode to a file */
1369 /*-----------------------------------------------------------------*/
1370 void printpCode(FILE *of, pCode *pc)
1381 fprintf(of,"warning - unable to print pCode\n");
1384 /*-----------------------------------------------------------------*/
1385 /* printpBlock - write the contents of a pBlock to a file */
1386 /*-----------------------------------------------------------------*/
1387 void printpBlock(FILE *of, pBlock *pb)
1397 for(pc = pb->pcHead; pc; pc = pc->next)
1402 /*-----------------------------------------------------------------*/
1404 /* pCode processing */
1408 /*-----------------------------------------------------------------*/
1410 static void unlinkPC(pCode *pc)
1412 if(pc && pc->prev && pc->next) {
1414 pc->prev->next = pc->next;
1415 pc->next->prev = pc->prev;
1418 static void genericDestruct(pCode *pc)
1420 fprintf(stderr,"warning, calling default pCode destructor\n");
1429 void pBlockRegs(FILE *of, pBlock *pb)
1434 r = setFirstItem(pb->registers);
1436 r = setNextItem(pb->registers);
1441 static char *get_op( pCodeInstruction *pcc)
1445 if(pcc && pcc->pcop) {
1448 switch(pcc->pcop->type) {
1452 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1453 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1454 pBlockRegs(stderr,pcc->pc.pb);
1458 if (pcc->pcop->name)
1459 return pcc->pcop->name;
1464 return "NO operand";
1467 /*-----------------------------------------------------------------*/
1468 /*-----------------------------------------------------------------*/
1469 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1472 fprintf(of,"pcodeopprint\n");
1475 char *pCode2str(char *str, int size, pCode *pc)
1483 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1485 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1487 if(PCI(pc)->bit_inst) {
1488 if(PCI(pc)->pcop->type == PO_BIT) {
1489 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1490 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1491 PCI(pc)->pcop->name ,
1492 PCI(pc)->pcop->name );
1494 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1495 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1497 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1498 //PCI(pc)->pcop->t.bit );
1501 if(PCI(pc)->pcop->type == PO_BIT) {
1502 if( PCI(pc)->num_ops == 2)
1503 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1505 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1508 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1510 if( PCI(pc)->num_ops == 2)
1511 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1519 /* assuming that comment ends with a \n */
1520 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1524 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1527 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1530 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1539 /*-----------------------------------------------------------------*/
1540 /* genericPrint - the contents of a pCode to a file */
1541 /*-----------------------------------------------------------------*/
1542 static void genericPrint(FILE *of, pCode *pc)
1550 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1554 // If the opcode has a label, print that first
1556 pBranch *pbl = pc->label;
1558 if(pbl->pc->type == PC_LABEL)
1559 pCodePrintLabel(of, pbl->pc);
1568 pCode2str(str, 256, pc);
1570 fprintf(of,"%s",str);
1574 pBranch *dpb = pc->to; // debug
1576 switch ( dpb->pc->type) {
1578 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1581 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1584 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1598 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1600 pCodePrintLabel(of, pc->label->pc);
1602 if(PCW(pc)->operand) {
1603 fprintf(of,";\toperand ");
1604 pCodeOpPrint(of,PCW(pc)->operand );
1610 fprintf(of,"unknown pCode type %d\n",pc->type);
1615 /*-----------------------------------------------------------------*/
1616 /* pCodePrintFunction - prints function begin/end */
1617 /*-----------------------------------------------------------------*/
1619 static void pCodePrintFunction(FILE *of, pCode *pc)
1625 if( ((pCodeFunction *)pc)->modname)
1626 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1628 if(PCF(pc)->fname) {
1629 pBranch *exits = pc->to;
1631 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1634 exits = exits->next;
1637 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1641 pc->from->pc->type == PC_FUNCTION &&
1642 PCF(pc->from->pc)->fname)
1643 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1645 fprintf(of,"; exit point [can't find entry point]\n");
1648 /*-----------------------------------------------------------------*/
1649 /* pCodePrintLabel - prints label */
1650 /*-----------------------------------------------------------------*/
1652 static void pCodePrintLabel(FILE *of, pCode *pc)
1659 fprintf(of,"%s\n",PCL(pc)->label);
1660 else if (PCL(pc)->key >=0)
1661 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1663 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1666 /*-----------------------------------------------------------------*/
1668 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1684 /*-----------------------------------------------------------------*/
1685 /* pBranchLink - given two pcodes, this function will link them */
1686 /* together through their pBranches */
1687 /*-----------------------------------------------------------------*/
1688 static void pBranchLink(pCode *f, pCode *t)
1692 // Declare a new branch object for the 'from' pCode.
1694 _ALLOC(b,sizeof(pBranch));
1695 b->pc = t; // The link to the 'to' pCode.
1698 f->to = pBranchAppend(f->to,b);
1700 // Now do the same for the 'to' pCode.
1702 _ALLOC(b,sizeof(pBranch));
1706 t->from = pBranchAppend(t->from,b);
1711 /*-----------------------------------------------------------------*/
1712 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1714 /*-----------------------------------------------------------------*/
1715 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1728 /*-----------------------------------------------------------------*/
1729 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1730 /*-----------------------------------------------------------------*/
1731 static void pCodeUnlink(pCode *pc)
1736 if(!pc->prev || !pc->next) {
1737 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1741 /* first remove the pCode from the chain */
1742 pc->prev->next = pc->next;
1743 pc->next->prev = pc->prev;
1745 /* Now for the hard part... */
1747 /* Remove the branches */
1751 pc1 = pb1->pc; /* Get the pCode that branches to the
1752 * one we're unlinking */
1754 /* search for the link back to this pCode (the one we're
1756 if(pb2 = pBranchFind(pc1->to,pc)) {
1757 pb2->pc = pc->to->pc; // make the replacement
1759 /* if the pCode we're unlinking contains multiple 'to'
1760 * branches (e.g. this a skip instruction) then we need
1761 * to copy these extra branches to the chain. */
1763 pBranchAppend(pb2, pc->to->next);
1772 /*-----------------------------------------------------------------*/
1773 /*-----------------------------------------------------------------*/
1774 static void genericAnalyze(pCode *pc)
1784 // Go through the pCodes that are in pCode chain and link
1785 // them together through the pBranches. Note, the pCodes
1786 // are linked together as a contiguous stream like the
1787 // assembly source code lines. The linking here mimics this
1788 // except that comments are not linked in.
1790 pCode *npc = pc->next;
1792 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1793 pBranchLink(pc,npc);
1802 /*-----------------------------------------------------------------*/
1803 /* findLabel - Search the pCode for a particular label */
1804 /*-----------------------------------------------------------------*/
1805 pCode * findLabel(pCodeOpLabel *pcop_label)
1814 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1815 for(pc = pb->pcHead; pc; pc = pc->next) {
1816 if(pc->type == PC_LABEL) {
1817 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1820 if(pc->type == PC_OPCODE) {
1823 if(pbr->pc->type == PC_LABEL) {
1824 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1834 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1838 /*-----------------------------------------------------------------*/
1839 /* findNextInstruction - given a pCode, find the next instruction */
1840 /* in the linked list */
1841 /*-----------------------------------------------------------------*/
1842 pCode * findNextInstruction(pCode *pc)
1846 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1852 fprintf(stderr,"Couldn't find instruction\n");
1856 /*-----------------------------------------------------------------*/
1857 /* findFunctionEnd - given a pCode find the end of the function */
1858 /* that contains it t */
1859 /*-----------------------------------------------------------------*/
1860 pCode * findFunctionEnd(pCode *pc)
1864 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1870 fprintf(stderr,"Couldn't find function end\n");
1875 /*-----------------------------------------------------------------*/
1876 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1877 /* instruction with which it is associated. */
1878 /*-----------------------------------------------------------------*/
1879 static void AnalyzeLabel(pCode *pc)
1887 static void AnalyzeGOTO(pCode *pc)
1890 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1894 static void AnalyzeSKIP(pCode *pc)
1897 pBranchLink(pc,findNextInstruction(pc->next));
1898 pBranchLink(pc,findNextInstruction(pc->next->next));
1902 static void AnalyzeRETURN(pCode *pc)
1905 // branch_link(pc,findFunctionEnd(pc->next));
1910 void AnalyzepBlock(pBlock *pb)
1917 /* Find all of the registers used in this pBlock */
1918 for(pc = pb->pcHead; pc; pc = pc->next) {
1919 if(pc->type == PC_OPCODE) {
1920 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1922 /* Loop through all of the registers declared so far in
1923 this block and see if we find this new there */
1925 regs *r = setFirstItem(pb->registers);
1928 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1929 PCOR(PCI(pc)->pcop)->r = r;
1932 r = setNextItem(pb->registers);
1936 /* register wasn't found */
1937 r = Safe_calloc(1, sizeof(regs));
1938 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1939 addSet(&pb->registers, r);
1940 PCOR(PCI(pc)->pcop)->r = r;
1941 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1943 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1949 int OptimizepBlock(pBlock *pb)
1954 if(!pb || !peepOptimizing)
1957 fprintf(stderr," Optimizing pBlock\n");
1959 for(pc = pb->pcHead; pc; pc = pc->next)
1960 matches += pCodePeepMatchRule(pc);
1965 /*-----------------------------------------------------------------*/
1966 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1967 /* chain and put them into pBranches that are */
1968 /* associated with the appropriate pCode */
1970 /*-----------------------------------------------------------------*/
1971 void pBlockMergeLabels(pBlock *pb)
1974 pCode *pc, *pcnext=NULL;
1979 for(pc = pb->pcHead; pc; pc = pc->next) {
1981 if(pc->type == PC_LABEL) {
1982 if( !(pcnext = findNextInstruction(pc)) )
1983 return; // Couldn't find an instruction associated with this label
1985 // Unlink the pCode label from it's pCode chain
1987 pc->prev->next = pc->next;
1989 pc->next->prev = pc->prev;
1991 // And link it into the instruction's pBranch labels. (Note, since
1992 // it's possible to have multiple labels associated with one instruction
1993 // we must provide a means to accomodate the additional labels. Thus
1994 // the labels are placed into the singly-linked list "label" as
1995 // opposed to being a single member of the pCodeInstruction.)
1997 _ALLOC(pbr,sizeof(pBranch));
2001 pcnext->label = pBranchAppend(pcnext->label,pbr);
2008 /*-----------------------------------------------------------------*/
2009 /*-----------------------------------------------------------------*/
2010 void OptimizepCode(char dbName)
2012 #define MAX_PASSES 4
2021 fprintf(stderr," Optimizing pCode\n");
2024 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2025 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2026 matches += OptimizepBlock(pb);
2029 while(matches && ++passes < MAX_PASSES);
2033 /*-----------------------------------------------------------------*/
2034 /* AnalyzepCode - parse the pCode that has been generated and form */
2035 /* all of the logical connections. */
2037 /* Essentially what's done here is that the pCode flow is */
2039 /*-----------------------------------------------------------------*/
2041 void AnalyzepCode(char dbName)
2050 fprintf(stderr," Analyzing pCode");
2052 /* First, merge the labels with the instructions */
2053 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2054 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2055 pBlockMergeLabels(pb);
2060 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2061 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2065 /* Now build the call tree.
2066 First we examine all of the pCodes for functions.
2067 Keep in mind that the function boundaries coincide
2068 with pBlock boundaries.
2070 The algorithm goes something like this:
2071 We have two nested loops. The outer loop iterates
2072 through all of the pBlocks/functions. The inner
2073 loop iterates through all of the pCodes for
2074 a given pBlock. When we begin iterating through
2075 a pBlock, the variable pc_fstart, pCode of the start
2076 of a function, is cleared. We then search for pCodes
2077 of type PC_FUNCTION. When one is encountered, we
2078 initialize pc_fstart to this and at the same time
2079 associate a new pBranch object that signifies a
2080 branch entry. If a return is found, then this signifies
2081 a function exit point. We'll link the pCodes of these
2082 returns to the matching pc_fstart.
2084 When we're done, a doubly linked list of pBranches
2085 will exist. The head of this list is stored in
2086 `the_pFile', which is the meta structure for all
2087 of the pCode. Look at the printCallTree function
2088 on how the pBranches are linked together.
2091 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2092 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2093 pCode *pc_fstart=NULL;
2094 for(pc = pb->pcHead; pc; pc = pc->next) {
2095 if(pc->type == PC_FUNCTION) {
2096 if (PCF(pc)->fname) {
2097 // I'm not liking this....
2098 // Found the beginning of a function.
2099 _ALLOC(pbr,sizeof(pBranch));
2100 pbr->pc = pc_fstart = pc;
2103 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2105 // Here's a better way of doing the same:
2106 addSet(&pb->function_entries, pc);
2109 // Found an exit point in a function, e.g. return
2110 // (Note, there may be more than one return per function)
2112 pBranchLink(pc_fstart, pc);
2114 addSet(&pb->function_exits, pc);
2116 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2117 addSet(&pb->function_calls,pc);
2124 /*-----------------------------------------------------------------*/
2125 /* ispCodeFunction - returns true if *pc is the pCode of a */
2127 /*-----------------------------------------------------------------*/
2128 bool ispCodeFunction(pCode *pc)
2131 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2137 /*-----------------------------------------------------------------*/
2138 /* findFunction - Search for a function by name (given the name) */
2139 /* in the set of all functions that are in a pBlock */
2140 /* (note - I expect this to change because I'm planning to limit */
2141 /* pBlock's to just one function declaration */
2142 /*-----------------------------------------------------------------*/
2143 pCode *findFunction(char *fname)
2150 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2152 pc = setFirstItem(pb->function_entries);
2155 if((pc->type == PC_FUNCTION) &&
2157 (strcmp(fname, PCF(pc)->fname)==0))
2160 pc = setNextItem(pb->function_entries);
2168 void MarkUsedRegisters(set *regset)
2173 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2174 r2 = pic14_regWithIdx(r1->rIdx);
2180 void pBlockStats(FILE *of, pBlock *pb)
2186 fprintf(of,"***\n pBlock Stats\n***\n");
2188 // for now just print the first element of each set
2189 pc = setFirstItem(pb->function_entries);
2191 fprintf(of,"entry\n");
2194 pc = setFirstItem(pb->function_exits);
2196 fprintf(of,"has an exit\n");
2200 pc = setFirstItem(pb->function_calls);
2202 fprintf(of,"functions called\n");
2206 pc = setNextItem(pb->function_calls);
2210 r = setFirstItem(pb->registers);
2212 int n = elementsInSet(pb->registers);
2214 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2217 fprintf(of," %s\n",r->name);
2218 r = setNextItem(pb->registers);
2223 /*-----------------------------------------------------------------*/
2224 /*-----------------------------------------------------------------*/
2225 void sequencepCode(void)
2231 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2233 pb->seq = GpCodeSequenceNumber+1;
2235 for( pc = pb->pcHead; pc; pc = pc->next)
2236 pc->seq = ++GpCodeSequenceNumber;
2241 /*-----------------------------------------------------------------*/
2242 /*-----------------------------------------------------------------*/
2243 set *register_usage(pBlock *pb)
2246 set *registers=NULL;
2247 set *registersInCallPath = NULL;
2249 /* check recursion */
2251 pc = setFirstItem(pb->function_entries);
2258 if(pc->type != PC_FUNCTION)
2259 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2261 pc = setFirstItem(pb->function_calls);
2262 for( ; pc; pc = setNextItem(pb->function_calls)) {
2264 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2265 char *dest = get_op(PCI(pc));
2267 pcn = findFunction(dest);
2269 registersInCallPath = register_usage(pcn->pb);
2271 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2276 pBlockStats(stderr,pb); // debug
2277 if(registersInCallPath) {
2278 /* registers were used in the functions this pBlock has called */
2279 /* so now, we need to see if these collide with the ones we are */
2282 regs *r1,*r2, *newreg;
2284 fprintf(stderr,"comparing registers\n");
2286 r1 = setFirstItem(registersInCallPath);
2289 r2 = setFirstItem(pb->registers);
2293 if(r2->rIdx == r1->rIdx) {
2294 newreg = pic14_findFreeReg();
2298 fprintf(stderr,"Bummer, no more registers.\n");
2302 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2303 r1->rIdx, newreg->rIdx);
2304 r2->rIdx = newreg->rIdx;
2305 //if(r2->name) free(r2->name);
2306 r2->name = Safe_strdup(newreg->name);
2308 newreg->wasUsed = 1;
2310 r2 = setNextItem(pb->registers);
2313 r1 = setNextItem(registersInCallPath);
2316 /* Collisions have been resolved. Now free the registers in the call path */
2317 r1 = setFirstItem(registersInCallPath);
2319 newreg = pic14_regWithIdx(r1->rIdx);
2321 r1 = setNextItem(registersInCallPath);
2325 MarkUsedRegisters(pb->registers);
2327 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2330 fprintf(stderr,"returning regs\n");
2332 fprintf(stderr,"not returning regs\n");
2334 fprintf(stderr,"pBlock after register optim.\n");
2335 pBlockStats(stderr,pb); // debug
2341 /*-----------------------------------------------------------------*/
2342 /* printCallTree - writes the call tree to a file */
2344 /*-----------------------------------------------------------------*/
2345 void pct2(FILE *of,pBlock *pb,int indent)
2349 // set *registersInCallPath = NULL;
2352 return;// registers;
2355 return; // registers; //recursion ?
2357 pc = setFirstItem(pb->function_entries);
2364 for(i=0;i<indent;i++) // Indentation
2367 if(pc->type == PC_FUNCTION)
2368 fprintf(of,"%s\n",PCF(pc)->fname);
2373 pc = setFirstItem(pb->function_calls);
2374 for( ; pc; pc = setNextItem(pb->function_calls)) {
2376 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2377 char *dest = get_op(PCI(pc));
2379 pcn = findFunction(dest);
2381 pct2(of,pcn->pb,indent+1);
2383 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2391 fprintf(stderr,"pBlock before register optim.\n");
2392 pBlockStats(stderr,pb); // debug
2394 if(registersInCallPath) {
2395 /* registers were used in the functions this pBlock has called */
2396 /* so now, we need to see if these collide with the ones we are using here */
2398 regs *r1,*r2, *newreg;
2400 fprintf(stderr,"comparing registers\n");
2402 r1 = setFirstItem(registersInCallPath);
2405 r2 = setFirstItem(pb->registers);
2409 if(r2->rIdx == r1->rIdx) {
2410 newreg = pic14_findFreeReg();
2414 fprintf(stderr,"Bummer, no more registers.\n");
2418 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2419 r1->rIdx, newreg->rIdx);
2420 r2->rIdx = newreg->rIdx;
2421 //if(r2->name) free(r2->name);
2422 r2->name = Safe_strdup(newreg->name);
2424 newreg->wasUsed = 1;
2426 r2 = setNextItem(pb->registers);
2429 r1 = setNextItem(registersInCallPath);
2432 /* Collisions have been resolved. Now free the registers in the call path */
2433 r1 = setFirstItem(registersInCallPath);
2435 newreg = pic14_regWithIdx(r1->rIdx);
2437 r1 = setNextItem(registersInCallPath);
2441 MarkUsedRegisters(pb->registers);
2443 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2446 fprintf(stderr,"returning regs\n");
2448 fprintf(stderr,"not returning regs\n");
2450 fprintf(stderr,"pBlock after register optim.\n");
2451 pBlockStats(stderr,pb); // debug
2459 /*-----------------------------------------------------------------*/
2460 /* printCallTree - writes the call tree to a file */
2462 /*-----------------------------------------------------------------*/
2464 void printCallTree(FILE *of)
2476 fprintf(of, "\npBlock statistics\n");
2477 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2478 pBlockStats(stderr,pb);
2482 fprintf(of,"Call Tree\n");
2483 pbr = the_pFile->functions;
2487 if(!ispCodeFunction(pc))
2488 fprintf(of,"bug in call tree");
2491 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2493 while(pc->next && !ispCodeFunction(pc->next)) {
2495 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2496 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2504 /* Re-allocate the registers so that there are no collisions
2505 * between local variables when one function call another */
2507 pic14_deallocateAllRegs();
2509 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2514 fprintf(of,"\n**************\n\na better call tree\n");
2515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2521 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));