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;
1133 pcc->comment = Safe_strdup(cP);
1135 return ( (pCode *)pcc);
1139 /*-----------------------------------------------------------------*/
1140 /* newpCodeGLabel - create a new global label */
1141 /*-----------------------------------------------------------------*/
1144 pCode *newpCodeFunction(char *mod,char *f)
1148 _ALLOC(pcf,sizeof(pCodeFunction));
1150 pcf->pc.type = PC_FUNCTION;
1151 pcf->pc.prev = pcf->pc.next = NULL;
1152 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1155 pcf->pc.analyze = genericAnalyze;
1156 pcf->pc.destruct = genericDestruct;
1157 pcf->pc.print = pCodePrintFunction;
1160 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1161 strcpy(pcf->modname,mod);
1163 pcf->modname = NULL;
1166 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1167 strcpy(pcf->fname,f);
1171 return ( (pCode *)pcf);
1175 static void pCodeLabelDestruct(pCode *pc)
1183 if((pc->type == PC_LABEL) && PCL(pc)->label)
1184 free(PCL(pc)->label);
1190 pCode *newpCodeLabel(int key)
1196 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1198 pcl->pc.type = PC_LABEL;
1199 pcl->pc.prev = pcl->pc.next = NULL;
1200 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1203 pcl->pc.analyze = genericAnalyze;
1204 pcl->pc.destruct = pCodeLabelDestruct;
1205 pcl->pc.print = pCodePrintLabel;
1210 sprintf(s,"_%05d_DS_",key);
1211 pcl->label = Safe_strdup(s);
1215 return ( (pCode *)pcl);
1218 pCode *newpCodeLabelStr(char *str)
1220 pCode *pc = newpCodeLabel(-1);
1222 PCL(pc)->label = Safe_strdup(str);
1227 /*-----------------------------------------------------------------*/
1228 /* newpBlock - create and return a pointer to a new pBlock */
1229 /*-----------------------------------------------------------------*/
1230 pBlock *newpBlock(void)
1235 PpB = Safe_calloc(1,sizeof(pBlock) );
1236 PpB->next = PpB->prev = NULL;
1238 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1239 PpB->registers = NULL;
1246 /*-----------------------------------------------------------------*/
1247 /* newpCodeChai0n - create a new chain of pCodes */
1248 /*-----------------------------------------------------------------*
1250 * This function will create a new pBlock and the pointer to the
1251 * pCode that is passed in will be the first pCode in the block.
1252 *-----------------------------------------------------------------*/
1255 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1258 pBlock *pB = newpBlock();
1260 pB->pcHead = pB->pcTail = pc;
1267 /*-----------------------------------------------------------------*/
1268 /* newpCodeOpLabel - Create a new label given the key */
1269 /* Note, a negative key means that the label is part of wild card */
1270 /* (and hence a wild card label) used in the pCodePeep */
1271 /* optimizations). */
1272 /*-----------------------------------------------------------------*/
1274 pCodeOp *newpCodeOpLabel(int key)
1279 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1280 pcop->type = PO_LABEL;
1283 sprintf(s,"_%05d_DS_",key);
1284 pcop->name = Safe_strdup(s);
1288 ((pCodeOpLabel *)pcop)->key = key;
1293 pCodeOp *newpCodeOpLit(int lit)
1299 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1300 pcop->type = PO_LITERAL;
1302 sprintf(s,"0x%02x",lit);
1303 pcop->name = Safe_strdup(s);
1307 ((pCodeOpLit *)pcop)->lit = lit;
1312 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1318 if(!pcp || !subtype) {
1319 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1323 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1324 pcop->type = PO_WILD;
1325 sprintf(s,"%%%d",id);
1326 pcop->name = Safe_strdup(s);
1328 PCOW(pcop)->id = id;
1329 PCOW(pcop)->pcp = pcp;
1330 PCOW(pcop)->subtype = subtype;
1331 PCOW(pcop)->matched = NULL;
1336 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1340 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1341 pcop->type = PO_BIT;
1342 pcop->name = Safe_strdup(s);
1344 PCOB(pcop)->bit = bit;
1345 PCOB(pcop)->inBitSpace = inBitSpace;
1350 pCodeOp *newpCodeOpReg(int rIdx)
1354 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1356 PCOR(pcop)->rIdx = rIdx;
1357 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1358 pcop->type = PCOR(pcop)->r->pc_type;
1363 /*-----------------------------------------------------------------*/
1364 /*-----------------------------------------------------------------*/
1366 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1372 pcop = newpCodeOpBit(name, -1,0);
1376 pcop = newpCodeOpLit(-1);
1380 pcop = newpCodeOpLabel(-1);
1384 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1386 pcop->name = Safe_strdup(name);
1392 /*-----------------------------------------------------------------*/
1393 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1394 /*-----------------------------------------------------------------*/
1395 void addpCode2pBlock(pBlock *pb, pCode *pc)
1398 /* If this is the first pcode to be added to a block that
1399 * was initialized with a NULL pcode, then go ahead and
1400 * make this pcode the head and tail */
1401 pb->pcHead = pb->pcTail = pc;
1403 pb->pcTail->next = pc;
1404 pc->prev = pb->pcTail;
1411 /*-----------------------------------------------------------------*/
1412 /* addpBlock - place a pBlock into the pFile */
1413 /*-----------------------------------------------------------------*/
1414 void addpBlock(pBlock *pb)
1418 /* First time called, we'll pass through here. */
1419 _ALLOC(the_pFile,sizeof(the_pFile));
1420 the_pFile->pbHead = the_pFile->pbTail = pb;
1421 the_pFile->functions = NULL;
1425 the_pFile->pbTail->next = pb;
1426 pb->prev = the_pFile->pbTail;
1428 the_pFile->pbTail = pb;
1431 /*-----------------------------------------------------------------*/
1432 /* printpCode - write the contents of a pCode to a file */
1433 /*-----------------------------------------------------------------*/
1434 void printpCode(FILE *of, pCode *pc)
1445 fprintf(of,"warning - unable to print pCode\n");
1448 /*-----------------------------------------------------------------*/
1449 /* printpBlock - write the contents of a pBlock to a file */
1450 /*-----------------------------------------------------------------*/
1451 void printpBlock(FILE *of, pBlock *pb)
1461 for(pc = pb->pcHead; pc; pc = pc->next)
1466 /*-----------------------------------------------------------------*/
1468 /* pCode processing */
1472 /*-----------------------------------------------------------------*/
1474 static void unlinkPC(pCode *pc)
1481 pc->prev->next = pc->next;
1483 pc->next->prev = pc->prev;
1485 pc->prev = pc->next = NULL;
1488 static void genericDestruct(pCode *pc)
1490 fprintf(stderr,"warning, calling default pCode destructor\n");
1499 void pBlockRegs(FILE *of, pBlock *pb)
1504 r = setFirstItem(pb->registers);
1506 r = setNextItem(pb->registers);
1511 static char *get_op( pCodeInstruction *pcc)
1515 if(pcc && pcc->pcop) {
1518 switch(pcc->pcop->type) {
1523 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1524 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1525 pBlockRegs(stderr,pcc->pc.pb);
1529 if (pcc->pcop->name)
1530 return pcc->pcop->name;
1535 return "NO operand";
1538 /*-----------------------------------------------------------------*/
1539 /*-----------------------------------------------------------------*/
1540 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1543 fprintf(of,"pcodeopprint\n");
1546 char *pCode2str(char *str, int size, pCode *pc)
1554 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1556 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1558 if(PCI(pc)->bit_inst) {
1559 if(PCI(pc)->pcop->type == PO_BIT) {
1560 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1561 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1562 PCI(pc)->pcop->name ,
1563 PCI(pc)->pcop->name );
1565 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1566 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1567 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1568 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1570 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1571 //PCI(pc)->pcop->t.bit );
1574 if(PCI(pc)->pcop->type == PO_BIT) {
1575 if( PCI(pc)->num_ops == 2)
1576 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1578 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1581 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1583 if( PCI(pc)->num_ops == 2)
1584 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1592 /* assuming that comment ends with a \n */
1593 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1597 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1600 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1603 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1612 /*-----------------------------------------------------------------*/
1613 /* genericPrint - the contents of a pCode to a file */
1614 /*-----------------------------------------------------------------*/
1615 static void genericPrint(FILE *of, pCode *pc)
1623 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1627 // If the opcode has a label, print that first
1629 pBranch *pbl = pc->label;
1631 if(pbl->pc->type == PC_LABEL)
1632 pCodePrintLabel(of, pbl->pc);
1641 pCode2str(str, 256, pc);
1643 fprintf(of,"%s",str);
1647 pBranch *dpb = pc->to; // debug
1649 switch ( dpb->pc->type) {
1651 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1654 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1657 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1671 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1673 pCodePrintLabel(of, pc->label->pc);
1675 if(PCW(pc)->operand) {
1676 fprintf(of,";\toperand ");
1677 pCodeOpPrint(of,PCW(pc)->operand );
1683 fprintf(of,"unknown pCode type %d\n",pc->type);
1688 /*-----------------------------------------------------------------*/
1689 /* pCodePrintFunction - prints function begin/end */
1690 /*-----------------------------------------------------------------*/
1692 static void pCodePrintFunction(FILE *of, pCode *pc)
1698 if( ((pCodeFunction *)pc)->modname)
1699 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1701 if(PCF(pc)->fname) {
1702 pBranch *exits = pc->to;
1704 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1707 exits = exits->next;
1710 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1714 pc->from->pc->type == PC_FUNCTION &&
1715 PCF(pc->from->pc)->fname)
1716 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1718 fprintf(of,"; exit point [can't find entry point]\n");
1721 /*-----------------------------------------------------------------*/
1722 /* pCodePrintLabel - prints label */
1723 /*-----------------------------------------------------------------*/
1725 static void pCodePrintLabel(FILE *of, pCode *pc)
1732 fprintf(of,"%s\n",PCL(pc)->label);
1733 else if (PCL(pc)->key >=0)
1734 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1736 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1739 /*-----------------------------------------------------------------*/
1740 static void unlinkpCodeFromBranch(pBranch *pb , pCode *pc)
1749 bprev->next = b->next;
1757 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1773 /*-----------------------------------------------------------------*/
1774 /* pBranchLink - given two pcodes, this function will link them */
1775 /* together through their pBranches */
1776 /*-----------------------------------------------------------------*/
1777 static void pBranchLink(pCode *f, pCode *t)
1781 // Declare a new branch object for the 'from' pCode.
1783 _ALLOC(b,sizeof(pBranch));
1784 b->pc = t; // The link to the 'to' pCode.
1787 f->to = pBranchAppend(f->to,b);
1789 // Now do the same for the 'to' pCode.
1791 _ALLOC(b,sizeof(pBranch));
1795 t->from = pBranchAppend(t->from,b);
1800 /*-----------------------------------------------------------------*/
1801 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1803 /*-----------------------------------------------------------------*/
1804 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1817 /*-----------------------------------------------------------------*/
1818 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1819 /*-----------------------------------------------------------------*/
1820 static void pCodeUnlink(pCode *pc)
1825 if(!pc->prev || !pc->next) {
1826 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1830 /* first remove the pCode from the chain */
1831 pc->prev->next = pc->next;
1832 pc->next->prev = pc->prev;
1834 /* Now for the hard part... */
1836 /* Remove the branches */
1840 pc1 = pb1->pc; /* Get the pCode that branches to the
1841 * one we're unlinking */
1843 /* search for the link back to this pCode (the one we're
1845 if(pb2 = pBranchFind(pc1->to,pc)) {
1846 pb2->pc = pc->to->pc; // make the replacement
1848 /* if the pCode we're unlinking contains multiple 'to'
1849 * branches (e.g. this a skip instruction) then we need
1850 * to copy these extra branches to the chain. */
1852 pBranchAppend(pb2, pc->to->next);
1861 /*-----------------------------------------------------------------*/
1862 /*-----------------------------------------------------------------*/
1863 static void genericAnalyze(pCode *pc)
1873 // Go through the pCodes that are in pCode chain and link
1874 // them together through the pBranches. Note, the pCodes
1875 // are linked together as a contiguous stream like the
1876 // assembly source code lines. The linking here mimics this
1877 // except that comments are not linked in.
1879 pCode *npc = pc->next;
1881 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1882 pBranchLink(pc,npc);
1891 /*-----------------------------------------------------------------*/
1892 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1896 if(pc->type == PC_LABEL) {
1897 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1900 if(pc->type == PC_OPCODE) {
1903 if(pbr->pc->type == PC_LABEL) {
1904 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1914 /*-----------------------------------------------------------------*/
1915 /* findLabel - Search the pCode for a particular label */
1916 /*-----------------------------------------------------------------*/
1917 pCode * findLabel(pCodeOpLabel *pcop_label)
1925 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1926 for(pc = pb->pcHead; pc; pc = pc->next)
1927 if(compareLabel(pc,pcop_label))
1932 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1936 /*-----------------------------------------------------------------*/
1937 /* findNextInstruction - given a pCode, find the next instruction */
1938 /* in the linked list */
1939 /*-----------------------------------------------------------------*/
1940 pCode * findNextInstruction(pCode *pc)
1944 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1950 fprintf(stderr,"Couldn't find instruction\n");
1954 /*-----------------------------------------------------------------*/
1955 /* findFunctionEnd - given a pCode find the end of the function */
1956 /* that contains it t */
1957 /*-----------------------------------------------------------------*/
1958 pCode * findFunctionEnd(pCode *pc)
1962 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1968 fprintf(stderr,"Couldn't find function end\n");
1973 /*-----------------------------------------------------------------*/
1974 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1975 /* instruction with which it is associated. */
1976 /*-----------------------------------------------------------------*/
1977 static void AnalyzeLabel(pCode *pc)
1985 static void AnalyzeGOTO(pCode *pc)
1988 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1992 static void AnalyzeSKIP(pCode *pc)
1995 pBranchLink(pc,findNextInstruction(pc->next));
1996 pBranchLink(pc,findNextInstruction(pc->next->next));
2000 static void AnalyzeRETURN(pCode *pc)
2003 // branch_link(pc,findFunctionEnd(pc->next));
2008 void AnalyzepBlock(pBlock *pb)
2015 /* Find all of the registers used in this pBlock */
2016 for(pc = pb->pcHead; pc; pc = pc->next) {
2017 if(pc->type == PC_OPCODE) {
2018 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2020 /* Loop through all of the registers declared so far in
2021 this block and see if we find this new there */
2023 regs *r = setFirstItem(pb->registers);
2026 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2027 PCOR(PCI(pc)->pcop)->r = r;
2030 r = setNextItem(pb->registers);
2034 /* register wasn't found */
2035 r = Safe_calloc(1, sizeof(regs));
2036 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2037 addSet(&pb->registers, r);
2038 PCOR(PCI(pc)->pcop)->r = r;
2039 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2041 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2047 int OptimizepBlock(pBlock *pb)
2052 if(!pb || !peepOptimizing)
2055 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2056 for(pc = pb->pcHead; pc; pc = pc->next)
2057 matches += pCodePeepMatchRule(pc);
2063 /*-----------------------------------------------------------------*/
2064 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2065 /*-----------------------------------------------------------------*/
2066 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2070 for(pc = pcs; pc; pc = pc->next) {
2072 if((pc->type == PC_OPCODE) &&
2074 (PCI(pc)->pcop->type == PO_LABEL) &&
2075 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2083 /*-----------------------------------------------------------------*/
2084 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2085 /* pCode chain if they're not used. */
2086 /*-----------------------------------------------------------------*/
2087 void pBlockRemoveUnusedLabels(pBlock *pb)
2089 pCode *pc; pCodeLabel *pcl;
2094 for(pc = pb->pcHead; pc; pc = pc->next) {
2096 if(pc->type == PC_LABEL)
2099 pcl = PCL(pc->label->pc);
2102 /* This pCode is a label, so search the pBlock to see if anyone
2105 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2106 /* Couldn't find an instruction that refers to this label
2107 * So, unlink the pCode label from it's pCode chain
2108 * and destroy the label */
2110 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2112 if(pc->type == PC_LABEL) {
2114 pCodeLabelDestruct(pc);
2116 unlinkpCodeFromBranch(pc->label, pc);
2117 if(pc->label->next == NULL && pc->label->pc == NULL) {
2128 /*-----------------------------------------------------------------*/
2129 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2130 /* chain and put them into pBranches that are */
2131 /* associated with the appropriate pCode */
2133 /*-----------------------------------------------------------------*/
2134 void pBlockMergeLabels(pBlock *pb)
2137 pCode *pc, *pcnext=NULL;
2142 /* First, Try to remove any unused labels */
2143 //pBlockRemoveUnusedLabels(pb);
2145 /* Now loop through the pBlock and merge the labels with the opcodes */
2147 for(pc = pb->pcHead; pc; pc = pc->next) {
2149 if(pc->type == PC_LABEL) {
2150 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2151 if( !(pcnext = findNextInstruction(pc)) )
2152 return; // Couldn't find an instruction associated with this label
2154 // Unlink the pCode label from it's pCode chain
2157 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2158 // And link it into the instruction's pBranch labels. (Note, since
2159 // it's possible to have multiple labels associated with one instruction
2160 // we must provide a means to accomodate the additional labels. Thus
2161 // the labels are placed into the singly-linked list "label" as
2162 // opposed to being a single member of the pCodeInstruction.)
2164 _ALLOC(pbr,sizeof(pBranch));
2168 pcnext->label = pBranchAppend(pcnext->label,pbr);
2176 pBlockRemoveUnusedLabels(pb);
2180 /*-----------------------------------------------------------------*/
2181 /*-----------------------------------------------------------------*/
2182 void OptimizepCode(char dbName)
2184 #define MAX_PASSES 4
2193 fprintf(stderr," Optimizing pCode\n");
2196 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2197 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2198 matches += OptimizepBlock(pb);
2201 while(matches && ++passes < MAX_PASSES);
2205 /*-----------------------------------------------------------------*/
2206 /* AnalyzepCode - parse the pCode that has been generated and form */
2207 /* all of the logical connections. */
2209 /* Essentially what's done here is that the pCode flow is */
2211 /*-----------------------------------------------------------------*/
2213 void AnalyzepCode(char dbName)
2222 fprintf(stderr," Analyzing pCode");
2224 /* First, merge the labels with the instructions */
2225 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2226 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2228 fprintf(stderr," analyze and merging block %c\n",dbName);
2229 pBlockMergeLabels(pb);
2234 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2235 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2239 /* Now build the call tree.
2240 First we examine all of the pCodes for functions.
2241 Keep in mind that the function boundaries coincide
2242 with pBlock boundaries.
2244 The algorithm goes something like this:
2245 We have two nested loops. The outer loop iterates
2246 through all of the pBlocks/functions. The inner
2247 loop iterates through all of the pCodes for
2248 a given pBlock. When we begin iterating through
2249 a pBlock, the variable pc_fstart, pCode of the start
2250 of a function, is cleared. We then search for pCodes
2251 of type PC_FUNCTION. When one is encountered, we
2252 initialize pc_fstart to this and at the same time
2253 associate a new pBranch object that signifies a
2254 branch entry. If a return is found, then this signifies
2255 a function exit point. We'll link the pCodes of these
2256 returns to the matching pc_fstart.
2258 When we're done, a doubly linked list of pBranches
2259 will exist. The head of this list is stored in
2260 `the_pFile', which is the meta structure for all
2261 of the pCode. Look at the printCallTree function
2262 on how the pBranches are linked together.
2265 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2266 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2267 pCode *pc_fstart=NULL;
2268 for(pc = pb->pcHead; pc; pc = pc->next) {
2269 if(pc->type == PC_FUNCTION) {
2270 if (PCF(pc)->fname) {
2271 // I'm not liking this....
2272 // Found the beginning of a function.
2273 _ALLOC(pbr,sizeof(pBranch));
2274 pbr->pc = pc_fstart = pc;
2277 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2279 // Here's a better way of doing the same:
2280 addSet(&pb->function_entries, pc);
2283 // Found an exit point in a function, e.g. return
2284 // (Note, there may be more than one return per function)
2286 pBranchLink(pc_fstart, pc);
2288 addSet(&pb->function_exits, pc);
2290 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2291 addSet(&pb->function_calls,pc);
2298 /*-----------------------------------------------------------------*/
2299 /* ispCodeFunction - returns true if *pc is the pCode of a */
2301 /*-----------------------------------------------------------------*/
2302 bool ispCodeFunction(pCode *pc)
2305 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2311 /*-----------------------------------------------------------------*/
2312 /* findFunction - Search for a function by name (given the name) */
2313 /* in the set of all functions that are in a pBlock */
2314 /* (note - I expect this to change because I'm planning to limit */
2315 /* pBlock's to just one function declaration */
2316 /*-----------------------------------------------------------------*/
2317 pCode *findFunction(char *fname)
2324 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2326 pc = setFirstItem(pb->function_entries);
2329 if((pc->type == PC_FUNCTION) &&
2331 (strcmp(fname, PCF(pc)->fname)==0))
2334 pc = setNextItem(pb->function_entries);
2342 void MarkUsedRegisters(set *regset)
2347 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2348 r2 = pic14_regWithIdx(r1->rIdx);
2354 void pBlockStats(FILE *of, pBlock *pb)
2360 fprintf(of,"***\n pBlock Stats\n***\n");
2362 // for now just print the first element of each set
2363 pc = setFirstItem(pb->function_entries);
2365 fprintf(of,"entry\n");
2368 pc = setFirstItem(pb->function_exits);
2370 fprintf(of,"has an exit\n");
2374 pc = setFirstItem(pb->function_calls);
2376 fprintf(of,"functions called\n");
2380 pc = setNextItem(pb->function_calls);
2384 r = setFirstItem(pb->registers);
2386 int n = elementsInSet(pb->registers);
2388 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2391 fprintf(of," %s\n",r->name);
2392 r = setNextItem(pb->registers);
2397 /*-----------------------------------------------------------------*/
2398 /*-----------------------------------------------------------------*/
2399 void sequencepCode(void)
2405 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2407 pb->seq = GpCodeSequenceNumber+1;
2409 for( pc = pb->pcHead; pc; pc = pc->next)
2410 pc->seq = ++GpCodeSequenceNumber;
2415 /*-----------------------------------------------------------------*/
2416 /*-----------------------------------------------------------------*/
2417 set *register_usage(pBlock *pb)
2420 set *registers=NULL;
2421 set *registersInCallPath = NULL;
2423 /* check recursion */
2425 pc = setFirstItem(pb->function_entries);
2432 if(pc->type != PC_FUNCTION)
2433 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2435 pc = setFirstItem(pb->function_calls);
2436 for( ; pc; pc = setNextItem(pb->function_calls)) {
2438 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2439 char *dest = get_op(PCI(pc));
2441 pcn = findFunction(dest);
2443 registersInCallPath = register_usage(pcn->pb);
2445 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2450 pBlockStats(stderr,pb); // debug
2451 if(registersInCallPath) {
2452 /* registers were used in the functions this pBlock has called */
2453 /* so now, we need to see if these collide with the ones we are */
2456 regs *r1,*r2, *newreg;
2458 fprintf(stderr,"comparing registers\n");
2460 r1 = setFirstItem(registersInCallPath);
2463 r2 = setFirstItem(pb->registers);
2467 if(r2->rIdx == r1->rIdx) {
2468 newreg = pic14_findFreeReg();
2472 fprintf(stderr,"Bummer, no more registers.\n");
2476 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2477 r1->rIdx, newreg->rIdx);
2478 r2->rIdx = newreg->rIdx;
2479 //if(r2->name) free(r2->name);
2480 r2->name = Safe_strdup(newreg->name);
2482 newreg->wasUsed = 1;
2484 r2 = setNextItem(pb->registers);
2487 r1 = setNextItem(registersInCallPath);
2490 /* Collisions have been resolved. Now free the registers in the call path */
2491 r1 = setFirstItem(registersInCallPath);
2493 newreg = pic14_regWithIdx(r1->rIdx);
2495 r1 = setNextItem(registersInCallPath);
2499 MarkUsedRegisters(pb->registers);
2501 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2504 fprintf(stderr,"returning regs\n");
2506 fprintf(stderr,"not returning regs\n");
2508 fprintf(stderr,"pBlock after register optim.\n");
2509 pBlockStats(stderr,pb); // debug
2515 /*-----------------------------------------------------------------*/
2516 /* printCallTree - writes the call tree to a file */
2518 /*-----------------------------------------------------------------*/
2519 void pct2(FILE *of,pBlock *pb,int indent)
2523 // set *registersInCallPath = NULL;
2526 return;// registers;
2529 return; // registers; //recursion ?
2531 pc = setFirstItem(pb->function_entries);
2538 for(i=0;i<indent;i++) // Indentation
2541 if(pc->type == PC_FUNCTION)
2542 fprintf(of,"%s\n",PCF(pc)->fname);
2547 pc = setFirstItem(pb->function_calls);
2548 for( ; pc; pc = setNextItem(pb->function_calls)) {
2550 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2551 char *dest = get_op(PCI(pc));
2553 pcn = findFunction(dest);
2555 pct2(of,pcn->pb,indent+1);
2557 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2565 fprintf(stderr,"pBlock before register optim.\n");
2566 pBlockStats(stderr,pb); // debug
2568 if(registersInCallPath) {
2569 /* registers were used in the functions this pBlock has called */
2570 /* so now, we need to see if these collide with the ones we are using here */
2572 regs *r1,*r2, *newreg;
2574 fprintf(stderr,"comparing registers\n");
2576 r1 = setFirstItem(registersInCallPath);
2579 r2 = setFirstItem(pb->registers);
2583 if(r2->rIdx == r1->rIdx) {
2584 newreg = pic14_findFreeReg();
2588 fprintf(stderr,"Bummer, no more registers.\n");
2592 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2593 r1->rIdx, newreg->rIdx);
2594 r2->rIdx = newreg->rIdx;
2595 //if(r2->name) free(r2->name);
2596 r2->name = Safe_strdup(newreg->name);
2598 newreg->wasUsed = 1;
2600 r2 = setNextItem(pb->registers);
2603 r1 = setNextItem(registersInCallPath);
2606 /* Collisions have been resolved. Now free the registers in the call path */
2607 r1 = setFirstItem(registersInCallPath);
2609 newreg = pic14_regWithIdx(r1->rIdx);
2611 r1 = setNextItem(registersInCallPath);
2615 MarkUsedRegisters(pb->registers);
2617 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2620 fprintf(stderr,"returning regs\n");
2622 fprintf(stderr,"not returning regs\n");
2624 fprintf(stderr,"pBlock after register optim.\n");
2625 pBlockStats(stderr,pb); // debug
2633 /*-----------------------------------------------------------------*/
2634 /* printCallTree - writes the call tree to a file */
2636 /*-----------------------------------------------------------------*/
2638 void printCallTree(FILE *of)
2650 fprintf(of, "\npBlock statistics\n");
2651 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2652 pBlockStats(stderr,pb);
2656 fprintf(of,"Call Tree\n");
2657 pbr = the_pFile->functions;
2661 if(!ispCodeFunction(pc))
2662 fprintf(of,"bug in call tree");
2665 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2667 while(pc->next && !ispCodeFunction(pc->next)) {
2669 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2670 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2678 /* Re-allocate the registers so that there are no collisions
2679 * between local variables when one function call another */
2681 pic14_deallocateAllRegs();
2683 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2688 fprintf(of,"\n**************\n\na better call tree\n");
2689 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2694 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2695 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));