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 DFPRINTF((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 DFPRINTF((stderr,"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 * by looking at each instruction and examining it's
2086 for(pc = pb->pcHead; pc; pc = pc->next) {
2088 /* Is this an instruction with operands? */
2089 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2091 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2093 /* Loop through all of the registers declared so far in
2094 this block and see if we find this one there */
2096 regs *r = setFirstItem(pb->registers);
2099 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2100 PCOR(PCI(pc)->pcop)->r = r;
2103 r = setNextItem(pb->registers);
2107 /* register wasn't found */
2108 r = Safe_calloc(1, sizeof(regs));
2109 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2110 addSet(&pb->registers, r);
2111 PCOR(PCI(pc)->pcop)->r = r;
2112 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2114 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2117 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2118 if(PCOR(PCI(pc)->pcop)->r) {
2119 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2120 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2122 if(PCI(pc)->pcop->name)
2123 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2125 fprintf(stderr,"ERROR: NULL register\n");
2134 /*-----------------------------------------------------------------*/
2135 /*-----------------------------------------------------------------*/
2136 int OptimizepBlock(pBlock *pb)
2141 if(!pb || !peepOptimizing)
2144 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
2145 for(pc = pb->pcHead; pc; pc = pc->next)
2146 matches += pCodePeepMatchRule(pc);
2148 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
2153 /*-----------------------------------------------------------------*/
2154 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2155 /*-----------------------------------------------------------------*/
2156 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2160 for(pc = pcs; pc; pc = pc->next) {
2162 if((pc->type == PC_OPCODE) &&
2164 (PCI(pc)->pcop->type == PO_LABEL) &&
2165 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2173 /*-----------------------------------------------------------------*/
2174 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2175 /* pCode chain if they're not used. */
2176 /*-----------------------------------------------------------------*/
2177 void pBlockRemoveUnusedLabels(pBlock *pb)
2179 pCode *pc; pCodeLabel *pcl;
2184 for(pc = pb->pcHead; pc; pc = pc->next) {
2186 if(pc->type == PC_LABEL)
2189 pcl = PCL(pc->label->pc);
2192 /* This pCode is a label, so search the pBlock to see if anyone
2195 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2196 /* Couldn't find an instruction that refers to this label
2197 * So, unlink the pCode label from it's pCode chain
2198 * and destroy the label */
2200 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
2202 if(pc->type == PC_LABEL) {
2204 pCodeLabelDestruct(pc);
2206 unlinkpCodeFromBranch(pc, PCODE(pcl));
2207 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
2218 /*-----------------------------------------------------------------*/
2219 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2220 /* chain and put them into pBranches that are */
2221 /* associated with the appropriate pCode */
2223 /*-----------------------------------------------------------------*/
2224 void pBlockMergeLabels(pBlock *pb)
2227 pCode *pc, *pcnext=NULL;
2232 /* First, Try to remove any unused labels */
2233 //pBlockRemoveUnusedLabels(pb);
2235 /* Now loop through the pBlock and merge the labels with the opcodes */
2237 for(pc = pb->pcHead; pc; pc = pc->next) {
2239 if(pc->type == PC_LABEL) {
2240 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2241 if( !(pcnext = findNextInstruction(pc)) )
2242 return; // Couldn't find an instruction associated with this label
2244 // Unlink the pCode label from it's pCode chain
2247 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2248 // And link it into the instruction's pBranch labels. (Note, since
2249 // it's possible to have multiple labels associated with one instruction
2250 // we must provide a means to accomodate the additional labels. Thus
2251 // the labels are placed into the singly-linked list "label" as
2252 // opposed to being a single member of the pCodeInstruction.)
2254 _ALLOC(pbr,sizeof(pBranch));
2258 pcnext->label = pBranchAppend(pcnext->label,pbr);
2266 pBlockRemoveUnusedLabels(pb);
2270 /*-----------------------------------------------------------------*/
2271 /*-----------------------------------------------------------------*/
2272 void OptimizepCode(char dbName)
2274 #define MAX_PASSES 4
2283 DFPRINTF((stderr," Optimizing pCode\n"));
2286 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2287 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2288 matches += OptimizepBlock(pb);
2291 while(matches && ++passes < MAX_PASSES);
2295 /*-----------------------------------------------------------------*/
2296 /* AnalyzepCode - parse the pCode that has been generated and form */
2297 /* all of the logical connections. */
2299 /* Essentially what's done here is that the pCode flow is */
2301 /*-----------------------------------------------------------------*/
2303 void AnalyzepCode(char dbName)
2318 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
2320 /* First, merge the labels with the instructions */
2321 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2322 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2324 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
2325 pBlockMergeLabels(pb);
2332 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2333 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2334 changes += OptimizepBlock(pb);
2337 } while(changes && (i++ < MAX_PASSES));
2339 /* Now build the call tree.
2340 First we examine all of the pCodes for functions.
2341 Keep in mind that the function boundaries coincide
2342 with pBlock boundaries.
2344 The algorithm goes something like this:
2345 We have two nested loops. The outer loop iterates
2346 through all of the pBlocks/functions. The inner
2347 loop iterates through all of the pCodes for
2348 a given pBlock. When we begin iterating through
2349 a pBlock, the variable pc_fstart, pCode of the start
2350 of a function, is cleared. We then search for pCodes
2351 of type PC_FUNCTION. When one is encountered, we
2352 initialize pc_fstart to this and at the same time
2353 associate a new pBranch object that signifies a
2354 branch entry. If a return is found, then this signifies
2355 a function exit point. We'll link the pCodes of these
2356 returns to the matching pc_fstart.
2358 When we're done, a doubly linked list of pBranches
2359 will exist. The head of this list is stored in
2360 `the_pFile', which is the meta structure for all
2361 of the pCode. Look at the printCallTree function
2362 on how the pBranches are linked together.
2365 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2366 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2367 pCode *pc_fstart=NULL;
2368 for(pc = pb->pcHead; pc; pc = pc->next) {
2369 if(pc->type == PC_FUNCTION) {
2370 if (PCF(pc)->fname) {
2371 // I'm not liking this....
2372 // Found the beginning of a function.
2373 _ALLOC(pbr,sizeof(pBranch));
2374 pbr->pc = pc_fstart = pc;
2377 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2379 // Here's a better way of doing the same:
2380 addSet(&pb->function_entries, pc);
2383 // Found an exit point in a function, e.g. return
2384 // (Note, there may be more than one return per function)
2386 pBranchLink(pc_fstart, pc);
2388 addSet(&pb->function_exits, pc);
2390 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2391 addSet(&pb->function_calls,pc);
2398 /*-----------------------------------------------------------------*/
2399 /* ispCodeFunction - returns true if *pc is the pCode of a */
2401 /*-----------------------------------------------------------------*/
2402 bool ispCodeFunction(pCode *pc)
2405 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2411 /*-----------------------------------------------------------------*/
2412 /* findFunction - Search for a function by name (given the name) */
2413 /* in the set of all functions that are in a pBlock */
2414 /* (note - I expect this to change because I'm planning to limit */
2415 /* pBlock's to just one function declaration */
2416 /*-----------------------------------------------------------------*/
2417 pCode *findFunction(char *fname)
2424 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2426 pc = setFirstItem(pb->function_entries);
2429 if((pc->type == PC_FUNCTION) &&
2431 (strcmp(fname, PCF(pc)->fname)==0))
2434 pc = setNextItem(pb->function_entries);
2442 void MarkUsedRegisters(set *regset)
2447 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2448 r2 = pic14_regWithIdx(r1->rIdx);
2454 void pBlockStats(FILE *of, pBlock *pb)
2460 fprintf(of,";***\n; pBlock Stats\n;***\n");
2462 // for now just print the first element of each set
2463 pc = setFirstItem(pb->function_entries);
2465 fprintf(of,";entry: ");
2468 pc = setFirstItem(pb->function_exits);
2470 fprintf(of,";has an exit\n");
2474 pc = setFirstItem(pb->function_calls);
2476 fprintf(of,";functions called:\n");
2479 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2480 fprintf(of,"; %s\n",get_op(PCI(pc)));
2482 pc = setNextItem(pb->function_calls);
2486 r = setFirstItem(pb->registers);
2488 int n = elementsInSet(pb->registers);
2490 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2493 fprintf(of,"; %s\n",r->name);
2494 r = setNextItem(pb->registers);
2499 /*-----------------------------------------------------------------*/
2500 /*-----------------------------------------------------------------*/
2501 void sequencepCode(void)
2507 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2509 pb->seq = GpCodeSequenceNumber+1;
2511 for( pc = pb->pcHead; pc; pc = pc->next)
2512 pc->seq = ++GpCodeSequenceNumber;
2517 /*-----------------------------------------------------------------*/
2518 /*-----------------------------------------------------------------*/
2519 set *register_usage(pBlock *pb)
2522 set *registers=NULL;
2523 set *registersInCallPath = NULL;
2525 /* check recursion */
2527 pc = setFirstItem(pb->function_entries);
2534 if(pc->type != PC_FUNCTION)
2535 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2537 pc = setFirstItem(pb->function_calls);
2538 for( ; pc; pc = setNextItem(pb->function_calls)) {
2540 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2541 char *dest = get_op(PCI(pc));
2543 pcn = findFunction(dest);
2545 registersInCallPath = register_usage(pcn->pb);
2547 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2552 pBlockStats(stderr,pb); // debug
2555 // Mark the registers in this block as used.
2557 MarkUsedRegisters(pb->registers);
2558 if(registersInCallPath) {
2559 /* registers were used in the functions this pBlock has called */
2560 /* so now, we need to see if these collide with the ones we are */
2563 regs *r1,*r2, *newreg;
2565 DFPRINTF((stderr,"comparing registers\n"));
2567 r1 = setFirstItem(registersInCallPath);
2570 r2 = setFirstItem(pb->registers);
2572 while(r2 && (r1->type != REG_STK)) {
2574 if(r2->rIdx == r1->rIdx) {
2575 newreg = pic14_findFreeReg(REG_GPR);
2579 DFPRINTF((stderr,"Bummer, no more registers.\n"));
2583 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
2584 r1->rIdx, newreg->rIdx));
2585 r2->rIdx = newreg->rIdx;
2586 //if(r2->name) free(r2->name);
2588 r2->name = Safe_strdup(newreg->name);
2592 newreg->wasUsed = 1;
2594 r2 = setNextItem(pb->registers);
2597 r1 = setNextItem(registersInCallPath);
2600 /* Collisions have been resolved. Now free the registers in the call path */
2601 r1 = setFirstItem(registersInCallPath);
2603 if(r1->type != REG_STK) {
2604 newreg = pic14_regWithIdx(r1->rIdx);
2607 r1 = setNextItem(registersInCallPath);
2611 // MarkUsedRegisters(pb->registers);
2613 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2616 DFPRINTF((stderr,"returning regs\n"));
2618 DFPRINTF((stderr,"not returning regs\n"));
2620 DFPRINTF((stderr,"pBlock after register optim.\n"));
2621 pBlockStats(stderr,pb); // debug
2627 /*-----------------------------------------------------------------*/
2628 /* printCallTree - writes the call tree to a file */
2630 /*-----------------------------------------------------------------*/
2631 void pct2(FILE *of,pBlock *pb,int indent)
2635 // set *registersInCallPath = NULL;
2638 return;// registers;
2641 return; // registers; //recursion ?
2643 pc = setFirstItem(pb->function_entries);
2650 for(i=0;i<indent;i++) // Indentation
2653 if(pc->type == PC_FUNCTION)
2654 fprintf(of,"%s\n",PCF(pc)->fname);
2659 pc = setFirstItem(pb->function_calls);
2660 for( ; pc; pc = setNextItem(pb->function_calls)) {
2662 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2663 char *dest = get_op(PCI(pc));
2665 pcn = findFunction(dest);
2667 pct2(of,pcn->pb,indent+1);
2669 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2677 fprintf(stderr,"pBlock before register optim.\n");
2678 pBlockStats(stderr,pb); // debug
2680 if(registersInCallPath) {
2681 /* registers were used in the functions this pBlock has called */
2682 /* so now, we need to see if these collide with the ones we are using here */
2684 regs *r1,*r2, *newreg;
2686 fprintf(stderr,"comparing registers\n");
2688 r1 = setFirstItem(registersInCallPath);
2691 r2 = setFirstItem(pb->registers);
2695 if(r2->rIdx == r1->rIdx) {
2696 newreg = pic14_findFreeReg();
2700 fprintf(stderr,"Bummer, no more registers.\n");
2704 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2705 r1->rIdx, newreg->rIdx);
2706 r2->rIdx = newreg->rIdx;
2707 //if(r2->name) free(r2->name);
2709 r2->name = Safe_strdup(newreg->name);
2713 newreg->wasUsed = 1;
2715 r2 = setNextItem(pb->registers);
2718 r1 = setNextItem(registersInCallPath);
2721 /* Collisions have been resolved. Now free the registers in the call path */
2722 r1 = setFirstItem(registersInCallPath);
2724 newreg = pic14_regWithIdx(r1->rIdx);
2726 r1 = setNextItem(registersInCallPath);
2730 MarkUsedRegisters(pb->registers);
2732 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2735 fprintf(stderr,"returning regs\n");
2737 fprintf(stderr,"not returning regs\n");
2739 fprintf(stderr,"pBlock after register optim.\n");
2740 pBlockStats(stderr,pb); // debug
2748 /*-----------------------------------------------------------------*/
2749 /* printCallTree - writes the call tree to a file */
2751 /*-----------------------------------------------------------------*/
2753 void printCallTree(FILE *of)
2765 fprintf(of, "\npBlock statistics\n");
2766 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2771 fprintf(of,"Call Tree\n");
2772 pbr = the_pFile->functions;
2776 if(!ispCodeFunction(pc))
2777 fprintf(of,"bug in call tree");
2780 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2782 while(pc->next && !ispCodeFunction(pc->next)) {
2784 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2785 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2793 /* Re-allocate the registers so that there are no collisions
2794 * between local variables when one function call another */
2796 pic14_deallocateAllRegs();
2798 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2803 fprintf(of,"\n**************\n\na better call tree\n");
2804 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2809 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2810 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));