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 *mnem)
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]);
771 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpADDLW), scpADDLW);
772 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpADDWF),scpADDWF);
773 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpANDLW),scpANDLW);
774 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpANDWF),scpANDWF);
775 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpBCF),scpBCF);
776 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpBSF),scpBSF);
777 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpBTFSC),scpBTFSC);
778 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpBTFSS),scpBTFSS);
779 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpCALL),scpCALL);
780 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpCOMF),scpCOMF);
781 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpCLRF),scpCLRF);
782 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpCLRW),scpCLRW);
783 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpDECF),scpDECF);
784 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpDECFSZ),scpDECFSZ);
785 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpGOTO),scpGOTO);
786 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpINCF),scpINCF);
787 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpINCFSZ),scpINCFSZ);
788 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpIORLW),scpIORLW);
789 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpIORWF),scpIORWF);
790 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpMOVF),scpMOVF);
791 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpMOVLW),scpMOVLW);
792 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpMOVWF),scpMOVWF);
793 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpNEGF),scpNEGF);
794 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpRETLW),scpRETLW);
795 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpRETURN),scpRETURN);
796 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpSUBLW),scpSUBLW);
797 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpSUBWF),scpSUBWF);
798 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpTRIS),scpTRIS);
799 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpXORLW),scpXORLW);
800 hTabAddItem(&pic14MnemonicsHash, mnem2key(scpXORWF),scpXORWF);
803 pci = hTabFirstItem(pic14MnemonicsHash, &key);
806 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
807 pci = hTabNextItem(pic14MnemonicsHash, &key);
810 mnemonics_initialized = 1;
814 char getpBlock_dbName(pBlock *pb)
820 return pb->cmemmap->dbName;
824 /*-----------------------------------------------------------------*/
825 /* movepBlock2Head - given the dbname of a pBlock, move all */
826 /* instances to the front of the doubly linked */
827 /* list of pBlocks */
828 /*-----------------------------------------------------------------*/
830 void movepBlock2Head(char dbName)
834 pb = the_pFile->pbHead;
838 if(getpBlock_dbName(pb) == dbName) {
839 pBlock *pbn = pb->next;
840 pb->next = the_pFile->pbHead;
841 the_pFile->pbHead->prev = pb;
842 the_pFile->pbHead = pb;
845 pb->prev->next = pbn;
847 // If the pBlock that we just moved was the last
848 // one in the link of all of the pBlocks, then we
849 // need to point the tail to the block just before
851 // Note: if pb->next is NULL, then pb must have
852 // been the last pBlock in the chain.
855 pbn->prev = pb->prev;
857 the_pFile->pbTail = pb->prev;
868 void copypCode(FILE *of, char dbName)
872 if(!of || !the_pFile)
875 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
876 if(getpBlock_dbName(pb) == dbName)
881 void pcode_test(void)
884 printf("pcode is alive!\n");
894 /* create the file name */
895 strcpy(buffer,srcFileName);
898 if( !(pFile = fopen(buffer, "w" ))) {
899 werror(E_FILE_OPEN_ERR,buffer);
903 fprintf(pFile,"pcode dump\n\n");
905 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
906 fprintf(pFile,"\n\tNew pBlock\n\n");
908 fprintf(pFile,"%s",pb->cmemmap->sname);
910 fprintf(pFile,"internal pblock");
912 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
913 printpBlock(pFile,pb);
917 static int RegCond(pCodeOp *pcop)
923 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
924 switch(PCOB(pcop)->bit) {
938 /*-----------------------------------------------------------------*/
939 /* newpCode - create and return a newly initialized pCode */
941 /* fixme - rename this */
943 /* The purpose of this routine is to create a new Instruction */
944 /* pCode. This is called by gen.c while the assembly code is being */
948 /* PIC_OPCODE op - the assembly instruction we wish to create. */
949 /* (note that the op is analogous to but not the */
950 /* same thing as the opcode of the instruction.) */
951 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
954 /* a pointer to the new malloc'd pCode is returned. */
958 /*-----------------------------------------------------------------*/
959 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
961 pCodeInstruction *pci ;
963 if(!mnemonics_initialized)
964 pic14initMnemonics();
966 pci = Safe_calloc(1, sizeof(pCodeInstruction));
968 if((op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
969 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
972 if(pci->inCond == PCC_EXAMINE_PCOP)
973 pci->inCond = RegCond(pcop);
975 if(pci->outCond == PCC_EXAMINE_PCOP)
976 pci->outCond = RegCond(pcop);
981 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
987 /*-----------------------------------------------------------------*/
988 /* newpCodeWild - create a "wild" as in wild card pCode */
990 /* Wild pcodes are used during the peep hole optimizer to serve */
991 /* as place holders for any instruction. When a snippet of code is */
992 /* compared to a peep hole rule, the wild card opcode will match */
993 /* any instruction. However, the optional operand and label are */
994 /* additional qualifiers that must also be matched before the */
995 /* line (of assembly code) is declared matched. Note that the */
996 /* operand may be wild too. */
998 /*-----------------------------------------------------------------*/
1000 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1005 pcw = Safe_calloc(1,sizeof(pCodeWild));
1007 pcw->pc.type = PC_WILD;
1008 pcw->pc.prev = pcw->pc.next = NULL;
1009 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1012 pcw->pc.analyze = genericAnalyze;
1013 pcw->pc.destruct = genericDestruct;
1014 pcw->pc.print = genericPrint;
1017 pcw->operand = optional_operand;
1018 pcw->label = optional_label;
1020 return ( (pCode *)pcw);
1024 /*-----------------------------------------------------------------*/
1025 /* newPcodeCharP - create a new pCode from a char string */
1026 /*-----------------------------------------------------------------*/
1028 pCode *newpCodeCharP(char *cP)
1033 pcc = Safe_calloc(1,sizeof(pCodeComment));
1035 pcc->pc.type = PC_COMMENT;
1036 pcc->pc.prev = pcc->pc.next = NULL;
1037 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1040 pcc->pc.analyze = genericAnalyze;
1041 pcc->pc.destruct = genericDestruct;
1042 pcc->pc.print = genericPrint;
1044 pcc->comment = Safe_strdup(cP);
1046 return ( (pCode *)pcc);
1050 /*-----------------------------------------------------------------*/
1051 /* newpCodeGLabel - create a new global label */
1052 /*-----------------------------------------------------------------*/
1055 pCode *newpCodeFunction(char *mod,char *f)
1059 _ALLOC(pcf,sizeof(pCodeFunction));
1061 pcf->pc.type = PC_FUNCTION;
1062 pcf->pc.prev = pcf->pc.next = NULL;
1063 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1066 pcf->pc.analyze = genericAnalyze;
1067 pcf->pc.destruct = genericDestruct;
1068 pcf->pc.print = pCodePrintFunction;
1071 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1072 strcpy(pcf->modname,mod);
1074 pcf->modname = NULL;
1077 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1078 strcpy(pcf->fname,f);
1082 return ( (pCode *)pcf);
1087 pCode *newpCodeLabel(int key)
1093 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1095 pcl->pc.type = PC_LABEL;
1096 pcl->pc.prev = pcl->pc.next = NULL;
1097 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1100 pcl->pc.analyze = genericAnalyze;
1101 pcl->pc.destruct = genericDestruct;
1102 pcl->pc.print = pCodePrintLabel;
1107 sprintf(s,"_%05d_DS_",key);
1108 pcl->label = Safe_strdup(s);
1112 return ( (pCode *)pcl);
1115 pCode *newpCodeLabelStr(char *str)
1117 pCode *pc = newpCodeLabel(-1);
1119 PCL(pc)->label = Safe_strdup(str);
1124 /*-----------------------------------------------------------------*/
1125 /* newpBlock - create and return a pointer to a new pBlock */
1126 /*-----------------------------------------------------------------*/
1127 pBlock *newpBlock(void)
1132 _ALLOC(PpB,sizeof(pBlock));
1133 PpB->next = PpB->prev = NULL;
1135 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1136 PpB->registers = NULL;
1143 /*-----------------------------------------------------------------*/
1144 /* newpCodeChain - create a new chain of pCodes */
1145 /*-----------------------------------------------------------------*
1147 * This function will create a new pBlock and the pointer to the
1148 * pCode that is passed in will be the first pCode in the block.
1149 *-----------------------------------------------------------------*/
1152 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1155 pBlock *pB = newpBlock();
1157 pB->pcHead = pB->pcTail = pc;
1164 /*-----------------------------------------------------------------*/
1165 /*-----------------------------------------------------------------*/
1167 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1171 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1173 pcop->name = Safe_strdup(name);
1178 /*-----------------------------------------------------------------*/
1179 /* newpCodeOpLabel - Create a new label given the key */
1180 /* Note, a negative key means that the label is part of wild card */
1181 /* (and hence a wild card label) used in the pCodePeep */
1182 /* optimizations). */
1183 /*-----------------------------------------------------------------*/
1185 pCodeOp *newpCodeOpLabel(int key)
1190 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1191 pcop->type = PO_LABEL;
1194 sprintf(s,"_%05d_DS_",key);
1195 pcop->name = Safe_strdup(s);
1199 ((pCodeOpLabel *)pcop)->key = key;
1204 pCodeOp *newpCodeOpLit(int lit)
1210 _ALLOC(pcop,sizeof(pCodeOpLit) );
1211 pcop->type = PO_LITERAL;
1212 sprintf(s,"0x%02x",lit);
1213 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
1214 strcpy(pcop->name,s);
1215 ((pCodeOpLit *)pcop)->lit = lit;
1220 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1226 if(!pcp || !subtype) {
1227 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1231 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1232 pcop->type = PO_WILD;
1233 sprintf(s,"%%%d",id);
1234 pcop->name = Safe_strdup(s);
1236 PCOW(pcop)->id = id;
1237 PCOW(pcop)->pcp = pcp;
1238 PCOW(pcop)->subtype = subtype;
1239 PCOW(pcop)->matched = NULL;
1244 pCodeOp *newpCodeOpBit(char *s, int bit)
1248 _ALLOC(pcop,sizeof(pCodeOpBit) );
1249 pcop->type = PO_BIT;
1250 pcop->name = Safe_strdup(s);
1251 PCOB(pcop)->bit = bit;
1253 PCOB(pcop)->inBitSpace = 1;
1255 PCOB(pcop)->inBitSpace = 0;
1260 /*-----------------------------------------------------------------*/
1261 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1262 /*-----------------------------------------------------------------*/
1263 void addpCode2pBlock(pBlock *pb, pCode *pc)
1266 pb->pcTail->next = pc;
1267 pc->prev = pb->pcTail;
1273 /*-----------------------------------------------------------------*/
1274 /* addpBlock - place a pBlock into the pFile */
1275 /*-----------------------------------------------------------------*/
1276 void addpBlock(pBlock *pb)
1280 /* First time called, we'll pass through here. */
1281 _ALLOC(the_pFile,sizeof(the_pFile));
1282 the_pFile->pbHead = the_pFile->pbTail = pb;
1283 the_pFile->functions = NULL;
1287 the_pFile->pbTail->next = pb;
1288 pb->prev = the_pFile->pbTail;
1290 the_pFile->pbTail = pb;
1293 /*-----------------------------------------------------------------*/
1294 /* printpCode - write the contents of a pCode to a file */
1295 /*-----------------------------------------------------------------*/
1296 void printpCode(FILE *of, pCode *pc)
1307 fprintf(of,"warning - unable to print pCode\n");
1310 /*-----------------------------------------------------------------*/
1311 /* printpBlock - write the contents of a pBlock to a file */
1312 /*-----------------------------------------------------------------*/
1313 void printpBlock(FILE *of, pBlock *pb)
1323 for(pc = pb->pcHead; pc; pc = pc->next)
1328 /*-----------------------------------------------------------------*/
1330 /* pCode processing */
1334 /*-----------------------------------------------------------------*/
1336 static void unlinkPC(pCode *pc)
1338 if(pc && pc->prev && pc->next) {
1340 pc->prev->next = pc->next;
1341 pc->next->prev = pc->prev;
1344 static void genericDestruct(pCode *pc)
1348 fprintf(stderr,"warning, calling default pCode destructor\n");
1353 void pBlockRegs(FILE *of, pBlock *pb)
1358 r = setFirstItem(pb->registers);
1360 fprintf(of," %s\n",r->name);
1361 r = setNextItem(pb->registers);
1366 static char *get_op( pCodeInstruction *pcc)
1370 if(pcc && pcc->pcop) {
1373 switch(pcc->pcop->type) {
1377 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1378 fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1379 pBlockRegs(stderr,pcc->pc.pb);
1383 if (pcc->pcop->name)
1384 return pcc->pcop->name;
1389 return "NO operand";
1392 /*-----------------------------------------------------------------*/
1393 /*-----------------------------------------------------------------*/
1394 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1397 fprintf(of,"pcodeopprint\n");
1400 /*-----------------------------------------------------------------*/
1401 /* genericPrint - the contents of a pCode to a file */
1402 /*-----------------------------------------------------------------*/
1403 static void genericPrint(FILE *of, pCode *pc)
1411 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1415 // If the opcode has a label, print that first
1417 pBranch *pbl = pc->label;
1419 if(pbl->pc->type == PC_LABEL)
1420 pCodePrintLabel(of, pbl->pc);
1425 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
1426 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1428 if(PCI(pc)->bit_inst) {
1429 if(PCI(pc)->pcop->type == PO_BIT) {
1430 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1431 fprintf(of,"(%s >> 3), (%s & 7)",
1432 PCI(pc)->pcop->name ,
1433 PCI(pc)->pcop->name );
1435 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1437 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
1438 //PCI(pc)->pcop->t.bit );
1441 if(PCI(pc)->pcop->type == PO_BIT) {
1442 if( PCI(pc)->num_ops == 2)
1443 fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1445 fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
1448 if( PCI(pc)->num_ops == 2)
1449 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
1451 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
1454 fprintf(of,"%s",get_op(PCI(pc)));
1456 if( PCI(pc)->num_ops == 2)
1457 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1463 pBranch *dpb = pc->to; // debug
1465 switch ( dpb->pc->type) {
1467 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1470 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1473 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1487 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1488 if(PCW(pc)->operand) {
1489 fprintf(of,";\toperand ");
1490 pCodeOpPrint(of,PCW(pc)->operand );
1496 fprintf(of,"unknown pCode type %d\n",pc->type);
1501 /*-----------------------------------------------------------------*/
1502 /* pCodePrintFunction - prints function begin/end */
1503 /*-----------------------------------------------------------------*/
1505 static void pCodePrintFunction(FILE *of, pCode *pc)
1511 if( ((pCodeFunction *)pc)->modname)
1512 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1514 if(PCF(pc)->fname) {
1515 pBranch *exits = pc->to;
1517 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1520 exits = exits->next;
1523 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1527 pc->from->pc->type == PC_FUNCTION &&
1528 PCF(pc->from->pc)->fname)
1529 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1531 fprintf(of,"; exit point [can't find entry point]\n");
1534 /*-----------------------------------------------------------------*/
1535 /* pCodePrintLabel - prints label */
1536 /*-----------------------------------------------------------------*/
1538 static void pCodePrintLabel(FILE *of, pCode *pc)
1545 fprintf(of,"%s\n",PCL(pc)->label);
1546 else if (PCL(pc)->key >=0)
1547 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1549 fprintf(of,";wild card label\n");
1552 /*-----------------------------------------------------------------*/
1554 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1570 /*-----------------------------------------------------------------*/
1571 /* pBranchLink - given two pcodes, this function will link them */
1572 /* together through their pBranches */
1573 /*-----------------------------------------------------------------*/
1574 static void pBranchLink(pCode *f, pCode *t)
1578 // Declare a new branch object for the 'from' pCode.
1580 _ALLOC(b,sizeof(pBranch));
1581 b->pc = t; // The link to the 'to' pCode.
1584 f->to = pBranchAppend(f->to,b);
1586 // Now do the same for the 'to' pCode.
1588 _ALLOC(b,sizeof(pBranch));
1592 t->from = pBranchAppend(t->from,b);
1597 /*-----------------------------------------------------------------*/
1598 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1600 /*-----------------------------------------------------------------*/
1601 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1614 /*-----------------------------------------------------------------*/
1615 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1616 /*-----------------------------------------------------------------*/
1617 static void pCodeUnlink(pCode *pc)
1622 if(!pc->prev || !pc->next) {
1623 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1627 /* first remove the pCode from the chain */
1628 pc->prev->next = pc->next;
1629 pc->next->prev = pc->prev;
1631 /* Now for the hard part... */
1633 /* Remove the branches */
1637 pc1 = pb1->pc; /* Get the pCode that branches to the
1638 * one we're unlinking */
1640 /* search for the link back to this pCode (the one we're
1642 if(pb2 = pBranchFind(pc1->to,pc)) {
1643 pb2->pc = pc->to->pc; // make the replacement
1645 /* if the pCode we're unlinking contains multiple 'to'
1646 * branches (e.g. this a skip instruction) then we need
1647 * to copy these extra branches to the chain. */
1649 pBranchAppend(pb2, pc->to->next);
1658 /*-----------------------------------------------------------------*/
1659 /*-----------------------------------------------------------------*/
1660 static void genericAnalyze(pCode *pc)
1670 // Go through the pCodes that are in pCode chain and link
1671 // them together through the pBranches. Note, the pCodes
1672 // are linked together as a contiguous stream like the
1673 // assembly source code lines. The linking here mimics this
1674 // except that comments are not linked in.
1676 pCode *npc = pc->next;
1678 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1679 pBranchLink(pc,npc);
1688 /*-----------------------------------------------------------------*/
1689 /* findLabel - Search the pCode for a particular label */
1690 /*-----------------------------------------------------------------*/
1691 pCode * findLabel(pCodeOpLabel *pcop_label)
1700 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1701 for(pc = pb->pcHead; pc; pc = pc->next) {
1702 if(pc->type == PC_LABEL) {
1703 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1706 if(pc->type == PC_OPCODE) {
1709 if(pbr->pc->type == PC_LABEL) {
1710 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1720 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1724 /*-----------------------------------------------------------------*/
1725 /* findNextInstruction - given a pCode, find the next instruction */
1726 /* in the linked list */
1727 /*-----------------------------------------------------------------*/
1728 pCode * findNextInstruction(pCode *pc)
1732 if(pc->type == PC_OPCODE)
1738 fprintf(stderr,"Couldn't find instruction\n");
1742 /*-----------------------------------------------------------------*/
1743 /* findFunctionEnd - given a pCode find the end of the function */
1744 /* that contains it t */
1745 /*-----------------------------------------------------------------*/
1746 pCode * findFunctionEnd(pCode *pc)
1750 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1756 fprintf(stderr,"Couldn't find function end\n");
1761 /*-----------------------------------------------------------------*/
1762 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1763 /* instruction with which it is associated. */
1764 /*-----------------------------------------------------------------*/
1765 static void AnalyzeLabel(pCode *pc)
1773 static void AnalyzeGOTO(pCode *pc)
1776 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1780 static void AnalyzeSKIP(pCode *pc)
1783 pBranchLink(pc,findNextInstruction(pc->next));
1784 pBranchLink(pc,findNextInstruction(pc->next->next));
1788 static void AnalyzeRETURN(pCode *pc)
1791 // branch_link(pc,findFunctionEnd(pc->next));
1796 void AnalyzepBlock(pBlock *pb)
1803 /* Find all of the registers used in this pBlock */
1804 for(pc = pb->pcHead; pc; pc = pc->next) {
1805 if(pc->type == PC_OPCODE) {
1806 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1808 /* Loop through all of the registers declared so far in
1809 this block and see if we find this new there */
1811 regs *r = setFirstItem(pb->registers);
1814 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1815 PCOR(PCI(pc)->pcop)->r = r;
1818 r = setNextItem(pb->registers);
1822 /* register wasn't found */
1823 r = Safe_calloc(1, sizeof(regs));
1824 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1825 addSet(&pb->registers, r);
1826 PCOR(PCI(pc)->pcop)->r = r;
1827 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1829 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1835 int OptimizepBlock(pBlock *pb)
1840 if(!pb || !peepOptimizing)
1843 fprintf(stderr," Optimizing pBlock\n");
1845 for(pc = pb->pcHead; pc; pc = pc->next)
1846 matches += pCodePeepMatchRule(pc);
1851 /*-----------------------------------------------------------------*/
1852 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1853 /* chain and put them into pBranches that are */
1854 /* associated with the appropriate pCode */
1856 /*-----------------------------------------------------------------*/
1857 void pBlockMergeLabels(pBlock *pb)
1860 pCode *pc, *pcnext=NULL;
1865 for(pc = pb->pcHead; pc; pc = pc->next) {
1867 if(pc->type == PC_LABEL) {
1868 if( !(pcnext = findNextInstruction(pc)) )
1869 return; // Couldn't find an instruction associated with this label
1871 // Unlink the pCode label from it's pCode chain
1873 pc->prev->next = pc->next;
1875 pc->next->prev = pc->prev;
1877 // And link it into the instruction's pBranch labels. (Note, since
1878 // it's possible to have multiple labels associated with one instruction
1879 // we must provide a means to accomodate the additional labels. Thus
1880 // the labels are placed into the singly-linked list "label" as
1881 // opposed to being a single member of the pCodeInstruction.)
1883 _ALLOC(pbr,sizeof(pBranch));
1887 pcnext->label = pBranchAppend(pcnext->label,pbr);
1894 /*-----------------------------------------------------------------*/
1895 /*-----------------------------------------------------------------*/
1896 void OptimizepCode(char dbName)
1898 #define MAX_PASSES 4
1907 fprintf(stderr," Optimizing pCode\n");
1910 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1911 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1912 matches += OptimizepBlock(pb);
1915 while(matches && ++passes < MAX_PASSES);
1919 /*-----------------------------------------------------------------*/
1920 /* AnalyzepCode - parse the pCode that has been generated and form */
1921 /* all of the logical connections. */
1923 /* Essentially what's done here is that the pCode flow is */
1925 /*-----------------------------------------------------------------*/
1927 void AnalyzepCode(char dbName)
1936 fprintf(stderr," Analyzing pCode");
1938 /* First, merge the labels with the instructions */
1939 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1940 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1941 pBlockMergeLabels(pb);
1946 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1947 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1951 /* Now build the call tree.
1952 First we examine all of the pCodes for functions.
1953 Keep in mind that the function boundaries coincide
1954 with pBlock boundaries.
1956 The algorithm goes something like this:
1957 We have two nested loops. The outer loop iterates
1958 through all of the pBlocks/functions. The inner
1959 loop iterates through all of the pCodes for
1960 a given pBlock. When we begin iterating through
1961 a pBlock, the variable pc_fstart, pCode of the start
1962 of a function, is cleared. We then search for pCodes
1963 of type PC_FUNCTION. When one is encountered, we
1964 initialize pc_fstart to this and at the same time
1965 associate a new pBranch object that signifies a
1966 branch entry. If a return is found, then this signifies
1967 a function exit point. We'll link the pCodes of these
1968 returns to the matching pc_fstart.
1970 When we're done, a doubly linked list of pBranches
1971 will exist. The head of this list is stored in
1972 `the_pFile', which is the meta structure for all
1973 of the pCode. Look at the printCallTree function
1974 on how the pBranches are linked together.
1977 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1978 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1979 pCode *pc_fstart=NULL;
1980 for(pc = pb->pcHead; pc; pc = pc->next) {
1981 if(pc->type == PC_FUNCTION) {
1982 if (PCF(pc)->fname) {
1983 // I'm not liking this....
1984 // Found the beginning of a function.
1985 _ALLOC(pbr,sizeof(pBranch));
1986 pbr->pc = pc_fstart = pc;
1989 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1991 // Here's a better way of doing the same:
1992 addSet(&pb->function_entries, pc);
1995 // Found an exit point in a function, e.g. return
1996 // (Note, there may be more than one return per function)
1998 pBranchLink(pc_fstart, pc);
2000 addSet(&pb->function_exits, pc);
2002 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2003 addSet(&pb->function_calls,pc);
2010 /*-----------------------------------------------------------------*/
2011 /* ispCodeFunction - returns true if *pc is the pCode of a */
2013 /*-----------------------------------------------------------------*/
2014 bool ispCodeFunction(pCode *pc)
2017 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2023 /*-----------------------------------------------------------------*/
2024 /* findFunction - Search for a function by name (given the name) */
2025 /* in the set of all functions that are in a pBlock */
2026 /* (note - I expect this to change because I'm planning to limit */
2027 /* pBlock's to just one function declaration */
2028 /*-----------------------------------------------------------------*/
2029 pCode *findFunction(char *fname)
2036 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2038 pc = setFirstItem(pb->function_entries);
2041 if((pc->type == PC_FUNCTION) &&
2043 (strcmp(fname, PCF(pc)->fname)==0))
2046 pc = setNextItem(pb->function_entries);
2054 void MarkUsedRegisters(set *regset)
2059 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2060 r2 = pic14_regWithIdx(r1->rIdx);
2066 void pBlockStats(FILE *of, pBlock *pb)
2072 fprintf(of,"***\n pBlock Stats\n***\n");
2074 // for now just print the first element of each set
2075 pc = setFirstItem(pb->function_entries);
2077 fprintf(of,"entry\n");
2080 pc = setFirstItem(pb->function_exits);
2082 fprintf(of,"has an exit\n");
2086 pc = setFirstItem(pb->function_calls);
2088 fprintf(of,"functions called\n");
2092 pc = setNextItem(pb->function_calls);
2096 r = setFirstItem(pb->registers);
2098 int n = elementsInSet(pb->registers);
2100 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2103 fprintf(of," %s\n",r->name);
2104 r = setNextItem(pb->registers);
2109 /*-----------------------------------------------------------------*/
2110 /*-----------------------------------------------------------------*/
2111 void sequencepCode(void)
2117 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2119 pb->seq = GpCodeSequenceNumber+1;
2121 for( pc = pb->pcHead; pc; pc = pc->next)
2122 pc->seq = ++GpCodeSequenceNumber;
2127 /*-----------------------------------------------------------------*/
2128 /*-----------------------------------------------------------------*/
2129 set *register_usage(pBlock *pb)
2132 set *registers=NULL;
2133 set *registersInCallPath = NULL;
2135 /* check recursion */
2137 pc = setFirstItem(pb->function_entries);
2144 if(pc->type != PC_FUNCTION)
2145 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2147 pc = setFirstItem(pb->function_calls);
2148 for( ; pc; pc = setNextItem(pb->function_calls)) {
2150 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2151 char *dest = get_op(PCI(pc));
2153 pcn = findFunction(dest);
2155 registersInCallPath = register_usage(pcn->pb);
2157 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2162 pBlockStats(stderr,pb); // debug
2163 if(registersInCallPath) {
2164 /* registers were used in the functions this pBlock has called */
2165 /* so now, we need to see if these collide with the ones we are */
2168 regs *r1,*r2, *newreg;
2170 fprintf(stderr,"comparing registers\n");
2172 r1 = setFirstItem(registersInCallPath);
2175 r2 = setFirstItem(pb->registers);
2179 if(r2->rIdx == r1->rIdx) {
2180 newreg = pic14_findFreeReg();
2184 fprintf(stderr,"Bummer, no more registers.\n");
2188 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2189 r1->rIdx, newreg->rIdx);
2190 r2->rIdx = newreg->rIdx;
2191 //if(r2->name) free(r2->name);
2192 r2->name = Safe_strdup(newreg->name);
2194 newreg->wasUsed = 1;
2196 r2 = setNextItem(pb->registers);
2199 r1 = setNextItem(registersInCallPath);
2202 /* Collisions have been resolved. Now free the registers in the call path */
2203 r1 = setFirstItem(registersInCallPath);
2205 newreg = pic14_regWithIdx(r1->rIdx);
2207 r1 = setNextItem(registersInCallPath);
2211 MarkUsedRegisters(pb->registers);
2213 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2216 fprintf(stderr,"returning regs\n");
2218 fprintf(stderr,"not returning regs\n");
2220 fprintf(stderr,"pBlock after register optim.\n");
2221 pBlockStats(stderr,pb); // debug
2227 /*-----------------------------------------------------------------*/
2228 /* printCallTree - writes the call tree to a file */
2230 /*-----------------------------------------------------------------*/
2231 void pct2(FILE *of,pBlock *pb,int indent)
2235 // set *registersInCallPath = NULL;
2238 return;// registers;
2241 return; // registers; //recursion ?
2243 pc = setFirstItem(pb->function_entries);
2250 for(i=0;i<indent;i++) // Indentation
2253 if(pc->type == PC_FUNCTION)
2254 fprintf(of,"%s\n",PCF(pc)->fname);
2259 pc = setFirstItem(pb->function_calls);
2260 for( ; pc; pc = setNextItem(pb->function_calls)) {
2262 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2263 char *dest = get_op(PCI(pc));
2265 pcn = findFunction(dest);
2267 pct2(of,pcn->pb,indent+1);
2269 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2277 fprintf(stderr,"pBlock before register optim.\n");
2278 pBlockStats(stderr,pb); // debug
2280 if(registersInCallPath) {
2281 /* registers were used in the functions this pBlock has called */
2282 /* so now, we need to see if these collide with the ones we are using here */
2284 regs *r1,*r2, *newreg;
2286 fprintf(stderr,"comparing registers\n");
2288 r1 = setFirstItem(registersInCallPath);
2291 r2 = setFirstItem(pb->registers);
2295 if(r2->rIdx == r1->rIdx) {
2296 newreg = pic14_findFreeReg();
2300 fprintf(stderr,"Bummer, no more registers.\n");
2304 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2305 r1->rIdx, newreg->rIdx);
2306 r2->rIdx = newreg->rIdx;
2307 //if(r2->name) free(r2->name);
2308 r2->name = Safe_strdup(newreg->name);
2310 newreg->wasUsed = 1;
2312 r2 = setNextItem(pb->registers);
2315 r1 = setNextItem(registersInCallPath);
2318 /* Collisions have been resolved. Now free the registers in the call path */
2319 r1 = setFirstItem(registersInCallPath);
2321 newreg = pic14_regWithIdx(r1->rIdx);
2323 r1 = setNextItem(registersInCallPath);
2327 MarkUsedRegisters(pb->registers);
2329 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2332 fprintf(stderr,"returning regs\n");
2334 fprintf(stderr,"not returning regs\n");
2336 fprintf(stderr,"pBlock after register optim.\n");
2337 pBlockStats(stderr,pb); // debug
2345 /*-----------------------------------------------------------------*/
2346 /* printCallTree - writes the call tree to a file */
2348 /*-----------------------------------------------------------------*/
2350 void printCallTree(FILE *of)
2362 fprintf(of, "\npBlock statistics\n");
2363 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2364 pBlockStats(stderr,pb);
2368 fprintf(of,"Call Tree\n");
2369 pbr = the_pFile->functions;
2373 if(!ispCodeFunction(pc))
2374 fprintf(of,"bug in call tree");
2377 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2379 while(pc->next && !ispCodeFunction(pc->next)) {
2381 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2382 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2390 /* Re-allocate the registers so that there are no collisions
2391 * between local variables when one function call another */
2393 pic14_deallocateAllRegs();
2395 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2400 fprintf(of,"\n**************\n\na better call tree\n");
2401 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2406 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2407 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));