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);
708 vsnprintf(*str, *size, format, val);
717 void pCodeInitRegisters(void)
721 pc_fsr.r = pic14_regWithIdx(4);
725 /*-----------------------------------------------------------------*/
726 /* mnem2key - convert a pic mnemonic into a hash key */
727 /* (BTW - this spreads the mnemonics quite well) */
729 /*-----------------------------------------------------------------*/
731 int mnem2key(char const *mnem)
740 key += toupper(*mnem++) +1;
748 void pic14initMnemonics(void)
753 pCodeInstruction *pci;
755 if(mnemonics_initialized)
758 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
759 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
760 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
761 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
762 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
763 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
764 pic14Mnemonics[POC_BCF] = &pciBCF;
765 pic14Mnemonics[POC_BSF] = &pciBSF;
766 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
767 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
768 pic14Mnemonics[POC_CALL] = &pciCALL;
769 pic14Mnemonics[POC_COMF] = &pciCOMF;
770 pic14Mnemonics[POC_CLRF] = &pciCLRF;
771 pic14Mnemonics[POC_CLRW] = &pciCLRW;
772 pic14Mnemonics[POC_DECF] = &pciDECF;
773 pic14Mnemonics[POC_DECFW] = &pciDECFW;
774 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
775 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
776 pic14Mnemonics[POC_GOTO] = &pciGOTO;
777 pic14Mnemonics[POC_INCF] = &pciINCF;
778 pic14Mnemonics[POC_INCFW] = &pciINCFW;
779 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
780 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
781 pic14Mnemonics[POC_IORLW] = &pciIORLW;
782 pic14Mnemonics[POC_IORWF] = &pciIORWF;
783 pic14Mnemonics[POC_IORFW] = &pciIORFW;
784 pic14Mnemonics[POC_MOVF] = &pciMOVF;
785 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
786 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
787 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
788 pic14Mnemonics[POC_NEGF] = &pciNEGF;
789 pic14Mnemonics[POC_RETLW] = &pciRETLW;
790 pic14Mnemonics[POC_RETURN] = &pciRETURN;
791 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
792 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
793 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
794 pic14Mnemonics[POC_TRIS] = &pciTRIS;
795 pic14Mnemonics[POC_XORLW] = &pciXORLW;
796 pic14Mnemonics[POC_XORWF] = &pciXORWF;
797 pic14Mnemonics[POC_XORFW] = &pciXORFW;
799 for(i=0; i<MAX_PIC14MNEMONICS; i++)
800 if(pic14Mnemonics[i])
801 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
802 pci = hTabFirstItem(pic14MnemonicsHash, &key);
805 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
806 pci = hTabNextItem(pic14MnemonicsHash, &key);
809 mnemonics_initialized = 1;
812 int getpCode(char *mnem,unsigned dest)
815 pCodeInstruction *pci;
816 int key = mnem2key(mnem);
818 if(!mnemonics_initialized)
819 pic14initMnemonics();
821 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
825 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
826 if((pci->num_ops <= 1) || (pci->dest == dest))
830 pci = hTabNextItemWK (pic14MnemonicsHash);
837 char getpBlock_dbName(pBlock *pb)
843 return pb->cmemmap->dbName;
847 /*-----------------------------------------------------------------*/
848 /* movepBlock2Head - given the dbname of a pBlock, move all */
849 /* instances to the front of the doubly linked */
850 /* list of pBlocks */
851 /*-----------------------------------------------------------------*/
853 void movepBlock2Head(char dbName)
857 pb = the_pFile->pbHead;
861 if(getpBlock_dbName(pb) == dbName) {
862 pBlock *pbn = pb->next;
863 pb->next = the_pFile->pbHead;
864 the_pFile->pbHead->prev = pb;
865 the_pFile->pbHead = pb;
868 pb->prev->next = pbn;
870 // If the pBlock that we just moved was the last
871 // one in the link of all of the pBlocks, then we
872 // need to point the tail to the block just before
874 // Note: if pb->next is NULL, then pb must have
875 // been the last pBlock in the chain.
878 pbn->prev = pb->prev;
880 the_pFile->pbTail = pb->prev;
891 void copypCode(FILE *of, char dbName)
895 if(!of || !the_pFile)
898 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
899 if(getpBlock_dbName(pb) == dbName)
904 void pcode_test(void)
907 printf("pcode is alive!\n");
917 /* create the file name */
918 strcpy(buffer,srcFileName);
921 if( !(pFile = fopen(buffer, "w" ))) {
922 werror(E_FILE_OPEN_ERR,buffer);
926 fprintf(pFile,"pcode dump\n\n");
928 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
929 fprintf(pFile,"\n\tNew pBlock\n\n");
931 fprintf(pFile,"%s",pb->cmemmap->sname);
933 fprintf(pFile,"internal pblock");
935 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
936 printpBlock(pFile,pb);
940 static int RegCond(pCodeOp *pcop)
946 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
947 switch(PCOB(pcop)->bit) {
961 /*-----------------------------------------------------------------*/
962 /* newpCode - create and return a newly initialized pCode */
964 /* fixme - rename this */
966 /* The purpose of this routine is to create a new Instruction */
967 /* pCode. This is called by gen.c while the assembly code is being */
971 /* PIC_OPCODE op - the assembly instruction we wish to create. */
972 /* (note that the op is analogous to but not the */
973 /* same thing as the opcode of the instruction.) */
974 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
977 /* a pointer to the new malloc'd pCode is returned. */
981 /*-----------------------------------------------------------------*/
982 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
984 pCodeInstruction *pci ;
986 if(!mnemonics_initialized)
987 pic14initMnemonics();
989 pci = Safe_calloc(1, sizeof(pCodeInstruction));
991 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
992 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
995 if(pci->inCond == PCC_EXAMINE_PCOP)
996 pci->inCond = RegCond(pcop);
998 if(pci->outCond == PCC_EXAMINE_PCOP)
999 pci->outCond = RegCond(pcop);
1001 return (pCode *)pci;
1004 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1010 /*-----------------------------------------------------------------*/
1011 /* newpCodeWild - create a "wild" as in wild card pCode */
1013 /* Wild pcodes are used during the peep hole optimizer to serve */
1014 /* as place holders for any instruction. When a snippet of code is */
1015 /* compared to a peep hole rule, the wild card opcode will match */
1016 /* any instruction. However, the optional operand and label are */
1017 /* additional qualifiers that must also be matched before the */
1018 /* line (of assembly code) is declared matched. Note that the */
1019 /* operand may be wild too. */
1021 /* Note, a wild instruction is specified just like a wild var: */
1022 /* %4 ; A wild instruction, */
1023 /* See the peeph.def file for additional examples */
1025 /*-----------------------------------------------------------------*/
1027 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1032 pcw = Safe_calloc(1,sizeof(pCodeWild));
1034 pcw->pc.type = PC_WILD;
1035 pcw->pc.prev = pcw->pc.next = NULL;
1036 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1039 pcw->pc.analyze = genericAnalyze;
1040 pcw->pc.destruct = genericDestruct;
1041 pcw->pc.print = genericPrint;
1043 pcw->id = pCodeID; // this is the 'n' in %n
1044 pcw->operand = optional_operand;
1045 pcw->label = optional_label;
1047 return ( (pCode *)pcw);
1051 /*-----------------------------------------------------------------*/
1052 /* newPcodeCharP - create a new pCode from a char string */
1053 /*-----------------------------------------------------------------*/
1055 pCode *newpCodeCharP(char *cP)
1060 pcc = Safe_calloc(1,sizeof(pCodeComment));
1062 pcc->pc.type = PC_COMMENT;
1063 pcc->pc.prev = pcc->pc.next = NULL;
1064 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1067 pcc->pc.analyze = genericAnalyze;
1068 pcc->pc.destruct = genericDestruct;
1069 pcc->pc.print = genericPrint;
1071 pcc->comment = Safe_strdup(cP);
1073 return ( (pCode *)pcc);
1077 /*-----------------------------------------------------------------*/
1078 /* newpCodeGLabel - create a new global label */
1079 /*-----------------------------------------------------------------*/
1082 pCode *newpCodeFunction(char *mod,char *f)
1086 _ALLOC(pcf,sizeof(pCodeFunction));
1088 pcf->pc.type = PC_FUNCTION;
1089 pcf->pc.prev = pcf->pc.next = NULL;
1090 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1093 pcf->pc.analyze = genericAnalyze;
1094 pcf->pc.destruct = genericDestruct;
1095 pcf->pc.print = pCodePrintFunction;
1098 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1099 strcpy(pcf->modname,mod);
1101 pcf->modname = NULL;
1104 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1105 strcpy(pcf->fname,f);
1109 return ( (pCode *)pcf);
1113 static void pCodeLabelDestruct(pCode *pc)
1122 free(PCL(pc)->label);
1128 pCode *newpCodeLabel(int key)
1134 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1136 pcl->pc.type = PC_LABEL;
1137 pcl->pc.prev = pcl->pc.next = NULL;
1138 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1141 pcl->pc.analyze = genericAnalyze;
1142 pcl->pc.destruct = pCodeLabelDestruct;
1143 pcl->pc.print = pCodePrintLabel;
1148 sprintf(s,"_%05d_DS_",key);
1149 pcl->label = Safe_strdup(s);
1153 return ( (pCode *)pcl);
1156 pCode *newpCodeLabelStr(char *str)
1158 pCode *pc = newpCodeLabel(-1);
1160 PCL(pc)->label = Safe_strdup(str);
1165 /*-----------------------------------------------------------------*/
1166 /* newpBlock - create and return a pointer to a new pBlock */
1167 /*-----------------------------------------------------------------*/
1168 pBlock *newpBlock(void)
1173 PpB = Safe_calloc(1,sizeof(pBlock) );
1174 PpB->next = PpB->prev = NULL;
1176 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1177 PpB->registers = NULL;
1184 /*-----------------------------------------------------------------*/
1185 /* newpCodeChai0n - create a new chain of pCodes */
1186 /*-----------------------------------------------------------------*
1188 * This function will create a new pBlock and the pointer to the
1189 * pCode that is passed in will be the first pCode in the block.
1190 *-----------------------------------------------------------------*/
1193 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1196 pBlock *pB = newpBlock();
1198 pB->pcHead = pB->pcTail = pc;
1205 /*-----------------------------------------------------------------*/
1206 /* newpCodeOpLabel - Create a new label given the key */
1207 /* Note, a negative key means that the label is part of wild card */
1208 /* (and hence a wild card label) used in the pCodePeep */
1209 /* optimizations). */
1210 /*-----------------------------------------------------------------*/
1212 pCodeOp *newpCodeOpLabel(int key)
1217 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1218 pcop->type = PO_LABEL;
1221 sprintf(s,"_%05d_DS_",key);
1222 pcop->name = Safe_strdup(s);
1226 ((pCodeOpLabel *)pcop)->key = key;
1231 pCodeOp *newpCodeOpLit(int lit)
1237 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1238 pcop->type = PO_LITERAL;
1240 sprintf(s,"0x%02x",lit);
1241 pcop->name = Safe_strdup(s);
1245 ((pCodeOpLit *)pcop)->lit = lit;
1250 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1256 if(!pcp || !subtype) {
1257 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1261 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1262 pcop->type = PO_WILD;
1263 sprintf(s,"%%%d",id);
1264 pcop->name = Safe_strdup(s);
1266 PCOW(pcop)->id = id;
1267 PCOW(pcop)->pcp = pcp;
1268 PCOW(pcop)->subtype = subtype;
1269 PCOW(pcop)->matched = NULL;
1274 pCodeOp *newpCodeOpBit(char *s, int bit)
1278 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1279 pcop->type = PO_BIT;
1280 pcop->name = Safe_strdup(s);
1282 PCOB(pcop)->bit = bit;
1284 PCOB(pcop)->inBitSpace = 1;
1286 PCOB(pcop)->inBitSpace = 0;
1291 /*-----------------------------------------------------------------*/
1292 /*-----------------------------------------------------------------*/
1294 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1300 pcop = newpCodeOpBit(name, -1);
1304 pcop = newpCodeOpLit(-1);
1308 pcop = newpCodeOpLabel(-1);
1312 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1314 pcop->name = Safe_strdup(name);
1320 /*-----------------------------------------------------------------*/
1321 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1322 /*-----------------------------------------------------------------*/
1323 void addpCode2pBlock(pBlock *pb, pCode *pc)
1326 /* If this is the first pcode to be added to a block that
1327 * was initialized with a NULL pcode, then go ahead and
1328 * make this pcode the head and tail */
1329 pb->pcHead = pb->pcTail = pc;
1331 pb->pcTail->next = pc;
1332 pc->prev = pb->pcTail;
1339 /*-----------------------------------------------------------------*/
1340 /* addpBlock - place a pBlock into the pFile */
1341 /*-----------------------------------------------------------------*/
1342 void addpBlock(pBlock *pb)
1346 /* First time called, we'll pass through here. */
1347 _ALLOC(the_pFile,sizeof(the_pFile));
1348 the_pFile->pbHead = the_pFile->pbTail = pb;
1349 the_pFile->functions = NULL;
1353 the_pFile->pbTail->next = pb;
1354 pb->prev = the_pFile->pbTail;
1356 the_pFile->pbTail = pb;
1359 /*-----------------------------------------------------------------*/
1360 /* printpCode - write the contents of a pCode to a file */
1361 /*-----------------------------------------------------------------*/
1362 void printpCode(FILE *of, pCode *pc)
1373 fprintf(of,"warning - unable to print pCode\n");
1376 /*-----------------------------------------------------------------*/
1377 /* printpBlock - write the contents of a pBlock to a file */
1378 /*-----------------------------------------------------------------*/
1379 void printpBlock(FILE *of, pBlock *pb)
1389 for(pc = pb->pcHead; pc; pc = pc->next)
1394 /*-----------------------------------------------------------------*/
1396 /* pCode processing */
1400 /*-----------------------------------------------------------------*/
1402 static void unlinkPC(pCode *pc)
1404 if(pc && pc->prev && pc->next) {
1406 pc->prev->next = pc->next;
1407 pc->next->prev = pc->prev;
1410 static void genericDestruct(pCode *pc)
1412 fprintf(stderr,"warning, calling default pCode destructor\n");
1421 void pBlockRegs(FILE *of, pBlock *pb)
1426 r = setFirstItem(pb->registers);
1428 r = setNextItem(pb->registers);
1433 static char *get_op( pCodeInstruction *pcc)
1437 if(pcc && pcc->pcop) {
1440 switch(pcc->pcop->type) {
1444 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1445 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1446 pBlockRegs(stderr,pcc->pc.pb);
1450 if (pcc->pcop->name)
1451 return pcc->pcop->name;
1456 return "NO operand";
1459 /*-----------------------------------------------------------------*/
1460 /*-----------------------------------------------------------------*/
1461 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1464 fprintf(of,"pcodeopprint\n");
1467 char *pCode2str(char *str, int size, pCode *pc)
1475 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1477 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1479 if(PCI(pc)->bit_inst) {
1480 if(PCI(pc)->pcop->type == PO_BIT) {
1481 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1482 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1483 PCI(pc)->pcop->name ,
1484 PCI(pc)->pcop->name );
1486 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1487 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1489 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1490 //PCI(pc)->pcop->t.bit );
1493 if(PCI(pc)->pcop->type == PO_BIT) {
1494 if( PCI(pc)->num_ops == 2)
1495 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1497 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1500 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1502 if( PCI(pc)->num_ops == 2)
1503 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1511 /* assuming that comment ends with a \n */
1512 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1516 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1519 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1522 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1531 /*-----------------------------------------------------------------*/
1532 /* genericPrint - the contents of a pCode to a file */
1533 /*-----------------------------------------------------------------*/
1534 static void genericPrint(FILE *of, pCode *pc)
1542 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1546 // If the opcode has a label, print that first
1548 pBranch *pbl = pc->label;
1550 if(pbl->pc->type == PC_LABEL)
1551 pCodePrintLabel(of, pbl->pc);
1560 pCode2str(str, 256, pc);
1562 fprintf(of,"%s",str);
1566 pBranch *dpb = pc->to; // debug
1568 switch ( dpb->pc->type) {
1570 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1573 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1576 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1590 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1592 pCodePrintLabel(of, pc->label->pc);
1594 if(PCW(pc)->operand) {
1595 fprintf(of,";\toperand ");
1596 pCodeOpPrint(of,PCW(pc)->operand );
1602 fprintf(of,"unknown pCode type %d\n",pc->type);
1607 /*-----------------------------------------------------------------*/
1608 /* pCodePrintFunction - prints function begin/end */
1609 /*-----------------------------------------------------------------*/
1611 static void pCodePrintFunction(FILE *of, pCode *pc)
1617 if( ((pCodeFunction *)pc)->modname)
1618 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1620 if(PCF(pc)->fname) {
1621 pBranch *exits = pc->to;
1623 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1626 exits = exits->next;
1629 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1633 pc->from->pc->type == PC_FUNCTION &&
1634 PCF(pc->from->pc)->fname)
1635 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1637 fprintf(of,"; exit point [can't find entry point]\n");
1640 /*-----------------------------------------------------------------*/
1641 /* pCodePrintLabel - prints label */
1642 /*-----------------------------------------------------------------*/
1644 static void pCodePrintLabel(FILE *of, pCode *pc)
1651 fprintf(of,"%s\n",PCL(pc)->label);
1652 else if (PCL(pc)->key >=0)
1653 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1655 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1658 /*-----------------------------------------------------------------*/
1660 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1676 /*-----------------------------------------------------------------*/
1677 /* pBranchLink - given two pcodes, this function will link them */
1678 /* together through their pBranches */
1679 /*-----------------------------------------------------------------*/
1680 static void pBranchLink(pCode *f, pCode *t)
1684 // Declare a new branch object for the 'from' pCode.
1686 _ALLOC(b,sizeof(pBranch));
1687 b->pc = t; // The link to the 'to' pCode.
1690 f->to = pBranchAppend(f->to,b);
1692 // Now do the same for the 'to' pCode.
1694 _ALLOC(b,sizeof(pBranch));
1698 t->from = pBranchAppend(t->from,b);
1703 /*-----------------------------------------------------------------*/
1704 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1706 /*-----------------------------------------------------------------*/
1707 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1720 /*-----------------------------------------------------------------*/
1721 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1722 /*-----------------------------------------------------------------*/
1723 static void pCodeUnlink(pCode *pc)
1728 if(!pc->prev || !pc->next) {
1729 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1733 /* first remove the pCode from the chain */
1734 pc->prev->next = pc->next;
1735 pc->next->prev = pc->prev;
1737 /* Now for the hard part... */
1739 /* Remove the branches */
1743 pc1 = pb1->pc; /* Get the pCode that branches to the
1744 * one we're unlinking */
1746 /* search for the link back to this pCode (the one we're
1748 if(pb2 = pBranchFind(pc1->to,pc)) {
1749 pb2->pc = pc->to->pc; // make the replacement
1751 /* if the pCode we're unlinking contains multiple 'to'
1752 * branches (e.g. this a skip instruction) then we need
1753 * to copy these extra branches to the chain. */
1755 pBranchAppend(pb2, pc->to->next);
1764 /*-----------------------------------------------------------------*/
1765 /*-----------------------------------------------------------------*/
1766 static void genericAnalyze(pCode *pc)
1776 // Go through the pCodes that are in pCode chain and link
1777 // them together through the pBranches. Note, the pCodes
1778 // are linked together as a contiguous stream like the
1779 // assembly source code lines. The linking here mimics this
1780 // except that comments are not linked in.
1782 pCode *npc = pc->next;
1784 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1785 pBranchLink(pc,npc);
1794 /*-----------------------------------------------------------------*/
1795 /* findLabel - Search the pCode for a particular label */
1796 /*-----------------------------------------------------------------*/
1797 pCode * findLabel(pCodeOpLabel *pcop_label)
1806 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1807 for(pc = pb->pcHead; pc; pc = pc->next) {
1808 if(pc->type == PC_LABEL) {
1809 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1812 if(pc->type == PC_OPCODE) {
1815 if(pbr->pc->type == PC_LABEL) {
1816 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1826 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1830 /*-----------------------------------------------------------------*/
1831 /* findNextInstruction - given a pCode, find the next instruction */
1832 /* in the linked list */
1833 /*-----------------------------------------------------------------*/
1834 pCode * findNextInstruction(pCode *pc)
1838 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1844 fprintf(stderr,"Couldn't find instruction\n");
1848 /*-----------------------------------------------------------------*/
1849 /* findFunctionEnd - given a pCode find the end of the function */
1850 /* that contains it t */
1851 /*-----------------------------------------------------------------*/
1852 pCode * findFunctionEnd(pCode *pc)
1856 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1862 fprintf(stderr,"Couldn't find function end\n");
1867 /*-----------------------------------------------------------------*/
1868 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1869 /* instruction with which it is associated. */
1870 /*-----------------------------------------------------------------*/
1871 static void AnalyzeLabel(pCode *pc)
1879 static void AnalyzeGOTO(pCode *pc)
1882 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1886 static void AnalyzeSKIP(pCode *pc)
1889 pBranchLink(pc,findNextInstruction(pc->next));
1890 pBranchLink(pc,findNextInstruction(pc->next->next));
1894 static void AnalyzeRETURN(pCode *pc)
1897 // branch_link(pc,findFunctionEnd(pc->next));
1902 void AnalyzepBlock(pBlock *pb)
1909 /* Find all of the registers used in this pBlock */
1910 for(pc = pb->pcHead; pc; pc = pc->next) {
1911 if(pc->type == PC_OPCODE) {
1912 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1914 /* Loop through all of the registers declared so far in
1915 this block and see if we find this new there */
1917 regs *r = setFirstItem(pb->registers);
1920 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1921 PCOR(PCI(pc)->pcop)->r = r;
1924 r = setNextItem(pb->registers);
1928 /* register wasn't found */
1929 r = Safe_calloc(1, sizeof(regs));
1930 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1931 addSet(&pb->registers, r);
1932 PCOR(PCI(pc)->pcop)->r = r;
1933 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1935 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1941 int OptimizepBlock(pBlock *pb)
1946 if(!pb || !peepOptimizing)
1949 fprintf(stderr," Optimizing pBlock\n");
1951 for(pc = pb->pcHead; pc; pc = pc->next)
1952 matches += pCodePeepMatchRule(pc);
1957 /*-----------------------------------------------------------------*/
1958 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1959 /* chain and put them into pBranches that are */
1960 /* associated with the appropriate pCode */
1962 /*-----------------------------------------------------------------*/
1963 void pBlockMergeLabels(pBlock *pb)
1966 pCode *pc, *pcnext=NULL;
1971 for(pc = pb->pcHead; pc; pc = pc->next) {
1973 if(pc->type == PC_LABEL) {
1974 if( !(pcnext = findNextInstruction(pc)) )
1975 return; // Couldn't find an instruction associated with this label
1977 // Unlink the pCode label from it's pCode chain
1979 pc->prev->next = pc->next;
1981 pc->next->prev = pc->prev;
1983 // And link it into the instruction's pBranch labels. (Note, since
1984 // it's possible to have multiple labels associated with one instruction
1985 // we must provide a means to accomodate the additional labels. Thus
1986 // the labels are placed into the singly-linked list "label" as
1987 // opposed to being a single member of the pCodeInstruction.)
1989 _ALLOC(pbr,sizeof(pBranch));
1993 pcnext->label = pBranchAppend(pcnext->label,pbr);
2000 /*-----------------------------------------------------------------*/
2001 /*-----------------------------------------------------------------*/
2002 void OptimizepCode(char dbName)
2004 #define MAX_PASSES 4
2013 fprintf(stderr," Optimizing pCode\n");
2016 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2017 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2018 matches += OptimizepBlock(pb);
2021 while(matches && ++passes < MAX_PASSES);
2025 /*-----------------------------------------------------------------*/
2026 /* AnalyzepCode - parse the pCode that has been generated and form */
2027 /* all of the logical connections. */
2029 /* Essentially what's done here is that the pCode flow is */
2031 /*-----------------------------------------------------------------*/
2033 void AnalyzepCode(char dbName)
2042 fprintf(stderr," Analyzing pCode");
2044 /* First, merge the labels with the instructions */
2045 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2046 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2047 pBlockMergeLabels(pb);
2052 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2053 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2057 /* Now build the call tree.
2058 First we examine all of the pCodes for functions.
2059 Keep in mind that the function boundaries coincide
2060 with pBlock boundaries.
2062 The algorithm goes something like this:
2063 We have two nested loops. The outer loop iterates
2064 through all of the pBlocks/functions. The inner
2065 loop iterates through all of the pCodes for
2066 a given pBlock. When we begin iterating through
2067 a pBlock, the variable pc_fstart, pCode of the start
2068 of a function, is cleared. We then search for pCodes
2069 of type PC_FUNCTION. When one is encountered, we
2070 initialize pc_fstart to this and at the same time
2071 associate a new pBranch object that signifies a
2072 branch entry. If a return is found, then this signifies
2073 a function exit point. We'll link the pCodes of these
2074 returns to the matching pc_fstart.
2076 When we're done, a doubly linked list of pBranches
2077 will exist. The head of this list is stored in
2078 `the_pFile', which is the meta structure for all
2079 of the pCode. Look at the printCallTree function
2080 on how the pBranches are linked together.
2083 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2084 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2085 pCode *pc_fstart=NULL;
2086 for(pc = pb->pcHead; pc; pc = pc->next) {
2087 if(pc->type == PC_FUNCTION) {
2088 if (PCF(pc)->fname) {
2089 // I'm not liking this....
2090 // Found the beginning of a function.
2091 _ALLOC(pbr,sizeof(pBranch));
2092 pbr->pc = pc_fstart = pc;
2095 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2097 // Here's a better way of doing the same:
2098 addSet(&pb->function_entries, pc);
2101 // Found an exit point in a function, e.g. return
2102 // (Note, there may be more than one return per function)
2104 pBranchLink(pc_fstart, pc);
2106 addSet(&pb->function_exits, pc);
2108 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2109 addSet(&pb->function_calls,pc);
2116 /*-----------------------------------------------------------------*/
2117 /* ispCodeFunction - returns true if *pc is the pCode of a */
2119 /*-----------------------------------------------------------------*/
2120 bool ispCodeFunction(pCode *pc)
2123 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2129 /*-----------------------------------------------------------------*/
2130 /* findFunction - Search for a function by name (given the name) */
2131 /* in the set of all functions that are in a pBlock */
2132 /* (note - I expect this to change because I'm planning to limit */
2133 /* pBlock's to just one function declaration */
2134 /*-----------------------------------------------------------------*/
2135 pCode *findFunction(char *fname)
2142 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2144 pc = setFirstItem(pb->function_entries);
2147 if((pc->type == PC_FUNCTION) &&
2149 (strcmp(fname, PCF(pc)->fname)==0))
2152 pc = setNextItem(pb->function_entries);
2160 void MarkUsedRegisters(set *regset)
2165 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2166 r2 = pic14_regWithIdx(r1->rIdx);
2172 void pBlockStats(FILE *of, pBlock *pb)
2178 fprintf(of,"***\n pBlock Stats\n***\n");
2180 // for now just print the first element of each set
2181 pc = setFirstItem(pb->function_entries);
2183 fprintf(of,"entry\n");
2186 pc = setFirstItem(pb->function_exits);
2188 fprintf(of,"has an exit\n");
2192 pc = setFirstItem(pb->function_calls);
2194 fprintf(of,"functions called\n");
2198 pc = setNextItem(pb->function_calls);
2202 r = setFirstItem(pb->registers);
2204 int n = elementsInSet(pb->registers);
2206 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2209 fprintf(of," %s\n",r->name);
2210 r = setNextItem(pb->registers);
2215 /*-----------------------------------------------------------------*/
2216 /*-----------------------------------------------------------------*/
2217 void sequencepCode(void)
2223 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2225 pb->seq = GpCodeSequenceNumber+1;
2227 for( pc = pb->pcHead; pc; pc = pc->next)
2228 pc->seq = ++GpCodeSequenceNumber;
2233 /*-----------------------------------------------------------------*/
2234 /*-----------------------------------------------------------------*/
2235 set *register_usage(pBlock *pb)
2238 set *registers=NULL;
2239 set *registersInCallPath = NULL;
2241 /* check recursion */
2243 pc = setFirstItem(pb->function_entries);
2250 if(pc->type != PC_FUNCTION)
2251 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2253 pc = setFirstItem(pb->function_calls);
2254 for( ; pc; pc = setNextItem(pb->function_calls)) {
2256 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2257 char *dest = get_op(PCI(pc));
2259 pcn = findFunction(dest);
2261 registersInCallPath = register_usage(pcn->pb);
2263 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2268 pBlockStats(stderr,pb); // debug
2269 if(registersInCallPath) {
2270 /* registers were used in the functions this pBlock has called */
2271 /* so now, we need to see if these collide with the ones we are */
2274 regs *r1,*r2, *newreg;
2276 fprintf(stderr,"comparing registers\n");
2278 r1 = setFirstItem(registersInCallPath);
2281 r2 = setFirstItem(pb->registers);
2285 if(r2->rIdx == r1->rIdx) {
2286 newreg = pic14_findFreeReg();
2290 fprintf(stderr,"Bummer, no more registers.\n");
2294 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2295 r1->rIdx, newreg->rIdx);
2296 r2->rIdx = newreg->rIdx;
2297 //if(r2->name) free(r2->name);
2298 r2->name = Safe_strdup(newreg->name);
2300 newreg->wasUsed = 1;
2302 r2 = setNextItem(pb->registers);
2305 r1 = setNextItem(registersInCallPath);
2308 /* Collisions have been resolved. Now free the registers in the call path */
2309 r1 = setFirstItem(registersInCallPath);
2311 newreg = pic14_regWithIdx(r1->rIdx);
2313 r1 = setNextItem(registersInCallPath);
2317 MarkUsedRegisters(pb->registers);
2319 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2322 fprintf(stderr,"returning regs\n");
2324 fprintf(stderr,"not returning regs\n");
2326 fprintf(stderr,"pBlock after register optim.\n");
2327 pBlockStats(stderr,pb); // debug
2333 /*-----------------------------------------------------------------*/
2334 /* printCallTree - writes the call tree to a file */
2336 /*-----------------------------------------------------------------*/
2337 void pct2(FILE *of,pBlock *pb,int indent)
2341 // set *registersInCallPath = NULL;
2344 return;// registers;
2347 return; // registers; //recursion ?
2349 pc = setFirstItem(pb->function_entries);
2356 for(i=0;i<indent;i++) // Indentation
2359 if(pc->type == PC_FUNCTION)
2360 fprintf(of,"%s\n",PCF(pc)->fname);
2365 pc = setFirstItem(pb->function_calls);
2366 for( ; pc; pc = setNextItem(pb->function_calls)) {
2368 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2369 char *dest = get_op(PCI(pc));
2371 pcn = findFunction(dest);
2373 pct2(of,pcn->pb,indent+1);
2375 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2383 fprintf(stderr,"pBlock before register optim.\n");
2384 pBlockStats(stderr,pb); // debug
2386 if(registersInCallPath) {
2387 /* registers were used in the functions this pBlock has called */
2388 /* so now, we need to see if these collide with the ones we are using here */
2390 regs *r1,*r2, *newreg;
2392 fprintf(stderr,"comparing registers\n");
2394 r1 = setFirstItem(registersInCallPath);
2397 r2 = setFirstItem(pb->registers);
2401 if(r2->rIdx == r1->rIdx) {
2402 newreg = pic14_findFreeReg();
2406 fprintf(stderr,"Bummer, no more registers.\n");
2410 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2411 r1->rIdx, newreg->rIdx);
2412 r2->rIdx = newreg->rIdx;
2413 //if(r2->name) free(r2->name);
2414 r2->name = Safe_strdup(newreg->name);
2416 newreg->wasUsed = 1;
2418 r2 = setNextItem(pb->registers);
2421 r1 = setNextItem(registersInCallPath);
2424 /* Collisions have been resolved. Now free the registers in the call path */
2425 r1 = setFirstItem(registersInCallPath);
2427 newreg = pic14_regWithIdx(r1->rIdx);
2429 r1 = setNextItem(registersInCallPath);
2433 MarkUsedRegisters(pb->registers);
2435 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2438 fprintf(stderr,"returning regs\n");
2440 fprintf(stderr,"not returning regs\n");
2442 fprintf(stderr,"pBlock after register optim.\n");
2443 pBlockStats(stderr,pb); // debug
2451 /*-----------------------------------------------------------------*/
2452 /* printCallTree - writes the call tree to a file */
2454 /*-----------------------------------------------------------------*/
2456 void printCallTree(FILE *of)
2468 fprintf(of, "\npBlock statistics\n");
2469 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2470 pBlockStats(stderr,pb);
2474 fprintf(of,"Call Tree\n");
2475 pbr = the_pFile->functions;
2479 if(!ispCodeFunction(pc))
2480 fprintf(of,"bug in call tree");
2483 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2485 while(pc->next && !ispCodeFunction(pc->next)) {
2487 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2488 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2496 /* Re-allocate the registers so that there are no collisions
2497 * between local variables when one function call another */
2499 pic14_deallocateAllRegs();
2501 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2506 fprintf(of,"\n**************\n\na better call tree\n");
2507 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2512 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2513 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));