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__);
692 void pCodeInitRegisters(void)
696 pc_fsr.r = pic14_regWithIdx(4);
700 /*-----------------------------------------------------------------*/
701 /* mnem2key - convert a pic mnemonic into a hash key */
702 /* (BTW - this spreads the mnemonics quite well) */
704 /*-----------------------------------------------------------------*/
706 int mnem2key(char const *mnem)
715 key += toupper(*mnem++) +1;
723 void pic14initMnemonics(void)
728 pCodeInstruction *pci;
730 if(mnemonics_initialized)
733 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
734 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
735 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
736 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
737 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
738 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
739 pic14Mnemonics[POC_BCF] = &pciBCF;
740 pic14Mnemonics[POC_BSF] = &pciBSF;
741 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
742 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
743 pic14Mnemonics[POC_CALL] = &pciCALL;
744 pic14Mnemonics[POC_COMF] = &pciCOMF;
745 pic14Mnemonics[POC_CLRF] = &pciCLRF;
746 pic14Mnemonics[POC_CLRW] = &pciCLRW;
747 pic14Mnemonics[POC_DECF] = &pciDECF;
748 pic14Mnemonics[POC_DECFW] = &pciDECFW;
749 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
750 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
751 pic14Mnemonics[POC_GOTO] = &pciGOTO;
752 pic14Mnemonics[POC_INCF] = &pciINCF;
753 pic14Mnemonics[POC_INCFW] = &pciINCFW;
754 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
755 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
756 pic14Mnemonics[POC_IORLW] = &pciIORLW;
757 pic14Mnemonics[POC_IORWF] = &pciIORWF;
758 pic14Mnemonics[POC_IORFW] = &pciIORFW;
759 pic14Mnemonics[POC_MOVF] = &pciMOVF;
760 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
761 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
762 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
763 pic14Mnemonics[POC_NEGF] = &pciNEGF;
764 pic14Mnemonics[POC_RETLW] = &pciRETLW;
765 pic14Mnemonics[POC_RETURN] = &pciRETURN;
766 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
767 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
768 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
769 pic14Mnemonics[POC_TRIS] = &pciTRIS;
770 pic14Mnemonics[POC_XORLW] = &pciXORLW;
771 pic14Mnemonics[POC_XORWF] = &pciXORWF;
772 pic14Mnemonics[POC_XORFW] = &pciXORFW;
774 for(i=0; i<MAX_PIC14MNEMONICS; i++)
775 if(pic14Mnemonics[i])
776 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
777 pci = hTabFirstItem(pic14MnemonicsHash, &key);
780 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
781 pci = hTabNextItem(pic14MnemonicsHash, &key);
784 mnemonics_initialized = 1;
787 int getpCode(char *mnem,unsigned dest)
790 pCodeInstruction *pci;
791 int key = mnem2key(mnem);
793 if(!mnemonics_initialized)
794 pic14initMnemonics();
796 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
800 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
801 if((pci->num_ops <= 1) || (pci->dest == dest))
805 pci = hTabNextItemWK (pic14MnemonicsHash);
812 char getpBlock_dbName(pBlock *pb)
818 return pb->cmemmap->dbName;
822 /*-----------------------------------------------------------------*/
823 /* movepBlock2Head - given the dbname of a pBlock, move all */
824 /* instances to the front of the doubly linked */
825 /* list of pBlocks */
826 /*-----------------------------------------------------------------*/
828 void movepBlock2Head(char dbName)
832 pb = the_pFile->pbHead;
836 if(getpBlock_dbName(pb) == dbName) {
837 pBlock *pbn = pb->next;
838 pb->next = the_pFile->pbHead;
839 the_pFile->pbHead->prev = pb;
840 the_pFile->pbHead = pb;
843 pb->prev->next = pbn;
845 // If the pBlock that we just moved was the last
846 // one in the link of all of the pBlocks, then we
847 // need to point the tail to the block just before
849 // Note: if pb->next is NULL, then pb must have
850 // been the last pBlock in the chain.
853 pbn->prev = pb->prev;
855 the_pFile->pbTail = pb->prev;
866 void copypCode(FILE *of, char dbName)
870 if(!of || !the_pFile)
873 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
874 if(getpBlock_dbName(pb) == dbName)
879 void pcode_test(void)
882 printf("pcode is alive!\n");
892 /* create the file name */
893 strcpy(buffer,srcFileName);
896 if( !(pFile = fopen(buffer, "w" ))) {
897 werror(E_FILE_OPEN_ERR,buffer);
901 fprintf(pFile,"pcode dump\n\n");
903 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
904 fprintf(pFile,"\n\tNew pBlock\n\n");
906 fprintf(pFile,"%s",pb->cmemmap->sname);
908 fprintf(pFile,"internal pblock");
910 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
911 printpBlock(pFile,pb);
915 static int RegCond(pCodeOp *pcop)
921 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
922 switch(PCOB(pcop)->bit) {
936 /*-----------------------------------------------------------------*/
937 /* newpCode - create and return a newly initialized pCode */
939 /* fixme - rename this */
941 /* The purpose of this routine is to create a new Instruction */
942 /* pCode. This is called by gen.c while the assembly code is being */
946 /* PIC_OPCODE op - the assembly instruction we wish to create. */
947 /* (note that the op is analogous to but not the */
948 /* same thing as the opcode of the instruction.) */
949 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
952 /* a pointer to the new malloc'd pCode is returned. */
956 /*-----------------------------------------------------------------*/
957 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
959 pCodeInstruction *pci ;
961 if(!mnemonics_initialized)
962 pic14initMnemonics();
964 pci = Safe_calloc(1, sizeof(pCodeInstruction));
966 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
967 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
970 if(pci->inCond == PCC_EXAMINE_PCOP)
971 pci->inCond = RegCond(pcop);
973 if(pci->outCond == PCC_EXAMINE_PCOP)
974 pci->outCond = RegCond(pcop);
979 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
985 /*-----------------------------------------------------------------*/
986 /* newpCodeWild - create a "wild" as in wild card pCode */
988 /* Wild pcodes are used during the peep hole optimizer to serve */
989 /* as place holders for any instruction. When a snippet of code is */
990 /* compared to a peep hole rule, the wild card opcode will match */
991 /* any instruction. However, the optional operand and label are */
992 /* additional qualifiers that must also be matched before the */
993 /* line (of assembly code) is declared matched. Note that the */
994 /* operand may be wild too. */
996 /* Note, a wild instruction is specified just like a wild var: */
997 /* %4 ; A wild instruction, */
998 /* See the peeph.def file for additional examples */
1000 /*-----------------------------------------------------------------*/
1002 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1007 pcw = Safe_calloc(1,sizeof(pCodeWild));
1009 pcw->pc.type = PC_WILD;
1010 pcw->pc.prev = pcw->pc.next = NULL;
1011 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1014 pcw->pc.analyze = genericAnalyze;
1015 pcw->pc.destruct = genericDestruct;
1016 pcw->pc.print = genericPrint;
1018 pcw->id = pCodeID; // this is the 'n' in %n
1019 pcw->operand = optional_operand;
1020 pcw->label = optional_label;
1022 return ( (pCode *)pcw);
1026 /*-----------------------------------------------------------------*/
1027 /* newPcodeCharP - create a new pCode from a char string */
1028 /*-----------------------------------------------------------------*/
1030 pCode *newpCodeCharP(char *cP)
1035 pcc = Safe_calloc(1,sizeof(pCodeComment));
1037 pcc->pc.type = PC_COMMENT;
1038 pcc->pc.prev = pcc->pc.next = NULL;
1039 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1042 pcc->pc.analyze = genericAnalyze;
1043 pcc->pc.destruct = genericDestruct;
1044 pcc->pc.print = genericPrint;
1046 pcc->comment = Safe_strdup(cP);
1048 return ( (pCode *)pcc);
1052 /*-----------------------------------------------------------------*/
1053 /* newpCodeGLabel - create a new global label */
1054 /*-----------------------------------------------------------------*/
1057 pCode *newpCodeFunction(char *mod,char *f)
1061 _ALLOC(pcf,sizeof(pCodeFunction));
1063 pcf->pc.type = PC_FUNCTION;
1064 pcf->pc.prev = pcf->pc.next = NULL;
1065 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1068 pcf->pc.analyze = genericAnalyze;
1069 pcf->pc.destruct = genericDestruct;
1070 pcf->pc.print = pCodePrintFunction;
1073 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1074 strcpy(pcf->modname,mod);
1076 pcf->modname = NULL;
1079 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1080 strcpy(pcf->fname,f);
1084 return ( (pCode *)pcf);
1088 static void pCodeLabelDestruct(pCode *pc)
1097 free(PCL(pc)->label);
1103 pCode *newpCodeLabel(int key)
1109 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1111 pcl->pc.type = PC_LABEL;
1112 pcl->pc.prev = pcl->pc.next = NULL;
1113 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1116 pcl->pc.analyze = genericAnalyze;
1117 pcl->pc.destruct = pCodeLabelDestruct;
1118 pcl->pc.print = pCodePrintLabel;
1123 sprintf(s,"_%05d_DS_",key);
1124 pcl->label = Safe_strdup(s);
1128 return ( (pCode *)pcl);
1131 pCode *newpCodeLabelStr(char *str)
1133 pCode *pc = newpCodeLabel(-1);
1135 PCL(pc)->label = Safe_strdup(str);
1140 /*-----------------------------------------------------------------*/
1141 /* newpBlock - create and return a pointer to a new pBlock */
1142 /*-----------------------------------------------------------------*/
1143 pBlock *newpBlock(void)
1148 PpB = Safe_calloc(1,sizeof(pBlock) );
1149 PpB->next = PpB->prev = NULL;
1151 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1152 PpB->registers = NULL;
1159 /*-----------------------------------------------------------------*/
1160 /* newpCodeChain - create a new chain of pCodes */
1161 /*-----------------------------------------------------------------*
1163 * This function will create a new pBlock and the pointer to the
1164 * pCode that is passed in will be the first pCode in the block.
1165 *-----------------------------------------------------------------*/
1168 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1171 pBlock *pB = newpBlock();
1173 pB->pcHead = pB->pcTail = pc;
1180 /*-----------------------------------------------------------------*/
1181 /* newpCodeOpLabel - Create a new label given the key */
1182 /* Note, a negative key means that the label is part of wild card */
1183 /* (and hence a wild card label) used in the pCodePeep */
1184 /* optimizations). */
1185 /*-----------------------------------------------------------------*/
1187 pCodeOp *newpCodeOpLabel(int key)
1192 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1193 pcop->type = PO_LABEL;
1196 sprintf(s,"_%05d_DS_",key);
1197 pcop->name = Safe_strdup(s);
1201 ((pCodeOpLabel *)pcop)->key = key;
1206 pCodeOp *newpCodeOpLit(int lit)
1212 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1213 pcop->type = PO_LITERAL;
1215 sprintf(s,"0x%02x",lit);
1216 pcop->name = Safe_strdup(s);
1220 ((pCodeOpLit *)pcop)->lit = lit;
1225 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1231 if(!pcp || !subtype) {
1232 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1236 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1237 pcop->type = PO_WILD;
1238 sprintf(s,"%%%d",id);
1239 pcop->name = Safe_strdup(s);
1241 PCOW(pcop)->id = id;
1242 PCOW(pcop)->pcp = pcp;
1243 PCOW(pcop)->subtype = subtype;
1244 PCOW(pcop)->matched = NULL;
1249 pCodeOp *newpCodeOpBit(char *s, int bit)
1253 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1254 pcop->type = PO_BIT;
1255 pcop->name = Safe_strdup(s);
1257 PCOB(pcop)->bit = bit;
1259 PCOB(pcop)->inBitSpace = 1;
1261 PCOB(pcop)->inBitSpace = 0;
1266 /*-----------------------------------------------------------------*/
1267 /*-----------------------------------------------------------------*/
1269 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1275 pcop = newpCodeOpBit(name, -1);
1279 pcop = newpCodeOpLit(-1);
1283 pcop = newpCodeOpLabel(-1);
1287 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1289 pcop->name = Safe_strdup(name);
1295 /*-----------------------------------------------------------------*/
1296 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1297 /*-----------------------------------------------------------------*/
1298 void addpCode2pBlock(pBlock *pb, pCode *pc)
1301 pb->pcTail->next = pc;
1302 pc->prev = pb->pcTail;
1308 /*-----------------------------------------------------------------*/
1309 /* addpBlock - place a pBlock into the pFile */
1310 /*-----------------------------------------------------------------*/
1311 void addpBlock(pBlock *pb)
1315 /* First time called, we'll pass through here. */
1316 _ALLOC(the_pFile,sizeof(the_pFile));
1317 the_pFile->pbHead = the_pFile->pbTail = pb;
1318 the_pFile->functions = NULL;
1322 the_pFile->pbTail->next = pb;
1323 pb->prev = the_pFile->pbTail;
1325 the_pFile->pbTail = pb;
1328 /*-----------------------------------------------------------------*/
1329 /* printpCode - write the contents of a pCode to a file */
1330 /*-----------------------------------------------------------------*/
1331 void printpCode(FILE *of, pCode *pc)
1342 fprintf(of,"warning - unable to print pCode\n");
1345 /*-----------------------------------------------------------------*/
1346 /* printpBlock - write the contents of a pBlock to a file */
1347 /*-----------------------------------------------------------------*/
1348 void printpBlock(FILE *of, pBlock *pb)
1358 for(pc = pb->pcHead; pc; pc = pc->next)
1363 /*-----------------------------------------------------------------*/
1365 /* pCode processing */
1369 /*-----------------------------------------------------------------*/
1371 static void unlinkPC(pCode *pc)
1373 if(pc && pc->prev && pc->next) {
1375 pc->prev->next = pc->next;
1376 pc->next->prev = pc->prev;
1379 static void genericDestruct(pCode *pc)
1381 fprintf(stderr,"warning, calling default pCode destructor\n");
1390 void pBlockRegs(FILE *of, pBlock *pb)
1395 r = setFirstItem(pb->registers);
1397 fprintf(of," %s\n",r->name);
1398 r = setNextItem(pb->registers);
1403 static char *get_op( pCodeInstruction *pcc)
1407 if(pcc && pcc->pcop) {
1410 switch(pcc->pcop->type) {
1414 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1415 fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1416 pBlockRegs(stderr,pcc->pc.pb);
1420 if (pcc->pcop->name)
1421 return pcc->pcop->name;
1426 return "NO operand";
1429 /*-----------------------------------------------------------------*/
1430 /*-----------------------------------------------------------------*/
1431 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1434 fprintf(of,"pcodeopprint\n");
1437 /*-----------------------------------------------------------------*/
1438 /* genericPrint - the contents of a pCode to a file */
1439 /*-----------------------------------------------------------------*/
1440 static void genericPrint(FILE *of, pCode *pc)
1448 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1452 // If the opcode has a label, print that first
1454 pBranch *pbl = pc->label;
1456 if(pbl->pc->type == PC_LABEL)
1457 pCodePrintLabel(of, pbl->pc);
1462 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
1463 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1465 if(PCI(pc)->bit_inst) {
1466 if(PCI(pc)->pcop->type == PO_BIT) {
1467 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1468 fprintf(of,"(%s >> 3), (%s & 7)",
1469 PCI(pc)->pcop->name ,
1470 PCI(pc)->pcop->name );
1472 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1474 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
1475 //PCI(pc)->pcop->t.bit );
1478 if(PCI(pc)->pcop->type == PO_BIT) {
1479 if( PCI(pc)->num_ops == 2)
1480 fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1482 fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
1485 if( PCI(pc)->num_ops == 2)
1486 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
1488 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
1491 fprintf(of,"%s",get_op(PCI(pc)));
1493 if( PCI(pc)->num_ops == 2)
1494 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1500 pBranch *dpb = pc->to; // debug
1502 switch ( dpb->pc->type) {
1504 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1507 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1510 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1524 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1525 if(PCW(pc)->operand) {
1526 fprintf(of,";\toperand ");
1527 pCodeOpPrint(of,PCW(pc)->operand );
1533 fprintf(of,"unknown pCode type %d\n",pc->type);
1538 /*-----------------------------------------------------------------*/
1539 /* pCodePrintFunction - prints function begin/end */
1540 /*-----------------------------------------------------------------*/
1542 static void pCodePrintFunction(FILE *of, pCode *pc)
1548 if( ((pCodeFunction *)pc)->modname)
1549 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1551 if(PCF(pc)->fname) {
1552 pBranch *exits = pc->to;
1554 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1557 exits = exits->next;
1560 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1564 pc->from->pc->type == PC_FUNCTION &&
1565 PCF(pc->from->pc)->fname)
1566 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1568 fprintf(of,"; exit point [can't find entry point]\n");
1571 /*-----------------------------------------------------------------*/
1572 /* pCodePrintLabel - prints label */
1573 /*-----------------------------------------------------------------*/
1575 static void pCodePrintLabel(FILE *of, pCode *pc)
1582 fprintf(of,"%s\n",PCL(pc)->label);
1583 else if (PCL(pc)->key >=0)
1584 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1586 fprintf(of,";wild card label\n");
1589 /*-----------------------------------------------------------------*/
1591 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1607 /*-----------------------------------------------------------------*/
1608 /* pBranchLink - given two pcodes, this function will link them */
1609 /* together through their pBranches */
1610 /*-----------------------------------------------------------------*/
1611 static void pBranchLink(pCode *f, pCode *t)
1615 // Declare a new branch object for the 'from' pCode.
1617 _ALLOC(b,sizeof(pBranch));
1618 b->pc = t; // The link to the 'to' pCode.
1621 f->to = pBranchAppend(f->to,b);
1623 // Now do the same for the 'to' pCode.
1625 _ALLOC(b,sizeof(pBranch));
1629 t->from = pBranchAppend(t->from,b);
1634 /*-----------------------------------------------------------------*/
1635 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1637 /*-----------------------------------------------------------------*/
1638 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1651 /*-----------------------------------------------------------------*/
1652 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1653 /*-----------------------------------------------------------------*/
1654 static void pCodeUnlink(pCode *pc)
1659 if(!pc->prev || !pc->next) {
1660 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1664 /* first remove the pCode from the chain */
1665 pc->prev->next = pc->next;
1666 pc->next->prev = pc->prev;
1668 /* Now for the hard part... */
1670 /* Remove the branches */
1674 pc1 = pb1->pc; /* Get the pCode that branches to the
1675 * one we're unlinking */
1677 /* search for the link back to this pCode (the one we're
1679 if(pb2 = pBranchFind(pc1->to,pc)) {
1680 pb2->pc = pc->to->pc; // make the replacement
1682 /* if the pCode we're unlinking contains multiple 'to'
1683 * branches (e.g. this a skip instruction) then we need
1684 * to copy these extra branches to the chain. */
1686 pBranchAppend(pb2, pc->to->next);
1695 /*-----------------------------------------------------------------*/
1696 /*-----------------------------------------------------------------*/
1697 static void genericAnalyze(pCode *pc)
1707 // Go through the pCodes that are in pCode chain and link
1708 // them together through the pBranches. Note, the pCodes
1709 // are linked together as a contiguous stream like the
1710 // assembly source code lines. The linking here mimics this
1711 // except that comments are not linked in.
1713 pCode *npc = pc->next;
1715 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1716 pBranchLink(pc,npc);
1725 /*-----------------------------------------------------------------*/
1726 /* findLabel - Search the pCode for a particular label */
1727 /*-----------------------------------------------------------------*/
1728 pCode * findLabel(pCodeOpLabel *pcop_label)
1737 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1738 for(pc = pb->pcHead; pc; pc = pc->next) {
1739 if(pc->type == PC_LABEL) {
1740 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1743 if(pc->type == PC_OPCODE) {
1746 if(pbr->pc->type == PC_LABEL) {
1747 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1757 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1761 /*-----------------------------------------------------------------*/
1762 /* findNextInstruction - given a pCode, find the next instruction */
1763 /* in the linked list */
1764 /*-----------------------------------------------------------------*/
1765 pCode * findNextInstruction(pCode *pc)
1769 if(pc->type == PC_OPCODE)
1775 fprintf(stderr,"Couldn't find instruction\n");
1779 /*-----------------------------------------------------------------*/
1780 /* findFunctionEnd - given a pCode find the end of the function */
1781 /* that contains it t */
1782 /*-----------------------------------------------------------------*/
1783 pCode * findFunctionEnd(pCode *pc)
1787 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1793 fprintf(stderr,"Couldn't find function end\n");
1798 /*-----------------------------------------------------------------*/
1799 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1800 /* instruction with which it is associated. */
1801 /*-----------------------------------------------------------------*/
1802 static void AnalyzeLabel(pCode *pc)
1810 static void AnalyzeGOTO(pCode *pc)
1813 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1817 static void AnalyzeSKIP(pCode *pc)
1820 pBranchLink(pc,findNextInstruction(pc->next));
1821 pBranchLink(pc,findNextInstruction(pc->next->next));
1825 static void AnalyzeRETURN(pCode *pc)
1828 // branch_link(pc,findFunctionEnd(pc->next));
1833 void AnalyzepBlock(pBlock *pb)
1840 /* Find all of the registers used in this pBlock */
1841 for(pc = pb->pcHead; pc; pc = pc->next) {
1842 if(pc->type == PC_OPCODE) {
1843 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1845 /* Loop through all of the registers declared so far in
1846 this block and see if we find this new there */
1848 regs *r = setFirstItem(pb->registers);
1851 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1852 PCOR(PCI(pc)->pcop)->r = r;
1855 r = setNextItem(pb->registers);
1859 /* register wasn't found */
1860 r = Safe_calloc(1, sizeof(regs));
1861 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1862 addSet(&pb->registers, r);
1863 PCOR(PCI(pc)->pcop)->r = r;
1864 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1866 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1872 int OptimizepBlock(pBlock *pb)
1877 if(!pb || !peepOptimizing)
1880 fprintf(stderr," Optimizing pBlock\n");
1882 for(pc = pb->pcHead; pc; pc = pc->next)
1883 matches += pCodePeepMatchRule(pc);
1888 /*-----------------------------------------------------------------*/
1889 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1890 /* chain and put them into pBranches that are */
1891 /* associated with the appropriate pCode */
1893 /*-----------------------------------------------------------------*/
1894 void pBlockMergeLabels(pBlock *pb)
1897 pCode *pc, *pcnext=NULL;
1902 for(pc = pb->pcHead; pc; pc = pc->next) {
1904 if(pc->type == PC_LABEL) {
1905 if( !(pcnext = findNextInstruction(pc)) )
1906 return; // Couldn't find an instruction associated with this label
1908 // Unlink the pCode label from it's pCode chain
1910 pc->prev->next = pc->next;
1912 pc->next->prev = pc->prev;
1914 // And link it into the instruction's pBranch labels. (Note, since
1915 // it's possible to have multiple labels associated with one instruction
1916 // we must provide a means to accomodate the additional labels. Thus
1917 // the labels are placed into the singly-linked list "label" as
1918 // opposed to being a single member of the pCodeInstruction.)
1920 _ALLOC(pbr,sizeof(pBranch));
1924 pcnext->label = pBranchAppend(pcnext->label,pbr);
1931 /*-----------------------------------------------------------------*/
1932 /*-----------------------------------------------------------------*/
1933 void OptimizepCode(char dbName)
1935 #define MAX_PASSES 4
1944 fprintf(stderr," Optimizing pCode\n");
1947 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1948 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1949 matches += OptimizepBlock(pb);
1952 while(matches && ++passes < MAX_PASSES);
1956 /*-----------------------------------------------------------------*/
1957 /* AnalyzepCode - parse the pCode that has been generated and form */
1958 /* all of the logical connections. */
1960 /* Essentially what's done here is that the pCode flow is */
1962 /*-----------------------------------------------------------------*/
1964 void AnalyzepCode(char dbName)
1973 fprintf(stderr," Analyzing pCode");
1975 /* First, merge the labels with the instructions */
1976 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1977 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1978 pBlockMergeLabels(pb);
1983 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1984 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1988 /* Now build the call tree.
1989 First we examine all of the pCodes for functions.
1990 Keep in mind that the function boundaries coincide
1991 with pBlock boundaries.
1993 The algorithm goes something like this:
1994 We have two nested loops. The outer loop iterates
1995 through all of the pBlocks/functions. The inner
1996 loop iterates through all of the pCodes for
1997 a given pBlock. When we begin iterating through
1998 a pBlock, the variable pc_fstart, pCode of the start
1999 of a function, is cleared. We then search for pCodes
2000 of type PC_FUNCTION. When one is encountered, we
2001 initialize pc_fstart to this and at the same time
2002 associate a new pBranch object that signifies a
2003 branch entry. If a return is found, then this signifies
2004 a function exit point. We'll link the pCodes of these
2005 returns to the matching pc_fstart.
2007 When we're done, a doubly linked list of pBranches
2008 will exist. The head of this list is stored in
2009 `the_pFile', which is the meta structure for all
2010 of the pCode. Look at the printCallTree function
2011 on how the pBranches are linked together.
2014 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2015 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2016 pCode *pc_fstart=NULL;
2017 for(pc = pb->pcHead; pc; pc = pc->next) {
2018 if(pc->type == PC_FUNCTION) {
2019 if (PCF(pc)->fname) {
2020 // I'm not liking this....
2021 // Found the beginning of a function.
2022 _ALLOC(pbr,sizeof(pBranch));
2023 pbr->pc = pc_fstart = pc;
2026 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2028 // Here's a better way of doing the same:
2029 addSet(&pb->function_entries, pc);
2032 // Found an exit point in a function, e.g. return
2033 // (Note, there may be more than one return per function)
2035 pBranchLink(pc_fstart, pc);
2037 addSet(&pb->function_exits, pc);
2039 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2040 addSet(&pb->function_calls,pc);
2047 /*-----------------------------------------------------------------*/
2048 /* ispCodeFunction - returns true if *pc is the pCode of a */
2050 /*-----------------------------------------------------------------*/
2051 bool ispCodeFunction(pCode *pc)
2054 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2060 /*-----------------------------------------------------------------*/
2061 /* findFunction - Search for a function by name (given the name) */
2062 /* in the set of all functions that are in a pBlock */
2063 /* (note - I expect this to change because I'm planning to limit */
2064 /* pBlock's to just one function declaration */
2065 /*-----------------------------------------------------------------*/
2066 pCode *findFunction(char *fname)
2073 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2075 pc = setFirstItem(pb->function_entries);
2078 if((pc->type == PC_FUNCTION) &&
2080 (strcmp(fname, PCF(pc)->fname)==0))
2083 pc = setNextItem(pb->function_entries);
2091 void MarkUsedRegisters(set *regset)
2096 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2097 r2 = pic14_regWithIdx(r1->rIdx);
2103 void pBlockStats(FILE *of, pBlock *pb)
2109 fprintf(of,"***\n pBlock Stats\n***\n");
2111 // for now just print the first element of each set
2112 pc = setFirstItem(pb->function_entries);
2114 fprintf(of,"entry\n");
2117 pc = setFirstItem(pb->function_exits);
2119 fprintf(of,"has an exit\n");
2123 pc = setFirstItem(pb->function_calls);
2125 fprintf(of,"functions called\n");
2129 pc = setNextItem(pb->function_calls);
2133 r = setFirstItem(pb->registers);
2135 int n = elementsInSet(pb->registers);
2137 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2140 fprintf(of," %s\n",r->name);
2141 r = setNextItem(pb->registers);
2146 /*-----------------------------------------------------------------*/
2147 /*-----------------------------------------------------------------*/
2148 void sequencepCode(void)
2154 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2156 pb->seq = GpCodeSequenceNumber+1;
2158 for( pc = pb->pcHead; pc; pc = pc->next)
2159 pc->seq = ++GpCodeSequenceNumber;
2164 /*-----------------------------------------------------------------*/
2165 /*-----------------------------------------------------------------*/
2166 set *register_usage(pBlock *pb)
2169 set *registers=NULL;
2170 set *registersInCallPath = NULL;
2172 /* check recursion */
2174 pc = setFirstItem(pb->function_entries);
2181 if(pc->type != PC_FUNCTION)
2182 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2184 pc = setFirstItem(pb->function_calls);
2185 for( ; pc; pc = setNextItem(pb->function_calls)) {
2187 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2188 char *dest = get_op(PCI(pc));
2190 pcn = findFunction(dest);
2192 registersInCallPath = register_usage(pcn->pb);
2194 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2199 pBlockStats(stderr,pb); // debug
2200 if(registersInCallPath) {
2201 /* registers were used in the functions this pBlock has called */
2202 /* so now, we need to see if these collide with the ones we are */
2205 regs *r1,*r2, *newreg;
2207 fprintf(stderr,"comparing registers\n");
2209 r1 = setFirstItem(registersInCallPath);
2212 r2 = setFirstItem(pb->registers);
2216 if(r2->rIdx == r1->rIdx) {
2217 newreg = pic14_findFreeReg();
2221 fprintf(stderr,"Bummer, no more registers.\n");
2225 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2226 r1->rIdx, newreg->rIdx);
2227 r2->rIdx = newreg->rIdx;
2228 //if(r2->name) free(r2->name);
2229 r2->name = Safe_strdup(newreg->name);
2231 newreg->wasUsed = 1;
2233 r2 = setNextItem(pb->registers);
2236 r1 = setNextItem(registersInCallPath);
2239 /* Collisions have been resolved. Now free the registers in the call path */
2240 r1 = setFirstItem(registersInCallPath);
2242 newreg = pic14_regWithIdx(r1->rIdx);
2244 r1 = setNextItem(registersInCallPath);
2248 MarkUsedRegisters(pb->registers);
2250 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2253 fprintf(stderr,"returning regs\n");
2255 fprintf(stderr,"not returning regs\n");
2257 fprintf(stderr,"pBlock after register optim.\n");
2258 pBlockStats(stderr,pb); // debug
2264 /*-----------------------------------------------------------------*/
2265 /* printCallTree - writes the call tree to a file */
2267 /*-----------------------------------------------------------------*/
2268 void pct2(FILE *of,pBlock *pb,int indent)
2272 // set *registersInCallPath = NULL;
2275 return;// registers;
2278 return; // registers; //recursion ?
2280 pc = setFirstItem(pb->function_entries);
2287 for(i=0;i<indent;i++) // Indentation
2290 if(pc->type == PC_FUNCTION)
2291 fprintf(of,"%s\n",PCF(pc)->fname);
2296 pc = setFirstItem(pb->function_calls);
2297 for( ; pc; pc = setNextItem(pb->function_calls)) {
2299 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2300 char *dest = get_op(PCI(pc));
2302 pcn = findFunction(dest);
2304 pct2(of,pcn->pb,indent+1);
2306 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2314 fprintf(stderr,"pBlock before register optim.\n");
2315 pBlockStats(stderr,pb); // debug
2317 if(registersInCallPath) {
2318 /* registers were used in the functions this pBlock has called */
2319 /* so now, we need to see if these collide with the ones we are using here */
2321 regs *r1,*r2, *newreg;
2323 fprintf(stderr,"comparing registers\n");
2325 r1 = setFirstItem(registersInCallPath);
2328 r2 = setFirstItem(pb->registers);
2332 if(r2->rIdx == r1->rIdx) {
2333 newreg = pic14_findFreeReg();
2337 fprintf(stderr,"Bummer, no more registers.\n");
2341 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2342 r1->rIdx, newreg->rIdx);
2343 r2->rIdx = newreg->rIdx;
2344 //if(r2->name) free(r2->name);
2345 r2->name = Safe_strdup(newreg->name);
2347 newreg->wasUsed = 1;
2349 r2 = setNextItem(pb->registers);
2352 r1 = setNextItem(registersInCallPath);
2355 /* Collisions have been resolved. Now free the registers in the call path */
2356 r1 = setFirstItem(registersInCallPath);
2358 newreg = pic14_regWithIdx(r1->rIdx);
2360 r1 = setNextItem(registersInCallPath);
2364 MarkUsedRegisters(pb->registers);
2366 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2369 fprintf(stderr,"returning regs\n");
2371 fprintf(stderr,"not returning regs\n");
2373 fprintf(stderr,"pBlock after register optim.\n");
2374 pBlockStats(stderr,pb); // debug
2382 /*-----------------------------------------------------------------*/
2383 /* printCallTree - writes the call tree to a file */
2385 /*-----------------------------------------------------------------*/
2387 void printCallTree(FILE *of)
2399 fprintf(of, "\npBlock statistics\n");
2400 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2401 pBlockStats(stderr,pb);
2405 fprintf(of,"Call Tree\n");
2406 pbr = the_pFile->functions;
2410 if(!ispCodeFunction(pc))
2411 fprintf(of,"bug in call tree");
2414 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2416 while(pc->next && !ispCodeFunction(pc->next)) {
2418 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2419 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2427 /* Re-allocate the registers so that there are no collisions
2428 * between local variables when one function call another */
2430 pic14_deallocateAllRegs();
2432 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2437 fprintf(of,"\n**************\n\na better call tree\n");
2438 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2443 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2444 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));