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
29 // Eventually this will go into device dependent files:
30 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,NULL};
31 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,NULL};
32 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,NULL};
34 static int mnemonics_initialized = 0;
37 //static char *PIC_mnemonics[] = {
38 static char *scpADDLW = "ADDLW";
39 static char *scpADDWF = "ADDWF";
40 static char *scpANDLW = "ANDLW";
41 static char *scpANDWF = "ANDWF";
42 static char *scpBCF = "BCF";
43 static char *scpBSF = "BSF";
44 static char *scpBTFSC = "BTFSC";
45 static char *scpBTFSS = "BTFSS";
46 static char *scpCALL = "CALL";
47 static char *scpCOMF = "COMF";
48 static char *scpCLRF = "CLRF";
49 static char *scpCLRW = "CLRW";
50 static char *scpDECF = "DECF";
51 static char *scpDECFSZ = "DECFSZ";
52 static char *scpGOTO = "GOTO";
53 static char *scpINCF = "INCF";
54 static char *scpINCFSZ = "INCFSZ";
55 static char *scpIORLW = "IORLW";
56 static char *scpIORWF = "IORWF";
57 static char *scpMOVF = "MOVF";
58 static char *scpMOVLW = "MOVLW";
59 static char *scpMOVWF = "MOVWF";
60 static char *scpNEGF = "NEGF";
61 static char *scpRETLW = "RETLW";
62 static char *scpRETURN = "RETURN";
63 static char *scpSUBLW = "SUBLW";
64 static char *scpSUBWF = "SUBWF";
65 static char *scpTRIS = "TRIS";
66 static char *scpXORLW = "XORLW";
67 static char *scpXORWF = "XORWF";
70 static hTab *pic14MnemonicsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static int peepOptimizing = 1;
76 static int GpCodeSequenceNumber = 1;
78 /****************************************************************/
79 /* Forward declarations */
80 /****************************************************************/
82 static void unlinkPC(pCode *pc);
83 static void genericAnalyze(pCode *pc);
84 static void AnalyzeGOTO(pCode *pc);
85 static void AnalyzeSKIP(pCode *pc);
86 static void AnalyzeRETURN(pCode *pc);
88 static void genericDestruct(pCode *pc);
89 static void genericPrint(FILE *of,pCode *pc);
91 static void pCodePrintLabel(FILE *of, pCode *pc);
92 static void pCodePrintFunction(FILE *of, pCode *pc);
93 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
94 static char *get_op( pCodeInstruction *pcc);
95 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
96 int pCodePeepMatchRule(pCode *pc);
99 pCodeInstruction pciADDWF = {
100 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
108 1,0, // dest, bit instruction
109 (PCC_W | PCC_REGISTER), // inCond
110 (PCC_REGISTER | PCC_Z) // outCond
113 pCodeInstruction pciADDFW = {
114 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
122 0,0, // dest, bit instruction
123 (PCC_W | PCC_REGISTER), // inCond
124 (PCC_W | PCC_Z) // outCond
127 pCodeInstruction pciADDLW = {
128 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
136 0,0, // dest, bit instruction
138 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
141 pCodeInstruction pciANDLW = {
142 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
150 0,0, // dest, bit instruction
152 (PCC_W | PCC_Z) // outCond
155 pCodeInstruction pciANDWF = {
156 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
164 1,0, // dest, bit instruction
165 (PCC_W | PCC_REGISTER), // inCond
166 (PCC_REGISTER | PCC_Z) // outCond
169 pCodeInstruction pciANDFW = {
170 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
178 0,0, // dest, bit instruction
179 (PCC_W | PCC_REGISTER), // inCond
180 (PCC_W | PCC_Z) // outCond
183 pCodeInstruction pciBCF = {
184 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
192 0,1, // dest, bit instruction
194 PCC_EXAMINE_PCOP // outCond
197 pCodeInstruction pciBSF = {
198 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
206 0,1, // dest, bit instruction
208 PCC_EXAMINE_PCOP // outCond
211 pCodeInstruction pciBTFSC = {
212 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
220 0,1, // dest, bit instruction
221 PCC_EXAMINE_PCOP, // inCond
225 pCodeInstruction pciBTFSS = {
226 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
234 0,1, // dest, bit instruction
235 PCC_EXAMINE_PCOP, // inCond
239 pCodeInstruction pciCALL = {
240 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
248 0,0, // dest, bit instruction
253 //fixme - need a COMFW instruction.
254 pCodeInstruction pciCOMF = {
255 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
263 0,0, // dest, bit instruction
268 pCodeInstruction pciCLRF = {
269 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
277 0,0, // dest, bit instruction
278 PCC_REGISTER, // inCond
279 PCC_REGISTER // outCond
282 pCodeInstruction pciCLRW = {
283 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
291 0,0, // dest, bit instruction
296 pCodeInstruction pciDECF = {
297 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
305 1,0, // dest, bit instruction
306 PCC_REGISTER, // inCond
307 PCC_REGISTER // outCond
310 pCodeInstruction pciDECFW = {
311 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
319 0,0, // dest, bit instruction
320 PCC_REGISTER, // inCond
324 pCodeInstruction pciDECFSZ = {
325 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
333 1,0, // dest, bit instruction
334 PCC_REGISTER, // inCond
335 PCC_REGISTER // outCond
338 pCodeInstruction pciDECFSZW = {
339 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
347 0,0, // dest, bit instruction
348 PCC_REGISTER, // inCond
352 pCodeInstruction pciGOTO = {
353 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
361 0,0, // dest, bit instruction
367 pCodeInstruction pciINCF = {
368 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
376 1,0, // dest, bit instruction
377 PCC_REGISTER, // inCond
378 PCC_REGISTER // outCond
381 pCodeInstruction pciINCFW = {
382 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
390 0,0, // dest, bit instruction
391 PCC_REGISTER, // inCond
395 pCodeInstruction pciINCFSZ = {
396 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
404 1,0, // dest, bit instruction
405 PCC_REGISTER, // inCond
406 PCC_REGISTER // outCond
409 pCodeInstruction pciINCFSZW = {
410 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
418 0,0, // dest, bit instruction
419 PCC_REGISTER, // inCond
423 pCodeInstruction pciIORWF = {
424 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
432 1,0, // dest, bit instruction
433 (PCC_W | PCC_REGISTER), // inCond
434 (PCC_REGISTER | PCC_Z) // outCond
437 pCodeInstruction pciIORFW = {
438 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
446 0,0, // dest, bit instruction
447 (PCC_W | PCC_REGISTER), // inCond
448 (PCC_W | PCC_Z) // outCond
451 pCodeInstruction pciIORLW = {
452 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
460 0,0, // dest, bit instruction
462 (PCC_W | PCC_Z) // outCond
465 pCodeInstruction pciMOVF = {
466 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
474 1,0, // dest, bit instruction
475 PCC_REGISTER, // inCond
479 pCodeInstruction pciMOVFW = {
480 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
488 0,0, // dest, bit instruction
489 PCC_REGISTER, // inCond
490 (PCC_W | PCC_Z) // outCond
493 pCodeInstruction pciMOVWF = {
494 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
502 0,0, // dest, bit instruction
507 pCodeInstruction pciMOVLW = {
508 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
516 0,0, // dest, bit instruction
521 pCodeInstruction pciNEGF = {
522 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
530 0,0, // dest, bit instruction
531 PCC_REGISTER, // inCond
536 pCodeInstruction pciRETLW = {
537 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
545 0,0, // dest, bit instruction
550 pCodeInstruction pciRETURN = {
551 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
559 0,0, // dest, bit instruction
565 pCodeInstruction pciSUBWF = {
566 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
574 1,0, // dest, bit instruction
575 (PCC_W | PCC_REGISTER), // inCond
576 (PCC_REGISTER | PCC_Z) // outCond
579 pCodeInstruction pciSUBFW = {
580 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
588 0,0, // dest, bit instruction
589 (PCC_W | PCC_REGISTER), // inCond
590 (PCC_W | PCC_Z) // outCond
593 pCodeInstruction pciSUBLW = {
594 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
602 0,0, // dest, bit instruction
604 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
607 pCodeInstruction pciTRIS = {
608 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
616 0,0, // dest, bit instruction
622 pCodeInstruction pciXORWF = {
623 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
631 1,0, // dest, bit instruction
632 (PCC_W | PCC_REGISTER), // inCond
633 (PCC_REGISTER | PCC_Z) // outCond
636 pCodeInstruction pciXORFW = {
637 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
645 0,0, // dest, bit instruction
646 (PCC_W | PCC_REGISTER), // inCond
647 (PCC_W | PCC_Z) // outCond
650 pCodeInstruction pciXORLW = {
651 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
659 0,0, // dest, bit instruction
661 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
665 #define MAX_PIC14MNEMONICS 100
666 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
668 char *Safe_strdup(char *str)
677 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
685 void pCodeInitRegisters(void)
689 pc_fsr.r = pic14_regWithIdx(4);
693 /*-----------------------------------------------------------------*/
694 /* mnem2key - convert a pic mnemonic into a hash key */
695 /* (BTW - this spreads the mnemonics quite well) */
697 /*-----------------------------------------------------------------*/
699 int mnem2key(char const *mnem)
708 key += toupper(*mnem++) +1;
716 void pic14initMnemonics(void)
721 pCodeInstruction *pci;
723 if(mnemonics_initialized)
726 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
727 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
728 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
729 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
730 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
731 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
732 pic14Mnemonics[POC_BCF] = &pciBCF;
733 pic14Mnemonics[POC_BSF] = &pciBSF;
734 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
735 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
736 pic14Mnemonics[POC_CALL] = &pciCALL;
737 pic14Mnemonics[POC_COMF] = &pciCOMF;
738 pic14Mnemonics[POC_CLRF] = &pciCLRF;
739 pic14Mnemonics[POC_CLRW] = &pciCLRW;
740 pic14Mnemonics[POC_DECF] = &pciDECF;
741 pic14Mnemonics[POC_DECFW] = &pciDECFW;
742 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
743 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
744 pic14Mnemonics[POC_GOTO] = &pciGOTO;
745 pic14Mnemonics[POC_INCF] = &pciINCF;
746 pic14Mnemonics[POC_INCFW] = &pciINCFW;
747 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
748 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
749 pic14Mnemonics[POC_IORLW] = &pciIORLW;
750 pic14Mnemonics[POC_IORWF] = &pciIORWF;
751 pic14Mnemonics[POC_IORFW] = &pciIORFW;
752 pic14Mnemonics[POC_MOVF] = &pciMOVF;
753 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
754 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
755 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
756 pic14Mnemonics[POC_NEGF] = &pciNEGF;
757 pic14Mnemonics[POC_RETLW] = &pciRETLW;
758 pic14Mnemonics[POC_RETURN] = &pciRETURN;
759 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
760 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
761 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
762 pic14Mnemonics[POC_TRIS] = &pciTRIS;
763 pic14Mnemonics[POC_XORLW] = &pciXORLW;
764 pic14Mnemonics[POC_XORWF] = &pciXORWF;
765 pic14Mnemonics[POC_XORFW] = &pciXORFW;
767 for(i=0; i<MAX_PIC14MNEMONICS; i++)
768 if(pic14Mnemonics[i])
769 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
770 pci = hTabFirstItem(pic14MnemonicsHash, &key);
773 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
774 pci = hTabNextItem(pic14MnemonicsHash, &key);
777 mnemonics_initialized = 1;
780 int getpCode(char *mnem)
783 pCodeInstruction *pci;
784 int key = mnem2key(mnem);
786 if(!mnemonics_initialized)
787 pic14initMnemonics();
789 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
793 if(strcasecmp(pci->mnemonic, mnem) == 0)
795 pci = hTabNextItemWK (pic14MnemonicsHash);
802 char getpBlock_dbName(pBlock *pb)
808 return pb->cmemmap->dbName;
812 /*-----------------------------------------------------------------*/
813 /* movepBlock2Head - given the dbname of a pBlock, move all */
814 /* instances to the front of the doubly linked */
815 /* list of pBlocks */
816 /*-----------------------------------------------------------------*/
818 void movepBlock2Head(char dbName)
822 pb = the_pFile->pbHead;
826 if(getpBlock_dbName(pb) == dbName) {
827 pBlock *pbn = pb->next;
828 pb->next = the_pFile->pbHead;
829 the_pFile->pbHead->prev = pb;
830 the_pFile->pbHead = pb;
833 pb->prev->next = pbn;
835 // If the pBlock that we just moved was the last
836 // one in the link of all of the pBlocks, then we
837 // need to point the tail to the block just before
839 // Note: if pb->next is NULL, then pb must have
840 // been the last pBlock in the chain.
843 pbn->prev = pb->prev;
845 the_pFile->pbTail = pb->prev;
856 void copypCode(FILE *of, char dbName)
860 if(!of || !the_pFile)
863 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
864 if(getpBlock_dbName(pb) == dbName)
869 void pcode_test(void)
872 printf("pcode is alive!\n");
882 /* create the file name */
883 strcpy(buffer,srcFileName);
886 if( !(pFile = fopen(buffer, "w" ))) {
887 werror(E_FILE_OPEN_ERR,buffer);
891 fprintf(pFile,"pcode dump\n\n");
893 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
894 fprintf(pFile,"\n\tNew pBlock\n\n");
896 fprintf(pFile,"%s",pb->cmemmap->sname);
898 fprintf(pFile,"internal pblock");
900 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
901 printpBlock(pFile,pb);
905 static int RegCond(pCodeOp *pcop)
911 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
912 switch(PCOB(pcop)->bit) {
926 /*-----------------------------------------------------------------*/
927 /* newpCode - create and return a newly initialized pCode */
929 /* fixme - rename this */
931 /* The purpose of this routine is to create a new Instruction */
932 /* pCode. This is called by gen.c while the assembly code is being */
936 /* PIC_OPCODE op - the assembly instruction we wish to create. */
937 /* (note that the op is analogous to but not the */
938 /* same thing as the opcode of the instruction.) */
939 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
942 /* a pointer to the new malloc'd pCode is returned. */
946 /*-----------------------------------------------------------------*/
947 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
949 pCodeInstruction *pci ;
951 if(!mnemonics_initialized)
952 pic14initMnemonics();
954 pci = Safe_calloc(1, sizeof(pCodeInstruction));
956 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
957 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
960 if(pci->inCond == PCC_EXAMINE_PCOP)
961 pci->inCond = RegCond(pcop);
963 if(pci->outCond == PCC_EXAMINE_PCOP)
964 pci->outCond = RegCond(pcop);
969 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
975 /*-----------------------------------------------------------------*/
976 /* newpCodeWild - create a "wild" as in wild card pCode */
978 /* Wild pcodes are used during the peep hole optimizer to serve */
979 /* as place holders for any instruction. When a snippet of code is */
980 /* compared to a peep hole rule, the wild card opcode will match */
981 /* any instruction. However, the optional operand and label are */
982 /* additional qualifiers that must also be matched before the */
983 /* line (of assembly code) is declared matched. Note that the */
984 /* operand may be wild too. */
986 /*-----------------------------------------------------------------*/
988 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
993 pcw = Safe_calloc(1,sizeof(pCodeWild));
995 pcw->pc.type = PC_WILD;
996 pcw->pc.prev = pcw->pc.next = NULL;
997 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1000 pcw->pc.analyze = genericAnalyze;
1001 pcw->pc.destruct = genericDestruct;
1002 pcw->pc.print = genericPrint;
1005 pcw->operand = optional_operand;
1006 pcw->label = optional_label;
1008 return ( (pCode *)pcw);
1012 /*-----------------------------------------------------------------*/
1013 /* newPcodeCharP - create a new pCode from a char string */
1014 /*-----------------------------------------------------------------*/
1016 pCode *newpCodeCharP(char *cP)
1021 pcc = Safe_calloc(1,sizeof(pCodeComment));
1023 pcc->pc.type = PC_COMMENT;
1024 pcc->pc.prev = pcc->pc.next = NULL;
1025 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1028 pcc->pc.analyze = genericAnalyze;
1029 pcc->pc.destruct = genericDestruct;
1030 pcc->pc.print = genericPrint;
1032 pcc->comment = Safe_strdup(cP);
1034 return ( (pCode *)pcc);
1038 /*-----------------------------------------------------------------*/
1039 /* newpCodeGLabel - create a new global label */
1040 /*-----------------------------------------------------------------*/
1043 pCode *newpCodeFunction(char *mod,char *f)
1047 _ALLOC(pcf,sizeof(pCodeFunction));
1049 pcf->pc.type = PC_FUNCTION;
1050 pcf->pc.prev = pcf->pc.next = NULL;
1051 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1054 pcf->pc.analyze = genericAnalyze;
1055 pcf->pc.destruct = genericDestruct;
1056 pcf->pc.print = pCodePrintFunction;
1059 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1060 strcpy(pcf->modname,mod);
1062 pcf->modname = NULL;
1065 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1066 strcpy(pcf->fname,f);
1070 return ( (pCode *)pcf);
1074 static void pCodeLabelDestruct(pCode *pc)
1083 free(PCL(pc)->label);
1088 pCode *newpCodeLabel(int key)
1094 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1096 pcl->pc.type = PC_LABEL;
1097 pcl->pc.prev = pcl->pc.next = NULL;
1098 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1101 pcl->pc.analyze = genericAnalyze;
1102 pcl->pc.destruct = pCodeLabelDestruct;
1103 pcl->pc.print = pCodePrintLabel;
1108 sprintf(s,"_%05d_DS_",key);
1109 pcl->label = Safe_strdup(s);
1113 return ( (pCode *)pcl);
1116 pCode *newpCodeLabelStr(char *str)
1118 pCode *pc = newpCodeLabel(-1);
1120 PCL(pc)->label = Safe_strdup(str);
1125 /*-----------------------------------------------------------------*/
1126 /* newpBlock - create and return a pointer to a new pBlock */
1127 /*-----------------------------------------------------------------*/
1128 pBlock *newpBlock(void)
1133 _ALLOC(PpB,sizeof(pBlock));
1134 PpB->next = PpB->prev = NULL;
1136 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1137 PpB->registers = NULL;
1144 /*-----------------------------------------------------------------*/
1145 /* newpCodeChain - create a new chain of pCodes */
1146 /*-----------------------------------------------------------------*
1148 * This function will create a new pBlock and the pointer to the
1149 * pCode that is passed in will be the first pCode in the block.
1150 *-----------------------------------------------------------------*/
1153 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1156 pBlock *pB = newpBlock();
1158 pB->pcHead = pB->pcTail = pc;
1165 /*-----------------------------------------------------------------*/
1166 /*-----------------------------------------------------------------*/
1168 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1172 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1174 pcop->name = Safe_strdup(name);
1179 /*-----------------------------------------------------------------*/
1180 /* newpCodeOpLabel - Create a new label given the key */
1181 /* Note, a negative key means that the label is part of wild card */
1182 /* (and hence a wild card label) used in the pCodePeep */
1183 /* optimizations). */
1184 /*-----------------------------------------------------------------*/
1186 pCodeOp *newpCodeOpLabel(int key)
1191 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1192 pcop->type = PO_LABEL;
1195 sprintf(s,"_%05d_DS_",key);
1196 pcop->name = Safe_strdup(s);
1200 ((pCodeOpLabel *)pcop)->key = key;
1205 pCodeOp *newpCodeOpLit(int lit)
1211 _ALLOC(pcop,sizeof(pCodeOpLit) );
1212 pcop->type = PO_LITERAL;
1213 sprintf(s,"0x%02x",lit);
1214 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1215 strcpy(pcop->name,s);
1216 ((pCodeOpLit *)pcop)->lit = lit;
1221 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1227 if(!pcp || !subtype) {
1228 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1232 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1233 pcop->type = PO_WILD;
1234 sprintf(s,"%%%d",id);
1235 pcop->name = Safe_strdup(s);
1237 PCOW(pcop)->id = id;
1238 PCOW(pcop)->pcp = pcp;
1239 PCOW(pcop)->subtype = subtype;
1240 PCOW(pcop)->matched = NULL;
1245 pCodeOp *newpCodeOpBit(char *s, int bit)
1249 _ALLOC(pcop,sizeof(pCodeOpBit) );
1250 pcop->type = PO_BIT;
1251 pcop->name = Safe_strdup(s);
1252 PCOB(pcop)->bit = bit;
1254 PCOB(pcop)->inBitSpace = 1;
1256 PCOB(pcop)->inBitSpace = 0;
1261 /*-----------------------------------------------------------------*/
1262 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1263 /*-----------------------------------------------------------------*/
1264 void addpCode2pBlock(pBlock *pb, pCode *pc)
1267 pb->pcTail->next = pc;
1268 pc->prev = pb->pcTail;
1274 /*-----------------------------------------------------------------*/
1275 /* addpBlock - place a pBlock into the pFile */
1276 /*-----------------------------------------------------------------*/
1277 void addpBlock(pBlock *pb)
1281 /* First time called, we'll pass through here. */
1282 _ALLOC(the_pFile,sizeof(the_pFile));
1283 the_pFile->pbHead = the_pFile->pbTail = pb;
1284 the_pFile->functions = NULL;
1288 the_pFile->pbTail->next = pb;
1289 pb->prev = the_pFile->pbTail;
1291 the_pFile->pbTail = pb;
1294 /*-----------------------------------------------------------------*/
1295 /* printpCode - write the contents of a pCode to a file */
1296 /*-----------------------------------------------------------------*/
1297 void printpCode(FILE *of, pCode *pc)
1308 fprintf(of,"warning - unable to print pCode\n");
1311 /*-----------------------------------------------------------------*/
1312 /* printpBlock - write the contents of a pBlock to a file */
1313 /*-----------------------------------------------------------------*/
1314 void printpBlock(FILE *of, pBlock *pb)
1324 for(pc = pb->pcHead; pc; pc = pc->next)
1329 /*-----------------------------------------------------------------*/
1331 /* pCode processing */
1335 /*-----------------------------------------------------------------*/
1337 static void unlinkPC(pCode *pc)
1339 if(pc && pc->prev && pc->next) {
1341 pc->prev->next = pc->next;
1342 pc->next->prev = pc->prev;
1345 static void genericDestruct(pCode *pc)
1349 fprintf(stderr,"warning, calling default pCode destructor\n");
1354 void pBlockRegs(FILE *of, pBlock *pb)
1359 r = setFirstItem(pb->registers);
1361 fprintf(of," %s\n",r->name);
1362 r = setNextItem(pb->registers);
1367 static char *get_op( pCodeInstruction *pcc)
1371 if(pcc && pcc->pcop) {
1374 switch(pcc->pcop->type) {
1378 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1379 fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1380 pBlockRegs(stderr,pcc->pc.pb);
1384 if (pcc->pcop->name)
1385 return pcc->pcop->name;
1390 return "NO operand";
1393 /*-----------------------------------------------------------------*/
1394 /*-----------------------------------------------------------------*/
1395 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1398 fprintf(of,"pcodeopprint\n");
1401 /*-----------------------------------------------------------------*/
1402 /* genericPrint - the contents of a pCode to a file */
1403 /*-----------------------------------------------------------------*/
1404 static void genericPrint(FILE *of, pCode *pc)
1412 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1416 // If the opcode has a label, print that first
1418 pBranch *pbl = pc->label;
1420 if(pbl->pc->type == PC_LABEL)
1421 pCodePrintLabel(of, pbl->pc);
1426 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
1427 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1429 if(PCI(pc)->bit_inst) {
1430 if(PCI(pc)->pcop->type == PO_BIT) {
1431 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1432 fprintf(of,"(%s >> 3), (%s & 7)",
1433 PCI(pc)->pcop->name ,
1434 PCI(pc)->pcop->name );
1436 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1438 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
1439 //PCI(pc)->pcop->t.bit );
1442 if(PCI(pc)->pcop->type == PO_BIT) {
1443 if( PCI(pc)->num_ops == 2)
1444 fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1446 fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
1449 if( PCI(pc)->num_ops == 2)
1450 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
1452 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
1455 fprintf(of,"%s",get_op(PCI(pc)));
1457 if( PCI(pc)->num_ops == 2)
1458 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1464 pBranch *dpb = pc->to; // debug
1466 switch ( dpb->pc->type) {
1468 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1471 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1474 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1488 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1489 if(PCW(pc)->operand) {
1490 fprintf(of,";\toperand ");
1491 pCodeOpPrint(of,PCW(pc)->operand );
1497 fprintf(of,"unknown pCode type %d\n",pc->type);
1502 /*-----------------------------------------------------------------*/
1503 /* pCodePrintFunction - prints function begin/end */
1504 /*-----------------------------------------------------------------*/
1506 static void pCodePrintFunction(FILE *of, pCode *pc)
1512 if( ((pCodeFunction *)pc)->modname)
1513 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1515 if(PCF(pc)->fname) {
1516 pBranch *exits = pc->to;
1518 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1521 exits = exits->next;
1524 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1528 pc->from->pc->type == PC_FUNCTION &&
1529 PCF(pc->from->pc)->fname)
1530 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1532 fprintf(of,"; exit point [can't find entry point]\n");
1535 /*-----------------------------------------------------------------*/
1536 /* pCodePrintLabel - prints label */
1537 /*-----------------------------------------------------------------*/
1539 static void pCodePrintLabel(FILE *of, pCode *pc)
1546 fprintf(of,"%s\n",PCL(pc)->label);
1547 else if (PCL(pc)->key >=0)
1548 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1550 fprintf(of,";wild card label\n");
1553 /*-----------------------------------------------------------------*/
1555 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1571 /*-----------------------------------------------------------------*/
1572 /* pBranchLink - given two pcodes, this function will link them */
1573 /* together through their pBranches */
1574 /*-----------------------------------------------------------------*/
1575 static void pBranchLink(pCode *f, pCode *t)
1579 // Declare a new branch object for the 'from' pCode.
1581 _ALLOC(b,sizeof(pBranch));
1582 b->pc = t; // The link to the 'to' pCode.
1585 f->to = pBranchAppend(f->to,b);
1587 // Now do the same for the 'to' pCode.
1589 _ALLOC(b,sizeof(pBranch));
1593 t->from = pBranchAppend(t->from,b);
1598 /*-----------------------------------------------------------------*/
1599 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1601 /*-----------------------------------------------------------------*/
1602 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1615 /*-----------------------------------------------------------------*/
1616 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1617 /*-----------------------------------------------------------------*/
1618 static void pCodeUnlink(pCode *pc)
1623 if(!pc->prev || !pc->next) {
1624 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1628 /* first remove the pCode from the chain */
1629 pc->prev->next = pc->next;
1630 pc->next->prev = pc->prev;
1632 /* Now for the hard part... */
1634 /* Remove the branches */
1638 pc1 = pb1->pc; /* Get the pCode that branches to the
1639 * one we're unlinking */
1641 /* search for the link back to this pCode (the one we're
1643 if(pb2 = pBranchFind(pc1->to,pc)) {
1644 pb2->pc = pc->to->pc; // make the replacement
1646 /* if the pCode we're unlinking contains multiple 'to'
1647 * branches (e.g. this a skip instruction) then we need
1648 * to copy these extra branches to the chain. */
1650 pBranchAppend(pb2, pc->to->next);
1659 /*-----------------------------------------------------------------*/
1660 /*-----------------------------------------------------------------*/
1661 static void genericAnalyze(pCode *pc)
1671 // Go through the pCodes that are in pCode chain and link
1672 // them together through the pBranches. Note, the pCodes
1673 // are linked together as a contiguous stream like the
1674 // assembly source code lines. The linking here mimics this
1675 // except that comments are not linked in.
1677 pCode *npc = pc->next;
1679 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1680 pBranchLink(pc,npc);
1689 /*-----------------------------------------------------------------*/
1690 /* findLabel - Search the pCode for a particular label */
1691 /*-----------------------------------------------------------------*/
1692 pCode * findLabel(pCodeOpLabel *pcop_label)
1701 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1702 for(pc = pb->pcHead; pc; pc = pc->next) {
1703 if(pc->type == PC_LABEL) {
1704 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1707 if(pc->type == PC_OPCODE) {
1710 if(pbr->pc->type == PC_LABEL) {
1711 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1721 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1725 /*-----------------------------------------------------------------*/
1726 /* findNextInstruction - given a pCode, find the next instruction */
1727 /* in the linked list */
1728 /*-----------------------------------------------------------------*/
1729 pCode * findNextInstruction(pCode *pc)
1733 if(pc->type == PC_OPCODE)
1739 fprintf(stderr,"Couldn't find instruction\n");
1743 /*-----------------------------------------------------------------*/
1744 /* findFunctionEnd - given a pCode find the end of the function */
1745 /* that contains it t */
1746 /*-----------------------------------------------------------------*/
1747 pCode * findFunctionEnd(pCode *pc)
1751 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1757 fprintf(stderr,"Couldn't find function end\n");
1762 /*-----------------------------------------------------------------*/
1763 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1764 /* instruction with which it is associated. */
1765 /*-----------------------------------------------------------------*/
1766 static void AnalyzeLabel(pCode *pc)
1774 static void AnalyzeGOTO(pCode *pc)
1777 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1781 static void AnalyzeSKIP(pCode *pc)
1784 pBranchLink(pc,findNextInstruction(pc->next));
1785 pBranchLink(pc,findNextInstruction(pc->next->next));
1789 static void AnalyzeRETURN(pCode *pc)
1792 // branch_link(pc,findFunctionEnd(pc->next));
1797 void AnalyzepBlock(pBlock *pb)
1804 /* Find all of the registers used in this pBlock */
1805 for(pc = pb->pcHead; pc; pc = pc->next) {
1806 if(pc->type == PC_OPCODE) {
1807 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1809 /* Loop through all of the registers declared so far in
1810 this block and see if we find this new there */
1812 regs *r = setFirstItem(pb->registers);
1815 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1816 PCOR(PCI(pc)->pcop)->r = r;
1819 r = setNextItem(pb->registers);
1823 /* register wasn't found */
1824 r = Safe_calloc(1, sizeof(regs));
1825 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1826 addSet(&pb->registers, r);
1827 PCOR(PCI(pc)->pcop)->r = r;
1828 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1830 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1836 int OptimizepBlock(pBlock *pb)
1841 if(!pb || !peepOptimizing)
1844 fprintf(stderr," Optimizing pBlock\n");
1846 for(pc = pb->pcHead; pc; pc = pc->next)
1847 matches += pCodePeepMatchRule(pc);
1852 /*-----------------------------------------------------------------*/
1853 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1854 /* chain and put them into pBranches that are */
1855 /* associated with the appropriate pCode */
1857 /*-----------------------------------------------------------------*/
1858 void pBlockMergeLabels(pBlock *pb)
1861 pCode *pc, *pcnext=NULL;
1866 for(pc = pb->pcHead; pc; pc = pc->next) {
1868 if(pc->type == PC_LABEL) {
1869 if( !(pcnext = findNextInstruction(pc)) )
1870 return; // Couldn't find an instruction associated with this label
1872 // Unlink the pCode label from it's pCode chain
1874 pc->prev->next = pc->next;
1876 pc->next->prev = pc->prev;
1878 // And link it into the instruction's pBranch labels. (Note, since
1879 // it's possible to have multiple labels associated with one instruction
1880 // we must provide a means to accomodate the additional labels. Thus
1881 // the labels are placed into the singly-linked list "label" as
1882 // opposed to being a single member of the pCodeInstruction.)
1884 _ALLOC(pbr,sizeof(pBranch));
1888 pcnext->label = pBranchAppend(pcnext->label,pbr);
1895 /*-----------------------------------------------------------------*/
1896 /*-----------------------------------------------------------------*/
1897 void OptimizepCode(char dbName)
1899 #define MAX_PASSES 4
1908 fprintf(stderr," Optimizing pCode\n");
1911 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1912 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1913 matches += OptimizepBlock(pb);
1916 while(matches && ++passes < MAX_PASSES);
1920 /*-----------------------------------------------------------------*/
1921 /* AnalyzepCode - parse the pCode that has been generated and form */
1922 /* all of the logical connections. */
1924 /* Essentially what's done here is that the pCode flow is */
1926 /*-----------------------------------------------------------------*/
1928 void AnalyzepCode(char dbName)
1937 fprintf(stderr," Analyzing pCode");
1939 /* First, merge the labels with the instructions */
1940 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1941 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1942 pBlockMergeLabels(pb);
1947 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1948 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1952 /* Now build the call tree.
1953 First we examine all of the pCodes for functions.
1954 Keep in mind that the function boundaries coincide
1955 with pBlock boundaries.
1957 The algorithm goes something like this:
1958 We have two nested loops. The outer loop iterates
1959 through all of the pBlocks/functions. The inner
1960 loop iterates through all of the pCodes for
1961 a given pBlock. When we begin iterating through
1962 a pBlock, the variable pc_fstart, pCode of the start
1963 of a function, is cleared. We then search for pCodes
1964 of type PC_FUNCTION. When one is encountered, we
1965 initialize pc_fstart to this and at the same time
1966 associate a new pBranch object that signifies a
1967 branch entry. If a return is found, then this signifies
1968 a function exit point. We'll link the pCodes of these
1969 returns to the matching pc_fstart.
1971 When we're done, a doubly linked list of pBranches
1972 will exist. The head of this list is stored in
1973 `the_pFile', which is the meta structure for all
1974 of the pCode. Look at the printCallTree function
1975 on how the pBranches are linked together.
1978 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1979 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1980 pCode *pc_fstart=NULL;
1981 for(pc = pb->pcHead; pc; pc = pc->next) {
1982 if(pc->type == PC_FUNCTION) {
1983 if (PCF(pc)->fname) {
1984 // I'm not liking this....
1985 // Found the beginning of a function.
1986 _ALLOC(pbr,sizeof(pBranch));
1987 pbr->pc = pc_fstart = pc;
1990 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1992 // Here's a better way of doing the same:
1993 addSet(&pb->function_entries, pc);
1996 // Found an exit point in a function, e.g. return
1997 // (Note, there may be more than one return per function)
1999 pBranchLink(pc_fstart, pc);
2001 addSet(&pb->function_exits, pc);
2003 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2004 addSet(&pb->function_calls,pc);
2011 /*-----------------------------------------------------------------*/
2012 /* ispCodeFunction - returns true if *pc is the pCode of a */
2014 /*-----------------------------------------------------------------*/
2015 bool ispCodeFunction(pCode *pc)
2018 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2024 /*-----------------------------------------------------------------*/
2025 /* findFunction - Search for a function by name (given the name) */
2026 /* in the set of all functions that are in a pBlock */
2027 /* (note - I expect this to change because I'm planning to limit */
2028 /* pBlock's to just one function declaration */
2029 /*-----------------------------------------------------------------*/
2030 pCode *findFunction(char *fname)
2037 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2039 pc = setFirstItem(pb->function_entries);
2042 if((pc->type == PC_FUNCTION) &&
2044 (strcmp(fname, PCF(pc)->fname)==0))
2047 pc = setNextItem(pb->function_entries);
2055 void MarkUsedRegisters(set *regset)
2060 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2061 r2 = pic14_regWithIdx(r1->rIdx);
2067 void pBlockStats(FILE *of, pBlock *pb)
2073 fprintf(of,"***\n pBlock Stats\n***\n");
2075 // for now just print the first element of each set
2076 pc = setFirstItem(pb->function_entries);
2078 fprintf(of,"entry\n");
2081 pc = setFirstItem(pb->function_exits);
2083 fprintf(of,"has an exit\n");
2087 pc = setFirstItem(pb->function_calls);
2089 fprintf(of,"functions called\n");
2093 pc = setNextItem(pb->function_calls);
2097 r = setFirstItem(pb->registers);
2099 int n = elementsInSet(pb->registers);
2101 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2104 fprintf(of," %s\n",r->name);
2105 r = setNextItem(pb->registers);
2110 /*-----------------------------------------------------------------*/
2111 /*-----------------------------------------------------------------*/
2112 void sequencepCode(void)
2118 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2120 pb->seq = GpCodeSequenceNumber+1;
2122 for( pc = pb->pcHead; pc; pc = pc->next)
2123 pc->seq = ++GpCodeSequenceNumber;
2128 /*-----------------------------------------------------------------*/
2129 /*-----------------------------------------------------------------*/
2130 set *register_usage(pBlock *pb)
2133 set *registers=NULL;
2134 set *registersInCallPath = NULL;
2136 /* check recursion */
2138 pc = setFirstItem(pb->function_entries);
2145 if(pc->type != PC_FUNCTION)
2146 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2148 pc = setFirstItem(pb->function_calls);
2149 for( ; pc; pc = setNextItem(pb->function_calls)) {
2151 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2152 char *dest = get_op(PCI(pc));
2154 pcn = findFunction(dest);
2156 registersInCallPath = register_usage(pcn->pb);
2158 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2163 pBlockStats(stderr,pb); // debug
2164 if(registersInCallPath) {
2165 /* registers were used in the functions this pBlock has called */
2166 /* so now, we need to see if these collide with the ones we are */
2169 regs *r1,*r2, *newreg;
2171 fprintf(stderr,"comparing registers\n");
2173 r1 = setFirstItem(registersInCallPath);
2176 r2 = setFirstItem(pb->registers);
2180 if(r2->rIdx == r1->rIdx) {
2181 newreg = pic14_findFreeReg();
2185 fprintf(stderr,"Bummer, no more registers.\n");
2189 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2190 r1->rIdx, newreg->rIdx);
2191 r2->rIdx = newreg->rIdx;
2192 //if(r2->name) free(r2->name);
2193 r2->name = Safe_strdup(newreg->name);
2195 newreg->wasUsed = 1;
2197 r2 = setNextItem(pb->registers);
2200 r1 = setNextItem(registersInCallPath);
2203 /* Collisions have been resolved. Now free the registers in the call path */
2204 r1 = setFirstItem(registersInCallPath);
2206 newreg = pic14_regWithIdx(r1->rIdx);
2208 r1 = setNextItem(registersInCallPath);
2212 MarkUsedRegisters(pb->registers);
2214 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2217 fprintf(stderr,"returning regs\n");
2219 fprintf(stderr,"not returning regs\n");
2221 fprintf(stderr,"pBlock after register optim.\n");
2222 pBlockStats(stderr,pb); // debug
2228 /*-----------------------------------------------------------------*/
2229 /* printCallTree - writes the call tree to a file */
2231 /*-----------------------------------------------------------------*/
2232 void pct2(FILE *of,pBlock *pb,int indent)
2236 // set *registersInCallPath = NULL;
2239 return;// registers;
2242 return; // registers; //recursion ?
2244 pc = setFirstItem(pb->function_entries);
2251 for(i=0;i<indent;i++) // Indentation
2254 if(pc->type == PC_FUNCTION)
2255 fprintf(of,"%s\n",PCF(pc)->fname);
2260 pc = setFirstItem(pb->function_calls);
2261 for( ; pc; pc = setNextItem(pb->function_calls)) {
2263 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2264 char *dest = get_op(PCI(pc));
2266 pcn = findFunction(dest);
2268 pct2(of,pcn->pb,indent+1);
2270 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2278 fprintf(stderr,"pBlock before register optim.\n");
2279 pBlockStats(stderr,pb); // debug
2281 if(registersInCallPath) {
2282 /* registers were used in the functions this pBlock has called */
2283 /* so now, we need to see if these collide with the ones we are using here */
2285 regs *r1,*r2, *newreg;
2287 fprintf(stderr,"comparing registers\n");
2289 r1 = setFirstItem(registersInCallPath);
2292 r2 = setFirstItem(pb->registers);
2296 if(r2->rIdx == r1->rIdx) {
2297 newreg = pic14_findFreeReg();
2301 fprintf(stderr,"Bummer, no more registers.\n");
2305 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2306 r1->rIdx, newreg->rIdx);
2307 r2->rIdx = newreg->rIdx;
2308 //if(r2->name) free(r2->name);
2309 r2->name = Safe_strdup(newreg->name);
2311 newreg->wasUsed = 1;
2313 r2 = setNextItem(pb->registers);
2316 r1 = setNextItem(registersInCallPath);
2319 /* Collisions have been resolved. Now free the registers in the call path */
2320 r1 = setFirstItem(registersInCallPath);
2322 newreg = pic14_regWithIdx(r1->rIdx);
2324 r1 = setNextItem(registersInCallPath);
2328 MarkUsedRegisters(pb->registers);
2330 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2333 fprintf(stderr,"returning regs\n");
2335 fprintf(stderr,"not returning regs\n");
2337 fprintf(stderr,"pBlock after register optim.\n");
2338 pBlockStats(stderr,pb); // debug
2346 /*-----------------------------------------------------------------*/
2347 /* printCallTree - writes the call tree to a file */
2349 /*-----------------------------------------------------------------*/
2351 void printCallTree(FILE *of)
2363 fprintf(of, "\npBlock statistics\n");
2364 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2365 pBlockStats(stderr,pb);
2369 fprintf(of,"Call Tree\n");
2370 pbr = the_pFile->functions;
2374 if(!ispCodeFunction(pc))
2375 fprintf(of,"bug in call tree");
2378 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2380 while(pc->next && !ispCodeFunction(pc->next)) {
2382 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2383 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2391 /* Re-allocate the registers so that there are no collisions
2392 * between local variables when one function call another */
2394 pic14_deallocateAllRegs();
2396 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2401 fprintf(of,"\n**************\n\na better call tree\n");
2402 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2407 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2408 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));