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(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) {
1539 r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
1544 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1545 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1546 pBlockRegs(stderr,pcc->pc.pb);
1550 if (pcc->pcop->name)
1551 return pcc->pcop->name;
1556 return "NO operand";
1559 /*-----------------------------------------------------------------*/
1560 /*-----------------------------------------------------------------*/
1561 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1564 fprintf(of,"pcodeopprint\n");
1567 char *pCode2str(char *str, int size, pCode *pc)
1575 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1577 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1579 if(PCI(pc)->bit_inst) {
1580 if(PCI(pc)->pcop->type == PO_BIT) {
1581 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1582 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1583 PCI(pc)->pcop->name ,
1584 PCI(pc)->pcop->name );
1586 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1587 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1588 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1589 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1591 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1592 //PCI(pc)->pcop->t.bit );
1595 if(PCI(pc)->pcop->type == PO_BIT) {
1596 if( PCI(pc)->num_ops == 2)
1597 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1599 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1602 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1604 if( PCI(pc)->num_ops == 2)
1605 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1613 /* assuming that comment ends with a \n */
1614 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1618 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1621 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1624 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1633 /*-----------------------------------------------------------------*/
1634 /* genericPrint - the contents of a pCode to a file */
1635 /*-----------------------------------------------------------------*/
1636 static void genericPrint(FILE *of, pCode *pc)
1644 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1648 // If the opcode has a label, print that first
1650 pBranch *pbl = pc->label;
1652 if(pbl->pc->type == PC_LABEL)
1653 pCodePrintLabel(of, pbl->pc);
1662 pCode2str(str, 256, pc);
1664 fprintf(of,"%s",str);
1668 pBranch *dpb = pc->to; // debug
1670 switch ( dpb->pc->type) {
1672 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1675 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1678 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1692 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1694 pCodePrintLabel(of, pc->label->pc);
1696 if(PCW(pc)->operand) {
1697 fprintf(of,";\toperand ");
1698 pCodeOpPrint(of,PCW(pc)->operand );
1704 fprintf(of,"unknown pCode type %d\n",pc->type);
1709 /*-----------------------------------------------------------------*/
1710 /* pCodePrintFunction - prints function begin/end */
1711 /*-----------------------------------------------------------------*/
1713 static void pCodePrintFunction(FILE *of, pCode *pc)
1719 if( ((pCodeFunction *)pc)->modname)
1720 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1722 if(PCF(pc)->fname) {
1723 pBranch *exits = pc->to;
1725 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1728 exits = exits->next;
1731 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1735 pc->from->pc->type == PC_FUNCTION &&
1736 PCF(pc->from->pc)->fname)
1737 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1739 fprintf(of,"; exit point [can't find entry point]\n");
1742 /*-----------------------------------------------------------------*/
1743 /* pCodePrintLabel - prints label */
1744 /*-----------------------------------------------------------------*/
1746 static void pCodePrintLabel(FILE *of, pCode *pc)
1753 fprintf(of,"%s\n",PCL(pc)->label);
1754 else if (PCL(pc)->key >=0)
1755 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1757 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1760 /*-----------------------------------------------------------------*/
1761 static void unlinkpCodeFromBranch(pBranch *pb , pCode *pc)
1770 bprev->next = b->next;
1778 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1794 /*-----------------------------------------------------------------*/
1795 /* pBranchLink - given two pcodes, this function will link them */
1796 /* together through their pBranches */
1797 /*-----------------------------------------------------------------*/
1798 static void pBranchLink(pCode *f, pCode *t)
1802 // Declare a new branch object for the 'from' pCode.
1804 _ALLOC(b,sizeof(pBranch));
1805 b->pc = t; // The link to the 'to' pCode.
1808 f->to = pBranchAppend(f->to,b);
1810 // Now do the same for the 'to' pCode.
1812 _ALLOC(b,sizeof(pBranch));
1816 t->from = pBranchAppend(t->from,b);
1821 /*-----------------------------------------------------------------*/
1822 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1824 /*-----------------------------------------------------------------*/
1825 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1838 /*-----------------------------------------------------------------*/
1839 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1840 /*-----------------------------------------------------------------*/
1841 static void pCodeUnlink(pCode *pc)
1846 if(!pc->prev || !pc->next) {
1847 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1851 /* first remove the pCode from the chain */
1852 pc->prev->next = pc->next;
1853 pc->next->prev = pc->prev;
1855 /* Now for the hard part... */
1857 /* Remove the branches */
1861 pc1 = pb1->pc; /* Get the pCode that branches to the
1862 * one we're unlinking */
1864 /* search for the link back to this pCode (the one we're
1866 if(pb2 = pBranchFind(pc1->to,pc)) {
1867 pb2->pc = pc->to->pc; // make the replacement
1869 /* if the pCode we're unlinking contains multiple 'to'
1870 * branches (e.g. this a skip instruction) then we need
1871 * to copy these extra branches to the chain. */
1873 pBranchAppend(pb2, pc->to->next);
1882 /*-----------------------------------------------------------------*/
1883 /*-----------------------------------------------------------------*/
1884 static void genericAnalyze(pCode *pc)
1894 // Go through the pCodes that are in pCode chain and link
1895 // them together through the pBranches. Note, the pCodes
1896 // are linked together as a contiguous stream like the
1897 // assembly source code lines. The linking here mimics this
1898 // except that comments are not linked in.
1900 pCode *npc = pc->next;
1902 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1903 pBranchLink(pc,npc);
1912 /*-----------------------------------------------------------------*/
1913 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1917 if(pc->type == PC_LABEL) {
1918 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1921 if(pc->type == PC_OPCODE) {
1924 if(pbr->pc->type == PC_LABEL) {
1925 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1935 /*-----------------------------------------------------------------*/
1936 /* findLabel - Search the pCode for a particular label */
1937 /*-----------------------------------------------------------------*/
1938 pCode * findLabel(pCodeOpLabel *pcop_label)
1946 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1947 for(pc = pb->pcHead; pc; pc = pc->next)
1948 if(compareLabel(pc,pcop_label))
1953 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1957 /*-----------------------------------------------------------------*/
1958 /* findNextInstruction - given a pCode, find the next instruction */
1959 /* in the linked list */
1960 /*-----------------------------------------------------------------*/
1961 pCode * findNextInstruction(pCode *pc)
1965 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1971 fprintf(stderr,"Couldn't find instruction\n");
1975 /*-----------------------------------------------------------------*/
1976 /* findFunctionEnd - given a pCode find the end of the function */
1977 /* that contains it t */
1978 /*-----------------------------------------------------------------*/
1979 pCode * findFunctionEnd(pCode *pc)
1983 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1989 fprintf(stderr,"Couldn't find function end\n");
1994 /*-----------------------------------------------------------------*/
1995 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1996 /* instruction with which it is associated. */
1997 /*-----------------------------------------------------------------*/
1998 static void AnalyzeLabel(pCode *pc)
2006 static void AnalyzeGOTO(pCode *pc)
2009 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2013 static void AnalyzeSKIP(pCode *pc)
2016 pBranchLink(pc,findNextInstruction(pc->next));
2017 pBranchLink(pc,findNextInstruction(pc->next->next));
2021 static void AnalyzeRETURN(pCode *pc)
2024 // branch_link(pc,findFunctionEnd(pc->next));
2029 void AnalyzepBlock(pBlock *pb)
2036 /* Find all of the registers used in this pBlock */
2037 for(pc = pb->pcHead; pc; pc = pc->next) {
2038 if(pc->type == PC_OPCODE) {
2039 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2041 /* Loop through all of the registers declared so far in
2042 this block and see if we find this new there */
2044 regs *r = setFirstItem(pb->registers);
2047 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2048 PCOR(PCI(pc)->pcop)->r = r;
2051 r = setNextItem(pb->registers);
2055 /* register wasn't found */
2056 r = Safe_calloc(1, sizeof(regs));
2057 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2058 addSet(&pb->registers, r);
2059 PCOR(PCI(pc)->pcop)->r = r;
2060 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2062 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2068 int OptimizepBlock(pBlock *pb)
2073 if(!pb || !peepOptimizing)
2076 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2077 for(pc = pb->pcHead; pc; pc = pc->next)
2078 matches += pCodePeepMatchRule(pc);
2084 /*-----------------------------------------------------------------*/
2085 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2086 /*-----------------------------------------------------------------*/
2087 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2091 for(pc = pcs; pc; pc = pc->next) {
2093 if((pc->type == PC_OPCODE) &&
2095 (PCI(pc)->pcop->type == PO_LABEL) &&
2096 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2104 /*-----------------------------------------------------------------*/
2105 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2106 /* pCode chain if they're not used. */
2107 /*-----------------------------------------------------------------*/
2108 void pBlockRemoveUnusedLabels(pBlock *pb)
2110 pCode *pc; pCodeLabel *pcl;
2115 for(pc = pb->pcHead; pc; pc = pc->next) {
2117 if(pc->type == PC_LABEL)
2120 pcl = PCL(pc->label->pc);
2123 /* This pCode is a label, so search the pBlock to see if anyone
2126 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2127 /* Couldn't find an instruction that refers to this label
2128 * So, unlink the pCode label from it's pCode chain
2129 * and destroy the label */
2131 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2133 if(pc->type == PC_LABEL) {
2135 pCodeLabelDestruct(pc);
2137 unlinkpCodeFromBranch(pc->label, pc);
2138 if(pc->label->next == NULL && pc->label->pc == NULL) {
2149 /*-----------------------------------------------------------------*/
2150 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2151 /* chain and put them into pBranches that are */
2152 /* associated with the appropriate pCode */
2154 /*-----------------------------------------------------------------*/
2155 void pBlockMergeLabels(pBlock *pb)
2158 pCode *pc, *pcnext=NULL;
2163 /* First, Try to remove any unused labels */
2164 //pBlockRemoveUnusedLabels(pb);
2166 /* Now loop through the pBlock and merge the labels with the opcodes */
2168 for(pc = pb->pcHead; pc; pc = pc->next) {
2170 if(pc->type == PC_LABEL) {
2171 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2172 if( !(pcnext = findNextInstruction(pc)) )
2173 return; // Couldn't find an instruction associated with this label
2175 // Unlink the pCode label from it's pCode chain
2178 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2179 // And link it into the instruction's pBranch labels. (Note, since
2180 // it's possible to have multiple labels associated with one instruction
2181 // we must provide a means to accomodate the additional labels. Thus
2182 // the labels are placed into the singly-linked list "label" as
2183 // opposed to being a single member of the pCodeInstruction.)
2185 _ALLOC(pbr,sizeof(pBranch));
2189 pcnext->label = pBranchAppend(pcnext->label,pbr);
2197 pBlockRemoveUnusedLabels(pb);
2201 /*-----------------------------------------------------------------*/
2202 /*-----------------------------------------------------------------*/
2203 void OptimizepCode(char dbName)
2205 #define MAX_PASSES 4
2214 fprintf(stderr," Optimizing pCode\n");
2217 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2218 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2219 matches += OptimizepBlock(pb);
2222 while(matches && ++passes < MAX_PASSES);
2226 /*-----------------------------------------------------------------*/
2227 /* AnalyzepCode - parse the pCode that has been generated and form */
2228 /* all of the logical connections. */
2230 /* Essentially what's done here is that the pCode flow is */
2232 /*-----------------------------------------------------------------*/
2234 void AnalyzepCode(char dbName)
2243 fprintf(stderr," Analyzing pCode");
2245 /* First, merge the labels with the instructions */
2246 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2247 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2249 fprintf(stderr," analyze and merging block %c\n",dbName);
2250 pBlockMergeLabels(pb);
2255 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2256 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2260 /* Now build the call tree.
2261 First we examine all of the pCodes for functions.
2262 Keep in mind that the function boundaries coincide
2263 with pBlock boundaries.
2265 The algorithm goes something like this:
2266 We have two nested loops. The outer loop iterates
2267 through all of the pBlocks/functions. The inner
2268 loop iterates through all of the pCodes for
2269 a given pBlock. When we begin iterating through
2270 a pBlock, the variable pc_fstart, pCode of the start
2271 of a function, is cleared. We then search for pCodes
2272 of type PC_FUNCTION. When one is encountered, we
2273 initialize pc_fstart to this and at the same time
2274 associate a new pBranch object that signifies a
2275 branch entry. If a return is found, then this signifies
2276 a function exit point. We'll link the pCodes of these
2277 returns to the matching pc_fstart.
2279 When we're done, a doubly linked list of pBranches
2280 will exist. The head of this list is stored in
2281 `the_pFile', which is the meta structure for all
2282 of the pCode. Look at the printCallTree function
2283 on how the pBranches are linked together.
2286 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2287 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2288 pCode *pc_fstart=NULL;
2289 for(pc = pb->pcHead; pc; pc = pc->next) {
2290 if(pc->type == PC_FUNCTION) {
2291 if (PCF(pc)->fname) {
2292 // I'm not liking this....
2293 // Found the beginning of a function.
2294 _ALLOC(pbr,sizeof(pBranch));
2295 pbr->pc = pc_fstart = pc;
2298 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2300 // Here's a better way of doing the same:
2301 addSet(&pb->function_entries, pc);
2304 // Found an exit point in a function, e.g. return
2305 // (Note, there may be more than one return per function)
2307 pBranchLink(pc_fstart, pc);
2309 addSet(&pb->function_exits, pc);
2311 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2312 addSet(&pb->function_calls,pc);
2319 /*-----------------------------------------------------------------*/
2320 /* ispCodeFunction - returns true if *pc is the pCode of a */
2322 /*-----------------------------------------------------------------*/
2323 bool ispCodeFunction(pCode *pc)
2326 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2332 /*-----------------------------------------------------------------*/
2333 /* findFunction - Search for a function by name (given the name) */
2334 /* in the set of all functions that are in a pBlock */
2335 /* (note - I expect this to change because I'm planning to limit */
2336 /* pBlock's to just one function declaration */
2337 /*-----------------------------------------------------------------*/
2338 pCode *findFunction(char *fname)
2345 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2347 pc = setFirstItem(pb->function_entries);
2350 if((pc->type == PC_FUNCTION) &&
2352 (strcmp(fname, PCF(pc)->fname)==0))
2355 pc = setNextItem(pb->function_entries);
2363 void MarkUsedRegisters(set *regset)
2368 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2369 r2 = pic14_regWithIdx(r1->rIdx);
2375 void pBlockStats(FILE *of, pBlock *pb)
2381 fprintf(of,"***\n pBlock Stats\n***\n");
2383 // for now just print the first element of each set
2384 pc = setFirstItem(pb->function_entries);
2386 fprintf(of,"entry\n");
2389 pc = setFirstItem(pb->function_exits);
2391 fprintf(of,"has an exit\n");
2395 pc = setFirstItem(pb->function_calls);
2397 fprintf(of,"functions called\n");
2401 pc = setNextItem(pb->function_calls);
2405 r = setFirstItem(pb->registers);
2407 int n = elementsInSet(pb->registers);
2409 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2412 fprintf(of," %s\n",r->name);
2413 r = setNextItem(pb->registers);
2418 /*-----------------------------------------------------------------*/
2419 /*-----------------------------------------------------------------*/
2420 void sequencepCode(void)
2426 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2428 pb->seq = GpCodeSequenceNumber+1;
2430 for( pc = pb->pcHead; pc; pc = pc->next)
2431 pc->seq = ++GpCodeSequenceNumber;
2436 /*-----------------------------------------------------------------*/
2437 /*-----------------------------------------------------------------*/
2438 set *register_usage(pBlock *pb)
2441 set *registers=NULL;
2442 set *registersInCallPath = NULL;
2444 /* check recursion */
2446 pc = setFirstItem(pb->function_entries);
2453 if(pc->type != PC_FUNCTION)
2454 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2456 pc = setFirstItem(pb->function_calls);
2457 for( ; pc; pc = setNextItem(pb->function_calls)) {
2459 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2460 char *dest = get_op(PCI(pc));
2462 pcn = findFunction(dest);
2464 registersInCallPath = register_usage(pcn->pb);
2466 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2471 pBlockStats(stderr,pb); // debug
2473 // Mark the registers in this block as used.
2475 MarkUsedRegisters(pb->registers);
2476 if(registersInCallPath) {
2477 /* registers were used in the functions this pBlock has called */
2478 /* so now, we need to see if these collide with the ones we are */
2481 regs *r1,*r2, *newreg;
2483 fprintf(stderr,"comparing registers\n");
2485 r1 = setFirstItem(registersInCallPath);
2488 r2 = setFirstItem(pb->registers);
2492 if(r2->rIdx == r1->rIdx) {
2493 newreg = pic14_findFreeReg();
2497 fprintf(stderr,"Bummer, no more registers.\n");
2501 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2502 r1->rIdx, newreg->rIdx);
2503 r2->rIdx = newreg->rIdx;
2504 //if(r2->name) free(r2->name);
2506 r2->name = Safe_strdup(newreg->name);
2510 newreg->wasUsed = 1;
2512 r2 = setNextItem(pb->registers);
2515 r1 = setNextItem(registersInCallPath);
2518 /* Collisions have been resolved. Now free the registers in the call path */
2519 r1 = setFirstItem(registersInCallPath);
2521 newreg = pic14_regWithIdx(r1->rIdx);
2523 r1 = setNextItem(registersInCallPath);
2527 // MarkUsedRegisters(pb->registers);
2529 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2532 fprintf(stderr,"returning regs\n");
2534 fprintf(stderr,"not returning regs\n");
2536 fprintf(stderr,"pBlock after register optim.\n");
2537 pBlockStats(stderr,pb); // debug
2543 /*-----------------------------------------------------------------*/
2544 /* printCallTree - writes the call tree to a file */
2546 /*-----------------------------------------------------------------*/
2547 void pct2(FILE *of,pBlock *pb,int indent)
2551 // set *registersInCallPath = NULL;
2554 return;// registers;
2557 return; // registers; //recursion ?
2559 pc = setFirstItem(pb->function_entries);
2566 for(i=0;i<indent;i++) // Indentation
2569 if(pc->type == PC_FUNCTION)
2570 fprintf(of,"%s\n",PCF(pc)->fname);
2575 pc = setFirstItem(pb->function_calls);
2576 for( ; pc; pc = setNextItem(pb->function_calls)) {
2578 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2579 char *dest = get_op(PCI(pc));
2581 pcn = findFunction(dest);
2583 pct2(of,pcn->pb,indent+1);
2585 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2593 fprintf(stderr,"pBlock before register optim.\n");
2594 pBlockStats(stderr,pb); // debug
2596 if(registersInCallPath) {
2597 /* registers were used in the functions this pBlock has called */
2598 /* so now, we need to see if these collide with the ones we are using here */
2600 regs *r1,*r2, *newreg;
2602 fprintf(stderr,"comparing registers\n");
2604 r1 = setFirstItem(registersInCallPath);
2607 r2 = setFirstItem(pb->registers);
2611 if(r2->rIdx == r1->rIdx) {
2612 newreg = pic14_findFreeReg();
2616 fprintf(stderr,"Bummer, no more registers.\n");
2620 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2621 r1->rIdx, newreg->rIdx);
2622 r2->rIdx = newreg->rIdx;
2623 //if(r2->name) free(r2->name);
2625 r2->name = Safe_strdup(newreg->name);
2629 newreg->wasUsed = 1;
2631 r2 = setNextItem(pb->registers);
2634 r1 = setNextItem(registersInCallPath);
2637 /* Collisions have been resolved. Now free the registers in the call path */
2638 r1 = setFirstItem(registersInCallPath);
2640 newreg = pic14_regWithIdx(r1->rIdx);
2642 r1 = setNextItem(registersInCallPath);
2646 MarkUsedRegisters(pb->registers);
2648 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2651 fprintf(stderr,"returning regs\n");
2653 fprintf(stderr,"not returning regs\n");
2655 fprintf(stderr,"pBlock after register optim.\n");
2656 pBlockStats(stderr,pb); // debug
2664 /*-----------------------------------------------------------------*/
2665 /* printCallTree - writes the call tree to a file */
2667 /*-----------------------------------------------------------------*/
2669 void printCallTree(FILE *of)
2681 fprintf(of, "\npBlock statistics\n");
2682 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2683 pBlockStats(stderr,pb);
2687 fprintf(of,"Call Tree\n");
2688 pbr = the_pFile->functions;
2692 if(!ispCodeFunction(pc))
2693 fprintf(of,"bug in call tree");
2696 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2698 while(pc->next && !ispCodeFunction(pc->next)) {
2700 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2701 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2709 /* Re-allocate the registers so that there are no collisions
2710 * between local variables when one function call another */
2712 pic14_deallocateAllRegs();
2714 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2719 fprintf(of,"\n**************\n\na better call tree\n");
2720 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2725 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2726 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));