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 pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,NULL};
45 static int mnemonics_initialized = 0;
48 static hTab *pic14MnemonicsHash = NULL;
52 static pFile *the_pFile = NULL;
53 static int peepOptimizing = 0;
54 static int GpCodeSequenceNumber = 1;
56 /****************************************************************/
57 /* Forward declarations */
58 /****************************************************************/
60 static void unlinkPC(pCode *pc);
61 static void genericAnalyze(pCode *pc);
62 static void AnalyzeGOTO(pCode *pc);
63 static void AnalyzeSKIP(pCode *pc);
64 static void AnalyzeRETURN(pCode *pc);
66 static void genericDestruct(pCode *pc);
67 static void genericPrint(FILE *of,pCode *pc);
69 static void pCodePrintLabel(FILE *of, pCode *pc);
70 static void pCodePrintFunction(FILE *of, pCode *pc);
71 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
72 static char *get_op( pCodeInstruction *pcc);
73 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
74 int pCodePeepMatchRule(pCode *pc);
75 void pBlockStats(FILE *of, pBlock *pb);
78 pCodeInstruction pciADDWF = {
79 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
87 1,0, // dest, bit instruction
88 (PCC_W | PCC_REGISTER), // inCond
89 (PCC_REGISTER | PCC_Z) // outCond
92 pCodeInstruction pciADDFW = {
93 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
101 0,0, // dest, bit instruction
102 (PCC_W | PCC_REGISTER), // inCond
103 (PCC_W | PCC_Z) // outCond
106 pCodeInstruction pciADDLW = {
107 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
115 0,0, // dest, bit instruction
117 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
120 pCodeInstruction pciANDLW = {
121 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
129 0,0, // dest, bit instruction
131 (PCC_W | PCC_Z) // outCond
134 pCodeInstruction pciANDWF = {
135 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
143 1,0, // dest, bit instruction
144 (PCC_W | PCC_REGISTER), // inCond
145 (PCC_REGISTER | PCC_Z) // outCond
148 pCodeInstruction pciANDFW = {
149 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
157 0,0, // dest, bit instruction
158 (PCC_W | PCC_REGISTER), // inCond
159 (PCC_W | PCC_Z) // outCond
162 pCodeInstruction pciBCF = {
163 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
171 0,1, // dest, bit instruction
173 PCC_EXAMINE_PCOP // outCond
176 pCodeInstruction pciBSF = {
177 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
185 0,1, // dest, bit instruction
187 PCC_EXAMINE_PCOP // outCond
190 pCodeInstruction pciBTFSC = {
191 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
199 0,1, // dest, bit instruction
200 PCC_EXAMINE_PCOP, // inCond
204 pCodeInstruction pciBTFSS = {
205 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
213 0,1, // dest, bit instruction
214 PCC_EXAMINE_PCOP, // inCond
218 pCodeInstruction pciCALL = {
219 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
227 0,0, // dest, bit instruction
232 pCodeInstruction pciCOMF = {
233 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
241 1,0, // dest, bit instruction
242 PCC_REGISTER, // inCond
243 PCC_REGISTER // outCond
246 pCodeInstruction pciCOMFW = {
247 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
255 0,0, // dest, bit instruction
256 PCC_REGISTER, // inCond
260 pCodeInstruction pciCLRF = {
261 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
269 0,0, // dest, bit instruction
270 PCC_REGISTER, // inCond
271 PCC_REGISTER // outCond
274 pCodeInstruction pciCLRW = {
275 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
283 0,0, // dest, bit instruction
288 pCodeInstruction pciDECF = {
289 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
297 1,0, // dest, bit instruction
298 PCC_REGISTER, // inCond
299 PCC_REGISTER // outCond
302 pCodeInstruction pciDECFW = {
303 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
311 0,0, // dest, bit instruction
312 PCC_REGISTER, // inCond
316 pCodeInstruction pciDECFSZ = {
317 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
325 1,0, // dest, bit instruction
326 PCC_REGISTER, // inCond
327 PCC_REGISTER // outCond
330 pCodeInstruction pciDECFSZW = {
331 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
339 0,0, // dest, bit instruction
340 PCC_REGISTER, // inCond
344 pCodeInstruction pciGOTO = {
345 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
353 0,0, // dest, bit instruction
359 pCodeInstruction pciINCF = {
360 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
368 1,0, // dest, bit instruction
369 PCC_REGISTER, // inCond
370 PCC_REGISTER // outCond
373 pCodeInstruction pciINCFW = {
374 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
382 0,0, // dest, bit instruction
383 PCC_REGISTER, // inCond
387 pCodeInstruction pciINCFSZ = {
388 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
396 1,0, // dest, bit instruction
397 PCC_REGISTER, // inCond
398 PCC_REGISTER // outCond
401 pCodeInstruction pciINCFSZW = {
402 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
410 0,0, // dest, bit instruction
411 PCC_REGISTER, // inCond
415 pCodeInstruction pciIORWF = {
416 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
424 1,0, // dest, bit instruction
425 (PCC_W | PCC_REGISTER), // inCond
426 (PCC_REGISTER | PCC_Z) // outCond
429 pCodeInstruction pciIORFW = {
430 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
438 0,0, // dest, bit instruction
439 (PCC_W | PCC_REGISTER), // inCond
440 (PCC_W | PCC_Z) // outCond
443 pCodeInstruction pciIORLW = {
444 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
452 0,0, // dest, bit instruction
454 (PCC_W | PCC_Z) // outCond
457 pCodeInstruction pciMOVF = {
458 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
466 1,0, // dest, bit instruction
467 PCC_REGISTER, // inCond
471 pCodeInstruction pciMOVFW = {
472 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
480 0,0, // dest, bit instruction
481 PCC_REGISTER, // inCond
482 (PCC_W | PCC_Z) // outCond
485 pCodeInstruction pciMOVWF = {
486 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
494 0,0, // dest, bit instruction
499 pCodeInstruction pciMOVLW = {
500 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
508 0,0, // dest, bit instruction
513 pCodeInstruction pciNEGF = {
514 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
522 0,0, // dest, bit instruction
523 PCC_REGISTER, // inCond
528 pCodeInstruction pciRETLW = {
529 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
537 0,0, // dest, bit instruction
542 pCodeInstruction pciRETURN = {
543 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
551 0,0, // dest, bit instruction
557 pCodeInstruction pciRLF = {
558 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
566 1,0, // dest, bit instruction
567 (PCC_C | PCC_REGISTER), // inCond
568 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
571 pCodeInstruction pciRLFW = {
572 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
580 0,0, // dest, bit instruction
581 (PCC_C | PCC_REGISTER), // inCond
582 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
585 pCodeInstruction pciRRF = {
586 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
594 1,0, // dest, bit instruction
595 (PCC_C | PCC_REGISTER), // inCond
596 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
599 pCodeInstruction pciRRFW = {
600 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
608 0,0, // dest, bit instruction
609 (PCC_C | PCC_REGISTER), // inCond
610 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
613 pCodeInstruction pciSUBWF = {
614 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
622 1,0, // dest, bit instruction
623 (PCC_W | PCC_REGISTER), // inCond
624 (PCC_REGISTER | PCC_Z) // outCond
627 pCodeInstruction pciSUBFW = {
628 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
636 0,0, // dest, bit instruction
637 (PCC_W | PCC_REGISTER), // inCond
638 (PCC_W | PCC_Z) // outCond
641 pCodeInstruction pciSUBLW = {
642 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
650 0,0, // dest, bit instruction
652 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
655 pCodeInstruction pciSWAPF = {
656 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
664 1,0, // dest, bit instruction
665 (PCC_REGISTER), // inCond
666 (PCC_REGISTER) // outCond
669 pCodeInstruction pciSWAPFW = {
670 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
678 0,0, // dest, bit instruction
679 (PCC_REGISTER), // inCond
682 pCodeInstruction pciTRIS = {
683 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
691 0,0, // dest, bit instruction
697 pCodeInstruction pciXORWF = {
698 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
706 1,0, // dest, bit instruction
707 (PCC_W | PCC_REGISTER), // inCond
708 (PCC_REGISTER | PCC_Z) // outCond
711 pCodeInstruction pciXORFW = {
712 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
720 0,0, // dest, bit instruction
721 (PCC_W | PCC_REGISTER), // inCond
722 (PCC_W | PCC_Z) // outCond
725 pCodeInstruction pciXORLW = {
726 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
734 0,0, // dest, bit instruction
736 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
740 #define MAX_PIC14MNEMONICS 100
741 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
743 /*-----------------------------------------------------------------*/
744 /* SAFE_snprintf - like snprintf except the string pointer is */
745 /* after the string has been printed to. This is */
746 /* useful for printing to string as though if it */
748 /*-----------------------------------------------------------------*/
749 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
757 va_start(val, format);
759 // Alas, vsnprintf is not ANSI standard, and does not exist
760 // on Solaris (and probably other non-Gnu flavored Unixes).
761 vsnprintf(*str, *size, format, val);
763 // This, of course, is *not* safe, despite the name.
764 vsprintf(*str, format, val);
775 void pCodeInitRegisters(void)
778 pc_fsr.rIdx = IDX_FSR;
779 pc_fsr.r = pic14_regWithIdx(IDX_FSR);
781 pc_indf.rIdx = IDX_INDF;
782 pc_indf.r = pic14_regWithIdx(IDX_INDF);
784 pc_kzero.rIdx = IDX_KZ;
785 pc_kzero.r = pic14_regWithIdx(IDX_KZ);
789 /*-----------------------------------------------------------------*/
790 /* mnem2key - convert a pic mnemonic into a hash key */
791 /* (BTW - this spreads the mnemonics quite well) */
793 /*-----------------------------------------------------------------*/
795 int mnem2key(char const *mnem)
804 key += toupper(*mnem++) +1;
812 void pic14initMnemonics(void)
817 pCodeInstruction *pci;
819 if(mnemonics_initialized)
822 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
823 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
824 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
825 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
826 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
827 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
828 pic14Mnemonics[POC_BCF] = &pciBCF;
829 pic14Mnemonics[POC_BSF] = &pciBSF;
830 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
831 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
832 pic14Mnemonics[POC_CALL] = &pciCALL;
833 pic14Mnemonics[POC_COMF] = &pciCOMF;
834 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
835 pic14Mnemonics[POC_CLRF] = &pciCLRF;
836 pic14Mnemonics[POC_CLRW] = &pciCLRW;
837 pic14Mnemonics[POC_DECF] = &pciDECF;
838 pic14Mnemonics[POC_DECFW] = &pciDECFW;
839 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
840 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
841 pic14Mnemonics[POC_GOTO] = &pciGOTO;
842 pic14Mnemonics[POC_INCF] = &pciINCF;
843 pic14Mnemonics[POC_INCFW] = &pciINCFW;
844 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
845 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
846 pic14Mnemonics[POC_IORLW] = &pciIORLW;
847 pic14Mnemonics[POC_IORWF] = &pciIORWF;
848 pic14Mnemonics[POC_IORFW] = &pciIORFW;
849 pic14Mnemonics[POC_MOVF] = &pciMOVF;
850 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
851 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
852 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
853 pic14Mnemonics[POC_NEGF] = &pciNEGF;
854 pic14Mnemonics[POC_RETLW] = &pciRETLW;
855 pic14Mnemonics[POC_RETURN] = &pciRETURN;
856 pic14Mnemonics[POC_RLF] = &pciRLF;
857 pic14Mnemonics[POC_RLFW] = &pciRLFW;
858 pic14Mnemonics[POC_RRF] = &pciRRF;
859 pic14Mnemonics[POC_RRFW] = &pciRRFW;
860 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
861 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
862 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
863 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
864 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
865 pic14Mnemonics[POC_TRIS] = &pciTRIS;
866 pic14Mnemonics[POC_XORLW] = &pciXORLW;
867 pic14Mnemonics[POC_XORWF] = &pciXORWF;
868 pic14Mnemonics[POC_XORFW] = &pciXORFW;
870 for(i=0; i<MAX_PIC14MNEMONICS; i++)
871 if(pic14Mnemonics[i])
872 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
873 pci = hTabFirstItem(pic14MnemonicsHash, &key);
876 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
877 pci = hTabNextItem(pic14MnemonicsHash, &key);
880 mnemonics_initialized = 1;
883 int getpCode(char *mnem,unsigned dest)
886 pCodeInstruction *pci;
887 int key = mnem2key(mnem);
889 if(!mnemonics_initialized)
890 pic14initMnemonics();
892 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
896 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
897 if((pci->num_ops <= 1) || (pci->dest == dest))
901 pci = hTabNextItemWK (pic14MnemonicsHash);
908 char getpBlock_dbName(pBlock *pb)
914 return pb->cmemmap->dbName;
918 /*-----------------------------------------------------------------*/
919 /* movepBlock2Head - given the dbname of a pBlock, move all */
920 /* instances to the front of the doubly linked */
921 /* list of pBlocks */
922 /*-----------------------------------------------------------------*/
924 void movepBlock2Head(char dbName)
928 pb = the_pFile->pbHead;
932 if(getpBlock_dbName(pb) == dbName) {
933 pBlock *pbn = pb->next;
934 pb->next = the_pFile->pbHead;
935 the_pFile->pbHead->prev = pb;
936 the_pFile->pbHead = pb;
939 pb->prev->next = pbn;
941 // If the pBlock that we just moved was the last
942 // one in the link of all of the pBlocks, then we
943 // need to point the tail to the block just before
945 // Note: if pb->next is NULL, then pb must have
946 // been the last pBlock in the chain.
949 pbn->prev = pb->prev;
951 the_pFile->pbTail = pb->prev;
962 void copypCode(FILE *of, char dbName)
966 if(!of || !the_pFile)
969 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
970 if(getpBlock_dbName(pb) == dbName) {
977 void pcode_test(void)
980 printf("pcode is alive!\n");
990 /* create the file name */
991 strcpy(buffer,srcFileName);
994 if( !(pFile = fopen(buffer, "w" ))) {
995 werror(E_FILE_OPEN_ERR,buffer);
999 fprintf(pFile,"pcode dump\n\n");
1001 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1002 fprintf(pFile,"\n\tNew pBlock\n\n");
1004 fprintf(pFile,"%s",pb->cmemmap->sname);
1006 fprintf(pFile,"internal pblock");
1008 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1009 printpBlock(pFile,pb);
1013 /*-----------------------------------------------------------------*/
1014 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1015 /* ister, RegCond will return the bit being referenced. */
1017 /* fixme - why not just OR in the pcop bit field */
1018 /*-----------------------------------------------------------------*/
1020 static int RegCond(pCodeOp *pcop)
1026 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1027 switch(PCOB(pcop)->bit) {
1041 /*-----------------------------------------------------------------*/
1042 /* newpCode - create and return a newly initialized pCode */
1044 /* fixme - rename this */
1046 /* The purpose of this routine is to create a new Instruction */
1047 /* pCode. This is called by gen.c while the assembly code is being */
1051 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1052 /* (note that the op is analogous to but not the */
1053 /* same thing as the opcode of the instruction.) */
1054 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1057 /* a pointer to the new malloc'd pCode is returned. */
1061 /*-----------------------------------------------------------------*/
1062 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1064 pCodeInstruction *pci ;
1066 if(!mnemonics_initialized)
1067 pic14initMnemonics();
1069 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1071 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1072 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1075 if(pci->inCond == PCC_EXAMINE_PCOP)
1076 pci->inCond = RegCond(pcop);
1078 if(pci->outCond == PCC_EXAMINE_PCOP)
1079 pci->outCond = RegCond(pcop);
1081 return (pCode *)pci;
1084 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1090 /*-----------------------------------------------------------------*/
1091 /* newpCodeWild - create a "wild" as in wild card pCode */
1093 /* Wild pcodes are used during the peep hole optimizer to serve */
1094 /* as place holders for any instruction. When a snippet of code is */
1095 /* compared to a peep hole rule, the wild card opcode will match */
1096 /* any instruction. However, the optional operand and label are */
1097 /* additional qualifiers that must also be matched before the */
1098 /* line (of assembly code) is declared matched. Note that the */
1099 /* operand may be wild too. */
1101 /* Note, a wild instruction is specified just like a wild var: */
1102 /* %4 ; A wild instruction, */
1103 /* See the peeph.def file for additional examples */
1105 /*-----------------------------------------------------------------*/
1107 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1112 pcw = Safe_calloc(1,sizeof(pCodeWild));
1114 pcw->pc.type = PC_WILD;
1115 pcw->pc.prev = pcw->pc.next = NULL;
1116 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1119 pcw->pc.analyze = genericAnalyze;
1120 pcw->pc.destruct = genericDestruct;
1121 pcw->pc.print = genericPrint;
1123 pcw->id = pCodeID; // this is the 'n' in %n
1124 pcw->operand = optional_operand;
1125 pcw->label = optional_label;
1127 return ( (pCode *)pcw);
1131 /*-----------------------------------------------------------------*/
1132 /* newPcodeCharP - create a new pCode from a char string */
1133 /*-----------------------------------------------------------------*/
1135 pCode *newpCodeCharP(char *cP)
1140 pcc = Safe_calloc(1,sizeof(pCodeComment));
1142 pcc->pc.type = PC_COMMENT;
1143 pcc->pc.prev = pcc->pc.next = NULL;
1144 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1147 pcc->pc.analyze = genericAnalyze;
1148 pcc->pc.destruct = genericDestruct;
1149 pcc->pc.print = genericPrint;
1152 pcc->comment = Safe_strdup(cP);
1154 pcc->comment = NULL;
1156 return ( (pCode *)pcc);
1160 /*-----------------------------------------------------------------*/
1161 /* newpCodeGLabel - create a new global label */
1162 /*-----------------------------------------------------------------*/
1165 pCode *newpCodeFunction(char *mod,char *f)
1169 _ALLOC(pcf,sizeof(pCodeFunction));
1171 pcf->pc.type = PC_FUNCTION;
1172 pcf->pc.prev = pcf->pc.next = NULL;
1173 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1176 pcf->pc.analyze = genericAnalyze;
1177 pcf->pc.destruct = genericDestruct;
1178 pcf->pc.print = pCodePrintFunction;
1181 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1182 strcpy(pcf->modname,mod);
1184 pcf->modname = NULL;
1187 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1188 strcpy(pcf->fname,f);
1192 return ( (pCode *)pcf);
1196 /*-----------------------------------------------------------------*/
1197 /* pCodeLabelDestruct - free memory used by a label. */
1198 /*-----------------------------------------------------------------*/
1199 static void pCodeLabelDestruct(pCode *pc)
1205 if((pc->type == PC_LABEL) && PCL(pc)->label)
1206 free(PCL(pc)->label);
1212 pCode *newpCodeLabel(int key)
1218 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1220 pcl->pc.type = PC_LABEL;
1221 pcl->pc.prev = pcl->pc.next = NULL;
1222 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1225 pcl->pc.analyze = genericAnalyze;
1226 pcl->pc.destruct = pCodeLabelDestruct;
1227 pcl->pc.print = pCodePrintLabel;
1233 sprintf(s,"_%05d_DS_",key);
1235 pcl->label = Safe_strdup(s);
1239 return ( (pCode *)pcl);
1242 pCode *newpCodeLabelStr(char *str)
1244 pCode *pc = newpCodeLabel(-1);
1247 PCL(pc)->label = Safe_strdup(str);
1249 PCL(pc)->label = NULL;
1254 /*-----------------------------------------------------------------*/
1255 /* newpBlock - create and return a pointer to a new pBlock */
1256 /*-----------------------------------------------------------------*/
1257 pBlock *newpBlock(void)
1262 PpB = Safe_calloc(1,sizeof(pBlock) );
1263 PpB->next = PpB->prev = NULL;
1265 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1266 PpB->registers = NULL;
1273 /*-----------------------------------------------------------------*/
1274 /* newpCodeChain - create a new chain of pCodes */
1275 /*-----------------------------------------------------------------*
1277 * This function will create a new pBlock and the pointer to the
1278 * pCode that is passed in will be the first pCode in the block.
1279 *-----------------------------------------------------------------*/
1282 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1285 pBlock *pB = newpBlock();
1287 pB->pcHead = pB->pcTail = pc;
1294 /*-----------------------------------------------------------------*/
1295 /* newpCodeOpLabel - Create a new label given the key */
1296 /* Note, a negative key means that the label is part of wild card */
1297 /* (and hence a wild card label) used in the pCodePeep */
1298 /* optimizations). */
1299 /*-----------------------------------------------------------------*/
1301 pCodeOp *newpCodeOpLabel(int key)
1306 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1307 pcop->type = PO_LABEL;
1311 sprintf(s,"_%05d_DS_",key);
1313 pcop->name = Safe_strdup(s);
1317 ((pCodeOpLabel *)pcop)->key = key;
1322 /*-----------------------------------------------------------------*/
1323 /*-----------------------------------------------------------------*/
1324 pCodeOp *newpCodeOpLit(int lit)
1330 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1331 pcop->type = PO_LITERAL;
1334 sprintf(s,"0x%02x",lit);
1336 pcop->name = Safe_strdup(s);
1340 ((pCodeOpLit *)pcop)->lit = lit;
1345 /*-----------------------------------------------------------------*/
1346 /*-----------------------------------------------------------------*/
1347 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1353 if(!pcp || !subtype) {
1354 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1358 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1359 pcop->type = PO_WILD;
1360 sprintf(s,"%%%d",id);
1361 pcop->name = Safe_strdup(s);
1363 PCOW(pcop)->id = id;
1364 PCOW(pcop)->pcp = pcp;
1365 PCOW(pcop)->subtype = subtype;
1366 PCOW(pcop)->matched = NULL;
1371 /*-----------------------------------------------------------------*/
1372 /*-----------------------------------------------------------------*/
1373 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1377 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1378 pcop->type = PO_BIT;
1380 pcop->name = Safe_strdup(s);
1384 PCOB(pcop)->bit = bit;
1385 PCOB(pcop)->inBitSpace = inBitSpace;
1390 pCodeOp *newpCodeOpReg(int rIdx)
1394 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1396 PCOR(pcop)->rIdx = rIdx;
1397 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1398 pcop->type = PCOR(pcop)->r->pc_type;
1403 /*-----------------------------------------------------------------*/
1404 /*-----------------------------------------------------------------*/
1406 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1412 pcop = newpCodeOpBit(name, -1,0);
1416 pcop = newpCodeOpLit(-1);
1420 pcop = newpCodeOpLabel(-1);
1424 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1427 pcop->name = Safe_strdup(name);
1435 /*-----------------------------------------------------------------*/
1436 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1437 /*-----------------------------------------------------------------*/
1438 void addpCode2pBlock(pBlock *pb, pCode *pc)
1441 /* If this is the first pcode to be added to a block that
1442 * was initialized with a NULL pcode, then go ahead and
1443 * make this pcode the head and tail */
1444 pb->pcHead = pb->pcTail = pc;
1446 pb->pcTail->next = pc;
1447 pc->prev = pb->pcTail;
1454 /*-----------------------------------------------------------------*/
1455 /* addpBlock - place a pBlock into the pFile */
1456 /*-----------------------------------------------------------------*/
1457 void addpBlock(pBlock *pb)
1461 /* First time called, we'll pass through here. */
1462 _ALLOC(the_pFile,sizeof(pFile));
1463 the_pFile->pbHead = the_pFile->pbTail = pb;
1464 the_pFile->functions = NULL;
1468 the_pFile->pbTail->next = pb;
1469 pb->prev = the_pFile->pbTail;
1471 the_pFile->pbTail = pb;
1474 /*-----------------------------------------------------------------*/
1475 /* printpCode - write the contents of a pCode to a file */
1476 /*-----------------------------------------------------------------*/
1477 void printpCode(FILE *of, pCode *pc)
1488 fprintf(of,"warning - unable to print pCode\n");
1491 /*-----------------------------------------------------------------*/
1492 /* printpBlock - write the contents of a pBlock to a file */
1493 /*-----------------------------------------------------------------*/
1494 void printpBlock(FILE *of, pBlock *pb)
1504 for(pc = pb->pcHead; pc; pc = pc->next)
1509 /*-----------------------------------------------------------------*/
1511 /* pCode processing */
1515 /*-----------------------------------------------------------------*/
1517 static void unlinkPC(pCode *pc)
1524 pc->prev->next = pc->next;
1526 pc->next->prev = pc->prev;
1528 pc->prev = pc->next = NULL;
1531 static void genericDestruct(pCode *pc)
1533 fprintf(stderr,"warning, calling default pCode destructor\n");
1542 /*-----------------------------------------------------------------*/
1543 /*-----------------------------------------------------------------*/
1544 void pBlockRegs(FILE *of, pBlock *pb)
1549 r = setFirstItem(pb->registers);
1551 r = setNextItem(pb->registers);
1556 static char *get_op( pCodeInstruction *pcc)
1560 if(pcc && pcc->pcop) {
1563 switch(pcc->pcop->type) {
1566 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
1567 r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
1572 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1573 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1574 pBlockRegs(stderr,pcc->pc.pb);
1578 if (pcc->pcop->name)
1579 return pcc->pcop->name;
1584 return "NO operand";
1587 /*-----------------------------------------------------------------*/
1588 /*-----------------------------------------------------------------*/
1589 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1592 fprintf(of,"pcodeopprint\n");
1595 char *pCode2str(char *str, int size, pCode *pc)
1603 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1605 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1607 if(PCI(pc)->bit_inst) {
1608 if(PCI(pc)->pcop->type == PO_BIT) {
1609 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1610 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1611 PCI(pc)->pcop->name ,
1612 PCI(pc)->pcop->name );
1614 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1615 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1616 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1617 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1619 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1620 //PCI(pc)->pcop->t.bit );
1623 if(PCI(pc)->pcop->type == PO_BIT) {
1624 if( PCI(pc)->num_ops == 2)
1625 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1627 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1630 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1632 if( PCI(pc)->num_ops == 2)
1633 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1641 /* assuming that comment ends with a \n */
1642 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1646 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1649 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1652 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1661 /*-----------------------------------------------------------------*/
1662 /* genericPrint - the contents of a pCode to a file */
1663 /*-----------------------------------------------------------------*/
1664 static void genericPrint(FILE *of, pCode *pc)
1672 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1676 // If the opcode has a label, print that first
1678 pBranch *pbl = pc->label;
1679 while(pbl && pbl->pc) {
1680 if(pbl->pc->type == PC_LABEL)
1681 pCodePrintLabel(of, pbl->pc);
1690 pCode2str(str, 256, pc);
1692 fprintf(of,"%s",str);
1696 pBranch *dpb = pc->to; // debug
1698 switch ( dpb->pc->type) {
1700 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1703 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1706 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1720 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1722 pCodePrintLabel(of, pc->label->pc);
1724 if(PCW(pc)->operand) {
1725 fprintf(of,";\toperand ");
1726 pCodeOpPrint(of,PCW(pc)->operand );
1732 fprintf(of,"unknown pCode type %d\n",pc->type);
1737 /*-----------------------------------------------------------------*/
1738 /* pCodePrintFunction - prints function begin/end */
1739 /*-----------------------------------------------------------------*/
1741 static void pCodePrintFunction(FILE *of, pCode *pc)
1747 if( ((pCodeFunction *)pc)->modname)
1748 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1750 if(PCF(pc)->fname) {
1751 pBranch *exits = pc->to;
1753 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1756 exits = exits->next;
1759 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1763 pc->from->pc->type == PC_FUNCTION &&
1764 PCF(pc->from->pc)->fname)
1765 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1767 fprintf(of,"; exit point [can't find entry point]\n");
1770 /*-----------------------------------------------------------------*/
1771 /* pCodePrintLabel - prints label */
1772 /*-----------------------------------------------------------------*/
1774 static void pCodePrintLabel(FILE *of, pCode *pc)
1781 fprintf(of,"%s\n",PCL(pc)->label);
1782 else if (PCL(pc)->key >=0)
1783 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1785 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1788 /*-----------------------------------------------------------------*/
1789 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
1790 /* remove it if it is found. */
1791 /*-----------------------------------------------------------------*/
1792 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
1803 bprev->next = b->next; /* Not first pCode in chain */
1807 pcl->label = b->next; /* First pCode in chain */
1810 return; /* A label can't occur more than once */
1818 /*-----------------------------------------------------------------*/
1819 /*-----------------------------------------------------------------*/
1820 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1836 /*-----------------------------------------------------------------*/
1837 /* pBranchLink - given two pcodes, this function will link them */
1838 /* together through their pBranches */
1839 /*-----------------------------------------------------------------*/
1840 static void pBranchLink(pCode *f, pCode *t)
1844 // Declare a new branch object for the 'from' pCode.
1846 _ALLOC(b,sizeof(pBranch));
1847 b->pc = t; // The link to the 'to' pCode.
1850 f->to = pBranchAppend(f->to,b);
1852 // Now do the same for the 'to' pCode.
1854 _ALLOC(b,sizeof(pBranch));
1858 t->from = pBranchAppend(t->from,b);
1863 /*-----------------------------------------------------------------*/
1864 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1866 /*-----------------------------------------------------------------*/
1867 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1880 /*-----------------------------------------------------------------*/
1881 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1882 /*-----------------------------------------------------------------*/
1883 static void pCodeUnlink(pCode *pc)
1888 if(!pc->prev || !pc->next) {
1889 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1893 /* first remove the pCode from the chain */
1894 pc->prev->next = pc->next;
1895 pc->next->prev = pc->prev;
1897 /* Now for the hard part... */
1899 /* Remove the branches */
1903 pc1 = pb1->pc; /* Get the pCode that branches to the
1904 * one we're unlinking */
1906 /* search for the link back to this pCode (the one we're
1908 if(pb2 = pBranchFind(pc1->to,pc)) {
1909 pb2->pc = pc->to->pc; // make the replacement
1911 /* if the pCode we're unlinking contains multiple 'to'
1912 * branches (e.g. this a skip instruction) then we need
1913 * to copy these extra branches to the chain. */
1915 pBranchAppend(pb2, pc->to->next);
1924 /*-----------------------------------------------------------------*/
1925 /*-----------------------------------------------------------------*/
1926 static void genericAnalyze(pCode *pc)
1936 // Go through the pCodes that are in pCode chain and link
1937 // them together through the pBranches. Note, the pCodes
1938 // are linked together as a contiguous stream like the
1939 // assembly source code lines. The linking here mimics this
1940 // except that comments are not linked in.
1942 pCode *npc = pc->next;
1944 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1945 pBranchLink(pc,npc);
1950 /* reached the end of the pcode chain without finding
1951 * an instruction we could link to. */
1956 /*-----------------------------------------------------------------*/
1957 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1961 if(pc->type == PC_LABEL) {
1962 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1965 if(pc->type == PC_OPCODE) {
1968 if(pbr->pc->type == PC_LABEL) {
1969 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1979 /*-----------------------------------------------------------------*/
1980 /* findLabel - Search the pCode for a particular label */
1981 /*-----------------------------------------------------------------*/
1982 pCode * findLabel(pCodeOpLabel *pcop_label)
1990 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1991 for(pc = pb->pcHead; pc; pc = pc->next)
1992 if(compareLabel(pc,pcop_label))
1997 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2001 /*-----------------------------------------------------------------*/
2002 /* findNextInstruction - given a pCode, find the next instruction */
2003 /* in the linked list */
2004 /*-----------------------------------------------------------------*/
2005 pCode * findNextInstruction(pCode *pc)
2009 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2015 fprintf(stderr,"Couldn't find instruction\n");
2019 /*-----------------------------------------------------------------*/
2020 /* findFunctionEnd - given a pCode find the end of the function */
2021 /* that contains it t */
2022 /*-----------------------------------------------------------------*/
2023 pCode * findFunctionEnd(pCode *pc)
2027 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2033 fprintf(stderr,"Couldn't find function end\n");
2038 /*-----------------------------------------------------------------*/
2039 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2040 /* instruction with which it is associated. */
2041 /*-----------------------------------------------------------------*/
2042 static void AnalyzeLabel(pCode *pc)
2050 static void AnalyzeGOTO(pCode *pc)
2053 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2057 static void AnalyzeSKIP(pCode *pc)
2060 pBranchLink(pc,findNextInstruction(pc->next));
2061 pBranchLink(pc,findNextInstruction(pc->next->next));
2065 static void AnalyzeRETURN(pCode *pc)
2068 // branch_link(pc,findFunctionEnd(pc->next));
2072 /*-----------------------------------------------------------------*/
2073 /*-----------------------------------------------------------------*/
2075 void AnalyzepBlock(pBlock *pb)
2082 /* Find all of the registers used in this pBlock */
2083 for(pc = pb->pcHead; pc; pc = pc->next) {
2084 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2085 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2087 /* Loop through all of the registers declared so far in
2088 this block and see if we find this one there */
2090 regs *r = setFirstItem(pb->registers);
2093 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2094 PCOR(PCI(pc)->pcop)->r = r;
2097 r = setNextItem(pb->registers);
2101 /* register wasn't found */
2102 r = Safe_calloc(1, sizeof(regs));
2103 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2104 addSet(&pb->registers, r);
2105 PCOR(PCI(pc)->pcop)->r = r;
2106 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2108 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2110 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2111 if(PCOR(PCI(pc)->pcop)->r) {
2112 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2113 fprintf(stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx);
2115 if(PCI(pc)->pcop->name)
2116 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2118 fprintf(stderr,"ERROR: NULL register\n");
2127 /*-----------------------------------------------------------------*/
2128 /*-----------------------------------------------------------------*/
2129 int OptimizepBlock(pBlock *pb)
2134 if(!pb || !peepOptimizing)
2137 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2138 for(pc = pb->pcHead; pc; pc = pc->next)
2139 matches += pCodePeepMatchRule(pc);
2145 /*-----------------------------------------------------------------*/
2146 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2147 /*-----------------------------------------------------------------*/
2148 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2152 for(pc = pcs; pc; pc = pc->next) {
2154 if((pc->type == PC_OPCODE) &&
2156 (PCI(pc)->pcop->type == PO_LABEL) &&
2157 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2165 /*-----------------------------------------------------------------*/
2166 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2167 /* pCode chain if they're not used. */
2168 /*-----------------------------------------------------------------*/
2169 void pBlockRemoveUnusedLabels(pBlock *pb)
2171 pCode *pc; pCodeLabel *pcl;
2176 for(pc = pb->pcHead; pc; pc = pc->next) {
2178 if(pc->type == PC_LABEL)
2181 pcl = PCL(pc->label->pc);
2184 /* This pCode is a label, so search the pBlock to see if anyone
2187 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2188 /* Couldn't find an instruction that refers to this label
2189 * So, unlink the pCode label from it's pCode chain
2190 * and destroy the label */
2192 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2194 if(pc->type == PC_LABEL) {
2196 pCodeLabelDestruct(pc);
2198 unlinkpCodeFromBranch(pc, PCODE(pcl));
2199 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
2210 /*-----------------------------------------------------------------*/
2211 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2212 /* chain and put them into pBranches that are */
2213 /* associated with the appropriate pCode */
2215 /*-----------------------------------------------------------------*/
2216 void pBlockMergeLabels(pBlock *pb)
2219 pCode *pc, *pcnext=NULL;
2224 /* First, Try to remove any unused labels */
2225 //pBlockRemoveUnusedLabels(pb);
2227 /* Now loop through the pBlock and merge the labels with the opcodes */
2229 for(pc = pb->pcHead; pc; pc = pc->next) {
2231 if(pc->type == PC_LABEL) {
2232 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2233 if( !(pcnext = findNextInstruction(pc)) )
2234 return; // Couldn't find an instruction associated with this label
2236 // Unlink the pCode label from it's pCode chain
2239 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2240 // And link it into the instruction's pBranch labels. (Note, since
2241 // it's possible to have multiple labels associated with one instruction
2242 // we must provide a means to accomodate the additional labels. Thus
2243 // the labels are placed into the singly-linked list "label" as
2244 // opposed to being a single member of the pCodeInstruction.)
2246 _ALLOC(pbr,sizeof(pBranch));
2250 pcnext->label = pBranchAppend(pcnext->label,pbr);
2258 pBlockRemoveUnusedLabels(pb);
2262 /*-----------------------------------------------------------------*/
2263 /*-----------------------------------------------------------------*/
2264 void OptimizepCode(char dbName)
2266 #define MAX_PASSES 4
2275 fprintf(stderr," Optimizing pCode\n");
2278 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2279 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2280 matches += OptimizepBlock(pb);
2283 while(matches && ++passes < MAX_PASSES);
2287 /*-----------------------------------------------------------------*/
2288 /* AnalyzepCode - parse the pCode that has been generated and form */
2289 /* all of the logical connections. */
2291 /* Essentially what's done here is that the pCode flow is */
2293 /*-----------------------------------------------------------------*/
2295 void AnalyzepCode(char dbName)
2306 fprintf(stderr," Analyzing pCode");
2311 /* First, merge the labels with the instructions */
2312 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2313 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2315 fprintf(stderr," analyze and merging block %c\n",dbName);
2316 pBlockMergeLabels(pb);
2321 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2322 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2323 changes += OptimizepBlock(pb);
2326 } while(changes && (i++ < MAX_PASSES));
2328 /* Now build the call tree.
2329 First we examine all of the pCodes for functions.
2330 Keep in mind that the function boundaries coincide
2331 with pBlock boundaries.
2333 The algorithm goes something like this:
2334 We have two nested loops. The outer loop iterates
2335 through all of the pBlocks/functions. The inner
2336 loop iterates through all of the pCodes for
2337 a given pBlock. When we begin iterating through
2338 a pBlock, the variable pc_fstart, pCode of the start
2339 of a function, is cleared. We then search for pCodes
2340 of type PC_FUNCTION. When one is encountered, we
2341 initialize pc_fstart to this and at the same time
2342 associate a new pBranch object that signifies a
2343 branch entry. If a return is found, then this signifies
2344 a function exit point. We'll link the pCodes of these
2345 returns to the matching pc_fstart.
2347 When we're done, a doubly linked list of pBranches
2348 will exist. The head of this list is stored in
2349 `the_pFile', which is the meta structure for all
2350 of the pCode. Look at the printCallTree function
2351 on how the pBranches are linked together.
2354 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2355 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2356 pCode *pc_fstart=NULL;
2357 for(pc = pb->pcHead; pc; pc = pc->next) {
2358 if(pc->type == PC_FUNCTION) {
2359 if (PCF(pc)->fname) {
2360 // I'm not liking this....
2361 // Found the beginning of a function.
2362 _ALLOC(pbr,sizeof(pBranch));
2363 pbr->pc = pc_fstart = pc;
2366 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2368 // Here's a better way of doing the same:
2369 addSet(&pb->function_entries, pc);
2372 // Found an exit point in a function, e.g. return
2373 // (Note, there may be more than one return per function)
2375 pBranchLink(pc_fstart, pc);
2377 addSet(&pb->function_exits, pc);
2379 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2380 addSet(&pb->function_calls,pc);
2387 /*-----------------------------------------------------------------*/
2388 /* ispCodeFunction - returns true if *pc is the pCode of a */
2390 /*-----------------------------------------------------------------*/
2391 bool ispCodeFunction(pCode *pc)
2394 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2400 /*-----------------------------------------------------------------*/
2401 /* findFunction - Search for a function by name (given the name) */
2402 /* in the set of all functions that are in a pBlock */
2403 /* (note - I expect this to change because I'm planning to limit */
2404 /* pBlock's to just one function declaration */
2405 /*-----------------------------------------------------------------*/
2406 pCode *findFunction(char *fname)
2413 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2415 pc = setFirstItem(pb->function_entries);
2418 if((pc->type == PC_FUNCTION) &&
2420 (strcmp(fname, PCF(pc)->fname)==0))
2423 pc = setNextItem(pb->function_entries);
2431 void MarkUsedRegisters(set *regset)
2436 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2437 r2 = pic14_regWithIdx(r1->rIdx);
2443 void pBlockStats(FILE *of, pBlock *pb)
2449 fprintf(of,";***\n; pBlock Stats\n;***\n");
2451 // for now just print the first element of each set
2452 pc = setFirstItem(pb->function_entries);
2454 fprintf(of,";entry: ");
2457 pc = setFirstItem(pb->function_exits);
2459 fprintf(of,";has an exit\n");
2463 pc = setFirstItem(pb->function_calls);
2465 fprintf(of,";functions called:\n");
2468 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2469 fprintf(of,"; %s\n",get_op(PCI(pc)));
2471 pc = setNextItem(pb->function_calls);
2475 r = setFirstItem(pb->registers);
2477 int n = elementsInSet(pb->registers);
2479 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2482 fprintf(of,"; %s\n",r->name);
2483 r = setNextItem(pb->registers);
2488 /*-----------------------------------------------------------------*/
2489 /*-----------------------------------------------------------------*/
2490 void sequencepCode(void)
2496 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2498 pb->seq = GpCodeSequenceNumber+1;
2500 for( pc = pb->pcHead; pc; pc = pc->next)
2501 pc->seq = ++GpCodeSequenceNumber;
2506 /*-----------------------------------------------------------------*/
2507 /*-----------------------------------------------------------------*/
2508 set *register_usage(pBlock *pb)
2511 set *registers=NULL;
2512 set *registersInCallPath = NULL;
2514 /* check recursion */
2516 pc = setFirstItem(pb->function_entries);
2523 if(pc->type != PC_FUNCTION)
2524 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2526 pc = setFirstItem(pb->function_calls);
2527 for( ; pc; pc = setNextItem(pb->function_calls)) {
2529 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2530 char *dest = get_op(PCI(pc));
2532 pcn = findFunction(dest);
2534 registersInCallPath = register_usage(pcn->pb);
2536 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2541 pBlockStats(stderr,pb); // debug
2543 // Mark the registers in this block as used.
2545 MarkUsedRegisters(pb->registers);
2546 if(registersInCallPath) {
2547 /* registers were used in the functions this pBlock has called */
2548 /* so now, we need to see if these collide with the ones we are */
2551 regs *r1,*r2, *newreg;
2553 fprintf(stderr,"comparing registers\n");
2555 r1 = setFirstItem(registersInCallPath);
2558 r2 = setFirstItem(pb->registers);
2560 while(r2 && (r1->type != REG_STK)) {
2562 if(r2->rIdx == r1->rIdx) {
2563 newreg = pic14_findFreeReg(REG_GPR);
2567 fprintf(stderr,"Bummer, no more registers.\n");
2571 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2572 r1->rIdx, newreg->rIdx);
2573 r2->rIdx = newreg->rIdx;
2574 //if(r2->name) free(r2->name);
2576 r2->name = Safe_strdup(newreg->name);
2580 newreg->wasUsed = 1;
2582 r2 = setNextItem(pb->registers);
2585 r1 = setNextItem(registersInCallPath);
2588 /* Collisions have been resolved. Now free the registers in the call path */
2589 r1 = setFirstItem(registersInCallPath);
2591 if(r1->type != REG_STK) {
2592 newreg = pic14_regWithIdx(r1->rIdx);
2595 r1 = setNextItem(registersInCallPath);
2599 // MarkUsedRegisters(pb->registers);
2601 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2604 fprintf(stderr,"returning regs\n");
2606 fprintf(stderr,"not returning regs\n");
2608 fprintf(stderr,"pBlock after register optim.\n");
2609 pBlockStats(stderr,pb); // debug
2615 /*-----------------------------------------------------------------*/
2616 /* printCallTree - writes the call tree to a file */
2618 /*-----------------------------------------------------------------*/
2619 void pct2(FILE *of,pBlock *pb,int indent)
2623 // set *registersInCallPath = NULL;
2626 return;// registers;
2629 return; // registers; //recursion ?
2631 pc = setFirstItem(pb->function_entries);
2638 for(i=0;i<indent;i++) // Indentation
2641 if(pc->type == PC_FUNCTION)
2642 fprintf(of,"%s\n",PCF(pc)->fname);
2647 pc = setFirstItem(pb->function_calls);
2648 for( ; pc; pc = setNextItem(pb->function_calls)) {
2650 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2651 char *dest = get_op(PCI(pc));
2653 pcn = findFunction(dest);
2655 pct2(of,pcn->pb,indent+1);
2657 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2665 fprintf(stderr,"pBlock before register optim.\n");
2666 pBlockStats(stderr,pb); // debug
2668 if(registersInCallPath) {
2669 /* registers were used in the functions this pBlock has called */
2670 /* so now, we need to see if these collide with the ones we are using here */
2672 regs *r1,*r2, *newreg;
2674 fprintf(stderr,"comparing registers\n");
2676 r1 = setFirstItem(registersInCallPath);
2679 r2 = setFirstItem(pb->registers);
2683 if(r2->rIdx == r1->rIdx) {
2684 newreg = pic14_findFreeReg();
2688 fprintf(stderr,"Bummer, no more registers.\n");
2692 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2693 r1->rIdx, newreg->rIdx);
2694 r2->rIdx = newreg->rIdx;
2695 //if(r2->name) free(r2->name);
2697 r2->name = Safe_strdup(newreg->name);
2701 newreg->wasUsed = 1;
2703 r2 = setNextItem(pb->registers);
2706 r1 = setNextItem(registersInCallPath);
2709 /* Collisions have been resolved. Now free the registers in the call path */
2710 r1 = setFirstItem(registersInCallPath);
2712 newreg = pic14_regWithIdx(r1->rIdx);
2714 r1 = setNextItem(registersInCallPath);
2718 MarkUsedRegisters(pb->registers);
2720 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2723 fprintf(stderr,"returning regs\n");
2725 fprintf(stderr,"not returning regs\n");
2727 fprintf(stderr,"pBlock after register optim.\n");
2728 pBlockStats(stderr,pb); // debug
2736 /*-----------------------------------------------------------------*/
2737 /* printCallTree - writes the call tree to a file */
2739 /*-----------------------------------------------------------------*/
2741 void printCallTree(FILE *of)
2753 fprintf(of, "\npBlock statistics\n");
2754 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2755 pBlockStats(stderr,pb);
2759 fprintf(of,"Call Tree\n");
2760 pbr = the_pFile->functions;
2764 if(!ispCodeFunction(pc))
2765 fprintf(of,"bug in call tree");
2768 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2770 while(pc->next && !ispCodeFunction(pc->next)) {
2772 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2773 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2781 /* Re-allocate the registers so that there are no collisions
2782 * between local variables when one function call another */
2784 pic14_deallocateAllRegs();
2786 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2791 fprintf(of,"\n**************\n\na better call tree\n");
2792 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2797 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2798 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));