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)
1184 if((pc->type == PC_LABEL) && PCL(pc)->label)
1185 free(PCL(pc)->label);
1191 pCode *newpCodeLabel(int key)
1197 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1199 pcl->pc.type = PC_LABEL;
1200 pcl->pc.prev = pcl->pc.next = NULL;
1201 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1204 pcl->pc.analyze = genericAnalyze;
1205 pcl->pc.destruct = pCodeLabelDestruct;
1206 pcl->pc.print = pCodePrintLabel;
1212 sprintf(s,"_%05d_DS_",key);
1214 pcl->label = Safe_strdup(s);
1218 return ( (pCode *)pcl);
1221 pCode *newpCodeLabelStr(char *str)
1223 pCode *pc = newpCodeLabel(-1);
1226 PCL(pc)->label = Safe_strdup(str);
1228 PCL(pc)->label = NULL;
1233 /*-----------------------------------------------------------------*/
1234 /* newpBlock - create and return a pointer to a new pBlock */
1235 /*-----------------------------------------------------------------*/
1236 pBlock *newpBlock(void)
1241 PpB = Safe_calloc(1,sizeof(pBlock) );
1242 PpB->next = PpB->prev = NULL;
1244 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1245 PpB->registers = NULL;
1252 /*-----------------------------------------------------------------*/
1253 /* newpCodeChai0n - create a new chain of pCodes */
1254 /*-----------------------------------------------------------------*
1256 * This function will create a new pBlock and the pointer to the
1257 * pCode that is passed in will be the first pCode in the block.
1258 *-----------------------------------------------------------------*/
1261 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1264 pBlock *pB = newpBlock();
1266 pB->pcHead = pB->pcTail = pc;
1273 /*-----------------------------------------------------------------*/
1274 /* newpCodeOpLabel - Create a new label given the key */
1275 /* Note, a negative key means that the label is part of wild card */
1276 /* (and hence a wild card label) used in the pCodePeep */
1277 /* optimizations). */
1278 /*-----------------------------------------------------------------*/
1280 pCodeOp *newpCodeOpLabel(int key)
1285 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1286 pcop->type = PO_LABEL;
1290 sprintf(s,"_%05d_DS_",key);
1292 pcop->name = Safe_strdup(s);
1296 ((pCodeOpLabel *)pcop)->key = key;
1301 pCodeOp *newpCodeOpLit(int lit)
1307 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1308 pcop->type = PO_LITERAL;
1311 sprintf(s,"0x%02x",lit);
1313 pcop->name = Safe_strdup(s);
1317 ((pCodeOpLit *)pcop)->lit = lit;
1322 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1328 if(!pcp || !subtype) {
1329 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1333 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1334 pcop->type = PO_WILD;
1335 sprintf(s,"%%%d",id);
1336 pcop->name = Safe_strdup(s);
1338 PCOW(pcop)->id = id;
1339 PCOW(pcop)->pcp = pcp;
1340 PCOW(pcop)->subtype = subtype;
1341 PCOW(pcop)->matched = NULL;
1346 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1350 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1351 pcop->type = PO_BIT;
1353 pcop->name = Safe_strdup(s);
1357 PCOB(pcop)->bit = bit;
1358 PCOB(pcop)->inBitSpace = inBitSpace;
1363 pCodeOp *newpCodeOpReg(int rIdx)
1367 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1369 PCOR(pcop)->rIdx = rIdx;
1370 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1371 pcop->type = PCOR(pcop)->r->pc_type;
1376 /*-----------------------------------------------------------------*/
1377 /*-----------------------------------------------------------------*/
1379 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1385 pcop = newpCodeOpBit(name, -1,0);
1389 pcop = newpCodeOpLit(-1);
1393 pcop = newpCodeOpLabel(-1);
1397 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1400 pcop->name = Safe_strdup(name);
1408 /*-----------------------------------------------------------------*/
1409 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1410 /*-----------------------------------------------------------------*/
1411 void addpCode2pBlock(pBlock *pb, pCode *pc)
1414 /* If this is the first pcode to be added to a block that
1415 * was initialized with a NULL pcode, then go ahead and
1416 * make this pcode the head and tail */
1417 pb->pcHead = pb->pcTail = pc;
1419 pb->pcTail->next = pc;
1420 pc->prev = pb->pcTail;
1427 /*-----------------------------------------------------------------*/
1428 /* addpBlock - place a pBlock into the pFile */
1429 /*-----------------------------------------------------------------*/
1430 void addpBlock(pBlock *pb)
1434 /* First time called, we'll pass through here. */
1435 _ALLOC(the_pFile,sizeof(pFile));
1436 the_pFile->pbHead = the_pFile->pbTail = pb;
1437 the_pFile->functions = NULL;
1441 the_pFile->pbTail->next = pb;
1442 pb->prev = the_pFile->pbTail;
1444 the_pFile->pbTail = pb;
1447 /*-----------------------------------------------------------------*/
1448 /* printpCode - write the contents of a pCode to a file */
1449 /*-----------------------------------------------------------------*/
1450 void printpCode(FILE *of, pCode *pc)
1461 fprintf(of,"warning - unable to print pCode\n");
1464 /*-----------------------------------------------------------------*/
1465 /* printpBlock - write the contents of a pBlock to a file */
1466 /*-----------------------------------------------------------------*/
1467 void printpBlock(FILE *of, pBlock *pb)
1477 for(pc = pb->pcHead; pc; pc = pc->next)
1482 /*-----------------------------------------------------------------*/
1484 /* pCode processing */
1488 /*-----------------------------------------------------------------*/
1490 static void unlinkPC(pCode *pc)
1497 pc->prev->next = pc->next;
1499 pc->next->prev = pc->prev;
1501 pc->prev = pc->next = NULL;
1504 static void genericDestruct(pCode *pc)
1506 fprintf(stderr,"warning, calling default pCode destructor\n");
1515 void pBlockRegs(FILE *of, pBlock *pb)
1520 r = setFirstItem(pb->registers);
1522 r = setNextItem(pb->registers);
1527 static char *get_op( pCodeInstruction *pcc)
1531 if(pcc && pcc->pcop) {
1534 switch(pcc->pcop->type) {
1537 r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
1542 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1543 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1544 pBlockRegs(stderr,pcc->pc.pb);
1548 if (pcc->pcop->name)
1549 return pcc->pcop->name;
1554 return "NO operand";
1557 /*-----------------------------------------------------------------*/
1558 /*-----------------------------------------------------------------*/
1559 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1562 fprintf(of,"pcodeopprint\n");
1565 char *pCode2str(char *str, int size, pCode *pc)
1573 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1575 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1577 if(PCI(pc)->bit_inst) {
1578 if(PCI(pc)->pcop->type == PO_BIT) {
1579 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1580 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1581 PCI(pc)->pcop->name ,
1582 PCI(pc)->pcop->name );
1584 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1585 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1586 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1587 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1589 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1590 //PCI(pc)->pcop->t.bit );
1593 if(PCI(pc)->pcop->type == PO_BIT) {
1594 if( PCI(pc)->num_ops == 2)
1595 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1597 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1600 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1602 if( PCI(pc)->num_ops == 2)
1603 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1611 /* assuming that comment ends with a \n */
1612 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1616 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1619 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1622 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1631 /*-----------------------------------------------------------------*/
1632 /* genericPrint - the contents of a pCode to a file */
1633 /*-----------------------------------------------------------------*/
1634 static void genericPrint(FILE *of, pCode *pc)
1642 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1646 // If the opcode has a label, print that first
1648 pBranch *pbl = pc->label;
1649 while(pbl && pbl->pc) {
1650 if(pbl->pc->type == PC_LABEL)
1651 pCodePrintLabel(of, pbl->pc);
1660 pCode2str(str, 256, pc);
1662 fprintf(of,"%s",str);
1666 pBranch *dpb = pc->to; // debug
1668 switch ( dpb->pc->type) {
1670 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1673 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1676 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1690 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1692 pCodePrintLabel(of, pc->label->pc);
1694 if(PCW(pc)->operand) {
1695 fprintf(of,";\toperand ");
1696 pCodeOpPrint(of,PCW(pc)->operand );
1702 fprintf(of,"unknown pCode type %d\n",pc->type);
1707 /*-----------------------------------------------------------------*/
1708 /* pCodePrintFunction - prints function begin/end */
1709 /*-----------------------------------------------------------------*/
1711 static void pCodePrintFunction(FILE *of, pCode *pc)
1717 if( ((pCodeFunction *)pc)->modname)
1718 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1720 if(PCF(pc)->fname) {
1721 pBranch *exits = pc->to;
1723 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1726 exits = exits->next;
1729 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1733 pc->from->pc->type == PC_FUNCTION &&
1734 PCF(pc->from->pc)->fname)
1735 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1737 fprintf(of,"; exit point [can't find entry point]\n");
1740 /*-----------------------------------------------------------------*/
1741 /* pCodePrintLabel - prints label */
1742 /*-----------------------------------------------------------------*/
1744 static void pCodePrintLabel(FILE *of, pCode *pc)
1751 fprintf(of,"%s\n",PCL(pc)->label);
1752 else if (PCL(pc)->key >=0)
1753 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1755 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1758 /*-----------------------------------------------------------------*/
1759 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
1760 /* remove it if it is found. */
1761 /*-----------------------------------------------------------------*/
1762 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
1773 bprev->next = b->next; /* Not first pCode in chain */
1777 pcl->label = b->next; /* First pCode in chain */
1780 return; /* A label can't occur more than once */
1788 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1804 /*-----------------------------------------------------------------*/
1805 /* pBranchLink - given two pcodes, this function will link them */
1806 /* together through their pBranches */
1807 /*-----------------------------------------------------------------*/
1808 static void pBranchLink(pCode *f, pCode *t)
1812 // Declare a new branch object for the 'from' pCode.
1814 _ALLOC(b,sizeof(pBranch));
1815 b->pc = t; // The link to the 'to' pCode.
1818 f->to = pBranchAppend(f->to,b);
1820 // Now do the same for the 'to' pCode.
1822 _ALLOC(b,sizeof(pBranch));
1826 t->from = pBranchAppend(t->from,b);
1831 /*-----------------------------------------------------------------*/
1832 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1834 /*-----------------------------------------------------------------*/
1835 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1848 /*-----------------------------------------------------------------*/
1849 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1850 /*-----------------------------------------------------------------*/
1851 static void pCodeUnlink(pCode *pc)
1856 if(!pc->prev || !pc->next) {
1857 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1861 /* first remove the pCode from the chain */
1862 pc->prev->next = pc->next;
1863 pc->next->prev = pc->prev;
1865 /* Now for the hard part... */
1867 /* Remove the branches */
1871 pc1 = pb1->pc; /* Get the pCode that branches to the
1872 * one we're unlinking */
1874 /* search for the link back to this pCode (the one we're
1876 if(pb2 = pBranchFind(pc1->to,pc)) {
1877 pb2->pc = pc->to->pc; // make the replacement
1879 /* if the pCode we're unlinking contains multiple 'to'
1880 * branches (e.g. this a skip instruction) then we need
1881 * to copy these extra branches to the chain. */
1883 pBranchAppend(pb2, pc->to->next);
1892 /*-----------------------------------------------------------------*/
1893 /*-----------------------------------------------------------------*/
1894 static void genericAnalyze(pCode *pc)
1904 // Go through the pCodes that are in pCode chain and link
1905 // them together through the pBranches. Note, the pCodes
1906 // are linked together as a contiguous stream like the
1907 // assembly source code lines. The linking here mimics this
1908 // except that comments are not linked in.
1910 pCode *npc = pc->next;
1912 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1913 pBranchLink(pc,npc);
1922 /*-----------------------------------------------------------------*/
1923 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1927 if(pc->type == PC_LABEL) {
1928 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1931 if(pc->type == PC_OPCODE) {
1934 if(pbr->pc->type == PC_LABEL) {
1935 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1945 /*-----------------------------------------------------------------*/
1946 /* findLabel - Search the pCode for a particular label */
1947 /*-----------------------------------------------------------------*/
1948 pCode * findLabel(pCodeOpLabel *pcop_label)
1956 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1957 for(pc = pb->pcHead; pc; pc = pc->next)
1958 if(compareLabel(pc,pcop_label))
1963 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1967 /*-----------------------------------------------------------------*/
1968 /* findNextInstruction - given a pCode, find the next instruction */
1969 /* in the linked list */
1970 /*-----------------------------------------------------------------*/
1971 pCode * findNextInstruction(pCode *pc)
1975 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1981 fprintf(stderr,"Couldn't find instruction\n");
1985 /*-----------------------------------------------------------------*/
1986 /* findFunctionEnd - given a pCode find the end of the function */
1987 /* that contains it t */
1988 /*-----------------------------------------------------------------*/
1989 pCode * findFunctionEnd(pCode *pc)
1993 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1999 fprintf(stderr,"Couldn't find function end\n");
2004 /*-----------------------------------------------------------------*/
2005 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2006 /* instruction with which it is associated. */
2007 /*-----------------------------------------------------------------*/
2008 static void AnalyzeLabel(pCode *pc)
2016 static void AnalyzeGOTO(pCode *pc)
2019 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2023 static void AnalyzeSKIP(pCode *pc)
2026 pBranchLink(pc,findNextInstruction(pc->next));
2027 pBranchLink(pc,findNextInstruction(pc->next->next));
2031 static void AnalyzeRETURN(pCode *pc)
2034 // branch_link(pc,findFunctionEnd(pc->next));
2039 void AnalyzepBlock(pBlock *pb)
2046 /* Find all of the registers used in this pBlock */
2047 for(pc = pb->pcHead; pc; pc = pc->next) {
2048 if(pc->type == PC_OPCODE) {
2049 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2051 /* Loop through all of the registers declared so far in
2052 this block and see if we find this new there */
2054 regs *r = setFirstItem(pb->registers);
2057 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2058 PCOR(PCI(pc)->pcop)->r = r;
2061 r = setNextItem(pb->registers);
2065 /* register wasn't found */
2066 r = Safe_calloc(1, sizeof(regs));
2067 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2068 addSet(&pb->registers, r);
2069 PCOR(PCI(pc)->pcop)->r = r;
2070 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2072 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2078 int OptimizepBlock(pBlock *pb)
2083 if(!pb || !peepOptimizing)
2086 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2087 for(pc = pb->pcHead; pc; pc = pc->next)
2088 matches += pCodePeepMatchRule(pc);
2094 /*-----------------------------------------------------------------*/
2095 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2096 /*-----------------------------------------------------------------*/
2097 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2101 for(pc = pcs; pc; pc = pc->next) {
2103 if((pc->type == PC_OPCODE) &&
2105 (PCI(pc)->pcop->type == PO_LABEL) &&
2106 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2114 /*-----------------------------------------------------------------*/
2115 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2116 /* pCode chain if they're not used. */
2117 /*-----------------------------------------------------------------*/
2118 void pBlockRemoveUnusedLabels(pBlock *pb)
2120 pCode *pc; pCodeLabel *pcl;
2125 for(pc = pb->pcHead; pc; pc = pc->next) {
2127 if(pc->type == PC_LABEL)
2130 pcl = PCL(pc->label->pc);
2133 /* This pCode is a label, so search the pBlock to see if anyone
2136 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2137 /* Couldn't find an instruction that refers to this label
2138 * So, unlink the pCode label from it's pCode chain
2139 * and destroy the label */
2141 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2143 if(pc->type == PC_LABEL) {
2145 pCodeLabelDestruct(pc);
2147 unlinkpCodeFromBranch(pc, PCODE(pcl));
2148 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
2159 /*-----------------------------------------------------------------*/
2160 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2161 /* chain and put them into pBranches that are */
2162 /* associated with the appropriate pCode */
2164 /*-----------------------------------------------------------------*/
2165 void pBlockMergeLabels(pBlock *pb)
2168 pCode *pc, *pcnext=NULL;
2173 /* First, Try to remove any unused labels */
2174 //pBlockRemoveUnusedLabels(pb);
2176 /* Now loop through the pBlock and merge the labels with the opcodes */
2178 for(pc = pb->pcHead; pc; pc = pc->next) {
2180 if(pc->type == PC_LABEL) {
2181 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2182 if( !(pcnext = findNextInstruction(pc)) )
2183 return; // Couldn't find an instruction associated with this label
2185 // Unlink the pCode label from it's pCode chain
2188 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2189 // And link it into the instruction's pBranch labels. (Note, since
2190 // it's possible to have multiple labels associated with one instruction
2191 // we must provide a means to accomodate the additional labels. Thus
2192 // the labels are placed into the singly-linked list "label" as
2193 // opposed to being a single member of the pCodeInstruction.)
2195 _ALLOC(pbr,sizeof(pBranch));
2199 pcnext->label = pBranchAppend(pcnext->label,pbr);
2207 pBlockRemoveUnusedLabels(pb);
2211 /*-----------------------------------------------------------------*/
2212 /*-----------------------------------------------------------------*/
2213 void OptimizepCode(char dbName)
2215 #define MAX_PASSES 4
2224 fprintf(stderr," Optimizing pCode\n");
2227 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2228 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2229 matches += OptimizepBlock(pb);
2232 while(matches && ++passes < MAX_PASSES);
2236 /*-----------------------------------------------------------------*/
2237 /* AnalyzepCode - parse the pCode that has been generated and form */
2238 /* all of the logical connections. */
2240 /* Essentially what's done here is that the pCode flow is */
2242 /*-----------------------------------------------------------------*/
2244 void AnalyzepCode(char dbName)
2255 fprintf(stderr," Analyzing pCode");
2260 /* First, merge the labels with the instructions */
2261 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2262 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2264 fprintf(stderr," analyze and merging block %c\n",dbName);
2265 pBlockMergeLabels(pb);
2270 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2271 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2272 changes += OptimizepBlock(pb);
2275 } while(changes && (i++ < MAX_PASSES));
2277 /* Now build the call tree.
2278 First we examine all of the pCodes for functions.
2279 Keep in mind that the function boundaries coincide
2280 with pBlock boundaries.
2282 The algorithm goes something like this:
2283 We have two nested loops. The outer loop iterates
2284 through all of the pBlocks/functions. The inner
2285 loop iterates through all of the pCodes for
2286 a given pBlock. When we begin iterating through
2287 a pBlock, the variable pc_fstart, pCode of the start
2288 of a function, is cleared. We then search for pCodes
2289 of type PC_FUNCTION. When one is encountered, we
2290 initialize pc_fstart to this and at the same time
2291 associate a new pBranch object that signifies a
2292 branch entry. If a return is found, then this signifies
2293 a function exit point. We'll link the pCodes of these
2294 returns to the matching pc_fstart.
2296 When we're done, a doubly linked list of pBranches
2297 will exist. The head of this list is stored in
2298 `the_pFile', which is the meta structure for all
2299 of the pCode. Look at the printCallTree function
2300 on how the pBranches are linked together.
2303 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2304 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2305 pCode *pc_fstart=NULL;
2306 for(pc = pb->pcHead; pc; pc = pc->next) {
2307 if(pc->type == PC_FUNCTION) {
2308 if (PCF(pc)->fname) {
2309 // I'm not liking this....
2310 // Found the beginning of a function.
2311 _ALLOC(pbr,sizeof(pBranch));
2312 pbr->pc = pc_fstart = pc;
2315 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2317 // Here's a better way of doing the same:
2318 addSet(&pb->function_entries, pc);
2321 // Found an exit point in a function, e.g. return
2322 // (Note, there may be more than one return per function)
2324 pBranchLink(pc_fstart, pc);
2326 addSet(&pb->function_exits, pc);
2328 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2329 addSet(&pb->function_calls,pc);
2336 /*-----------------------------------------------------------------*/
2337 /* ispCodeFunction - returns true if *pc is the pCode of a */
2339 /*-----------------------------------------------------------------*/
2340 bool ispCodeFunction(pCode *pc)
2343 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2349 /*-----------------------------------------------------------------*/
2350 /* findFunction - Search for a function by name (given the name) */
2351 /* in the set of all functions that are in a pBlock */
2352 /* (note - I expect this to change because I'm planning to limit */
2353 /* pBlock's to just one function declaration */
2354 /*-----------------------------------------------------------------*/
2355 pCode *findFunction(char *fname)
2362 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2364 pc = setFirstItem(pb->function_entries);
2367 if((pc->type == PC_FUNCTION) &&
2369 (strcmp(fname, PCF(pc)->fname)==0))
2372 pc = setNextItem(pb->function_entries);
2380 void MarkUsedRegisters(set *regset)
2385 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2386 r2 = pic14_regWithIdx(r1->rIdx);
2392 void pBlockStats(FILE *of, pBlock *pb)
2398 fprintf(of,"***\n pBlock Stats\n***\n");
2400 // for now just print the first element of each set
2401 pc = setFirstItem(pb->function_entries);
2403 fprintf(of,"entry\n");
2406 pc = setFirstItem(pb->function_exits);
2408 fprintf(of,"has an exit\n");
2412 pc = setFirstItem(pb->function_calls);
2414 fprintf(of,"functions called\n");
2418 pc = setNextItem(pb->function_calls);
2422 r = setFirstItem(pb->registers);
2424 int n = elementsInSet(pb->registers);
2426 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2429 fprintf(of," %s\n",r->name);
2430 r = setNextItem(pb->registers);
2435 /*-----------------------------------------------------------------*/
2436 /*-----------------------------------------------------------------*/
2437 void sequencepCode(void)
2443 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2445 pb->seq = GpCodeSequenceNumber+1;
2447 for( pc = pb->pcHead; pc; pc = pc->next)
2448 pc->seq = ++GpCodeSequenceNumber;
2453 /*-----------------------------------------------------------------*/
2454 /*-----------------------------------------------------------------*/
2455 set *register_usage(pBlock *pb)
2458 set *registers=NULL;
2459 set *registersInCallPath = NULL;
2461 /* check recursion */
2463 pc = setFirstItem(pb->function_entries);
2470 if(pc->type != PC_FUNCTION)
2471 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2473 pc = setFirstItem(pb->function_calls);
2474 for( ; pc; pc = setNextItem(pb->function_calls)) {
2476 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2477 char *dest = get_op(PCI(pc));
2479 pcn = findFunction(dest);
2481 registersInCallPath = register_usage(pcn->pb);
2483 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2488 pBlockStats(stderr,pb); // debug
2490 // Mark the registers in this block as used.
2492 MarkUsedRegisters(pb->registers);
2493 if(registersInCallPath) {
2494 /* registers were used in the functions this pBlock has called */
2495 /* so now, we need to see if these collide with the ones we are */
2498 regs *r1,*r2, *newreg;
2500 fprintf(stderr,"comparing registers\n");
2502 r1 = setFirstItem(registersInCallPath);
2505 r2 = setFirstItem(pb->registers);
2509 if(r2->rIdx == r1->rIdx) {
2510 newreg = pic14_findFreeReg();
2514 fprintf(stderr,"Bummer, no more registers.\n");
2518 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2519 r1->rIdx, newreg->rIdx);
2520 r2->rIdx = newreg->rIdx;
2521 //if(r2->name) free(r2->name);
2523 r2->name = Safe_strdup(newreg->name);
2527 newreg->wasUsed = 1;
2529 r2 = setNextItem(pb->registers);
2532 r1 = setNextItem(registersInCallPath);
2535 /* Collisions have been resolved. Now free the registers in the call path */
2536 r1 = setFirstItem(registersInCallPath);
2538 newreg = pic14_regWithIdx(r1->rIdx);
2540 r1 = setNextItem(registersInCallPath);
2544 // MarkUsedRegisters(pb->registers);
2546 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2549 fprintf(stderr,"returning regs\n");
2551 fprintf(stderr,"not returning regs\n");
2553 fprintf(stderr,"pBlock after register optim.\n");
2554 pBlockStats(stderr,pb); // debug
2560 /*-----------------------------------------------------------------*/
2561 /* printCallTree - writes the call tree to a file */
2563 /*-----------------------------------------------------------------*/
2564 void pct2(FILE *of,pBlock *pb,int indent)
2568 // set *registersInCallPath = NULL;
2571 return;// registers;
2574 return; // registers; //recursion ?
2576 pc = setFirstItem(pb->function_entries);
2583 for(i=0;i<indent;i++) // Indentation
2586 if(pc->type == PC_FUNCTION)
2587 fprintf(of,"%s\n",PCF(pc)->fname);
2592 pc = setFirstItem(pb->function_calls);
2593 for( ; pc; pc = setNextItem(pb->function_calls)) {
2595 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2596 char *dest = get_op(PCI(pc));
2598 pcn = findFunction(dest);
2600 pct2(of,pcn->pb,indent+1);
2602 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2610 fprintf(stderr,"pBlock before register optim.\n");
2611 pBlockStats(stderr,pb); // debug
2613 if(registersInCallPath) {
2614 /* registers were used in the functions this pBlock has called */
2615 /* so now, we need to see if these collide with the ones we are using here */
2617 regs *r1,*r2, *newreg;
2619 fprintf(stderr,"comparing registers\n");
2621 r1 = setFirstItem(registersInCallPath);
2624 r2 = setFirstItem(pb->registers);
2628 if(r2->rIdx == r1->rIdx) {
2629 newreg = pic14_findFreeReg();
2633 fprintf(stderr,"Bummer, no more registers.\n");
2637 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2638 r1->rIdx, newreg->rIdx);
2639 r2->rIdx = newreg->rIdx;
2640 //if(r2->name) free(r2->name);
2642 r2->name = Safe_strdup(newreg->name);
2646 newreg->wasUsed = 1;
2648 r2 = setNextItem(pb->registers);
2651 r1 = setNextItem(registersInCallPath);
2654 /* Collisions have been resolved. Now free the registers in the call path */
2655 r1 = setFirstItem(registersInCallPath);
2657 newreg = pic14_regWithIdx(r1->rIdx);
2659 r1 = setNextItem(registersInCallPath);
2663 MarkUsedRegisters(pb->registers);
2665 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2668 fprintf(stderr,"returning regs\n");
2670 fprintf(stderr,"not returning regs\n");
2672 fprintf(stderr,"pBlock after register optim.\n");
2673 pBlockStats(stderr,pb); // debug
2681 /*-----------------------------------------------------------------*/
2682 /* printCallTree - writes the call tree to a file */
2684 /*-----------------------------------------------------------------*/
2686 void printCallTree(FILE *of)
2698 fprintf(of, "\npBlock statistics\n");
2699 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2700 pBlockStats(stderr,pb);
2704 fprintf(of,"Call Tree\n");
2705 pbr = the_pFile->functions;
2709 if(!ispCodeFunction(pc))
2710 fprintf(of,"bug in call tree");
2713 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2715 while(pc->next && !ispCodeFunction(pc->next)) {
2717 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2718 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2726 /* Re-allocate the registers so that there are no collisions
2727 * between local variables when one function call another */
2729 pic14_deallocateAllRegs();
2731 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2736 fprintf(of,"\n**************\n\na better call tree\n");
2737 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2742 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2743 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));