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 = 0;
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);
73 void pBlockStats(FILE *of, pBlock *pb);
76 pCodeInstruction pciADDWF = {
77 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
85 1,0, // dest, bit instruction
86 (PCC_W | PCC_REGISTER), // inCond
87 (PCC_REGISTER | PCC_Z) // outCond
90 pCodeInstruction pciADDFW = {
91 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
99 0,0, // dest, bit instruction
100 (PCC_W | PCC_REGISTER), // inCond
101 (PCC_W | PCC_Z) // outCond
104 pCodeInstruction pciADDLW = {
105 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
113 0,0, // dest, bit instruction
115 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
118 pCodeInstruction pciANDLW = {
119 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
127 0,0, // dest, bit instruction
129 (PCC_W | PCC_Z) // outCond
132 pCodeInstruction pciANDWF = {
133 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
141 1,0, // dest, bit instruction
142 (PCC_W | PCC_REGISTER), // inCond
143 (PCC_REGISTER | PCC_Z) // outCond
146 pCodeInstruction pciANDFW = {
147 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
155 0,0, // dest, bit instruction
156 (PCC_W | PCC_REGISTER), // inCond
157 (PCC_W | PCC_Z) // outCond
160 pCodeInstruction pciBCF = {
161 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
169 0,1, // dest, bit instruction
171 PCC_EXAMINE_PCOP // outCond
174 pCodeInstruction pciBSF = {
175 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
183 0,1, // dest, bit instruction
185 PCC_EXAMINE_PCOP // outCond
188 pCodeInstruction pciBTFSC = {
189 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
197 0,1, // dest, bit instruction
198 PCC_EXAMINE_PCOP, // inCond
202 pCodeInstruction pciBTFSS = {
203 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
211 0,1, // dest, bit instruction
212 PCC_EXAMINE_PCOP, // inCond
216 pCodeInstruction pciCALL = {
217 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
225 0,0, // dest, bit instruction
230 pCodeInstruction pciCOMF = {
231 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
239 1,0, // dest, bit instruction
240 PCC_REGISTER, // inCond
241 PCC_REGISTER // outCond
244 pCodeInstruction pciCOMFW = {
245 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
253 0,0, // dest, bit instruction
254 PCC_REGISTER, // inCond
258 pCodeInstruction pciCLRF = {
259 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
267 0,0, // dest, bit instruction
268 PCC_REGISTER, // inCond
269 PCC_REGISTER // outCond
272 pCodeInstruction pciCLRW = {
273 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
281 0,0, // dest, bit instruction
286 pCodeInstruction pciDECF = {
287 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
295 1,0, // dest, bit instruction
296 PCC_REGISTER, // inCond
297 PCC_REGISTER // outCond
300 pCodeInstruction pciDECFW = {
301 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
309 0,0, // dest, bit instruction
310 PCC_REGISTER, // inCond
314 pCodeInstruction pciDECFSZ = {
315 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
323 1,0, // dest, bit instruction
324 PCC_REGISTER, // inCond
325 PCC_REGISTER // outCond
328 pCodeInstruction pciDECFSZW = {
329 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
337 0,0, // dest, bit instruction
338 PCC_REGISTER, // inCond
342 pCodeInstruction pciGOTO = {
343 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
351 0,0, // dest, bit instruction
357 pCodeInstruction pciINCF = {
358 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
366 1,0, // dest, bit instruction
367 PCC_REGISTER, // inCond
368 PCC_REGISTER // outCond
371 pCodeInstruction pciINCFW = {
372 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
380 0,0, // dest, bit instruction
381 PCC_REGISTER, // inCond
385 pCodeInstruction pciINCFSZ = {
386 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
394 1,0, // dest, bit instruction
395 PCC_REGISTER, // inCond
396 PCC_REGISTER // outCond
399 pCodeInstruction pciINCFSZW = {
400 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
408 0,0, // dest, bit instruction
409 PCC_REGISTER, // inCond
413 pCodeInstruction pciIORWF = {
414 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
422 1,0, // dest, bit instruction
423 (PCC_W | PCC_REGISTER), // inCond
424 (PCC_REGISTER | PCC_Z) // outCond
427 pCodeInstruction pciIORFW = {
428 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
436 0,0, // dest, bit instruction
437 (PCC_W | PCC_REGISTER), // inCond
438 (PCC_W | PCC_Z) // outCond
441 pCodeInstruction pciIORLW = {
442 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
450 0,0, // dest, bit instruction
452 (PCC_W | PCC_Z) // outCond
455 pCodeInstruction pciMOVF = {
456 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
464 1,0, // dest, bit instruction
465 PCC_REGISTER, // inCond
469 pCodeInstruction pciMOVFW = {
470 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
478 0,0, // dest, bit instruction
479 PCC_REGISTER, // inCond
480 (PCC_W | PCC_Z) // outCond
483 pCodeInstruction pciMOVWF = {
484 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
492 0,0, // dest, bit instruction
497 pCodeInstruction pciMOVLW = {
498 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
506 0,0, // dest, bit instruction
511 pCodeInstruction pciNEGF = {
512 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
520 0,0, // dest, bit instruction
521 PCC_REGISTER, // inCond
526 pCodeInstruction pciRETLW = {
527 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
535 0,0, // dest, bit instruction
540 pCodeInstruction pciRETURN = {
541 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
549 0,0, // dest, bit instruction
555 pCodeInstruction pciRLF = {
556 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
564 1,0, // dest, bit instruction
565 (PCC_C | PCC_REGISTER), // inCond
566 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
569 pCodeInstruction pciRLFW = {
570 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
578 0,0, // dest, bit instruction
579 (PCC_C | PCC_REGISTER), // inCond
580 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
583 pCodeInstruction pciRRF = {
584 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
592 1,0, // dest, bit instruction
593 (PCC_C | PCC_REGISTER), // inCond
594 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
597 pCodeInstruction pciRRFW = {
598 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
606 0,0, // dest, bit instruction
607 (PCC_C | PCC_REGISTER), // inCond
608 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
611 pCodeInstruction pciSUBWF = {
612 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
620 1,0, // dest, bit instruction
621 (PCC_W | PCC_REGISTER), // inCond
622 (PCC_REGISTER | PCC_Z) // outCond
625 pCodeInstruction pciSUBFW = {
626 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
634 0,0, // dest, bit instruction
635 (PCC_W | PCC_REGISTER), // inCond
636 (PCC_W | PCC_Z) // outCond
639 pCodeInstruction pciSUBLW = {
640 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
648 0,0, // dest, bit instruction
650 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
653 pCodeInstruction pciSWAPF = {
654 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
662 1,0, // dest, bit instruction
663 (PCC_REGISTER), // inCond
664 (PCC_REGISTER) // outCond
667 pCodeInstruction pciSWAPFW = {
668 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
676 0,0, // dest, bit instruction
677 (PCC_REGISTER), // inCond
680 pCodeInstruction pciTRIS = {
681 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
689 0,0, // dest, bit instruction
695 pCodeInstruction pciXORWF = {
696 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
704 1,0, // dest, bit instruction
705 (PCC_W | PCC_REGISTER), // inCond
706 (PCC_REGISTER | PCC_Z) // outCond
709 pCodeInstruction pciXORFW = {
710 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
718 0,0, // dest, bit instruction
719 (PCC_W | PCC_REGISTER), // inCond
720 (PCC_W | PCC_Z) // outCond
723 pCodeInstruction pciXORLW = {
724 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
732 0,0, // dest, bit instruction
734 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
738 #define MAX_PIC14MNEMONICS 100
739 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
741 /*-----------------------------------------------------------------*/
742 /* SAFE_snprintf - like snprintf except the string pointer is */
743 /* after the string has been printed to. This is */
744 /* useful for printing to string as though if it */
746 /*-----------------------------------------------------------------*/
747 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
755 va_start(val, format);
757 // Alas, vsnprintf is not ANSI standard, and does not exist
758 // on Solaris (and probably other non-Gnu flavored Unixes).
759 vsnprintf(*str, *size, format, val);
761 // This, of course, is *not* safe, despite the name.
762 vsprintf(*str, format, val);
773 void pCodeInitRegisters(void)
777 pc_fsr.r = pic14_regWithIdx(4);
780 pc_indf.r = pic14_regWithIdx(0);
784 /*-----------------------------------------------------------------*/
785 /* mnem2key - convert a pic mnemonic into a hash key */
786 /* (BTW - this spreads the mnemonics quite well) */
788 /*-----------------------------------------------------------------*/
790 int mnem2key(char const *mnem)
799 key += toupper(*mnem++) +1;
807 void pic14initMnemonics(void)
812 pCodeInstruction *pci;
814 if(mnemonics_initialized)
817 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
818 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
819 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
820 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
821 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
822 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
823 pic14Mnemonics[POC_BCF] = &pciBCF;
824 pic14Mnemonics[POC_BSF] = &pciBSF;
825 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
826 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
827 pic14Mnemonics[POC_CALL] = &pciCALL;
828 pic14Mnemonics[POC_COMF] = &pciCOMF;
829 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
830 pic14Mnemonics[POC_CLRF] = &pciCLRF;
831 pic14Mnemonics[POC_CLRW] = &pciCLRW;
832 pic14Mnemonics[POC_DECF] = &pciDECF;
833 pic14Mnemonics[POC_DECFW] = &pciDECFW;
834 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
835 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
836 pic14Mnemonics[POC_GOTO] = &pciGOTO;
837 pic14Mnemonics[POC_INCF] = &pciINCF;
838 pic14Mnemonics[POC_INCFW] = &pciINCFW;
839 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
840 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
841 pic14Mnemonics[POC_IORLW] = &pciIORLW;
842 pic14Mnemonics[POC_IORWF] = &pciIORWF;
843 pic14Mnemonics[POC_IORFW] = &pciIORFW;
844 pic14Mnemonics[POC_MOVF] = &pciMOVF;
845 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
846 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
847 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
848 pic14Mnemonics[POC_NEGF] = &pciNEGF;
849 pic14Mnemonics[POC_RETLW] = &pciRETLW;
850 pic14Mnemonics[POC_RETURN] = &pciRETURN;
851 pic14Mnemonics[POC_RLF] = &pciRLF;
852 pic14Mnemonics[POC_RLFW] = &pciRLFW;
853 pic14Mnemonics[POC_RRF] = &pciRRF;
854 pic14Mnemonics[POC_RRFW] = &pciRRFW;
855 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
856 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
857 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
858 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
859 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
860 pic14Mnemonics[POC_TRIS] = &pciTRIS;
861 pic14Mnemonics[POC_XORLW] = &pciXORLW;
862 pic14Mnemonics[POC_XORWF] = &pciXORWF;
863 pic14Mnemonics[POC_XORFW] = &pciXORFW;
865 for(i=0; i<MAX_PIC14MNEMONICS; i++)
866 if(pic14Mnemonics[i])
867 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
868 pci = hTabFirstItem(pic14MnemonicsHash, &key);
871 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
872 pci = hTabNextItem(pic14MnemonicsHash, &key);
875 mnemonics_initialized = 1;
878 int getpCode(char *mnem,unsigned dest)
881 pCodeInstruction *pci;
882 int key = mnem2key(mnem);
884 if(!mnemonics_initialized)
885 pic14initMnemonics();
887 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
891 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
892 if((pci->num_ops <= 1) || (pci->dest == dest))
896 pci = hTabNextItemWK (pic14MnemonicsHash);
903 char getpBlock_dbName(pBlock *pb)
909 return pb->cmemmap->dbName;
913 /*-----------------------------------------------------------------*/
914 /* movepBlock2Head - given the dbname of a pBlock, move all */
915 /* instances to the front of the doubly linked */
916 /* list of pBlocks */
917 /*-----------------------------------------------------------------*/
919 void movepBlock2Head(char dbName)
923 pb = the_pFile->pbHead;
927 if(getpBlock_dbName(pb) == dbName) {
928 pBlock *pbn = pb->next;
929 pb->next = the_pFile->pbHead;
930 the_pFile->pbHead->prev = pb;
931 the_pFile->pbHead = pb;
934 pb->prev->next = pbn;
936 // If the pBlock that we just moved was the last
937 // one in the link of all of the pBlocks, then we
938 // need to point the tail to the block just before
940 // Note: if pb->next is NULL, then pb must have
941 // been the last pBlock in the chain.
944 pbn->prev = pb->prev;
946 the_pFile->pbTail = pb->prev;
957 void copypCode(FILE *of, char dbName)
961 if(!of || !the_pFile)
964 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
965 if(getpBlock_dbName(pb) == dbName) {
972 void pcode_test(void)
975 printf("pcode is alive!\n");
985 /* create the file name */
986 strcpy(buffer,srcFileName);
989 if( !(pFile = fopen(buffer, "w" ))) {
990 werror(E_FILE_OPEN_ERR,buffer);
994 fprintf(pFile,"pcode dump\n\n");
996 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
997 fprintf(pFile,"\n\tNew pBlock\n\n");
999 fprintf(pFile,"%s",pb->cmemmap->sname);
1001 fprintf(pFile,"internal pblock");
1003 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1004 printpBlock(pFile,pb);
1008 /*-----------------------------------------------------------------*/
1009 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1010 /* ister, RegCond will return the bit being referenced. */
1012 /* fixme - why not just OR in the pcop bit field */
1013 /*-----------------------------------------------------------------*/
1015 static int RegCond(pCodeOp *pcop)
1021 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1022 switch(PCOB(pcop)->bit) {
1036 /*-----------------------------------------------------------------*/
1037 /* newpCode - create and return a newly initialized pCode */
1039 /* fixme - rename this */
1041 /* The purpose of this routine is to create a new Instruction */
1042 /* pCode. This is called by gen.c while the assembly code is being */
1046 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1047 /* (note that the op is analogous to but not the */
1048 /* same thing as the opcode of the instruction.) */
1049 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1052 /* a pointer to the new malloc'd pCode is returned. */
1056 /*-----------------------------------------------------------------*/
1057 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1059 pCodeInstruction *pci ;
1061 if(!mnemonics_initialized)
1062 pic14initMnemonics();
1064 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1066 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1067 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1070 if(pci->inCond == PCC_EXAMINE_PCOP)
1071 pci->inCond = RegCond(pcop);
1073 if(pci->outCond == PCC_EXAMINE_PCOP)
1074 pci->outCond = RegCond(pcop);
1076 return (pCode *)pci;
1079 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1085 /*-----------------------------------------------------------------*/
1086 /* newpCodeWild - create a "wild" as in wild card pCode */
1088 /* Wild pcodes are used during the peep hole optimizer to serve */
1089 /* as place holders for any instruction. When a snippet of code is */
1090 /* compared to a peep hole rule, the wild card opcode will match */
1091 /* any instruction. However, the optional operand and label are */
1092 /* additional qualifiers that must also be matched before the */
1093 /* line (of assembly code) is declared matched. Note that the */
1094 /* operand may be wild too. */
1096 /* Note, a wild instruction is specified just like a wild var: */
1097 /* %4 ; A wild instruction, */
1098 /* See the peeph.def file for additional examples */
1100 /*-----------------------------------------------------------------*/
1102 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1107 pcw = Safe_calloc(1,sizeof(pCodeWild));
1109 pcw->pc.type = PC_WILD;
1110 pcw->pc.prev = pcw->pc.next = NULL;
1111 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1114 pcw->pc.analyze = genericAnalyze;
1115 pcw->pc.destruct = genericDestruct;
1116 pcw->pc.print = genericPrint;
1118 pcw->id = pCodeID; // this is the 'n' in %n
1119 pcw->operand = optional_operand;
1120 pcw->label = optional_label;
1122 return ( (pCode *)pcw);
1126 /*-----------------------------------------------------------------*/
1127 /* newPcodeCharP - create a new pCode from a char string */
1128 /*-----------------------------------------------------------------*/
1130 pCode *newpCodeCharP(char *cP)
1135 pcc = Safe_calloc(1,sizeof(pCodeComment));
1137 pcc->pc.type = PC_COMMENT;
1138 pcc->pc.prev = pcc->pc.next = NULL;
1139 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1142 pcc->pc.analyze = genericAnalyze;
1143 pcc->pc.destruct = genericDestruct;
1144 pcc->pc.print = genericPrint;
1147 pcc->comment = Safe_strdup(cP);
1149 pcc->comment = NULL;
1151 return ( (pCode *)pcc);
1155 /*-----------------------------------------------------------------*/
1156 /* newpCodeGLabel - create a new global label */
1157 /*-----------------------------------------------------------------*/
1160 pCode *newpCodeFunction(char *mod,char *f)
1164 _ALLOC(pcf,sizeof(pCodeFunction));
1166 pcf->pc.type = PC_FUNCTION;
1167 pcf->pc.prev = pcf->pc.next = NULL;
1168 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1171 pcf->pc.analyze = genericAnalyze;
1172 pcf->pc.destruct = genericDestruct;
1173 pcf->pc.print = pCodePrintFunction;
1176 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1177 strcpy(pcf->modname,mod);
1179 pcf->modname = NULL;
1182 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1183 strcpy(pcf->fname,f);
1187 return ( (pCode *)pcf);
1191 /*-----------------------------------------------------------------*/
1192 /* pCodeLabelDestruct - free memory used by a label. */
1193 /*-----------------------------------------------------------------*/
1194 static void pCodeLabelDestruct(pCode *pc)
1200 if((pc->type == PC_LABEL) && PCL(pc)->label)
1201 free(PCL(pc)->label);
1207 pCode *newpCodeLabel(int key)
1213 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1215 pcl->pc.type = PC_LABEL;
1216 pcl->pc.prev = pcl->pc.next = NULL;
1217 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1220 pcl->pc.analyze = genericAnalyze;
1221 pcl->pc.destruct = pCodeLabelDestruct;
1222 pcl->pc.print = pCodePrintLabel;
1228 sprintf(s,"_%05d_DS_",key);
1230 pcl->label = Safe_strdup(s);
1234 return ( (pCode *)pcl);
1237 pCode *newpCodeLabelStr(char *str)
1239 pCode *pc = newpCodeLabel(-1);
1242 PCL(pc)->label = Safe_strdup(str);
1244 PCL(pc)->label = NULL;
1249 /*-----------------------------------------------------------------*/
1250 /* newpBlock - create and return a pointer to a new pBlock */
1251 /*-----------------------------------------------------------------*/
1252 pBlock *newpBlock(void)
1257 PpB = Safe_calloc(1,sizeof(pBlock) );
1258 PpB->next = PpB->prev = NULL;
1260 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1261 PpB->registers = NULL;
1268 /*-----------------------------------------------------------------*/
1269 /* newpCodeChain - create a new chain of pCodes */
1270 /*-----------------------------------------------------------------*
1272 * This function will create a new pBlock and the pointer to the
1273 * pCode that is passed in will be the first pCode in the block.
1274 *-----------------------------------------------------------------*/
1277 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1280 pBlock *pB = newpBlock();
1282 pB->pcHead = pB->pcTail = pc;
1289 /*-----------------------------------------------------------------*/
1290 /* newpCodeOpLabel - Create a new label given the key */
1291 /* Note, a negative key means that the label is part of wild card */
1292 /* (and hence a wild card label) used in the pCodePeep */
1293 /* optimizations). */
1294 /*-----------------------------------------------------------------*/
1296 pCodeOp *newpCodeOpLabel(int key)
1301 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1302 pcop->type = PO_LABEL;
1306 sprintf(s,"_%05d_DS_",key);
1308 pcop->name = Safe_strdup(s);
1312 ((pCodeOpLabel *)pcop)->key = key;
1317 /*-----------------------------------------------------------------*/
1318 /*-----------------------------------------------------------------*/
1319 pCodeOp *newpCodeOpLit(int lit)
1325 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1326 pcop->type = PO_LITERAL;
1329 sprintf(s,"0x%02x",lit);
1331 pcop->name = Safe_strdup(s);
1335 ((pCodeOpLit *)pcop)->lit = lit;
1340 /*-----------------------------------------------------------------*/
1341 /*-----------------------------------------------------------------*/
1342 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1348 if(!pcp || !subtype) {
1349 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1353 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1354 pcop->type = PO_WILD;
1355 sprintf(s,"%%%d",id);
1356 pcop->name = Safe_strdup(s);
1358 PCOW(pcop)->id = id;
1359 PCOW(pcop)->pcp = pcp;
1360 PCOW(pcop)->subtype = subtype;
1361 PCOW(pcop)->matched = NULL;
1366 /*-----------------------------------------------------------------*/
1367 /*-----------------------------------------------------------------*/
1368 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1372 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1373 pcop->type = PO_BIT;
1375 pcop->name = Safe_strdup(s);
1379 PCOB(pcop)->bit = bit;
1380 PCOB(pcop)->inBitSpace = inBitSpace;
1385 pCodeOp *newpCodeOpReg(int rIdx)
1389 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1391 PCOR(pcop)->rIdx = rIdx;
1392 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1393 pcop->type = PCOR(pcop)->r->pc_type;
1398 /*-----------------------------------------------------------------*/
1399 /*-----------------------------------------------------------------*/
1401 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1407 pcop = newpCodeOpBit(name, -1,0);
1411 pcop = newpCodeOpLit(-1);
1415 pcop = newpCodeOpLabel(-1);
1419 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1422 pcop->name = Safe_strdup(name);
1430 /*-----------------------------------------------------------------*/
1431 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1432 /*-----------------------------------------------------------------*/
1433 void addpCode2pBlock(pBlock *pb, pCode *pc)
1436 /* If this is the first pcode to be added to a block that
1437 * was initialized with a NULL pcode, then go ahead and
1438 * make this pcode the head and tail */
1439 pb->pcHead = pb->pcTail = pc;
1441 pb->pcTail->next = pc;
1442 pc->prev = pb->pcTail;
1449 /*-----------------------------------------------------------------*/
1450 /* addpBlock - place a pBlock into the pFile */
1451 /*-----------------------------------------------------------------*/
1452 void addpBlock(pBlock *pb)
1456 /* First time called, we'll pass through here. */
1457 _ALLOC(the_pFile,sizeof(pFile));
1458 the_pFile->pbHead = the_pFile->pbTail = pb;
1459 the_pFile->functions = NULL;
1463 the_pFile->pbTail->next = pb;
1464 pb->prev = the_pFile->pbTail;
1466 the_pFile->pbTail = pb;
1469 /*-----------------------------------------------------------------*/
1470 /* printpCode - write the contents of a pCode to a file */
1471 /*-----------------------------------------------------------------*/
1472 void printpCode(FILE *of, pCode *pc)
1483 fprintf(of,"warning - unable to print pCode\n");
1486 /*-----------------------------------------------------------------*/
1487 /* printpBlock - write the contents of a pBlock to a file */
1488 /*-----------------------------------------------------------------*/
1489 void printpBlock(FILE *of, pBlock *pb)
1499 for(pc = pb->pcHead; pc; pc = pc->next)
1504 /*-----------------------------------------------------------------*/
1506 /* pCode processing */
1510 /*-----------------------------------------------------------------*/
1512 static void unlinkPC(pCode *pc)
1519 pc->prev->next = pc->next;
1521 pc->next->prev = pc->prev;
1523 pc->prev = pc->next = NULL;
1526 static void genericDestruct(pCode *pc)
1528 fprintf(stderr,"warning, calling default pCode destructor\n");
1537 /*-----------------------------------------------------------------*/
1538 /*-----------------------------------------------------------------*/
1539 void pBlockRegs(FILE *of, pBlock *pb)
1544 r = setFirstItem(pb->registers);
1546 r = setNextItem(pb->registers);
1551 static char *get_op( pCodeInstruction *pcc)
1555 if(pcc && pcc->pcop) {
1558 switch(pcc->pcop->type) {
1561 //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
1562 r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
1567 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1568 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1569 pBlockRegs(stderr,pcc->pc.pb);
1573 if (pcc->pcop->name)
1574 return pcc->pcop->name;
1579 return "NO operand";
1582 /*-----------------------------------------------------------------*/
1583 /*-----------------------------------------------------------------*/
1584 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1587 fprintf(of,"pcodeopprint\n");
1590 char *pCode2str(char *str, int size, pCode *pc)
1598 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1600 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1602 if(PCI(pc)->bit_inst) {
1603 if(PCI(pc)->pcop->type == PO_BIT) {
1604 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1605 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1606 PCI(pc)->pcop->name ,
1607 PCI(pc)->pcop->name );
1609 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1610 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1611 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1612 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1614 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1615 //PCI(pc)->pcop->t.bit );
1618 if(PCI(pc)->pcop->type == PO_BIT) {
1619 if( PCI(pc)->num_ops == 2)
1620 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1622 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1625 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1627 if( PCI(pc)->num_ops == 2)
1628 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1636 /* assuming that comment ends with a \n */
1637 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1641 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1644 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1647 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1656 /*-----------------------------------------------------------------*/
1657 /* genericPrint - the contents of a pCode to a file */
1658 /*-----------------------------------------------------------------*/
1659 static void genericPrint(FILE *of, pCode *pc)
1667 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1671 // If the opcode has a label, print that first
1673 pBranch *pbl = pc->label;
1674 while(pbl && pbl->pc) {
1675 if(pbl->pc->type == PC_LABEL)
1676 pCodePrintLabel(of, pbl->pc);
1685 pCode2str(str, 256, pc);
1687 fprintf(of,"%s",str);
1691 pBranch *dpb = pc->to; // debug
1693 switch ( dpb->pc->type) {
1695 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1698 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1701 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1715 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1717 pCodePrintLabel(of, pc->label->pc);
1719 if(PCW(pc)->operand) {
1720 fprintf(of,";\toperand ");
1721 pCodeOpPrint(of,PCW(pc)->operand );
1727 fprintf(of,"unknown pCode type %d\n",pc->type);
1732 /*-----------------------------------------------------------------*/
1733 /* pCodePrintFunction - prints function begin/end */
1734 /*-----------------------------------------------------------------*/
1736 static void pCodePrintFunction(FILE *of, pCode *pc)
1742 if( ((pCodeFunction *)pc)->modname)
1743 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1745 if(PCF(pc)->fname) {
1746 pBranch *exits = pc->to;
1748 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1751 exits = exits->next;
1754 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1758 pc->from->pc->type == PC_FUNCTION &&
1759 PCF(pc->from->pc)->fname)
1760 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1762 fprintf(of,"; exit point [can't find entry point]\n");
1765 /*-----------------------------------------------------------------*/
1766 /* pCodePrintLabel - prints label */
1767 /*-----------------------------------------------------------------*/
1769 static void pCodePrintLabel(FILE *of, pCode *pc)
1776 fprintf(of,"%s\n",PCL(pc)->label);
1777 else if (PCL(pc)->key >=0)
1778 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1780 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1783 /*-----------------------------------------------------------------*/
1784 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
1785 /* remove it if it is found. */
1786 /*-----------------------------------------------------------------*/
1787 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
1798 bprev->next = b->next; /* Not first pCode in chain */
1802 pcl->label = b->next; /* First pCode in chain */
1805 return; /* A label can't occur more than once */
1813 /*-----------------------------------------------------------------*/
1814 /*-----------------------------------------------------------------*/
1815 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1831 /*-----------------------------------------------------------------*/
1832 /* pBranchLink - given two pcodes, this function will link them */
1833 /* together through their pBranches */
1834 /*-----------------------------------------------------------------*/
1835 static void pBranchLink(pCode *f, pCode *t)
1839 // Declare a new branch object for the 'from' pCode.
1841 _ALLOC(b,sizeof(pBranch));
1842 b->pc = t; // The link to the 'to' pCode.
1845 f->to = pBranchAppend(f->to,b);
1847 // Now do the same for the 'to' pCode.
1849 _ALLOC(b,sizeof(pBranch));
1853 t->from = pBranchAppend(t->from,b);
1858 /*-----------------------------------------------------------------*/
1859 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1861 /*-----------------------------------------------------------------*/
1862 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1875 /*-----------------------------------------------------------------*/
1876 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1877 /*-----------------------------------------------------------------*/
1878 static void pCodeUnlink(pCode *pc)
1883 if(!pc->prev || !pc->next) {
1884 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1888 /* first remove the pCode from the chain */
1889 pc->prev->next = pc->next;
1890 pc->next->prev = pc->prev;
1892 /* Now for the hard part... */
1894 /* Remove the branches */
1898 pc1 = pb1->pc; /* Get the pCode that branches to the
1899 * one we're unlinking */
1901 /* search for the link back to this pCode (the one we're
1903 if(pb2 = pBranchFind(pc1->to,pc)) {
1904 pb2->pc = pc->to->pc; // make the replacement
1906 /* if the pCode we're unlinking contains multiple 'to'
1907 * branches (e.g. this a skip instruction) then we need
1908 * to copy these extra branches to the chain. */
1910 pBranchAppend(pb2, pc->to->next);
1919 /*-----------------------------------------------------------------*/
1920 /*-----------------------------------------------------------------*/
1921 static void genericAnalyze(pCode *pc)
1931 // Go through the pCodes that are in pCode chain and link
1932 // them together through the pBranches. Note, the pCodes
1933 // are linked together as a contiguous stream like the
1934 // assembly source code lines. The linking here mimics this
1935 // except that comments are not linked in.
1937 pCode *npc = pc->next;
1939 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1940 pBranchLink(pc,npc);
1945 /* reached the end of the pcode chain without finding
1946 * an instruction we could link to. */
1951 /*-----------------------------------------------------------------*/
1952 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1956 if(pc->type == PC_LABEL) {
1957 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1960 if(pc->type == PC_OPCODE) {
1963 if(pbr->pc->type == PC_LABEL) {
1964 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1974 /*-----------------------------------------------------------------*/
1975 /* findLabel - Search the pCode for a particular label */
1976 /*-----------------------------------------------------------------*/
1977 pCode * findLabel(pCodeOpLabel *pcop_label)
1985 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1986 for(pc = pb->pcHead; pc; pc = pc->next)
1987 if(compareLabel(pc,pcop_label))
1992 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1996 /*-----------------------------------------------------------------*/
1997 /* findNextInstruction - given a pCode, find the next instruction */
1998 /* in the linked list */
1999 /*-----------------------------------------------------------------*/
2000 pCode * findNextInstruction(pCode *pc)
2004 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2010 fprintf(stderr,"Couldn't find instruction\n");
2014 /*-----------------------------------------------------------------*/
2015 /* findFunctionEnd - given a pCode find the end of the function */
2016 /* that contains it t */
2017 /*-----------------------------------------------------------------*/
2018 pCode * findFunctionEnd(pCode *pc)
2022 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2028 fprintf(stderr,"Couldn't find function end\n");
2033 /*-----------------------------------------------------------------*/
2034 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2035 /* instruction with which it is associated. */
2036 /*-----------------------------------------------------------------*/
2037 static void AnalyzeLabel(pCode *pc)
2045 static void AnalyzeGOTO(pCode *pc)
2048 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2052 static void AnalyzeSKIP(pCode *pc)
2055 pBranchLink(pc,findNextInstruction(pc->next));
2056 pBranchLink(pc,findNextInstruction(pc->next->next));
2060 static void AnalyzeRETURN(pCode *pc)
2063 // branch_link(pc,findFunctionEnd(pc->next));
2067 /*-----------------------------------------------------------------*/
2068 /*-----------------------------------------------------------------*/
2070 void AnalyzepBlock(pBlock *pb)
2077 /* Find all of the registers used in this pBlock */
2078 for(pc = pb->pcHead; pc; pc = pc->next) {
2079 if(pc->type == PC_OPCODE) {
2080 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2082 /* Loop through all of the registers declared so far in
2083 this block and see if we find this one there */
2085 regs *r = setFirstItem(pb->registers);
2088 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2089 PCOR(PCI(pc)->pcop)->r = r;
2092 r = setNextItem(pb->registers);
2096 /* register wasn't found */
2097 r = Safe_calloc(1, sizeof(regs));
2098 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2099 addSet(&pb->registers, r);
2100 PCOR(PCI(pc)->pcop)->r = r;
2101 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2103 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2109 /*-----------------------------------------------------------------*/
2110 /*-----------------------------------------------------------------*/
2111 int OptimizepBlock(pBlock *pb)
2116 if(!pb || !peepOptimizing)
2119 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2120 for(pc = pb->pcHead; pc; pc = pc->next)
2121 matches += pCodePeepMatchRule(pc);
2127 /*-----------------------------------------------------------------*/
2128 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2129 /*-----------------------------------------------------------------*/
2130 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2134 for(pc = pcs; pc; pc = pc->next) {
2136 if((pc->type == PC_OPCODE) &&
2138 (PCI(pc)->pcop->type == PO_LABEL) &&
2139 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2147 /*-----------------------------------------------------------------*/
2148 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2149 /* pCode chain if they're not used. */
2150 /*-----------------------------------------------------------------*/
2151 void pBlockRemoveUnusedLabels(pBlock *pb)
2153 pCode *pc; pCodeLabel *pcl;
2158 for(pc = pb->pcHead; pc; pc = pc->next) {
2160 if(pc->type == PC_LABEL)
2163 pcl = PCL(pc->label->pc);
2166 /* This pCode is a label, so search the pBlock to see if anyone
2169 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2170 /* Couldn't find an instruction that refers to this label
2171 * So, unlink the pCode label from it's pCode chain
2172 * and destroy the label */
2174 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2176 if(pc->type == PC_LABEL) {
2178 pCodeLabelDestruct(pc);
2180 unlinkpCodeFromBranch(pc, PCODE(pcl));
2181 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
2192 /*-----------------------------------------------------------------*/
2193 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2194 /* chain and put them into pBranches that are */
2195 /* associated with the appropriate pCode */
2197 /*-----------------------------------------------------------------*/
2198 void pBlockMergeLabels(pBlock *pb)
2201 pCode *pc, *pcnext=NULL;
2206 /* First, Try to remove any unused labels */
2207 //pBlockRemoveUnusedLabels(pb);
2209 /* Now loop through the pBlock and merge the labels with the opcodes */
2211 for(pc = pb->pcHead; pc; pc = pc->next) {
2213 if(pc->type == PC_LABEL) {
2214 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2215 if( !(pcnext = findNextInstruction(pc)) )
2216 return; // Couldn't find an instruction associated with this label
2218 // Unlink the pCode label from it's pCode chain
2221 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2222 // And link it into the instruction's pBranch labels. (Note, since
2223 // it's possible to have multiple labels associated with one instruction
2224 // we must provide a means to accomodate the additional labels. Thus
2225 // the labels are placed into the singly-linked list "label" as
2226 // opposed to being a single member of the pCodeInstruction.)
2228 _ALLOC(pbr,sizeof(pBranch));
2232 pcnext->label = pBranchAppend(pcnext->label,pbr);
2240 pBlockRemoveUnusedLabels(pb);
2244 /*-----------------------------------------------------------------*/
2245 /*-----------------------------------------------------------------*/
2246 void OptimizepCode(char dbName)
2248 #define MAX_PASSES 4
2257 fprintf(stderr," Optimizing pCode\n");
2260 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2261 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2262 matches += OptimizepBlock(pb);
2265 while(matches && ++passes < MAX_PASSES);
2269 /*-----------------------------------------------------------------*/
2270 /* AnalyzepCode - parse the pCode that has been generated and form */
2271 /* all of the logical connections. */
2273 /* Essentially what's done here is that the pCode flow is */
2275 /*-----------------------------------------------------------------*/
2277 void AnalyzepCode(char dbName)
2288 fprintf(stderr," Analyzing pCode");
2293 /* First, merge the labels with the instructions */
2294 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2295 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2297 fprintf(stderr," analyze and merging block %c\n",dbName);
2298 pBlockMergeLabels(pb);
2303 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2304 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2305 changes += OptimizepBlock(pb);
2308 } while(changes && (i++ < MAX_PASSES));
2310 /* Now build the call tree.
2311 First we examine all of the pCodes for functions.
2312 Keep in mind that the function boundaries coincide
2313 with pBlock boundaries.
2315 The algorithm goes something like this:
2316 We have two nested loops. The outer loop iterates
2317 through all of the pBlocks/functions. The inner
2318 loop iterates through all of the pCodes for
2319 a given pBlock. When we begin iterating through
2320 a pBlock, the variable pc_fstart, pCode of the start
2321 of a function, is cleared. We then search for pCodes
2322 of type PC_FUNCTION. When one is encountered, we
2323 initialize pc_fstart to this and at the same time
2324 associate a new pBranch object that signifies a
2325 branch entry. If a return is found, then this signifies
2326 a function exit point. We'll link the pCodes of these
2327 returns to the matching pc_fstart.
2329 When we're done, a doubly linked list of pBranches
2330 will exist. The head of this list is stored in
2331 `the_pFile', which is the meta structure for all
2332 of the pCode. Look at the printCallTree function
2333 on how the pBranches are linked together.
2336 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2337 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2338 pCode *pc_fstart=NULL;
2339 for(pc = pb->pcHead; pc; pc = pc->next) {
2340 if(pc->type == PC_FUNCTION) {
2341 if (PCF(pc)->fname) {
2342 // I'm not liking this....
2343 // Found the beginning of a function.
2344 _ALLOC(pbr,sizeof(pBranch));
2345 pbr->pc = pc_fstart = pc;
2348 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2350 // Here's a better way of doing the same:
2351 addSet(&pb->function_entries, pc);
2354 // Found an exit point in a function, e.g. return
2355 // (Note, there may be more than one return per function)
2357 pBranchLink(pc_fstart, pc);
2359 addSet(&pb->function_exits, pc);
2361 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2362 addSet(&pb->function_calls,pc);
2369 /*-----------------------------------------------------------------*/
2370 /* ispCodeFunction - returns true if *pc is the pCode of a */
2372 /*-----------------------------------------------------------------*/
2373 bool ispCodeFunction(pCode *pc)
2376 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2382 /*-----------------------------------------------------------------*/
2383 /* findFunction - Search for a function by name (given the name) */
2384 /* in the set of all functions that are in a pBlock */
2385 /* (note - I expect this to change because I'm planning to limit */
2386 /* pBlock's to just one function declaration */
2387 /*-----------------------------------------------------------------*/
2388 pCode *findFunction(char *fname)
2395 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2397 pc = setFirstItem(pb->function_entries);
2400 if((pc->type == PC_FUNCTION) &&
2402 (strcmp(fname, PCF(pc)->fname)==0))
2405 pc = setNextItem(pb->function_entries);
2413 void MarkUsedRegisters(set *regset)
2418 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2419 r2 = pic14_regWithIdx(r1->rIdx);
2425 void pBlockStats(FILE *of, pBlock *pb)
2431 fprintf(of,";***\n; pBlock Stats\n;***\n");
2433 // for now just print the first element of each set
2434 pc = setFirstItem(pb->function_entries);
2436 fprintf(of,";entry: ");
2439 pc = setFirstItem(pb->function_exits);
2441 fprintf(of,";has an exit\n");
2445 pc = setFirstItem(pb->function_calls);
2447 fprintf(of,";functions called:\n");
2450 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2451 fprintf(of,"; %s\n",get_op(PCI(pc)));
2453 pc = setNextItem(pb->function_calls);
2457 r = setFirstItem(pb->registers);
2459 int n = elementsInSet(pb->registers);
2461 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2464 fprintf(of,"; %s\n",r->name);
2465 r = setNextItem(pb->registers);
2470 /*-----------------------------------------------------------------*/
2471 /*-----------------------------------------------------------------*/
2472 void sequencepCode(void)
2478 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2480 pb->seq = GpCodeSequenceNumber+1;
2482 for( pc = pb->pcHead; pc; pc = pc->next)
2483 pc->seq = ++GpCodeSequenceNumber;
2488 /*-----------------------------------------------------------------*/
2489 /*-----------------------------------------------------------------*/
2490 set *register_usage(pBlock *pb)
2493 set *registers=NULL;
2494 set *registersInCallPath = NULL;
2496 /* check recursion */
2498 pc = setFirstItem(pb->function_entries);
2505 if(pc->type != PC_FUNCTION)
2506 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2508 pc = setFirstItem(pb->function_calls);
2509 for( ; pc; pc = setNextItem(pb->function_calls)) {
2511 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2512 char *dest = get_op(PCI(pc));
2514 pcn = findFunction(dest);
2516 registersInCallPath = register_usage(pcn->pb);
2518 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2523 pBlockStats(stderr,pb); // debug
2525 // Mark the registers in this block as used.
2527 MarkUsedRegisters(pb->registers);
2528 if(registersInCallPath) {
2529 /* registers were used in the functions this pBlock has called */
2530 /* so now, we need to see if these collide with the ones we are */
2533 regs *r1,*r2, *newreg;
2535 fprintf(stderr,"comparing registers\n");
2537 r1 = setFirstItem(registersInCallPath);
2540 r2 = setFirstItem(pb->registers);
2542 while(r2 && (r1->type != REG_STK)) {
2544 if(r2->rIdx == r1->rIdx) {
2545 newreg = pic14_findFreeReg(REG_GPR);
2549 fprintf(stderr,"Bummer, no more registers.\n");
2553 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2554 r1->rIdx, newreg->rIdx);
2555 r2->rIdx = newreg->rIdx;
2556 //if(r2->name) free(r2->name);
2558 r2->name = Safe_strdup(newreg->name);
2562 newreg->wasUsed = 1;
2564 r2 = setNextItem(pb->registers);
2567 r1 = setNextItem(registersInCallPath);
2570 /* Collisions have been resolved. Now free the registers in the call path */
2571 r1 = setFirstItem(registersInCallPath);
2573 if(r1->type != REG_STK) {
2574 newreg = pic14_regWithIdx(r1->rIdx);
2577 r1 = setNextItem(registersInCallPath);
2581 // MarkUsedRegisters(pb->registers);
2583 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2586 fprintf(stderr,"returning regs\n");
2588 fprintf(stderr,"not returning regs\n");
2590 fprintf(stderr,"pBlock after register optim.\n");
2591 pBlockStats(stderr,pb); // debug
2597 /*-----------------------------------------------------------------*/
2598 /* printCallTree - writes the call tree to a file */
2600 /*-----------------------------------------------------------------*/
2601 void pct2(FILE *of,pBlock *pb,int indent)
2605 // set *registersInCallPath = NULL;
2608 return;// registers;
2611 return; // registers; //recursion ?
2613 pc = setFirstItem(pb->function_entries);
2620 for(i=0;i<indent;i++) // Indentation
2623 if(pc->type == PC_FUNCTION)
2624 fprintf(of,"%s\n",PCF(pc)->fname);
2629 pc = setFirstItem(pb->function_calls);
2630 for( ; pc; pc = setNextItem(pb->function_calls)) {
2632 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2633 char *dest = get_op(PCI(pc));
2635 pcn = findFunction(dest);
2637 pct2(of,pcn->pb,indent+1);
2639 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2647 fprintf(stderr,"pBlock before register optim.\n");
2648 pBlockStats(stderr,pb); // debug
2650 if(registersInCallPath) {
2651 /* registers were used in the functions this pBlock has called */
2652 /* so now, we need to see if these collide with the ones we are using here */
2654 regs *r1,*r2, *newreg;
2656 fprintf(stderr,"comparing registers\n");
2658 r1 = setFirstItem(registersInCallPath);
2661 r2 = setFirstItem(pb->registers);
2665 if(r2->rIdx == r1->rIdx) {
2666 newreg = pic14_findFreeReg();
2670 fprintf(stderr,"Bummer, no more registers.\n");
2674 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2675 r1->rIdx, newreg->rIdx);
2676 r2->rIdx = newreg->rIdx;
2677 //if(r2->name) free(r2->name);
2679 r2->name = Safe_strdup(newreg->name);
2683 newreg->wasUsed = 1;
2685 r2 = setNextItem(pb->registers);
2688 r1 = setNextItem(registersInCallPath);
2691 /* Collisions have been resolved. Now free the registers in the call path */
2692 r1 = setFirstItem(registersInCallPath);
2694 newreg = pic14_regWithIdx(r1->rIdx);
2696 r1 = setNextItem(registersInCallPath);
2700 MarkUsedRegisters(pb->registers);
2702 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2705 fprintf(stderr,"returning regs\n");
2707 fprintf(stderr,"not returning regs\n");
2709 fprintf(stderr,"pBlock after register optim.\n");
2710 pBlockStats(stderr,pb); // debug
2718 /*-----------------------------------------------------------------*/
2719 /* printCallTree - writes the call tree to a file */
2721 /*-----------------------------------------------------------------*/
2723 void printCallTree(FILE *of)
2735 fprintf(of, "\npBlock statistics\n");
2736 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2737 pBlockStats(stderr,pb);
2741 fprintf(of,"Call Tree\n");
2742 pbr = the_pFile->functions;
2746 if(!ispCodeFunction(pc))
2747 fprintf(of,"bug in call tree");
2750 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2752 while(pc->next && !ispCodeFunction(pc->next)) {
2754 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2755 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2763 /* Re-allocate the registers so that there are no collisions
2764 * between local variables when one function call another */
2766 pic14_deallocateAllRegs();
2768 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2773 fprintf(of,"\n**************\n\na better call tree\n");
2774 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2779 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2780 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));