1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
30 #if defined(__BORLANDC__) || defined(_MSC_VER)
31 #define STRCASECMP stricmp
33 #define STRCASECMP strcasecmp
36 // Eventually this will go into device dependent files:
37 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,NULL};
38 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,NULL};
39 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,NULL};
40 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,NULL};
41 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,NULL};
43 static int mnemonics_initialized = 0;
46 static hTab *pic14MnemonicsHash = NULL;
50 static pFile *the_pFile = NULL;
51 static int peepOptimizing = 1;
52 static int GpCodeSequenceNumber = 1;
54 /****************************************************************/
55 /* Forward declarations */
56 /****************************************************************/
58 static void unlinkPC(pCode *pc);
59 static void genericAnalyze(pCode *pc);
60 static void AnalyzeGOTO(pCode *pc);
61 static void AnalyzeSKIP(pCode *pc);
62 static void AnalyzeRETURN(pCode *pc);
64 static void genericDestruct(pCode *pc);
65 static void genericPrint(FILE *of,pCode *pc);
67 static void pCodePrintLabel(FILE *of, pCode *pc);
68 static void pCodePrintFunction(FILE *of, pCode *pc);
69 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
70 static char *get_op( pCodeInstruction *pcc);
71 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
72 int pCodePeepMatchRule(pCode *pc);
75 pCodeInstruction pciADDWF = {
76 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
84 1,0, // dest, bit instruction
85 (PCC_W | PCC_REGISTER), // inCond
86 (PCC_REGISTER | PCC_Z) // outCond
89 pCodeInstruction pciADDFW = {
90 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
98 0,0, // dest, bit instruction
99 (PCC_W | PCC_REGISTER), // inCond
100 (PCC_W | PCC_Z) // outCond
103 pCodeInstruction pciADDLW = {
104 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
112 0,0, // dest, bit instruction
114 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
117 pCodeInstruction pciANDLW = {
118 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
126 0,0, // dest, bit instruction
128 (PCC_W | PCC_Z) // outCond
131 pCodeInstruction pciANDWF = {
132 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
140 1,0, // dest, bit instruction
141 (PCC_W | PCC_REGISTER), // inCond
142 (PCC_REGISTER | PCC_Z) // outCond
145 pCodeInstruction pciANDFW = {
146 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
154 0,0, // dest, bit instruction
155 (PCC_W | PCC_REGISTER), // inCond
156 (PCC_W | PCC_Z) // outCond
159 pCodeInstruction pciBCF = {
160 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
168 0,1, // dest, bit instruction
170 PCC_EXAMINE_PCOP // outCond
173 pCodeInstruction pciBSF = {
174 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
182 0,1, // dest, bit instruction
184 PCC_EXAMINE_PCOP // outCond
187 pCodeInstruction pciBTFSC = {
188 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
196 0,1, // dest, bit instruction
197 PCC_EXAMINE_PCOP, // inCond
201 pCodeInstruction pciBTFSS = {
202 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
210 0,1, // dest, bit instruction
211 PCC_EXAMINE_PCOP, // inCond
215 pCodeInstruction pciCALL = {
216 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
224 0,0, // dest, bit instruction
229 pCodeInstruction pciCOMF = {
230 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
238 1,0, // dest, bit instruction
239 PCC_REGISTER, // inCond
240 PCC_REGISTER // outCond
243 pCodeInstruction pciCOMFW = {
244 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
252 0,0, // dest, bit instruction
253 PCC_REGISTER, // inCond
257 pCodeInstruction pciCLRF = {
258 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
266 0,0, // dest, bit instruction
267 PCC_REGISTER, // inCond
268 PCC_REGISTER // outCond
271 pCodeInstruction pciCLRW = {
272 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
280 0,0, // dest, bit instruction
285 pCodeInstruction pciDECF = {
286 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
294 1,0, // dest, bit instruction
295 PCC_REGISTER, // inCond
296 PCC_REGISTER // outCond
299 pCodeInstruction pciDECFW = {
300 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
308 0,0, // dest, bit instruction
309 PCC_REGISTER, // inCond
313 pCodeInstruction pciDECFSZ = {
314 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
322 1,0, // dest, bit instruction
323 PCC_REGISTER, // inCond
324 PCC_REGISTER // outCond
327 pCodeInstruction pciDECFSZW = {
328 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
336 0,0, // dest, bit instruction
337 PCC_REGISTER, // inCond
341 pCodeInstruction pciGOTO = {
342 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
350 0,0, // dest, bit instruction
356 pCodeInstruction pciINCF = {
357 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
365 1,0, // dest, bit instruction
366 PCC_REGISTER, // inCond
367 PCC_REGISTER // outCond
370 pCodeInstruction pciINCFW = {
371 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
379 0,0, // dest, bit instruction
380 PCC_REGISTER, // inCond
384 pCodeInstruction pciINCFSZ = {
385 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
393 1,0, // dest, bit instruction
394 PCC_REGISTER, // inCond
395 PCC_REGISTER // outCond
398 pCodeInstruction pciINCFSZW = {
399 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
407 0,0, // dest, bit instruction
408 PCC_REGISTER, // inCond
412 pCodeInstruction pciIORWF = {
413 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
421 1,0, // dest, bit instruction
422 (PCC_W | PCC_REGISTER), // inCond
423 (PCC_REGISTER | PCC_Z) // outCond
426 pCodeInstruction pciIORFW = {
427 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
435 0,0, // dest, bit instruction
436 (PCC_W | PCC_REGISTER), // inCond
437 (PCC_W | PCC_Z) // outCond
440 pCodeInstruction pciIORLW = {
441 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
449 0,0, // dest, bit instruction
451 (PCC_W | PCC_Z) // outCond
454 pCodeInstruction pciMOVF = {
455 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
463 1,0, // dest, bit instruction
464 PCC_REGISTER, // inCond
468 pCodeInstruction pciMOVFW = {
469 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
477 0,0, // dest, bit instruction
478 PCC_REGISTER, // inCond
479 (PCC_W | PCC_Z) // outCond
482 pCodeInstruction pciMOVWF = {
483 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
491 0,0, // dest, bit instruction
496 pCodeInstruction pciMOVLW = {
497 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
505 0,0, // dest, bit instruction
510 pCodeInstruction pciNEGF = {
511 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
519 0,0, // dest, bit instruction
520 PCC_REGISTER, // inCond
525 pCodeInstruction pciRETLW = {
526 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
534 0,0, // dest, bit instruction
539 pCodeInstruction pciRETURN = {
540 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
548 0,0, // dest, bit instruction
554 pCodeInstruction pciRLF = {
555 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
563 1,0, // dest, bit instruction
564 (PCC_C | PCC_REGISTER), // inCond
565 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
568 pCodeInstruction pciRLFW = {
569 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
577 0,0, // dest, bit instruction
578 (PCC_C | PCC_REGISTER), // inCond
579 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
582 pCodeInstruction pciRRF = {
583 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
591 1,0, // dest, bit instruction
592 (PCC_C | PCC_REGISTER), // inCond
593 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
596 pCodeInstruction pciRRFW = {
597 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
605 0,0, // dest, bit instruction
606 (PCC_C | PCC_REGISTER), // inCond
607 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
610 pCodeInstruction pciSUBWF = {
611 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
619 1,0, // dest, bit instruction
620 (PCC_W | PCC_REGISTER), // inCond
621 (PCC_REGISTER | PCC_Z) // outCond
624 pCodeInstruction pciSUBFW = {
625 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
633 0,0, // dest, bit instruction
634 (PCC_W | PCC_REGISTER), // inCond
635 (PCC_W | PCC_Z) // outCond
638 pCodeInstruction pciSUBLW = {
639 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
647 0,0, // dest, bit instruction
649 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
652 pCodeInstruction pciSWAPF = {
653 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
661 1,0, // dest, bit instruction
662 (PCC_REGISTER), // inCond
663 (PCC_REGISTER) // outCond
666 pCodeInstruction pciSWAPFW = {
667 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
675 0,0, // dest, bit instruction
676 (PCC_REGISTER), // inCond
679 pCodeInstruction pciTRIS = {
680 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
688 0,0, // dest, bit instruction
694 pCodeInstruction pciXORWF = {
695 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
703 1,0, // dest, bit instruction
704 (PCC_W | PCC_REGISTER), // inCond
705 (PCC_REGISTER | PCC_Z) // outCond
708 pCodeInstruction pciXORFW = {
709 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
717 0,0, // dest, bit instruction
718 (PCC_W | PCC_REGISTER), // inCond
719 (PCC_W | PCC_Z) // outCond
722 pCodeInstruction pciXORLW = {
723 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
731 0,0, // dest, bit instruction
733 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
737 #define MAX_PIC14MNEMONICS 100
738 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
740 char *Safe_strdup(char *str)
749 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
758 /*-----------------------------------------------------------------*/
759 /* SAFE_snprintf - like snprintf except the string pointer is */
760 /* after the string has been printed to. This is */
761 /* useful for printing to string as though if it */
763 /*-----------------------------------------------------------------*/
764 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
772 va_start(val, format);
774 // Alas, vsnprintf is not ANSI standard, and does not exist
775 // on Solaris (and probably other non-Gnu flavored Unixes).
776 vsnprintf(*str, *size, format, val);
778 // This, of course, is *not* safe, despite the name.
779 vsprintf(*str, format, val);
790 void pCodeInitRegisters(void)
794 pc_fsr.r = pic14_regWithIdx(4);
798 /*-----------------------------------------------------------------*/
799 /* mnem2key - convert a pic mnemonic into a hash key */
800 /* (BTW - this spreads the mnemonics quite well) */
802 /*-----------------------------------------------------------------*/
804 int mnem2key(char const *mnem)
813 key += toupper(*mnem++) +1;
821 void pic14initMnemonics(void)
826 pCodeInstruction *pci;
828 if(mnemonics_initialized)
831 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
832 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
833 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
834 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
835 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
836 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
837 pic14Mnemonics[POC_BCF] = &pciBCF;
838 pic14Mnemonics[POC_BSF] = &pciBSF;
839 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
840 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
841 pic14Mnemonics[POC_CALL] = &pciCALL;
842 pic14Mnemonics[POC_COMF] = &pciCOMF;
843 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
844 pic14Mnemonics[POC_CLRF] = &pciCLRF;
845 pic14Mnemonics[POC_CLRW] = &pciCLRW;
846 pic14Mnemonics[POC_DECF] = &pciDECF;
847 pic14Mnemonics[POC_DECFW] = &pciDECFW;
848 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
849 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
850 pic14Mnemonics[POC_GOTO] = &pciGOTO;
851 pic14Mnemonics[POC_INCF] = &pciINCF;
852 pic14Mnemonics[POC_INCFW] = &pciINCFW;
853 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
854 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
855 pic14Mnemonics[POC_IORLW] = &pciIORLW;
856 pic14Mnemonics[POC_IORWF] = &pciIORWF;
857 pic14Mnemonics[POC_IORFW] = &pciIORFW;
858 pic14Mnemonics[POC_MOVF] = &pciMOVF;
859 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
860 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
861 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
862 pic14Mnemonics[POC_NEGF] = &pciNEGF;
863 pic14Mnemonics[POC_RETLW] = &pciRETLW;
864 pic14Mnemonics[POC_RETURN] = &pciRETURN;
865 pic14Mnemonics[POC_RLF] = &pciRLF;
866 pic14Mnemonics[POC_RLFW] = &pciRLFW;
867 pic14Mnemonics[POC_RRF] = &pciRRF;
868 pic14Mnemonics[POC_RRFW] = &pciRRFW;
869 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
870 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
871 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
872 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
873 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
874 pic14Mnemonics[POC_TRIS] = &pciTRIS;
875 pic14Mnemonics[POC_XORLW] = &pciXORLW;
876 pic14Mnemonics[POC_XORWF] = &pciXORWF;
877 pic14Mnemonics[POC_XORFW] = &pciXORFW;
879 for(i=0; i<MAX_PIC14MNEMONICS; i++)
880 if(pic14Mnemonics[i])
881 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
882 pci = hTabFirstItem(pic14MnemonicsHash, &key);
885 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
886 pci = hTabNextItem(pic14MnemonicsHash, &key);
889 mnemonics_initialized = 1;
892 int getpCode(char *mnem,unsigned dest)
895 pCodeInstruction *pci;
896 int key = mnem2key(mnem);
898 if(!mnemonics_initialized)
899 pic14initMnemonics();
901 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
905 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
906 if((pci->num_ops <= 1) || (pci->dest == dest))
910 pci = hTabNextItemWK (pic14MnemonicsHash);
917 char getpBlock_dbName(pBlock *pb)
923 return pb->cmemmap->dbName;
927 /*-----------------------------------------------------------------*/
928 /* movepBlock2Head - given the dbname of a pBlock, move all */
929 /* instances to the front of the doubly linked */
930 /* list of pBlocks */
931 /*-----------------------------------------------------------------*/
933 void movepBlock2Head(char dbName)
937 pb = the_pFile->pbHead;
941 if(getpBlock_dbName(pb) == dbName) {
942 pBlock *pbn = pb->next;
943 pb->next = the_pFile->pbHead;
944 the_pFile->pbHead->prev = pb;
945 the_pFile->pbHead = pb;
948 pb->prev->next = pbn;
950 // If the pBlock that we just moved was the last
951 // one in the link of all of the pBlocks, then we
952 // need to point the tail to the block just before
954 // Note: if pb->next is NULL, then pb must have
955 // been the last pBlock in the chain.
958 pbn->prev = pb->prev;
960 the_pFile->pbTail = pb->prev;
971 void copypCode(FILE *of, char dbName)
975 if(!of || !the_pFile)
978 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
979 if(getpBlock_dbName(pb) == dbName)
984 void pcode_test(void)
987 printf("pcode is alive!\n");
997 /* create the file name */
998 strcpy(buffer,srcFileName);
1001 if( !(pFile = fopen(buffer, "w" ))) {
1002 werror(E_FILE_OPEN_ERR,buffer);
1006 fprintf(pFile,"pcode dump\n\n");
1008 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1009 fprintf(pFile,"\n\tNew pBlock\n\n");
1011 fprintf(pFile,"%s",pb->cmemmap->sname);
1013 fprintf(pFile,"internal pblock");
1015 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1016 printpBlock(pFile,pb);
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;
1151 pcc->comment = Safe_strdup(cP);
1153 return ( (pCode *)pcc);
1157 /*-----------------------------------------------------------------*/
1158 /* newpCodeGLabel - create a new global label */
1159 /*-----------------------------------------------------------------*/
1162 pCode *newpCodeFunction(char *mod,char *f)
1166 _ALLOC(pcf,sizeof(pCodeFunction));
1168 pcf->pc.type = PC_FUNCTION;
1169 pcf->pc.prev = pcf->pc.next = NULL;
1170 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1173 pcf->pc.analyze = genericAnalyze;
1174 pcf->pc.destruct = genericDestruct;
1175 pcf->pc.print = pCodePrintFunction;
1178 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1179 strcpy(pcf->modname,mod);
1181 pcf->modname = NULL;
1184 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1185 strcpy(pcf->fname,f);
1189 return ( (pCode *)pcf);
1193 static void pCodeLabelDestruct(pCode *pc)
1201 if((pc->type == PC_LABEL) && PCL(pc)->label)
1202 free(PCL(pc)->label);
1208 pCode *newpCodeLabel(int key)
1214 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1216 pcl->pc.type = PC_LABEL;
1217 pcl->pc.prev = pcl->pc.next = NULL;
1218 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1221 pcl->pc.analyze = genericAnalyze;
1222 pcl->pc.destruct = pCodeLabelDestruct;
1223 pcl->pc.print = pCodePrintLabel;
1228 sprintf(s,"_%05d_DS_",key);
1229 pcl->label = Safe_strdup(s);
1233 return ( (pCode *)pcl);
1236 pCode *newpCodeLabelStr(char *str)
1238 pCode *pc = newpCodeLabel(-1);
1240 PCL(pc)->label = Safe_strdup(str);
1245 /*-----------------------------------------------------------------*/
1246 /* newpBlock - create and return a pointer to a new pBlock */
1247 /*-----------------------------------------------------------------*/
1248 pBlock *newpBlock(void)
1253 PpB = Safe_calloc(1,sizeof(pBlock) );
1254 PpB->next = PpB->prev = NULL;
1256 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1257 PpB->registers = NULL;
1264 /*-----------------------------------------------------------------*/
1265 /* newpCodeChai0n - create a new chain of pCodes */
1266 /*-----------------------------------------------------------------*
1268 * This function will create a new pBlock and the pointer to the
1269 * pCode that is passed in will be the first pCode in the block.
1270 *-----------------------------------------------------------------*/
1273 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1276 pBlock *pB = newpBlock();
1278 pB->pcHead = pB->pcTail = pc;
1285 /*-----------------------------------------------------------------*/
1286 /* newpCodeOpLabel - Create a new label given the key */
1287 /* Note, a negative key means that the label is part of wild card */
1288 /* (and hence a wild card label) used in the pCodePeep */
1289 /* optimizations). */
1290 /*-----------------------------------------------------------------*/
1292 pCodeOp *newpCodeOpLabel(int key)
1297 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1298 pcop->type = PO_LABEL;
1301 sprintf(s,"_%05d_DS_",key);
1302 pcop->name = Safe_strdup(s);
1306 ((pCodeOpLabel *)pcop)->key = key;
1311 pCodeOp *newpCodeOpLit(int lit)
1317 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1318 pcop->type = PO_LITERAL;
1320 sprintf(s,"0x%02x",lit);
1321 pcop->name = Safe_strdup(s);
1325 ((pCodeOpLit *)pcop)->lit = lit;
1330 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1336 if(!pcp || !subtype) {
1337 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1341 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1342 pcop->type = PO_WILD;
1343 sprintf(s,"%%%d",id);
1344 pcop->name = Safe_strdup(s);
1346 PCOW(pcop)->id = id;
1347 PCOW(pcop)->pcp = pcp;
1348 PCOW(pcop)->subtype = subtype;
1349 PCOW(pcop)->matched = NULL;
1354 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1358 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1359 pcop->type = PO_BIT;
1360 pcop->name = Safe_strdup(s);
1362 PCOB(pcop)->bit = bit;
1363 PCOB(pcop)->inBitSpace = inBitSpace;
1368 pCodeOp *newpCodeOpReg(int rIdx)
1372 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1374 PCOR(pcop)->rIdx = rIdx;
1375 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1376 pcop->type = PCOR(pcop)->r->pc_type;
1381 /*-----------------------------------------------------------------*/
1382 /*-----------------------------------------------------------------*/
1384 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1390 pcop = newpCodeOpBit(name, -1,0);
1394 pcop = newpCodeOpLit(-1);
1398 pcop = newpCodeOpLabel(-1);
1402 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1404 pcop->name = Safe_strdup(name);
1410 /*-----------------------------------------------------------------*/
1411 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1412 /*-----------------------------------------------------------------*/
1413 void addpCode2pBlock(pBlock *pb, pCode *pc)
1416 /* If this is the first pcode to be added to a block that
1417 * was initialized with a NULL pcode, then go ahead and
1418 * make this pcode the head and tail */
1419 pb->pcHead = pb->pcTail = pc;
1421 pb->pcTail->next = pc;
1422 pc->prev = pb->pcTail;
1429 /*-----------------------------------------------------------------*/
1430 /* addpBlock - place a pBlock into the pFile */
1431 /*-----------------------------------------------------------------*/
1432 void addpBlock(pBlock *pb)
1436 /* First time called, we'll pass through here. */
1437 _ALLOC(the_pFile,sizeof(the_pFile));
1438 the_pFile->pbHead = the_pFile->pbTail = pb;
1439 the_pFile->functions = NULL;
1443 the_pFile->pbTail->next = pb;
1444 pb->prev = the_pFile->pbTail;
1446 the_pFile->pbTail = pb;
1449 /*-----------------------------------------------------------------*/
1450 /* printpCode - write the contents of a pCode to a file */
1451 /*-----------------------------------------------------------------*/
1452 void printpCode(FILE *of, pCode *pc)
1463 fprintf(of,"warning - unable to print pCode\n");
1466 /*-----------------------------------------------------------------*/
1467 /* printpBlock - write the contents of a pBlock to a file */
1468 /*-----------------------------------------------------------------*/
1469 void printpBlock(FILE *of, pBlock *pb)
1479 for(pc = pb->pcHead; pc; pc = pc->next)
1484 /*-----------------------------------------------------------------*/
1486 /* pCode processing */
1490 /*-----------------------------------------------------------------*/
1492 static void unlinkPC(pCode *pc)
1499 pc->prev->next = pc->next;
1501 pc->next->prev = pc->prev;
1503 pc->prev = pc->next = NULL;
1506 static void genericDestruct(pCode *pc)
1508 fprintf(stderr,"warning, calling default pCode destructor\n");
1517 void pBlockRegs(FILE *of, pBlock *pb)
1522 r = setFirstItem(pb->registers);
1524 r = setNextItem(pb->registers);
1529 static char *get_op( pCodeInstruction *pcc)
1533 if(pcc && pcc->pcop) {
1536 switch(pcc->pcop->type) {
1541 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1542 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1543 pBlockRegs(stderr,pcc->pc.pb);
1547 if (pcc->pcop->name)
1548 return pcc->pcop->name;
1553 return "NO operand";
1556 /*-----------------------------------------------------------------*/
1557 /*-----------------------------------------------------------------*/
1558 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1561 fprintf(of,"pcodeopprint\n");
1564 char *pCode2str(char *str, int size, pCode *pc)
1572 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1574 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1576 if(PCI(pc)->bit_inst) {
1577 if(PCI(pc)->pcop->type == PO_BIT) {
1578 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1579 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1580 PCI(pc)->pcop->name ,
1581 PCI(pc)->pcop->name );
1583 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1584 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1585 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1586 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1588 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1589 //PCI(pc)->pcop->t.bit );
1592 if(PCI(pc)->pcop->type == PO_BIT) {
1593 if( PCI(pc)->num_ops == 2)
1594 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1596 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1599 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1601 if( PCI(pc)->num_ops == 2)
1602 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1610 /* assuming that comment ends with a \n */
1611 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1615 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1618 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1621 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1630 /*-----------------------------------------------------------------*/
1631 /* genericPrint - the contents of a pCode to a file */
1632 /*-----------------------------------------------------------------*/
1633 static void genericPrint(FILE *of, pCode *pc)
1641 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1645 // If the opcode has a label, print that first
1647 pBranch *pbl = pc->label;
1649 if(pbl->pc->type == PC_LABEL)
1650 pCodePrintLabel(of, pbl->pc);
1659 pCode2str(str, 256, pc);
1661 fprintf(of,"%s",str);
1665 pBranch *dpb = pc->to; // debug
1667 switch ( dpb->pc->type) {
1669 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1672 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1675 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1689 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1691 pCodePrintLabel(of, pc->label->pc);
1693 if(PCW(pc)->operand) {
1694 fprintf(of,";\toperand ");
1695 pCodeOpPrint(of,PCW(pc)->operand );
1701 fprintf(of,"unknown pCode type %d\n",pc->type);
1706 /*-----------------------------------------------------------------*/
1707 /* pCodePrintFunction - prints function begin/end */
1708 /*-----------------------------------------------------------------*/
1710 static void pCodePrintFunction(FILE *of, pCode *pc)
1716 if( ((pCodeFunction *)pc)->modname)
1717 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1719 if(PCF(pc)->fname) {
1720 pBranch *exits = pc->to;
1722 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1725 exits = exits->next;
1728 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1732 pc->from->pc->type == PC_FUNCTION &&
1733 PCF(pc->from->pc)->fname)
1734 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1736 fprintf(of,"; exit point [can't find entry point]\n");
1739 /*-----------------------------------------------------------------*/
1740 /* pCodePrintLabel - prints label */
1741 /*-----------------------------------------------------------------*/
1743 static void pCodePrintLabel(FILE *of, pCode *pc)
1750 fprintf(of,"%s\n",PCL(pc)->label);
1751 else if (PCL(pc)->key >=0)
1752 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1754 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1757 /*-----------------------------------------------------------------*/
1758 static void unlinkpCodeFromBranch(pBranch *pb , pCode *pc)
1767 bprev->next = b->next;
1775 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1791 /*-----------------------------------------------------------------*/
1792 /* pBranchLink - given two pcodes, this function will link them */
1793 /* together through their pBranches */
1794 /*-----------------------------------------------------------------*/
1795 static void pBranchLink(pCode *f, pCode *t)
1799 // Declare a new branch object for the 'from' pCode.
1801 _ALLOC(b,sizeof(pBranch));
1802 b->pc = t; // The link to the 'to' pCode.
1805 f->to = pBranchAppend(f->to,b);
1807 // Now do the same for the 'to' pCode.
1809 _ALLOC(b,sizeof(pBranch));
1813 t->from = pBranchAppend(t->from,b);
1818 /*-----------------------------------------------------------------*/
1819 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1821 /*-----------------------------------------------------------------*/
1822 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1835 /*-----------------------------------------------------------------*/
1836 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1837 /*-----------------------------------------------------------------*/
1838 static void pCodeUnlink(pCode *pc)
1843 if(!pc->prev || !pc->next) {
1844 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1848 /* first remove the pCode from the chain */
1849 pc->prev->next = pc->next;
1850 pc->next->prev = pc->prev;
1852 /* Now for the hard part... */
1854 /* Remove the branches */
1858 pc1 = pb1->pc; /* Get the pCode that branches to the
1859 * one we're unlinking */
1861 /* search for the link back to this pCode (the one we're
1863 if(pb2 = pBranchFind(pc1->to,pc)) {
1864 pb2->pc = pc->to->pc; // make the replacement
1866 /* if the pCode we're unlinking contains multiple 'to'
1867 * branches (e.g. this a skip instruction) then we need
1868 * to copy these extra branches to the chain. */
1870 pBranchAppend(pb2, pc->to->next);
1879 /*-----------------------------------------------------------------*/
1880 /*-----------------------------------------------------------------*/
1881 static void genericAnalyze(pCode *pc)
1891 // Go through the pCodes that are in pCode chain and link
1892 // them together through the pBranches. Note, the pCodes
1893 // are linked together as a contiguous stream like the
1894 // assembly source code lines. The linking here mimics this
1895 // except that comments are not linked in.
1897 pCode *npc = pc->next;
1899 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1900 pBranchLink(pc,npc);
1909 /*-----------------------------------------------------------------*/
1910 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1914 if(pc->type == PC_LABEL) {
1915 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1918 if(pc->type == PC_OPCODE) {
1921 if(pbr->pc->type == PC_LABEL) {
1922 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1932 /*-----------------------------------------------------------------*/
1933 /* findLabel - Search the pCode for a particular label */
1934 /*-----------------------------------------------------------------*/
1935 pCode * findLabel(pCodeOpLabel *pcop_label)
1943 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1944 for(pc = pb->pcHead; pc; pc = pc->next)
1945 if(compareLabel(pc,pcop_label))
1950 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1954 /*-----------------------------------------------------------------*/
1955 /* findNextInstruction - given a pCode, find the next instruction */
1956 /* in the linked list */
1957 /*-----------------------------------------------------------------*/
1958 pCode * findNextInstruction(pCode *pc)
1962 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1968 fprintf(stderr,"Couldn't find instruction\n");
1972 /*-----------------------------------------------------------------*/
1973 /* findFunctionEnd - given a pCode find the end of the function */
1974 /* that contains it t */
1975 /*-----------------------------------------------------------------*/
1976 pCode * findFunctionEnd(pCode *pc)
1980 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1986 fprintf(stderr,"Couldn't find function end\n");
1991 /*-----------------------------------------------------------------*/
1992 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1993 /* instruction with which it is associated. */
1994 /*-----------------------------------------------------------------*/
1995 static void AnalyzeLabel(pCode *pc)
2003 static void AnalyzeGOTO(pCode *pc)
2006 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2010 static void AnalyzeSKIP(pCode *pc)
2013 pBranchLink(pc,findNextInstruction(pc->next));
2014 pBranchLink(pc,findNextInstruction(pc->next->next));
2018 static void AnalyzeRETURN(pCode *pc)
2021 // branch_link(pc,findFunctionEnd(pc->next));
2026 void AnalyzepBlock(pBlock *pb)
2033 /* Find all of the registers used in this pBlock */
2034 for(pc = pb->pcHead; pc; pc = pc->next) {
2035 if(pc->type == PC_OPCODE) {
2036 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2038 /* Loop through all of the registers declared so far in
2039 this block and see if we find this new there */
2041 regs *r = setFirstItem(pb->registers);
2044 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2045 PCOR(PCI(pc)->pcop)->r = r;
2048 r = setNextItem(pb->registers);
2052 /* register wasn't found */
2053 r = Safe_calloc(1, sizeof(regs));
2054 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2055 addSet(&pb->registers, r);
2056 PCOR(PCI(pc)->pcop)->r = r;
2057 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2059 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2065 int OptimizepBlock(pBlock *pb)
2070 if(!pb || !peepOptimizing)
2073 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2074 for(pc = pb->pcHead; pc; pc = pc->next)
2075 matches += pCodePeepMatchRule(pc);
2081 /*-----------------------------------------------------------------*/
2082 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2083 /*-----------------------------------------------------------------*/
2084 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2088 for(pc = pcs; pc; pc = pc->next) {
2090 if((pc->type == PC_OPCODE) &&
2092 (PCI(pc)->pcop->type == PO_LABEL) &&
2093 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2101 /*-----------------------------------------------------------------*/
2102 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2103 /* pCode chain if they're not used. */
2104 /*-----------------------------------------------------------------*/
2105 void pBlockRemoveUnusedLabels(pBlock *pb)
2107 pCode *pc; pCodeLabel *pcl;
2112 for(pc = pb->pcHead; pc; pc = pc->next) {
2114 if(pc->type == PC_LABEL)
2117 pcl = PCL(pc->label->pc);
2120 /* This pCode is a label, so search the pBlock to see if anyone
2123 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2124 /* Couldn't find an instruction that refers to this label
2125 * So, unlink the pCode label from it's pCode chain
2126 * and destroy the label */
2128 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2130 if(pc->type == PC_LABEL) {
2132 pCodeLabelDestruct(pc);
2134 unlinkpCodeFromBranch(pc->label, pc);
2135 if(pc->label->next == NULL && pc->label->pc == NULL) {
2146 /*-----------------------------------------------------------------*/
2147 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2148 /* chain and put them into pBranches that are */
2149 /* associated with the appropriate pCode */
2151 /*-----------------------------------------------------------------*/
2152 void pBlockMergeLabels(pBlock *pb)
2155 pCode *pc, *pcnext=NULL;
2160 /* First, Try to remove any unused labels */
2161 //pBlockRemoveUnusedLabels(pb);
2163 /* Now loop through the pBlock and merge the labels with the opcodes */
2165 for(pc = pb->pcHead; pc; pc = pc->next) {
2167 if(pc->type == PC_LABEL) {
2168 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2169 if( !(pcnext = findNextInstruction(pc)) )
2170 return; // Couldn't find an instruction associated with this label
2172 // Unlink the pCode label from it's pCode chain
2175 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2176 // And link it into the instruction's pBranch labels. (Note, since
2177 // it's possible to have multiple labels associated with one instruction
2178 // we must provide a means to accomodate the additional labels. Thus
2179 // the labels are placed into the singly-linked list "label" as
2180 // opposed to being a single member of the pCodeInstruction.)
2182 _ALLOC(pbr,sizeof(pBranch));
2186 pcnext->label = pBranchAppend(pcnext->label,pbr);
2194 pBlockRemoveUnusedLabels(pb);
2198 /*-----------------------------------------------------------------*/
2199 /*-----------------------------------------------------------------*/
2200 void OptimizepCode(char dbName)
2202 #define MAX_PASSES 4
2211 fprintf(stderr," Optimizing pCode\n");
2214 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2215 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2216 matches += OptimizepBlock(pb);
2219 while(matches && ++passes < MAX_PASSES);
2223 /*-----------------------------------------------------------------*/
2224 /* AnalyzepCode - parse the pCode that has been generated and form */
2225 /* all of the logical connections. */
2227 /* Essentially what's done here is that the pCode flow is */
2229 /*-----------------------------------------------------------------*/
2231 void AnalyzepCode(char dbName)
2240 fprintf(stderr," Analyzing pCode");
2242 /* First, merge the labels with the instructions */
2243 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2244 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2246 fprintf(stderr," analyze and merging block %c\n",dbName);
2247 pBlockMergeLabels(pb);
2252 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2253 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2257 /* Now build the call tree.
2258 First we examine all of the pCodes for functions.
2259 Keep in mind that the function boundaries coincide
2260 with pBlock boundaries.
2262 The algorithm goes something like this:
2263 We have two nested loops. The outer loop iterates
2264 through all of the pBlocks/functions. The inner
2265 loop iterates through all of the pCodes for
2266 a given pBlock. When we begin iterating through
2267 a pBlock, the variable pc_fstart, pCode of the start
2268 of a function, is cleared. We then search for pCodes
2269 of type PC_FUNCTION. When one is encountered, we
2270 initialize pc_fstart to this and at the same time
2271 associate a new pBranch object that signifies a
2272 branch entry. If a return is found, then this signifies
2273 a function exit point. We'll link the pCodes of these
2274 returns to the matching pc_fstart.
2276 When we're done, a doubly linked list of pBranches
2277 will exist. The head of this list is stored in
2278 `the_pFile', which is the meta structure for all
2279 of the pCode. Look at the printCallTree function
2280 on how the pBranches are linked together.
2283 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2284 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2285 pCode *pc_fstart=NULL;
2286 for(pc = pb->pcHead; pc; pc = pc->next) {
2287 if(pc->type == PC_FUNCTION) {
2288 if (PCF(pc)->fname) {
2289 // I'm not liking this....
2290 // Found the beginning of a function.
2291 _ALLOC(pbr,sizeof(pBranch));
2292 pbr->pc = pc_fstart = pc;
2295 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2297 // Here's a better way of doing the same:
2298 addSet(&pb->function_entries, pc);
2301 // Found an exit point in a function, e.g. return
2302 // (Note, there may be more than one return per function)
2304 pBranchLink(pc_fstart, pc);
2306 addSet(&pb->function_exits, pc);
2308 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2309 addSet(&pb->function_calls,pc);
2316 /*-----------------------------------------------------------------*/
2317 /* ispCodeFunction - returns true if *pc is the pCode of a */
2319 /*-----------------------------------------------------------------*/
2320 bool ispCodeFunction(pCode *pc)
2323 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2329 /*-----------------------------------------------------------------*/
2330 /* findFunction - Search for a function by name (given the name) */
2331 /* in the set of all functions that are in a pBlock */
2332 /* (note - I expect this to change because I'm planning to limit */
2333 /* pBlock's to just one function declaration */
2334 /*-----------------------------------------------------------------*/
2335 pCode *findFunction(char *fname)
2342 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2344 pc = setFirstItem(pb->function_entries);
2347 if((pc->type == PC_FUNCTION) &&
2349 (strcmp(fname, PCF(pc)->fname)==0))
2352 pc = setNextItem(pb->function_entries);
2360 void MarkUsedRegisters(set *regset)
2365 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2366 r2 = pic14_regWithIdx(r1->rIdx);
2372 void pBlockStats(FILE *of, pBlock *pb)
2378 fprintf(of,"***\n pBlock Stats\n***\n");
2380 // for now just print the first element of each set
2381 pc = setFirstItem(pb->function_entries);
2383 fprintf(of,"entry\n");
2386 pc = setFirstItem(pb->function_exits);
2388 fprintf(of,"has an exit\n");
2392 pc = setFirstItem(pb->function_calls);
2394 fprintf(of,"functions called\n");
2398 pc = setNextItem(pb->function_calls);
2402 r = setFirstItem(pb->registers);
2404 int n = elementsInSet(pb->registers);
2406 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2409 fprintf(of," %s\n",r->name);
2410 r = setNextItem(pb->registers);
2415 /*-----------------------------------------------------------------*/
2416 /*-----------------------------------------------------------------*/
2417 void sequencepCode(void)
2423 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2425 pb->seq = GpCodeSequenceNumber+1;
2427 for( pc = pb->pcHead; pc; pc = pc->next)
2428 pc->seq = ++GpCodeSequenceNumber;
2433 /*-----------------------------------------------------------------*/
2434 /*-----------------------------------------------------------------*/
2435 set *register_usage(pBlock *pb)
2438 set *registers=NULL;
2439 set *registersInCallPath = NULL;
2441 /* check recursion */
2443 pc = setFirstItem(pb->function_entries);
2450 if(pc->type != PC_FUNCTION)
2451 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2453 pc = setFirstItem(pb->function_calls);
2454 for( ; pc; pc = setNextItem(pb->function_calls)) {
2456 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2457 char *dest = get_op(PCI(pc));
2459 pcn = findFunction(dest);
2461 registersInCallPath = register_usage(pcn->pb);
2463 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2468 pBlockStats(stderr,pb); // debug
2469 if(registersInCallPath) {
2470 /* registers were used in the functions this pBlock has called */
2471 /* so now, we need to see if these collide with the ones we are */
2474 regs *r1,*r2, *newreg;
2476 fprintf(stderr,"comparing registers\n");
2478 r1 = setFirstItem(registersInCallPath);
2481 r2 = setFirstItem(pb->registers);
2485 if(r2->rIdx == r1->rIdx) {
2486 newreg = pic14_findFreeReg();
2490 fprintf(stderr,"Bummer, no more registers.\n");
2494 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2495 r1->rIdx, newreg->rIdx);
2496 r2->rIdx = newreg->rIdx;
2497 //if(r2->name) free(r2->name);
2498 r2->name = Safe_strdup(newreg->name);
2500 newreg->wasUsed = 1;
2502 r2 = setNextItem(pb->registers);
2505 r1 = setNextItem(registersInCallPath);
2508 /* Collisions have been resolved. Now free the registers in the call path */
2509 r1 = setFirstItem(registersInCallPath);
2511 newreg = pic14_regWithIdx(r1->rIdx);
2513 r1 = setNextItem(registersInCallPath);
2517 MarkUsedRegisters(pb->registers);
2519 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2522 fprintf(stderr,"returning regs\n");
2524 fprintf(stderr,"not returning regs\n");
2526 fprintf(stderr,"pBlock after register optim.\n");
2527 pBlockStats(stderr,pb); // debug
2533 /*-----------------------------------------------------------------*/
2534 /* printCallTree - writes the call tree to a file */
2536 /*-----------------------------------------------------------------*/
2537 void pct2(FILE *of,pBlock *pb,int indent)
2541 // set *registersInCallPath = NULL;
2544 return;// registers;
2547 return; // registers; //recursion ?
2549 pc = setFirstItem(pb->function_entries);
2556 for(i=0;i<indent;i++) // Indentation
2559 if(pc->type == PC_FUNCTION)
2560 fprintf(of,"%s\n",PCF(pc)->fname);
2565 pc = setFirstItem(pb->function_calls);
2566 for( ; pc; pc = setNextItem(pb->function_calls)) {
2568 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2569 char *dest = get_op(PCI(pc));
2571 pcn = findFunction(dest);
2573 pct2(of,pcn->pb,indent+1);
2575 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2583 fprintf(stderr,"pBlock before register optim.\n");
2584 pBlockStats(stderr,pb); // debug
2586 if(registersInCallPath) {
2587 /* registers were used in the functions this pBlock has called */
2588 /* so now, we need to see if these collide with the ones we are using here */
2590 regs *r1,*r2, *newreg;
2592 fprintf(stderr,"comparing registers\n");
2594 r1 = setFirstItem(registersInCallPath);
2597 r2 = setFirstItem(pb->registers);
2601 if(r2->rIdx == r1->rIdx) {
2602 newreg = pic14_findFreeReg();
2606 fprintf(stderr,"Bummer, no more registers.\n");
2610 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2611 r1->rIdx, newreg->rIdx);
2612 r2->rIdx = newreg->rIdx;
2613 //if(r2->name) free(r2->name);
2614 r2->name = Safe_strdup(newreg->name);
2616 newreg->wasUsed = 1;
2618 r2 = setNextItem(pb->registers);
2621 r1 = setNextItem(registersInCallPath);
2624 /* Collisions have been resolved. Now free the registers in the call path */
2625 r1 = setFirstItem(registersInCallPath);
2627 newreg = pic14_regWithIdx(r1->rIdx);
2629 r1 = setNextItem(registersInCallPath);
2633 MarkUsedRegisters(pb->registers);
2635 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2638 fprintf(stderr,"returning regs\n");
2640 fprintf(stderr,"not returning regs\n");
2642 fprintf(stderr,"pBlock after register optim.\n");
2643 pBlockStats(stderr,pb); // debug
2651 /*-----------------------------------------------------------------*/
2652 /* printCallTree - writes the call tree to a file */
2654 /*-----------------------------------------------------------------*/
2656 void printCallTree(FILE *of)
2668 fprintf(of, "\npBlock statistics\n");
2669 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2670 pBlockStats(stderr,pb);
2674 fprintf(of,"Call Tree\n");
2675 pbr = the_pFile->functions;
2679 if(!ispCodeFunction(pc))
2680 fprintf(of,"bug in call tree");
2683 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2685 while(pc->next && !ispCodeFunction(pc->next)) {
2687 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2688 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2696 /* Re-allocate the registers so that there are no collisions
2697 * between local variables when one function call another */
2699 pic14_deallocateAllRegs();
2701 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2706 fprintf(of,"\n**************\n\na better call tree\n");
2707 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2712 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2713 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));