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};
40 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,NULL};
41 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,NULL};
43 static int mnemonics_initialized = 0;
46 static hTab *pic14MnemonicsHash = NULL;
50 static pFile *the_pFile = NULL;
51 static int peepOptimizing = 1;
52 static int GpCodeSequenceNumber = 1;
54 /****************************************************************/
55 /* Forward declarations */
56 /****************************************************************/
58 static void unlinkPC(pCode *pc);
59 static void genericAnalyze(pCode *pc);
60 static void AnalyzeGOTO(pCode *pc);
61 static void AnalyzeSKIP(pCode *pc);
62 static void AnalyzeRETURN(pCode *pc);
64 static void genericDestruct(pCode *pc);
65 static void genericPrint(FILE *of,pCode *pc);
67 static void pCodePrintLabel(FILE *of, pCode *pc);
68 static void pCodePrintFunction(FILE *of, pCode *pc);
69 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
70 static char *get_op( pCodeInstruction *pcc);
71 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
72 int pCodePeepMatchRule(pCode *pc);
75 pCodeInstruction pciADDWF = {
76 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
84 1,0, // dest, bit instruction
85 (PCC_W | PCC_REGISTER), // inCond
86 (PCC_REGISTER | PCC_Z) // outCond
89 pCodeInstruction pciADDFW = {
90 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
98 0,0, // dest, bit instruction
99 (PCC_W | PCC_REGISTER), // inCond
100 (PCC_W | PCC_Z) // outCond
103 pCodeInstruction pciADDLW = {
104 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
112 0,0, // dest, bit instruction
114 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
117 pCodeInstruction pciANDLW = {
118 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
126 0,0, // dest, bit instruction
128 (PCC_W | PCC_Z) // outCond
131 pCodeInstruction pciANDWF = {
132 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
140 1,0, // dest, bit instruction
141 (PCC_W | PCC_REGISTER), // inCond
142 (PCC_REGISTER | PCC_Z) // outCond
145 pCodeInstruction pciANDFW = {
146 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
154 0,0, // dest, bit instruction
155 (PCC_W | PCC_REGISTER), // inCond
156 (PCC_W | PCC_Z) // outCond
159 pCodeInstruction pciBCF = {
160 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
168 0,1, // dest, bit instruction
170 PCC_EXAMINE_PCOP // outCond
173 pCodeInstruction pciBSF = {
174 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
182 0,1, // dest, bit instruction
184 PCC_EXAMINE_PCOP // outCond
187 pCodeInstruction pciBTFSC = {
188 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
196 0,1, // dest, bit instruction
197 PCC_EXAMINE_PCOP, // inCond
201 pCodeInstruction pciBTFSS = {
202 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
210 0,1, // dest, bit instruction
211 PCC_EXAMINE_PCOP, // inCond
215 pCodeInstruction pciCALL = {
216 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
224 0,0, // dest, bit instruction
229 pCodeInstruction pciCOMF = {
230 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
238 1,0, // dest, bit instruction
239 PCC_REGISTER, // inCond
240 PCC_REGISTER // outCond
243 pCodeInstruction pciCOMFW = {
244 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
252 0,0, // dest, bit instruction
253 PCC_REGISTER, // inCond
257 pCodeInstruction pciCLRF = {
258 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
266 0,0, // dest, bit instruction
267 PCC_REGISTER, // inCond
268 PCC_REGISTER // outCond
271 pCodeInstruction pciCLRW = {
272 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
280 0,0, // dest, bit instruction
285 pCodeInstruction pciDECF = {
286 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
294 1,0, // dest, bit instruction
295 PCC_REGISTER, // inCond
296 PCC_REGISTER // outCond
299 pCodeInstruction pciDECFW = {
300 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
308 0,0, // dest, bit instruction
309 PCC_REGISTER, // inCond
313 pCodeInstruction pciDECFSZ = {
314 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
322 1,0, // dest, bit instruction
323 PCC_REGISTER, // inCond
324 PCC_REGISTER // outCond
327 pCodeInstruction pciDECFSZW = {
328 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
336 0,0, // dest, bit instruction
337 PCC_REGISTER, // inCond
341 pCodeInstruction pciGOTO = {
342 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
350 0,0, // dest, bit instruction
356 pCodeInstruction pciINCF = {
357 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
365 1,0, // dest, bit instruction
366 PCC_REGISTER, // inCond
367 PCC_REGISTER // outCond
370 pCodeInstruction pciINCFW = {
371 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
379 0,0, // dest, bit instruction
380 PCC_REGISTER, // inCond
384 pCodeInstruction pciINCFSZ = {
385 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
393 1,0, // dest, bit instruction
394 PCC_REGISTER, // inCond
395 PCC_REGISTER // outCond
398 pCodeInstruction pciINCFSZW = {
399 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
407 0,0, // dest, bit instruction
408 PCC_REGISTER, // inCond
412 pCodeInstruction pciIORWF = {
413 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
421 1,0, // dest, bit instruction
422 (PCC_W | PCC_REGISTER), // inCond
423 (PCC_REGISTER | PCC_Z) // outCond
426 pCodeInstruction pciIORFW = {
427 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
435 0,0, // dest, bit instruction
436 (PCC_W | PCC_REGISTER), // inCond
437 (PCC_W | PCC_Z) // outCond
440 pCodeInstruction pciIORLW = {
441 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
449 0,0, // dest, bit instruction
451 (PCC_W | PCC_Z) // outCond
454 pCodeInstruction pciMOVF = {
455 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
463 1,0, // dest, bit instruction
464 PCC_REGISTER, // inCond
468 pCodeInstruction pciMOVFW = {
469 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
477 0,0, // dest, bit instruction
478 PCC_REGISTER, // inCond
479 (PCC_W | PCC_Z) // outCond
482 pCodeInstruction pciMOVWF = {
483 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
491 0,0, // dest, bit instruction
496 pCodeInstruction pciMOVLW = {
497 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
505 0,0, // dest, bit instruction
510 pCodeInstruction pciNEGF = {
511 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
519 0,0, // dest, bit instruction
520 PCC_REGISTER, // inCond
525 pCodeInstruction pciRETLW = {
526 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
534 0,0, // dest, bit instruction
539 pCodeInstruction pciRETURN = {
540 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
548 0,0, // dest, bit instruction
554 pCodeInstruction pciRLF = {
555 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
563 1,0, // dest, bit instruction
564 (PCC_C | PCC_REGISTER), // inCond
565 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
568 pCodeInstruction pciRLFW = {
569 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
577 0,0, // dest, bit instruction
578 (PCC_C | PCC_REGISTER), // inCond
579 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
582 pCodeInstruction pciRRF = {
583 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
591 1,0, // dest, bit instruction
592 (PCC_C | PCC_REGISTER), // inCond
593 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
596 pCodeInstruction pciRRFW = {
597 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
605 0,0, // dest, bit instruction
606 (PCC_C | PCC_REGISTER), // inCond
607 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
610 pCodeInstruction pciSUBWF = {
611 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
619 1,0, // dest, bit instruction
620 (PCC_W | PCC_REGISTER), // inCond
621 (PCC_REGISTER | PCC_Z) // outCond
624 pCodeInstruction pciSUBFW = {
625 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
633 0,0, // dest, bit instruction
634 (PCC_W | PCC_REGISTER), // inCond
635 (PCC_W | PCC_Z) // outCond
638 pCodeInstruction pciSUBLW = {
639 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
647 0,0, // dest, bit instruction
649 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
652 pCodeInstruction pciSWAPF = {
653 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
661 1,0, // dest, bit instruction
662 (PCC_REGISTER), // inCond
663 (PCC_REGISTER) // outCond
666 pCodeInstruction pciSWAPFW = {
667 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
675 0,0, // dest, bit instruction
676 (PCC_REGISTER), // inCond
679 pCodeInstruction pciTRIS = {
680 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
688 0,0, // dest, bit instruction
694 pCodeInstruction pciXORWF = {
695 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
703 1,0, // dest, bit instruction
704 (PCC_W | PCC_REGISTER), // inCond
705 (PCC_REGISTER | PCC_Z) // outCond
708 pCodeInstruction pciXORFW = {
709 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
717 0,0, // dest, bit instruction
718 (PCC_W | PCC_REGISTER), // inCond
719 (PCC_W | PCC_Z) // outCond
722 pCodeInstruction pciXORLW = {
723 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
731 0,0, // dest, bit instruction
733 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
737 #define MAX_PIC14MNEMONICS 100
738 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
740 /*-----------------------------------------------------------------*/
741 /* SAFE_snprintf - like snprintf except the string pointer is */
742 /* after the string has been printed to. This is */
743 /* useful for printing to string as though if it */
745 /*-----------------------------------------------------------------*/
746 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
754 va_start(val, format);
756 // Alas, vsnprintf is not ANSI standard, and does not exist
757 // on Solaris (and probably other non-Gnu flavored Unixes).
758 vsnprintf(*str, *size, format, val);
760 // This, of course, is *not* safe, despite the name.
761 vsprintf(*str, format, val);
772 void pCodeInitRegisters(void)
776 pc_fsr.r = pic14_regWithIdx(4);
780 /*-----------------------------------------------------------------*/
781 /* mnem2key - convert a pic mnemonic into a hash key */
782 /* (BTW - this spreads the mnemonics quite well) */
784 /*-----------------------------------------------------------------*/
786 int mnem2key(char const *mnem)
795 key += toupper(*mnem++) +1;
803 void pic14initMnemonics(void)
808 pCodeInstruction *pci;
810 if(mnemonics_initialized)
813 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
814 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
815 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
816 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
817 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
818 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
819 pic14Mnemonics[POC_BCF] = &pciBCF;
820 pic14Mnemonics[POC_BSF] = &pciBSF;
821 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
822 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
823 pic14Mnemonics[POC_CALL] = &pciCALL;
824 pic14Mnemonics[POC_COMF] = &pciCOMF;
825 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
826 pic14Mnemonics[POC_CLRF] = &pciCLRF;
827 pic14Mnemonics[POC_CLRW] = &pciCLRW;
828 pic14Mnemonics[POC_DECF] = &pciDECF;
829 pic14Mnemonics[POC_DECFW] = &pciDECFW;
830 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
831 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
832 pic14Mnemonics[POC_GOTO] = &pciGOTO;
833 pic14Mnemonics[POC_INCF] = &pciINCF;
834 pic14Mnemonics[POC_INCFW] = &pciINCFW;
835 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
836 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
837 pic14Mnemonics[POC_IORLW] = &pciIORLW;
838 pic14Mnemonics[POC_IORWF] = &pciIORWF;
839 pic14Mnemonics[POC_IORFW] = &pciIORFW;
840 pic14Mnemonics[POC_MOVF] = &pciMOVF;
841 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
842 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
843 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
844 pic14Mnemonics[POC_NEGF] = &pciNEGF;
845 pic14Mnemonics[POC_RETLW] = &pciRETLW;
846 pic14Mnemonics[POC_RETURN] = &pciRETURN;
847 pic14Mnemonics[POC_RLF] = &pciRLF;
848 pic14Mnemonics[POC_RLFW] = &pciRLFW;
849 pic14Mnemonics[POC_RRF] = &pciRRF;
850 pic14Mnemonics[POC_RRFW] = &pciRRFW;
851 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
852 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
853 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
854 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
855 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
856 pic14Mnemonics[POC_TRIS] = &pciTRIS;
857 pic14Mnemonics[POC_XORLW] = &pciXORLW;
858 pic14Mnemonics[POC_XORWF] = &pciXORWF;
859 pic14Mnemonics[POC_XORFW] = &pciXORFW;
861 for(i=0; i<MAX_PIC14MNEMONICS; i++)
862 if(pic14Mnemonics[i])
863 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
864 pci = hTabFirstItem(pic14MnemonicsHash, &key);
867 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
868 pci = hTabNextItem(pic14MnemonicsHash, &key);
871 mnemonics_initialized = 1;
874 int getpCode(char *mnem,unsigned dest)
877 pCodeInstruction *pci;
878 int key = mnem2key(mnem);
880 if(!mnemonics_initialized)
881 pic14initMnemonics();
883 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
887 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
888 if((pci->num_ops <= 1) || (pci->dest == dest))
892 pci = hTabNextItemWK (pic14MnemonicsHash);
899 char getpBlock_dbName(pBlock *pb)
905 return pb->cmemmap->dbName;
909 /*-----------------------------------------------------------------*/
910 /* movepBlock2Head - given the dbname of a pBlock, move all */
911 /* instances to the front of the doubly linked */
912 /* list of pBlocks */
913 /*-----------------------------------------------------------------*/
915 void movepBlock2Head(char dbName)
919 pb = the_pFile->pbHead;
923 if(getpBlock_dbName(pb) == dbName) {
924 pBlock *pbn = pb->next;
925 pb->next = the_pFile->pbHead;
926 the_pFile->pbHead->prev = pb;
927 the_pFile->pbHead = pb;
930 pb->prev->next = pbn;
932 // If the pBlock that we just moved was the last
933 // one in the link of all of the pBlocks, then we
934 // need to point the tail to the block just before
936 // Note: if pb->next is NULL, then pb must have
937 // been the last pBlock in the chain.
940 pbn->prev = pb->prev;
942 the_pFile->pbTail = pb->prev;
953 void copypCode(FILE *of, char dbName)
957 if(!of || !the_pFile)
960 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
961 if(getpBlock_dbName(pb) == dbName)
966 void pcode_test(void)
969 printf("pcode is alive!\n");
979 /* create the file name */
980 strcpy(buffer,srcFileName);
983 if( !(pFile = fopen(buffer, "w" ))) {
984 werror(E_FILE_OPEN_ERR,buffer);
988 fprintf(pFile,"pcode dump\n\n");
990 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
991 fprintf(pFile,"\n\tNew pBlock\n\n");
993 fprintf(pFile,"%s",pb->cmemmap->sname);
995 fprintf(pFile,"internal pblock");
997 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
998 printpBlock(pFile,pb);
1002 static int RegCond(pCodeOp *pcop)
1008 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1009 switch(PCOB(pcop)->bit) {
1023 /*-----------------------------------------------------------------*/
1024 /* newpCode - create and return a newly initialized pCode */
1026 /* fixme - rename this */
1028 /* The purpose of this routine is to create a new Instruction */
1029 /* pCode. This is called by gen.c while the assembly code is being */
1033 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1034 /* (note that the op is analogous to but not the */
1035 /* same thing as the opcode of the instruction.) */
1036 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1039 /* a pointer to the new malloc'd pCode is returned. */
1043 /*-----------------------------------------------------------------*/
1044 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1046 pCodeInstruction *pci ;
1048 if(!mnemonics_initialized)
1049 pic14initMnemonics();
1051 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1053 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1054 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1057 if(pci->inCond == PCC_EXAMINE_PCOP)
1058 pci->inCond = RegCond(pcop);
1060 if(pci->outCond == PCC_EXAMINE_PCOP)
1061 pci->outCond = RegCond(pcop);
1063 return (pCode *)pci;
1066 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1072 /*-----------------------------------------------------------------*/
1073 /* newpCodeWild - create a "wild" as in wild card pCode */
1075 /* Wild pcodes are used during the peep hole optimizer to serve */
1076 /* as place holders for any instruction. When a snippet of code is */
1077 /* compared to a peep hole rule, the wild card opcode will match */
1078 /* any instruction. However, the optional operand and label are */
1079 /* additional qualifiers that must also be matched before the */
1080 /* line (of assembly code) is declared matched. Note that the */
1081 /* operand may be wild too. */
1083 /* Note, a wild instruction is specified just like a wild var: */
1084 /* %4 ; A wild instruction, */
1085 /* See the peeph.def file for additional examples */
1087 /*-----------------------------------------------------------------*/
1089 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1094 pcw = Safe_calloc(1,sizeof(pCodeWild));
1096 pcw->pc.type = PC_WILD;
1097 pcw->pc.prev = pcw->pc.next = NULL;
1098 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1101 pcw->pc.analyze = genericAnalyze;
1102 pcw->pc.destruct = genericDestruct;
1103 pcw->pc.print = genericPrint;
1105 pcw->id = pCodeID; // this is the 'n' in %n
1106 pcw->operand = optional_operand;
1107 pcw->label = optional_label;
1109 return ( (pCode *)pcw);
1113 /*-----------------------------------------------------------------*/
1114 /* newPcodeCharP - create a new pCode from a char string */
1115 /*-----------------------------------------------------------------*/
1117 pCode *newpCodeCharP(char *cP)
1122 pcc = Safe_calloc(1,sizeof(pCodeComment));
1124 pcc->pc.type = PC_COMMENT;
1125 pcc->pc.prev = pcc->pc.next = NULL;
1126 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1129 pcc->pc.analyze = genericAnalyze;
1130 pcc->pc.destruct = genericDestruct;
1131 pcc->pc.print = genericPrint;
1134 pcc->comment = Safe_strdup(cP);
1136 pcc->comment = NULL;
1138 return ( (pCode *)pcc);
1142 /*-----------------------------------------------------------------*/
1143 /* newpCodeGLabel - create a new global label */
1144 /*-----------------------------------------------------------------*/
1147 pCode *newpCodeFunction(char *mod,char *f)
1151 _ALLOC(pcf,sizeof(pCodeFunction));
1153 pcf->pc.type = PC_FUNCTION;
1154 pcf->pc.prev = pcf->pc.next = NULL;
1155 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1158 pcf->pc.analyze = genericAnalyze;
1159 pcf->pc.destruct = genericDestruct;
1160 pcf->pc.print = pCodePrintFunction;
1163 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1164 strcpy(pcf->modname,mod);
1166 pcf->modname = NULL;
1169 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1170 strcpy(pcf->fname,f);
1174 return ( (pCode *)pcf);
1178 static void pCodeLabelDestruct(pCode *pc)
1186 if((pc->type == PC_LABEL) && PCL(pc)->label)
1187 free(PCL(pc)->label);
1193 pCode *newpCodeLabel(int key)
1199 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1201 pcl->pc.type = PC_LABEL;
1202 pcl->pc.prev = pcl->pc.next = NULL;
1203 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1206 pcl->pc.analyze = genericAnalyze;
1207 pcl->pc.destruct = pCodeLabelDestruct;
1208 pcl->pc.print = pCodePrintLabel;
1214 sprintf(s,"_%05d_DS_",key);
1216 pcl->label = Safe_strdup(s);
1220 return ( (pCode *)pcl);
1223 pCode *newpCodeLabelStr(char *str)
1225 pCode *pc = newpCodeLabel(-1);
1228 PCL(pc)->label = Safe_strdup(str);
1230 PCL(pc)->label = NULL;
1235 /*-----------------------------------------------------------------*/
1236 /* newpBlock - create and return a pointer to a new pBlock */
1237 /*-----------------------------------------------------------------*/
1238 pBlock *newpBlock(void)
1243 PpB = Safe_calloc(1,sizeof(pBlock) );
1244 PpB->next = PpB->prev = NULL;
1246 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1247 PpB->registers = NULL;
1254 /*-----------------------------------------------------------------*/
1255 /* newpCodeChai0n - create a new chain of pCodes */
1256 /*-----------------------------------------------------------------*
1258 * This function will create a new pBlock and the pointer to the
1259 * pCode that is passed in will be the first pCode in the block.
1260 *-----------------------------------------------------------------*/
1263 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1266 pBlock *pB = newpBlock();
1268 pB->pcHead = pB->pcTail = pc;
1275 /*-----------------------------------------------------------------*/
1276 /* newpCodeOpLabel - Create a new label given the key */
1277 /* Note, a negative key means that the label is part of wild card */
1278 /* (and hence a wild card label) used in the pCodePeep */
1279 /* optimizations). */
1280 /*-----------------------------------------------------------------*/
1282 pCodeOp *newpCodeOpLabel(int key)
1287 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1288 pcop->type = PO_LABEL;
1292 sprintf(s,"_%05d_DS_",key);
1294 pcop->name = Safe_strdup(s);
1298 ((pCodeOpLabel *)pcop)->key = key;
1303 pCodeOp *newpCodeOpLit(int lit)
1309 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1310 pcop->type = PO_LITERAL;
1313 sprintf(s,"0x%02x",lit);
1315 pcop->name = Safe_strdup(s);
1319 ((pCodeOpLit *)pcop)->lit = lit;
1324 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1330 if(!pcp || !subtype) {
1331 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1335 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1336 pcop->type = PO_WILD;
1337 sprintf(s,"%%%d",id);
1338 pcop->name = Safe_strdup(s);
1340 PCOW(pcop)->id = id;
1341 PCOW(pcop)->pcp = pcp;
1342 PCOW(pcop)->subtype = subtype;
1343 PCOW(pcop)->matched = NULL;
1348 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1352 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1353 pcop->type = PO_BIT;
1355 pcop->name = Safe_strdup(s);
1359 PCOB(pcop)->bit = bit;
1360 PCOB(pcop)->inBitSpace = inBitSpace;
1365 pCodeOp *newpCodeOpReg(int rIdx)
1369 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1371 PCOR(pcop)->rIdx = rIdx;
1372 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1373 pcop->type = PCOR(pcop)->r->pc_type;
1378 /*-----------------------------------------------------------------*/
1379 /*-----------------------------------------------------------------*/
1381 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1387 pcop = newpCodeOpBit(name, -1,0);
1391 pcop = newpCodeOpLit(-1);
1395 pcop = newpCodeOpLabel(-1);
1399 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1402 pcop->name = Safe_strdup(name);
1410 /*-----------------------------------------------------------------*/
1411 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1412 /*-----------------------------------------------------------------*/
1413 void addpCode2pBlock(pBlock *pb, pCode *pc)
1416 /* If this is the first pcode to be added to a block that
1417 * was initialized with a NULL pcode, then go ahead and
1418 * make this pcode the head and tail */
1419 pb->pcHead = pb->pcTail = pc;
1421 pb->pcTail->next = pc;
1422 pc->prev = pb->pcTail;
1429 /*-----------------------------------------------------------------*/
1430 /* addpBlock - place a pBlock into the pFile */
1431 /*-----------------------------------------------------------------*/
1432 void addpBlock(pBlock *pb)
1436 /* First time called, we'll pass through here. */
1437 _ALLOC(the_pFile,sizeof(the_pFile));
1438 the_pFile->pbHead = the_pFile->pbTail = pb;
1439 the_pFile->functions = NULL;
1443 the_pFile->pbTail->next = pb;
1444 pb->prev = the_pFile->pbTail;
1446 the_pFile->pbTail = pb;
1449 /*-----------------------------------------------------------------*/
1450 /* printpCode - write the contents of a pCode to a file */
1451 /*-----------------------------------------------------------------*/
1452 void printpCode(FILE *of, pCode *pc)
1463 fprintf(of,"warning - unable to print pCode\n");
1466 /*-----------------------------------------------------------------*/
1467 /* printpBlock - write the contents of a pBlock to a file */
1468 /*-----------------------------------------------------------------*/
1469 void printpBlock(FILE *of, pBlock *pb)
1479 for(pc = pb->pcHead; pc; pc = pc->next)
1484 /*-----------------------------------------------------------------*/
1486 /* pCode processing */
1490 /*-----------------------------------------------------------------*/
1492 static void unlinkPC(pCode *pc)
1499 pc->prev->next = pc->next;
1501 pc->next->prev = pc->prev;
1503 pc->prev = pc->next = NULL;
1506 static void genericDestruct(pCode *pc)
1508 fprintf(stderr,"warning, calling default pCode destructor\n");
1517 void pBlockRegs(FILE *of, pBlock *pb)
1522 r = setFirstItem(pb->registers);
1524 r = setNextItem(pb->registers);
1529 static char *get_op( pCodeInstruction *pcc)
1533 if(pcc && pcc->pcop) {
1536 switch(pcc->pcop->type) {
1541 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1542 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1543 pBlockRegs(stderr,pcc->pc.pb);
1547 if (pcc->pcop->name)
1548 return pcc->pcop->name;
1553 return "NO operand";
1556 /*-----------------------------------------------------------------*/
1557 /*-----------------------------------------------------------------*/
1558 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1561 fprintf(of,"pcodeopprint\n");
1564 char *pCode2str(char *str, int size, pCode *pc)
1572 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1574 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1576 if(PCI(pc)->bit_inst) {
1577 if(PCI(pc)->pcop->type == PO_BIT) {
1578 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1579 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1580 PCI(pc)->pcop->name ,
1581 PCI(pc)->pcop->name );
1583 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1584 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1585 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1586 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1588 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1589 //PCI(pc)->pcop->t.bit );
1592 if(PCI(pc)->pcop->type == PO_BIT) {
1593 if( PCI(pc)->num_ops == 2)
1594 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1596 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1599 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1601 if( PCI(pc)->num_ops == 2)
1602 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1610 /* assuming that comment ends with a \n */
1611 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1615 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1618 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1621 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1630 /*-----------------------------------------------------------------*/
1631 /* genericPrint - the contents of a pCode to a file */
1632 /*-----------------------------------------------------------------*/
1633 static void genericPrint(FILE *of, pCode *pc)
1641 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1645 // If the opcode has a label, print that first
1647 pBranch *pbl = pc->label;
1649 if(pbl->pc->type == PC_LABEL)
1650 pCodePrintLabel(of, pbl->pc);
1659 pCode2str(str, 256, pc);
1661 fprintf(of,"%s",str);
1665 pBranch *dpb = pc->to; // debug
1667 switch ( dpb->pc->type) {
1669 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1672 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1675 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1689 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1691 pCodePrintLabel(of, pc->label->pc);
1693 if(PCW(pc)->operand) {
1694 fprintf(of,";\toperand ");
1695 pCodeOpPrint(of,PCW(pc)->operand );
1701 fprintf(of,"unknown pCode type %d\n",pc->type);
1706 /*-----------------------------------------------------------------*/
1707 /* pCodePrintFunction - prints function begin/end */
1708 /*-----------------------------------------------------------------*/
1710 static void pCodePrintFunction(FILE *of, pCode *pc)
1716 if( ((pCodeFunction *)pc)->modname)
1717 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1719 if(PCF(pc)->fname) {
1720 pBranch *exits = pc->to;
1722 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1725 exits = exits->next;
1728 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1732 pc->from->pc->type == PC_FUNCTION &&
1733 PCF(pc->from->pc)->fname)
1734 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1736 fprintf(of,"; exit point [can't find entry point]\n");
1739 /*-----------------------------------------------------------------*/
1740 /* pCodePrintLabel - prints label */
1741 /*-----------------------------------------------------------------*/
1743 static void pCodePrintLabel(FILE *of, pCode *pc)
1750 fprintf(of,"%s\n",PCL(pc)->label);
1751 else if (PCL(pc)->key >=0)
1752 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1754 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1757 /*-----------------------------------------------------------------*/
1758 static void unlinkpCodeFromBranch(pBranch *pb , pCode *pc)
1767 bprev->next = b->next;
1775 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1791 /*-----------------------------------------------------------------*/
1792 /* pBranchLink - given two pcodes, this function will link them */
1793 /* together through their pBranches */
1794 /*-----------------------------------------------------------------*/
1795 static void pBranchLink(pCode *f, pCode *t)
1799 // Declare a new branch object for the 'from' pCode.
1801 _ALLOC(b,sizeof(pBranch));
1802 b->pc = t; // The link to the 'to' pCode.
1805 f->to = pBranchAppend(f->to,b);
1807 // Now do the same for the 'to' pCode.
1809 _ALLOC(b,sizeof(pBranch));
1813 t->from = pBranchAppend(t->from,b);
1818 /*-----------------------------------------------------------------*/
1819 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1821 /*-----------------------------------------------------------------*/
1822 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1835 /*-----------------------------------------------------------------*/
1836 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1837 /*-----------------------------------------------------------------*/
1838 static void pCodeUnlink(pCode *pc)
1843 if(!pc->prev || !pc->next) {
1844 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1848 /* first remove the pCode from the chain */
1849 pc->prev->next = pc->next;
1850 pc->next->prev = pc->prev;
1852 /* Now for the hard part... */
1854 /* Remove the branches */
1858 pc1 = pb1->pc; /* Get the pCode that branches to the
1859 * one we're unlinking */
1861 /* search for the link back to this pCode (the one we're
1863 if(pb2 = pBranchFind(pc1->to,pc)) {
1864 pb2->pc = pc->to->pc; // make the replacement
1866 /* if the pCode we're unlinking contains multiple 'to'
1867 * branches (e.g. this a skip instruction) then we need
1868 * to copy these extra branches to the chain. */
1870 pBranchAppend(pb2, pc->to->next);
1879 /*-----------------------------------------------------------------*/
1880 /*-----------------------------------------------------------------*/
1881 static void genericAnalyze(pCode *pc)
1891 // Go through the pCodes that are in pCode chain and link
1892 // them together through the pBranches. Note, the pCodes
1893 // are linked together as a contiguous stream like the
1894 // assembly source code lines. The linking here mimics this
1895 // except that comments are not linked in.
1897 pCode *npc = pc->next;
1899 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1900 pBranchLink(pc,npc);
1909 /*-----------------------------------------------------------------*/
1910 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1914 if(pc->type == PC_LABEL) {
1915 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1918 if(pc->type == PC_OPCODE) {
1921 if(pbr->pc->type == PC_LABEL) {
1922 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1932 /*-----------------------------------------------------------------*/
1933 /* findLabel - Search the pCode for a particular label */
1934 /*-----------------------------------------------------------------*/
1935 pCode * findLabel(pCodeOpLabel *pcop_label)
1943 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1944 for(pc = pb->pcHead; pc; pc = pc->next)
1945 if(compareLabel(pc,pcop_label))
1950 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1954 /*-----------------------------------------------------------------*/
1955 /* findNextInstruction - given a pCode, find the next instruction */
1956 /* in the linked list */
1957 /*-----------------------------------------------------------------*/
1958 pCode * findNextInstruction(pCode *pc)
1962 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1968 fprintf(stderr,"Couldn't find instruction\n");
1972 /*-----------------------------------------------------------------*/
1973 /* findFunctionEnd - given a pCode find the end of the function */
1974 /* that contains it t */
1975 /*-----------------------------------------------------------------*/
1976 pCode * findFunctionEnd(pCode *pc)
1980 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1986 fprintf(stderr,"Couldn't find function end\n");
1991 /*-----------------------------------------------------------------*/
1992 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1993 /* instruction with which it is associated. */
1994 /*-----------------------------------------------------------------*/
1995 static void AnalyzeLabel(pCode *pc)
2003 static void AnalyzeGOTO(pCode *pc)
2006 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2010 static void AnalyzeSKIP(pCode *pc)
2013 pBranchLink(pc,findNextInstruction(pc->next));
2014 pBranchLink(pc,findNextInstruction(pc->next->next));
2018 static void AnalyzeRETURN(pCode *pc)
2021 // branch_link(pc,findFunctionEnd(pc->next));
2026 void AnalyzepBlock(pBlock *pb)
2033 /* Find all of the registers used in this pBlock */
2034 for(pc = pb->pcHead; pc; pc = pc->next) {
2035 if(pc->type == PC_OPCODE) {
2036 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2038 /* Loop through all of the registers declared so far in
2039 this block and see if we find this new there */
2041 regs *r = setFirstItem(pb->registers);
2044 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2045 PCOR(PCI(pc)->pcop)->r = r;
2048 r = setNextItem(pb->registers);
2052 /* register wasn't found */
2053 r = Safe_calloc(1, sizeof(regs));
2054 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2055 addSet(&pb->registers, r);
2056 PCOR(PCI(pc)->pcop)->r = r;
2057 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2059 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2065 int OptimizepBlock(pBlock *pb)
2070 if(!pb || !peepOptimizing)
2073 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2074 for(pc = pb->pcHead; pc; pc = pc->next)
2075 matches += pCodePeepMatchRule(pc);
2081 /*-----------------------------------------------------------------*/
2082 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2083 /*-----------------------------------------------------------------*/
2084 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2088 for(pc = pcs; pc; pc = pc->next) {
2090 if((pc->type == PC_OPCODE) &&
2092 (PCI(pc)->pcop->type == PO_LABEL) &&
2093 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2101 /*-----------------------------------------------------------------*/
2102 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2103 /* pCode chain if they're not used. */
2104 /*-----------------------------------------------------------------*/
2105 void pBlockRemoveUnusedLabels(pBlock *pb)
2107 pCode *pc; pCodeLabel *pcl;
2112 for(pc = pb->pcHead; pc; pc = pc->next) {
2114 if(pc->type == PC_LABEL)
2117 pcl = PCL(pc->label->pc);
2120 /* This pCode is a label, so search the pBlock to see if anyone
2123 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2124 /* Couldn't find an instruction that refers to this label
2125 * So, unlink the pCode label from it's pCode chain
2126 * and destroy the label */
2128 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2130 if(pc->type == PC_LABEL) {
2132 pCodeLabelDestruct(pc);
2134 unlinkpCodeFromBranch(pc->label, pc);
2135 if(pc->label->next == NULL && pc->label->pc == NULL) {
2146 /*-----------------------------------------------------------------*/
2147 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2148 /* chain and put them into pBranches that are */
2149 /* associated with the appropriate pCode */
2151 /*-----------------------------------------------------------------*/
2152 void pBlockMergeLabels(pBlock *pb)
2155 pCode *pc, *pcnext=NULL;
2160 /* First, Try to remove any unused labels */
2161 //pBlockRemoveUnusedLabels(pb);
2163 /* Now loop through the pBlock and merge the labels with the opcodes */
2165 for(pc = pb->pcHead; pc; pc = pc->next) {
2167 if(pc->type == PC_LABEL) {
2168 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2169 if( !(pcnext = findNextInstruction(pc)) )
2170 return; // Couldn't find an instruction associated with this label
2172 // Unlink the pCode label from it's pCode chain
2175 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2176 // And link it into the instruction's pBranch labels. (Note, since
2177 // it's possible to have multiple labels associated with one instruction
2178 // we must provide a means to accomodate the additional labels. Thus
2179 // the labels are placed into the singly-linked list "label" as
2180 // opposed to being a single member of the pCodeInstruction.)
2182 _ALLOC(pbr,sizeof(pBranch));
2186 pcnext->label = pBranchAppend(pcnext->label,pbr);
2194 pBlockRemoveUnusedLabels(pb);
2198 /*-----------------------------------------------------------------*/
2199 /*-----------------------------------------------------------------*/
2200 void OptimizepCode(char dbName)
2202 #define MAX_PASSES 4
2211 fprintf(stderr," Optimizing pCode\n");
2214 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2215 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2216 matches += OptimizepBlock(pb);
2219 while(matches && ++passes < MAX_PASSES);
2223 /*-----------------------------------------------------------------*/
2224 /* AnalyzepCode - parse the pCode that has been generated and form */
2225 /* all of the logical connections. */
2227 /* Essentially what's done here is that the pCode flow is */
2229 /*-----------------------------------------------------------------*/
2231 void AnalyzepCode(char dbName)
2240 fprintf(stderr," Analyzing pCode");
2242 /* First, merge the labels with the instructions */
2243 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2244 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2246 fprintf(stderr," analyze and merging block %c\n",dbName);
2247 pBlockMergeLabels(pb);
2252 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2253 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2257 /* Now build the call tree.
2258 First we examine all of the pCodes for functions.
2259 Keep in mind that the function boundaries coincide
2260 with pBlock boundaries.
2262 The algorithm goes something like this:
2263 We have two nested loops. The outer loop iterates
2264 through all of the pBlocks/functions. The inner
2265 loop iterates through all of the pCodes for
2266 a given pBlock. When we begin iterating through
2267 a pBlock, the variable pc_fstart, pCode of the start
2268 of a function, is cleared. We then search for pCodes
2269 of type PC_FUNCTION. When one is encountered, we
2270 initialize pc_fstart to this and at the same time
2271 associate a new pBranch object that signifies a
2272 branch entry. If a return is found, then this signifies
2273 a function exit point. We'll link the pCodes of these
2274 returns to the matching pc_fstart.
2276 When we're done, a doubly linked list of pBranches
2277 will exist. The head of this list is stored in
2278 `the_pFile', which is the meta structure for all
2279 of the pCode. Look at the printCallTree function
2280 on how the pBranches are linked together.
2283 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2284 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2285 pCode *pc_fstart=NULL;
2286 for(pc = pb->pcHead; pc; pc = pc->next) {
2287 if(pc->type == PC_FUNCTION) {
2288 if (PCF(pc)->fname) {
2289 // I'm not liking this....
2290 // Found the beginning of a function.
2291 _ALLOC(pbr,sizeof(pBranch));
2292 pbr->pc = pc_fstart = pc;
2295 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2297 // Here's a better way of doing the same:
2298 addSet(&pb->function_entries, pc);
2301 // Found an exit point in a function, e.g. return
2302 // (Note, there may be more than one return per function)
2304 pBranchLink(pc_fstart, pc);
2306 addSet(&pb->function_exits, pc);
2308 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2309 addSet(&pb->function_calls,pc);
2316 /*-----------------------------------------------------------------*/
2317 /* ispCodeFunction - returns true if *pc is the pCode of a */
2319 /*-----------------------------------------------------------------*/
2320 bool ispCodeFunction(pCode *pc)
2323 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2329 /*-----------------------------------------------------------------*/
2330 /* findFunction - Search for a function by name (given the name) */
2331 /* in the set of all functions that are in a pBlock */
2332 /* (note - I expect this to change because I'm planning to limit */
2333 /* pBlock's to just one function declaration */
2334 /*-----------------------------------------------------------------*/
2335 pCode *findFunction(char *fname)
2342 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2344 pc = setFirstItem(pb->function_entries);
2347 if((pc->type == PC_FUNCTION) &&
2349 (strcmp(fname, PCF(pc)->fname)==0))
2352 pc = setNextItem(pb->function_entries);
2360 void MarkUsedRegisters(set *regset)
2365 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2366 r2 = pic14_regWithIdx(r1->rIdx);
2372 void pBlockStats(FILE *of, pBlock *pb)
2378 fprintf(of,"***\n pBlock Stats\n***\n");
2380 // for now just print the first element of each set
2381 pc = setFirstItem(pb->function_entries);
2383 fprintf(of,"entry\n");
2386 pc = setFirstItem(pb->function_exits);
2388 fprintf(of,"has an exit\n");
2392 pc = setFirstItem(pb->function_calls);
2394 fprintf(of,"functions called\n");
2398 pc = setNextItem(pb->function_calls);
2402 r = setFirstItem(pb->registers);
2404 int n = elementsInSet(pb->registers);
2406 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2409 fprintf(of," %s\n",r->name);
2410 r = setNextItem(pb->registers);
2415 /*-----------------------------------------------------------------*/
2416 /*-----------------------------------------------------------------*/
2417 void sequencepCode(void)
2423 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2425 pb->seq = GpCodeSequenceNumber+1;
2427 for( pc = pb->pcHead; pc; pc = pc->next)
2428 pc->seq = ++GpCodeSequenceNumber;
2433 /*-----------------------------------------------------------------*/
2434 /*-----------------------------------------------------------------*/
2435 set *register_usage(pBlock *pb)
2438 set *registers=NULL;
2439 set *registersInCallPath = NULL;
2441 /* check recursion */
2443 pc = setFirstItem(pb->function_entries);
2450 if(pc->type != PC_FUNCTION)
2451 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2453 pc = setFirstItem(pb->function_calls);
2454 for( ; pc; pc = setNextItem(pb->function_calls)) {
2456 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2457 char *dest = get_op(PCI(pc));
2459 pcn = findFunction(dest);
2461 registersInCallPath = register_usage(pcn->pb);
2463 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2468 pBlockStats(stderr,pb); // debug
2469 if(registersInCallPath) {
2470 /* registers were used in the functions this pBlock has called */
2471 /* so now, we need to see if these collide with the ones we are */
2474 regs *r1,*r2, *newreg;
2476 fprintf(stderr,"comparing registers\n");
2478 r1 = setFirstItem(registersInCallPath);
2481 r2 = setFirstItem(pb->registers);
2485 if(r2->rIdx == r1->rIdx) {
2486 newreg = pic14_findFreeReg();
2490 fprintf(stderr,"Bummer, no more registers.\n");
2494 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2495 r1->rIdx, newreg->rIdx);
2496 r2->rIdx = newreg->rIdx;
2497 //if(r2->name) free(r2->name);
2499 r2->name = Safe_strdup(newreg->name);
2503 newreg->wasUsed = 1;
2505 r2 = setNextItem(pb->registers);
2508 r1 = setNextItem(registersInCallPath);
2511 /* Collisions have been resolved. Now free the registers in the call path */
2512 r1 = setFirstItem(registersInCallPath);
2514 newreg = pic14_regWithIdx(r1->rIdx);
2516 r1 = setNextItem(registersInCallPath);
2520 MarkUsedRegisters(pb->registers);
2522 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2525 fprintf(stderr,"returning regs\n");
2527 fprintf(stderr,"not returning regs\n");
2529 fprintf(stderr,"pBlock after register optim.\n");
2530 pBlockStats(stderr,pb); // debug
2536 /*-----------------------------------------------------------------*/
2537 /* printCallTree - writes the call tree to a file */
2539 /*-----------------------------------------------------------------*/
2540 void pct2(FILE *of,pBlock *pb,int indent)
2544 // set *registersInCallPath = NULL;
2547 return;// registers;
2550 return; // registers; //recursion ?
2552 pc = setFirstItem(pb->function_entries);
2559 for(i=0;i<indent;i++) // Indentation
2562 if(pc->type == PC_FUNCTION)
2563 fprintf(of,"%s\n",PCF(pc)->fname);
2568 pc = setFirstItem(pb->function_calls);
2569 for( ; pc; pc = setNextItem(pb->function_calls)) {
2571 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2572 char *dest = get_op(PCI(pc));
2574 pcn = findFunction(dest);
2576 pct2(of,pcn->pb,indent+1);
2578 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2586 fprintf(stderr,"pBlock before register optim.\n");
2587 pBlockStats(stderr,pb); // debug
2589 if(registersInCallPath) {
2590 /* registers were used in the functions this pBlock has called */
2591 /* so now, we need to see if these collide with the ones we are using here */
2593 regs *r1,*r2, *newreg;
2595 fprintf(stderr,"comparing registers\n");
2597 r1 = setFirstItem(registersInCallPath);
2600 r2 = setFirstItem(pb->registers);
2604 if(r2->rIdx == r1->rIdx) {
2605 newreg = pic14_findFreeReg();
2609 fprintf(stderr,"Bummer, no more registers.\n");
2613 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2614 r1->rIdx, newreg->rIdx);
2615 r2->rIdx = newreg->rIdx;
2616 //if(r2->name) free(r2->name);
2618 r2->name = Safe_strdup(newreg->name);
2622 newreg->wasUsed = 1;
2624 r2 = setNextItem(pb->registers);
2627 r1 = setNextItem(registersInCallPath);
2630 /* Collisions have been resolved. Now free the registers in the call path */
2631 r1 = setFirstItem(registersInCallPath);
2633 newreg = pic14_regWithIdx(r1->rIdx);
2635 r1 = setNextItem(registersInCallPath);
2639 MarkUsedRegisters(pb->registers);
2641 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2644 fprintf(stderr,"returning regs\n");
2646 fprintf(stderr,"not returning regs\n");
2648 fprintf(stderr,"pBlock after register optim.\n");
2649 pBlockStats(stderr,pb); // debug
2657 /*-----------------------------------------------------------------*/
2658 /* printCallTree - writes the call tree to a file */
2660 /*-----------------------------------------------------------------*/
2662 void printCallTree(FILE *of)
2674 fprintf(of, "\npBlock statistics\n");
2675 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2676 pBlockStats(stderr,pb);
2680 fprintf(of,"Call Tree\n");
2681 pbr = the_pFile->functions;
2685 if(!ispCodeFunction(pc))
2686 fprintf(of,"bug in call tree");
2689 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2691 while(pc->next && !ispCodeFunction(pc->next)) {
2693 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2694 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2702 /* Re-allocate the registers so that there are no collisions
2703 * between local variables when one function call another */
2705 pic14_deallocateAllRegs();
2707 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2712 fprintf(of,"\n**************\n\na better call tree\n");
2713 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2718 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2719 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));