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);
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);
781 /*-----------------------------------------------------------------*/
782 /* mnem2key - convert a pic mnemonic into a hash key */
783 /* (BTW - this spreads the mnemonics quite well) */
785 /*-----------------------------------------------------------------*/
787 int mnem2key(char const *mnem)
796 key += toupper(*mnem++) +1;
804 void pic14initMnemonics(void)
809 pCodeInstruction *pci;
811 if(mnemonics_initialized)
814 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
815 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
816 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
817 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
818 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
819 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
820 pic14Mnemonics[POC_BCF] = &pciBCF;
821 pic14Mnemonics[POC_BSF] = &pciBSF;
822 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
823 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
824 pic14Mnemonics[POC_CALL] = &pciCALL;
825 pic14Mnemonics[POC_COMF] = &pciCOMF;
826 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
827 pic14Mnemonics[POC_CLRF] = &pciCLRF;
828 pic14Mnemonics[POC_CLRW] = &pciCLRW;
829 pic14Mnemonics[POC_DECF] = &pciDECF;
830 pic14Mnemonics[POC_DECFW] = &pciDECFW;
831 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
832 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
833 pic14Mnemonics[POC_GOTO] = &pciGOTO;
834 pic14Mnemonics[POC_INCF] = &pciINCF;
835 pic14Mnemonics[POC_INCFW] = &pciINCFW;
836 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
837 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
838 pic14Mnemonics[POC_IORLW] = &pciIORLW;
839 pic14Mnemonics[POC_IORWF] = &pciIORWF;
840 pic14Mnemonics[POC_IORFW] = &pciIORFW;
841 pic14Mnemonics[POC_MOVF] = &pciMOVF;
842 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
843 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
844 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
845 pic14Mnemonics[POC_NEGF] = &pciNEGF;
846 pic14Mnemonics[POC_RETLW] = &pciRETLW;
847 pic14Mnemonics[POC_RETURN] = &pciRETURN;
848 pic14Mnemonics[POC_RLF] = &pciRLF;
849 pic14Mnemonics[POC_RLFW] = &pciRLFW;
850 pic14Mnemonics[POC_RRF] = &pciRRF;
851 pic14Mnemonics[POC_RRFW] = &pciRRFW;
852 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
853 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
854 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
855 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
856 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
857 pic14Mnemonics[POC_TRIS] = &pciTRIS;
858 pic14Mnemonics[POC_XORLW] = &pciXORLW;
859 pic14Mnemonics[POC_XORWF] = &pciXORWF;
860 pic14Mnemonics[POC_XORFW] = &pciXORFW;
862 for(i=0; i<MAX_PIC14MNEMONICS; i++)
863 if(pic14Mnemonics[i])
864 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
865 pci = hTabFirstItem(pic14MnemonicsHash, &key);
868 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
869 pci = hTabNextItem(pic14MnemonicsHash, &key);
872 mnemonics_initialized = 1;
875 int getpCode(char *mnem,unsigned dest)
878 pCodeInstruction *pci;
879 int key = mnem2key(mnem);
881 if(!mnemonics_initialized)
882 pic14initMnemonics();
884 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
888 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
889 if((pci->num_ops <= 1) || (pci->dest == dest))
893 pci = hTabNextItemWK (pic14MnemonicsHash);
900 char getpBlock_dbName(pBlock *pb)
906 return pb->cmemmap->dbName;
910 /*-----------------------------------------------------------------*/
911 /* movepBlock2Head - given the dbname of a pBlock, move all */
912 /* instances to the front of the doubly linked */
913 /* list of pBlocks */
914 /*-----------------------------------------------------------------*/
916 void movepBlock2Head(char dbName)
920 pb = the_pFile->pbHead;
924 if(getpBlock_dbName(pb) == dbName) {
925 pBlock *pbn = pb->next;
926 pb->next = the_pFile->pbHead;
927 the_pFile->pbHead->prev = pb;
928 the_pFile->pbHead = pb;
931 pb->prev->next = pbn;
933 // If the pBlock that we just moved was the last
934 // one in the link of all of the pBlocks, then we
935 // need to point the tail to the block just before
937 // Note: if pb->next is NULL, then pb must have
938 // been the last pBlock in the chain.
941 pbn->prev = pb->prev;
943 the_pFile->pbTail = pb->prev;
954 void copypCode(FILE *of, char dbName)
958 if(!of || !the_pFile)
961 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
962 if(getpBlock_dbName(pb) == dbName) {
969 void pcode_test(void)
972 printf("pcode is alive!\n");
982 /* create the file name */
983 strcpy(buffer,srcFileName);
986 if( !(pFile = fopen(buffer, "w" ))) {
987 werror(E_FILE_OPEN_ERR,buffer);
991 fprintf(pFile,"pcode dump\n\n");
993 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
994 fprintf(pFile,"\n\tNew pBlock\n\n");
996 fprintf(pFile,"%s",pb->cmemmap->sname);
998 fprintf(pFile,"internal pblock");
1000 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1001 printpBlock(pFile,pb);
1005 /*-----------------------------------------------------------------*/
1006 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1007 /* ister, RegCond will return the bit being referenced. */
1009 /* fixme - why not just OR in the pcop bit field */
1010 /*-----------------------------------------------------------------*/
1012 static int RegCond(pCodeOp *pcop)
1018 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
1019 switch(PCOB(pcop)->bit) {
1033 /*-----------------------------------------------------------------*/
1034 /* newpCode - create and return a newly initialized pCode */
1036 /* fixme - rename this */
1038 /* The purpose of this routine is to create a new Instruction */
1039 /* pCode. This is called by gen.c while the assembly code is being */
1043 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1044 /* (note that the op is analogous to but not the */
1045 /* same thing as the opcode of the instruction.) */
1046 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1049 /* a pointer to the new malloc'd pCode is returned. */
1053 /*-----------------------------------------------------------------*/
1054 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1056 pCodeInstruction *pci ;
1058 if(!mnemonics_initialized)
1059 pic14initMnemonics();
1061 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1063 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1064 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1067 if(pci->inCond == PCC_EXAMINE_PCOP)
1068 pci->inCond = RegCond(pcop);
1070 if(pci->outCond == PCC_EXAMINE_PCOP)
1071 pci->outCond = RegCond(pcop);
1073 return (pCode *)pci;
1076 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1082 /*-----------------------------------------------------------------*/
1083 /* newpCodeWild - create a "wild" as in wild card pCode */
1085 /* Wild pcodes are used during the peep hole optimizer to serve */
1086 /* as place holders for any instruction. When a snippet of code is */
1087 /* compared to a peep hole rule, the wild card opcode will match */
1088 /* any instruction. However, the optional operand and label are */
1089 /* additional qualifiers that must also be matched before the */
1090 /* line (of assembly code) is declared matched. Note that the */
1091 /* operand may be wild too. */
1093 /* Note, a wild instruction is specified just like a wild var: */
1094 /* %4 ; A wild instruction, */
1095 /* See the peeph.def file for additional examples */
1097 /*-----------------------------------------------------------------*/
1099 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1104 pcw = Safe_calloc(1,sizeof(pCodeWild));
1106 pcw->pc.type = PC_WILD;
1107 pcw->pc.prev = pcw->pc.next = NULL;
1108 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1111 pcw->pc.analyze = genericAnalyze;
1112 pcw->pc.destruct = genericDestruct;
1113 pcw->pc.print = genericPrint;
1115 pcw->id = pCodeID; // this is the 'n' in %n
1116 pcw->operand = optional_operand;
1117 pcw->label = optional_label;
1119 return ( (pCode *)pcw);
1123 /*-----------------------------------------------------------------*/
1124 /* newPcodeCharP - create a new pCode from a char string */
1125 /*-----------------------------------------------------------------*/
1127 pCode *newpCodeCharP(char *cP)
1132 pcc = Safe_calloc(1,sizeof(pCodeComment));
1134 pcc->pc.type = PC_COMMENT;
1135 pcc->pc.prev = pcc->pc.next = NULL;
1136 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1139 pcc->pc.analyze = genericAnalyze;
1140 pcc->pc.destruct = genericDestruct;
1141 pcc->pc.print = genericPrint;
1144 pcc->comment = Safe_strdup(cP);
1146 pcc->comment = NULL;
1148 return ( (pCode *)pcc);
1152 /*-----------------------------------------------------------------*/
1153 /* newpCodeGLabel - create a new global label */
1154 /*-----------------------------------------------------------------*/
1157 pCode *newpCodeFunction(char *mod,char *f)
1161 _ALLOC(pcf,sizeof(pCodeFunction));
1163 pcf->pc.type = PC_FUNCTION;
1164 pcf->pc.prev = pcf->pc.next = NULL;
1165 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1168 pcf->pc.analyze = genericAnalyze;
1169 pcf->pc.destruct = genericDestruct;
1170 pcf->pc.print = pCodePrintFunction;
1173 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1174 strcpy(pcf->modname,mod);
1176 pcf->modname = NULL;
1179 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1180 strcpy(pcf->fname,f);
1184 return ( (pCode *)pcf);
1188 /*-----------------------------------------------------------------*/
1189 /* pCodeLabelDestruct - free memory used by a label. */
1190 /*-----------------------------------------------------------------*/
1191 static void pCodeLabelDestruct(pCode *pc)
1197 if((pc->type == PC_LABEL) && PCL(pc)->label)
1198 free(PCL(pc)->label);
1204 pCode *newpCodeLabel(int key)
1210 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1212 pcl->pc.type = PC_LABEL;
1213 pcl->pc.prev = pcl->pc.next = NULL;
1214 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1217 pcl->pc.analyze = genericAnalyze;
1218 pcl->pc.destruct = pCodeLabelDestruct;
1219 pcl->pc.print = pCodePrintLabel;
1225 sprintf(s,"_%05d_DS_",key);
1227 pcl->label = Safe_strdup(s);
1231 return ( (pCode *)pcl);
1234 pCode *newpCodeLabelStr(char *str)
1236 pCode *pc = newpCodeLabel(-1);
1239 PCL(pc)->label = Safe_strdup(str);
1241 PCL(pc)->label = NULL;
1246 /*-----------------------------------------------------------------*/
1247 /* newpBlock - create and return a pointer to a new pBlock */
1248 /*-----------------------------------------------------------------*/
1249 pBlock *newpBlock(void)
1254 PpB = Safe_calloc(1,sizeof(pBlock) );
1255 PpB->next = PpB->prev = NULL;
1257 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1258 PpB->registers = NULL;
1265 /*-----------------------------------------------------------------*/
1266 /* newpCodeChain - create a new chain of pCodes */
1267 /*-----------------------------------------------------------------*
1269 * This function will create a new pBlock and the pointer to the
1270 * pCode that is passed in will be the first pCode in the block.
1271 *-----------------------------------------------------------------*/
1274 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1277 pBlock *pB = newpBlock();
1279 pB->pcHead = pB->pcTail = pc;
1286 /*-----------------------------------------------------------------*/
1287 /* newpCodeOpLabel - Create a new label given the key */
1288 /* Note, a negative key means that the label is part of wild card */
1289 /* (and hence a wild card label) used in the pCodePeep */
1290 /* optimizations). */
1291 /*-----------------------------------------------------------------*/
1293 pCodeOp *newpCodeOpLabel(int key)
1298 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1299 pcop->type = PO_LABEL;
1303 sprintf(s,"_%05d_DS_",key);
1305 pcop->name = Safe_strdup(s);
1309 ((pCodeOpLabel *)pcop)->key = key;
1314 /*-----------------------------------------------------------------*/
1315 /*-----------------------------------------------------------------*/
1316 pCodeOp *newpCodeOpLit(int lit)
1322 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1323 pcop->type = PO_LITERAL;
1326 sprintf(s,"0x%02x",lit);
1328 pcop->name = Safe_strdup(s);
1332 ((pCodeOpLit *)pcop)->lit = lit;
1337 /*-----------------------------------------------------------------*/
1338 /*-----------------------------------------------------------------*/
1339 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1345 if(!pcp || !subtype) {
1346 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1350 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1351 pcop->type = PO_WILD;
1352 sprintf(s,"%%%d",id);
1353 pcop->name = Safe_strdup(s);
1355 PCOW(pcop)->id = id;
1356 PCOW(pcop)->pcp = pcp;
1357 PCOW(pcop)->subtype = subtype;
1358 PCOW(pcop)->matched = NULL;
1363 /*-----------------------------------------------------------------*/
1364 /*-----------------------------------------------------------------*/
1365 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1369 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1370 pcop->type = PO_BIT;
1372 pcop->name = Safe_strdup(s);
1376 PCOB(pcop)->bit = bit;
1377 PCOB(pcop)->inBitSpace = inBitSpace;
1382 pCodeOp *newpCodeOpReg(int rIdx)
1386 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1388 PCOR(pcop)->rIdx = rIdx;
1389 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1390 pcop->type = PCOR(pcop)->r->pc_type;
1395 /*-----------------------------------------------------------------*/
1396 /*-----------------------------------------------------------------*/
1398 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1404 pcop = newpCodeOpBit(name, -1,0);
1408 pcop = newpCodeOpLit(-1);
1412 pcop = newpCodeOpLabel(-1);
1416 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1419 pcop->name = Safe_strdup(name);
1427 /*-----------------------------------------------------------------*/
1428 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1429 /*-----------------------------------------------------------------*/
1430 void addpCode2pBlock(pBlock *pb, pCode *pc)
1433 /* If this is the first pcode to be added to a block that
1434 * was initialized with a NULL pcode, then go ahead and
1435 * make this pcode the head and tail */
1436 pb->pcHead = pb->pcTail = pc;
1438 pb->pcTail->next = pc;
1439 pc->prev = pb->pcTail;
1446 /*-----------------------------------------------------------------*/
1447 /* addpBlock - place a pBlock into the pFile */
1448 /*-----------------------------------------------------------------*/
1449 void addpBlock(pBlock *pb)
1453 /* First time called, we'll pass through here. */
1454 _ALLOC(the_pFile,sizeof(pFile));
1455 the_pFile->pbHead = the_pFile->pbTail = pb;
1456 the_pFile->functions = NULL;
1460 the_pFile->pbTail->next = pb;
1461 pb->prev = the_pFile->pbTail;
1463 the_pFile->pbTail = pb;
1466 /*-----------------------------------------------------------------*/
1467 /* printpCode - write the contents of a pCode to a file */
1468 /*-----------------------------------------------------------------*/
1469 void printpCode(FILE *of, pCode *pc)
1480 fprintf(of,"warning - unable to print pCode\n");
1483 /*-----------------------------------------------------------------*/
1484 /* printpBlock - write the contents of a pBlock to a file */
1485 /*-----------------------------------------------------------------*/
1486 void printpBlock(FILE *of, pBlock *pb)
1496 for(pc = pb->pcHead; pc; pc = pc->next)
1501 /*-----------------------------------------------------------------*/
1503 /* pCode processing */
1507 /*-----------------------------------------------------------------*/
1509 static void unlinkPC(pCode *pc)
1516 pc->prev->next = pc->next;
1518 pc->next->prev = pc->prev;
1520 pc->prev = pc->next = NULL;
1523 static void genericDestruct(pCode *pc)
1525 fprintf(stderr,"warning, calling default pCode destructor\n");
1534 /*-----------------------------------------------------------------*/
1535 /*-----------------------------------------------------------------*/
1536 void pBlockRegs(FILE *of, pBlock *pb)
1541 r = setFirstItem(pb->registers);
1543 r = setNextItem(pb->registers);
1548 static char *get_op( pCodeInstruction *pcc)
1552 if(pcc && pcc->pcop) {
1555 switch(pcc->pcop->type) {
1558 r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
1563 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1564 //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1565 pBlockRegs(stderr,pcc->pc.pb);
1569 if (pcc->pcop->name)
1570 return pcc->pcop->name;
1575 return "NO operand";
1578 /*-----------------------------------------------------------------*/
1579 /*-----------------------------------------------------------------*/
1580 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1583 fprintf(of,"pcodeopprint\n");
1586 char *pCode2str(char *str, int size, pCode *pc)
1594 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1596 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1598 if(PCI(pc)->bit_inst) {
1599 if(PCI(pc)->pcop->type == PO_BIT) {
1600 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1601 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
1602 PCI(pc)->pcop->name ,
1603 PCI(pc)->pcop->name );
1605 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),
1606 (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1607 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
1608 SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
1610 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1611 //PCI(pc)->pcop->t.bit );
1614 if(PCI(pc)->pcop->type == PO_BIT) {
1615 if( PCI(pc)->num_ops == 2)
1616 SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1618 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1621 SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1623 if( PCI(pc)->num_ops == 2)
1624 SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1632 /* assuming that comment ends with a \n */
1633 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1637 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1640 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1643 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1652 /*-----------------------------------------------------------------*/
1653 /* genericPrint - the contents of a pCode to a file */
1654 /*-----------------------------------------------------------------*/
1655 static void genericPrint(FILE *of, pCode *pc)
1663 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1667 // If the opcode has a label, print that first
1669 pBranch *pbl = pc->label;
1670 while(pbl && pbl->pc) {
1671 if(pbl->pc->type == PC_LABEL)
1672 pCodePrintLabel(of, pbl->pc);
1681 pCode2str(str, 256, pc);
1683 fprintf(of,"%s",str);
1687 pBranch *dpb = pc->to; // debug
1689 switch ( dpb->pc->type) {
1691 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1694 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1697 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1711 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1713 pCodePrintLabel(of, pc->label->pc);
1715 if(PCW(pc)->operand) {
1716 fprintf(of,";\toperand ");
1717 pCodeOpPrint(of,PCW(pc)->operand );
1723 fprintf(of,"unknown pCode type %d\n",pc->type);
1728 /*-----------------------------------------------------------------*/
1729 /* pCodePrintFunction - prints function begin/end */
1730 /*-----------------------------------------------------------------*/
1732 static void pCodePrintFunction(FILE *of, pCode *pc)
1738 if( ((pCodeFunction *)pc)->modname)
1739 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1741 if(PCF(pc)->fname) {
1742 pBranch *exits = pc->to;
1744 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1747 exits = exits->next;
1750 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1754 pc->from->pc->type == PC_FUNCTION &&
1755 PCF(pc->from->pc)->fname)
1756 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1758 fprintf(of,"; exit point [can't find entry point]\n");
1761 /*-----------------------------------------------------------------*/
1762 /* pCodePrintLabel - prints label */
1763 /*-----------------------------------------------------------------*/
1765 static void pCodePrintLabel(FILE *of, pCode *pc)
1772 fprintf(of,"%s\n",PCL(pc)->label);
1773 else if (PCL(pc)->key >=0)
1774 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1776 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1779 /*-----------------------------------------------------------------*/
1780 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
1781 /* remove it if it is found. */
1782 /*-----------------------------------------------------------------*/
1783 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
1794 bprev->next = b->next; /* Not first pCode in chain */
1798 pcl->label = b->next; /* First pCode in chain */
1801 return; /* A label can't occur more than once */
1809 /*-----------------------------------------------------------------*/
1810 /*-----------------------------------------------------------------*/
1811 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1827 /*-----------------------------------------------------------------*/
1828 /* pBranchLink - given two pcodes, this function will link them */
1829 /* together through their pBranches */
1830 /*-----------------------------------------------------------------*/
1831 static void pBranchLink(pCode *f, pCode *t)
1835 // Declare a new branch object for the 'from' pCode.
1837 _ALLOC(b,sizeof(pBranch));
1838 b->pc = t; // The link to the 'to' pCode.
1841 f->to = pBranchAppend(f->to,b);
1843 // Now do the same for the 'to' pCode.
1845 _ALLOC(b,sizeof(pBranch));
1849 t->from = pBranchAppend(t->from,b);
1854 /*-----------------------------------------------------------------*/
1855 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1857 /*-----------------------------------------------------------------*/
1858 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1871 /*-----------------------------------------------------------------*/
1872 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1873 /*-----------------------------------------------------------------*/
1874 static void pCodeUnlink(pCode *pc)
1879 if(!pc->prev || !pc->next) {
1880 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1884 /* first remove the pCode from the chain */
1885 pc->prev->next = pc->next;
1886 pc->next->prev = pc->prev;
1888 /* Now for the hard part... */
1890 /* Remove the branches */
1894 pc1 = pb1->pc; /* Get the pCode that branches to the
1895 * one we're unlinking */
1897 /* search for the link back to this pCode (the one we're
1899 if(pb2 = pBranchFind(pc1->to,pc)) {
1900 pb2->pc = pc->to->pc; // make the replacement
1902 /* if the pCode we're unlinking contains multiple 'to'
1903 * branches (e.g. this a skip instruction) then we need
1904 * to copy these extra branches to the chain. */
1906 pBranchAppend(pb2, pc->to->next);
1915 /*-----------------------------------------------------------------*/
1916 /*-----------------------------------------------------------------*/
1917 static void genericAnalyze(pCode *pc)
1927 // Go through the pCodes that are in pCode chain and link
1928 // them together through the pBranches. Note, the pCodes
1929 // are linked together as a contiguous stream like the
1930 // assembly source code lines. The linking here mimics this
1931 // except that comments are not linked in.
1933 pCode *npc = pc->next;
1935 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1936 pBranchLink(pc,npc);
1941 /* reached the end of the pcode chain without finding
1942 * an instruction we could link to. */
1947 /*-----------------------------------------------------------------*/
1948 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
1952 if(pc->type == PC_LABEL) {
1953 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1956 if(pc->type == PC_OPCODE) {
1959 if(pbr->pc->type == PC_LABEL) {
1960 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1970 /*-----------------------------------------------------------------*/
1971 /* findLabel - Search the pCode for a particular label */
1972 /*-----------------------------------------------------------------*/
1973 pCode * findLabel(pCodeOpLabel *pcop_label)
1981 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1982 for(pc = pb->pcHead; pc; pc = pc->next)
1983 if(compareLabel(pc,pcop_label))
1988 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1992 /*-----------------------------------------------------------------*/
1993 /* findNextInstruction - given a pCode, find the next instruction */
1994 /* in the linked list */
1995 /*-----------------------------------------------------------------*/
1996 pCode * findNextInstruction(pCode *pc)
2000 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2006 fprintf(stderr,"Couldn't find instruction\n");
2010 /*-----------------------------------------------------------------*/
2011 /* findFunctionEnd - given a pCode find the end of the function */
2012 /* that contains it t */
2013 /*-----------------------------------------------------------------*/
2014 pCode * findFunctionEnd(pCode *pc)
2018 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
2024 fprintf(stderr,"Couldn't find function end\n");
2029 /*-----------------------------------------------------------------*/
2030 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
2031 /* instruction with which it is associated. */
2032 /*-----------------------------------------------------------------*/
2033 static void AnalyzeLabel(pCode *pc)
2041 static void AnalyzeGOTO(pCode *pc)
2044 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2048 static void AnalyzeSKIP(pCode *pc)
2051 pBranchLink(pc,findNextInstruction(pc->next));
2052 pBranchLink(pc,findNextInstruction(pc->next->next));
2056 static void AnalyzeRETURN(pCode *pc)
2059 // branch_link(pc,findFunctionEnd(pc->next));
2063 /*-----------------------------------------------------------------*/
2064 /*-----------------------------------------------------------------*/
2066 void AnalyzepBlock(pBlock *pb)
2073 /* Find all of the registers used in this pBlock */
2074 for(pc = pb->pcHead; pc; pc = pc->next) {
2075 if(pc->type == PC_OPCODE) {
2076 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
2078 /* Loop through all of the registers declared so far in
2079 this block and see if we find this one there */
2081 regs *r = setFirstItem(pb->registers);
2084 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2085 PCOR(PCI(pc)->pcop)->r = r;
2088 r = setNextItem(pb->registers);
2092 /* register wasn't found */
2093 r = Safe_calloc(1, sizeof(regs));
2094 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2095 addSet(&pb->registers, r);
2096 PCOR(PCI(pc)->pcop)->r = r;
2097 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2099 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2105 /*-----------------------------------------------------------------*/
2106 /*-----------------------------------------------------------------*/
2107 int OptimizepBlock(pBlock *pb)
2112 if(!pb || !peepOptimizing)
2115 fprintf(stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb));
2116 for(pc = pb->pcHead; pc; pc = pc->next)
2117 matches += pCodePeepMatchRule(pc);
2123 /*-----------------------------------------------------------------*/
2124 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2125 /*-----------------------------------------------------------------*/
2126 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
2130 for(pc = pcs; pc; pc = pc->next) {
2132 if((pc->type == PC_OPCODE) &&
2134 (PCI(pc)->pcop->type == PO_LABEL) &&
2135 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
2143 /*-----------------------------------------------------------------*/
2144 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
2145 /* pCode chain if they're not used. */
2146 /*-----------------------------------------------------------------*/
2147 void pBlockRemoveUnusedLabels(pBlock *pb)
2149 pCode *pc; pCodeLabel *pcl;
2154 for(pc = pb->pcHead; pc; pc = pc->next) {
2156 if(pc->type == PC_LABEL)
2159 pcl = PCL(pc->label->pc);
2162 /* This pCode is a label, so search the pBlock to see if anyone
2165 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
2166 /* Couldn't find an instruction that refers to this label
2167 * So, unlink the pCode label from it's pCode chain
2168 * and destroy the label */
2170 fprintf(stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key);
2172 if(pc->type == PC_LABEL) {
2174 pCodeLabelDestruct(pc);
2176 unlinkpCodeFromBranch(pc, PCODE(pcl));
2177 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
2188 /*-----------------------------------------------------------------*/
2189 /* pBlockMergeLabels - remove the pCode labels from the pCode */
2190 /* chain and put them into pBranches that are */
2191 /* associated with the appropriate pCode */
2193 /*-----------------------------------------------------------------*/
2194 void pBlockMergeLabels(pBlock *pb)
2197 pCode *pc, *pcnext=NULL;
2202 /* First, Try to remove any unused labels */
2203 //pBlockRemoveUnusedLabels(pb);
2205 /* Now loop through the pBlock and merge the labels with the opcodes */
2207 for(pc = pb->pcHead; pc; pc = pc->next) {
2209 if(pc->type == PC_LABEL) {
2210 fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
2211 if( !(pcnext = findNextInstruction(pc)) )
2212 return; // Couldn't find an instruction associated with this label
2214 // Unlink the pCode label from it's pCode chain
2217 fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
2218 // And link it into the instruction's pBranch labels. (Note, since
2219 // it's possible to have multiple labels associated with one instruction
2220 // we must provide a means to accomodate the additional labels. Thus
2221 // the labels are placed into the singly-linked list "label" as
2222 // opposed to being a single member of the pCodeInstruction.)
2224 _ALLOC(pbr,sizeof(pBranch));
2228 pcnext->label = pBranchAppend(pcnext->label,pbr);
2236 pBlockRemoveUnusedLabels(pb);
2240 /*-----------------------------------------------------------------*/
2241 /*-----------------------------------------------------------------*/
2242 void OptimizepCode(char dbName)
2244 #define MAX_PASSES 4
2253 fprintf(stderr," Optimizing pCode\n");
2256 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2257 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2258 matches += OptimizepBlock(pb);
2261 while(matches && ++passes < MAX_PASSES);
2265 /*-----------------------------------------------------------------*/
2266 /* AnalyzepCode - parse the pCode that has been generated and form */
2267 /* all of the logical connections. */
2269 /* Essentially what's done here is that the pCode flow is */
2271 /*-----------------------------------------------------------------*/
2273 void AnalyzepCode(char dbName)
2284 fprintf(stderr," Analyzing pCode");
2289 /* First, merge the labels with the instructions */
2290 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2291 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2293 fprintf(stderr," analyze and merging block %c\n",dbName);
2294 pBlockMergeLabels(pb);
2299 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2300 if('*' == dbName || getpBlock_dbName(pb) == dbName)
2301 changes += OptimizepBlock(pb);
2304 } while(changes && (i++ < MAX_PASSES));
2306 /* Now build the call tree.
2307 First we examine all of the pCodes for functions.
2308 Keep in mind that the function boundaries coincide
2309 with pBlock boundaries.
2311 The algorithm goes something like this:
2312 We have two nested loops. The outer loop iterates
2313 through all of the pBlocks/functions. The inner
2314 loop iterates through all of the pCodes for
2315 a given pBlock. When we begin iterating through
2316 a pBlock, the variable pc_fstart, pCode of the start
2317 of a function, is cleared. We then search for pCodes
2318 of type PC_FUNCTION. When one is encountered, we
2319 initialize pc_fstart to this and at the same time
2320 associate a new pBranch object that signifies a
2321 branch entry. If a return is found, then this signifies
2322 a function exit point. We'll link the pCodes of these
2323 returns to the matching pc_fstart.
2325 When we're done, a doubly linked list of pBranches
2326 will exist. The head of this list is stored in
2327 `the_pFile', which is the meta structure for all
2328 of the pCode. Look at the printCallTree function
2329 on how the pBranches are linked together.
2332 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2333 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2334 pCode *pc_fstart=NULL;
2335 for(pc = pb->pcHead; pc; pc = pc->next) {
2336 if(pc->type == PC_FUNCTION) {
2337 if (PCF(pc)->fname) {
2338 // I'm not liking this....
2339 // Found the beginning of a function.
2340 _ALLOC(pbr,sizeof(pBranch));
2341 pbr->pc = pc_fstart = pc;
2344 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2346 // Here's a better way of doing the same:
2347 addSet(&pb->function_entries, pc);
2350 // Found an exit point in a function, e.g. return
2351 // (Note, there may be more than one return per function)
2353 pBranchLink(pc_fstart, pc);
2355 addSet(&pb->function_exits, pc);
2357 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2358 addSet(&pb->function_calls,pc);
2365 /*-----------------------------------------------------------------*/
2366 /* ispCodeFunction - returns true if *pc is the pCode of a */
2368 /*-----------------------------------------------------------------*/
2369 bool ispCodeFunction(pCode *pc)
2372 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2378 /*-----------------------------------------------------------------*/
2379 /* findFunction - Search for a function by name (given the name) */
2380 /* in the set of all functions that are in a pBlock */
2381 /* (note - I expect this to change because I'm planning to limit */
2382 /* pBlock's to just one function declaration */
2383 /*-----------------------------------------------------------------*/
2384 pCode *findFunction(char *fname)
2391 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2393 pc = setFirstItem(pb->function_entries);
2396 if((pc->type == PC_FUNCTION) &&
2398 (strcmp(fname, PCF(pc)->fname)==0))
2401 pc = setNextItem(pb->function_entries);
2409 void MarkUsedRegisters(set *regset)
2414 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2415 r2 = pic14_regWithIdx(r1->rIdx);
2421 void pBlockStats(FILE *of, pBlock *pb)
2427 fprintf(of,";***\n; pBlock Stats\n;***\n");
2429 // for now just print the first element of each set
2430 pc = setFirstItem(pb->function_entries);
2432 fprintf(of,";entry: ");
2435 pc = setFirstItem(pb->function_exits);
2437 fprintf(of,";has an exit\n");
2441 pc = setFirstItem(pb->function_calls);
2443 fprintf(of,";functions called:\n");
2448 pc = setNextItem(pb->function_calls);
2452 r = setFirstItem(pb->registers);
2454 int n = elementsInSet(pb->registers);
2456 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2459 fprintf(of,"; %s\n",r->name);
2460 r = setNextItem(pb->registers);
2465 /*-----------------------------------------------------------------*/
2466 /*-----------------------------------------------------------------*/
2467 void sequencepCode(void)
2473 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2475 pb->seq = GpCodeSequenceNumber+1;
2477 for( pc = pb->pcHead; pc; pc = pc->next)
2478 pc->seq = ++GpCodeSequenceNumber;
2483 /*-----------------------------------------------------------------*/
2484 /*-----------------------------------------------------------------*/
2485 set *register_usage(pBlock *pb)
2488 set *registers=NULL;
2489 set *registersInCallPath = NULL;
2491 /* check recursion */
2493 pc = setFirstItem(pb->function_entries);
2500 if(pc->type != PC_FUNCTION)
2501 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2503 pc = setFirstItem(pb->function_calls);
2504 for( ; pc; pc = setNextItem(pb->function_calls)) {
2506 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2507 char *dest = get_op(PCI(pc));
2509 pcn = findFunction(dest);
2511 registersInCallPath = register_usage(pcn->pb);
2513 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2518 pBlockStats(stderr,pb); // debug
2520 // Mark the registers in this block as used.
2522 MarkUsedRegisters(pb->registers);
2523 if(registersInCallPath) {
2524 /* registers were used in the functions this pBlock has called */
2525 /* so now, we need to see if these collide with the ones we are */
2528 regs *r1,*r2, *newreg;
2530 fprintf(stderr,"comparing registers\n");
2532 r1 = setFirstItem(registersInCallPath);
2535 r2 = setFirstItem(pb->registers);
2537 while(r2 && (r1->type != REG_STK)) {
2539 if(r2->rIdx == r1->rIdx) {
2540 newreg = pic14_findFreeReg(REG_GPR);
2544 fprintf(stderr,"Bummer, no more registers.\n");
2548 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2549 r1->rIdx, newreg->rIdx);
2550 r2->rIdx = newreg->rIdx;
2551 //if(r2->name) free(r2->name);
2553 r2->name = Safe_strdup(newreg->name);
2557 newreg->wasUsed = 1;
2559 r2 = setNextItem(pb->registers);
2562 r1 = setNextItem(registersInCallPath);
2565 /* Collisions have been resolved. Now free the registers in the call path */
2566 r1 = setFirstItem(registersInCallPath);
2568 if(r1->type != REG_STK) {
2569 newreg = pic14_regWithIdx(r1->rIdx);
2572 r1 = setNextItem(registersInCallPath);
2576 // MarkUsedRegisters(pb->registers);
2578 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2581 fprintf(stderr,"returning regs\n");
2583 fprintf(stderr,"not returning regs\n");
2585 fprintf(stderr,"pBlock after register optim.\n");
2586 pBlockStats(stderr,pb); // debug
2592 /*-----------------------------------------------------------------*/
2593 /* printCallTree - writes the call tree to a file */
2595 /*-----------------------------------------------------------------*/
2596 void pct2(FILE *of,pBlock *pb,int indent)
2600 // set *registersInCallPath = NULL;
2603 return;// registers;
2606 return; // registers; //recursion ?
2608 pc = setFirstItem(pb->function_entries);
2615 for(i=0;i<indent;i++) // Indentation
2618 if(pc->type == PC_FUNCTION)
2619 fprintf(of,"%s\n",PCF(pc)->fname);
2624 pc = setFirstItem(pb->function_calls);
2625 for( ; pc; pc = setNextItem(pb->function_calls)) {
2627 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2628 char *dest = get_op(PCI(pc));
2630 pcn = findFunction(dest);
2632 pct2(of,pcn->pb,indent+1);
2634 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2642 fprintf(stderr,"pBlock before register optim.\n");
2643 pBlockStats(stderr,pb); // debug
2645 if(registersInCallPath) {
2646 /* registers were used in the functions this pBlock has called */
2647 /* so now, we need to see if these collide with the ones we are using here */
2649 regs *r1,*r2, *newreg;
2651 fprintf(stderr,"comparing registers\n");
2653 r1 = setFirstItem(registersInCallPath);
2656 r2 = setFirstItem(pb->registers);
2660 if(r2->rIdx == r1->rIdx) {
2661 newreg = pic14_findFreeReg();
2665 fprintf(stderr,"Bummer, no more registers.\n");
2669 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2670 r1->rIdx, newreg->rIdx);
2671 r2->rIdx = newreg->rIdx;
2672 //if(r2->name) free(r2->name);
2674 r2->name = Safe_strdup(newreg->name);
2678 newreg->wasUsed = 1;
2680 r2 = setNextItem(pb->registers);
2683 r1 = setNextItem(registersInCallPath);
2686 /* Collisions have been resolved. Now free the registers in the call path */
2687 r1 = setFirstItem(registersInCallPath);
2689 newreg = pic14_regWithIdx(r1->rIdx);
2691 r1 = setNextItem(registersInCallPath);
2695 MarkUsedRegisters(pb->registers);
2697 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2700 fprintf(stderr,"returning regs\n");
2702 fprintf(stderr,"not returning regs\n");
2704 fprintf(stderr,"pBlock after register optim.\n");
2705 pBlockStats(stderr,pb); // debug
2713 /*-----------------------------------------------------------------*/
2714 /* printCallTree - writes the call tree to a file */
2716 /*-----------------------------------------------------------------*/
2718 void printCallTree(FILE *of)
2730 fprintf(of, "\npBlock statistics\n");
2731 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2732 pBlockStats(stderr,pb);
2736 fprintf(of,"Call Tree\n");
2737 pbr = the_pFile->functions;
2741 if(!ispCodeFunction(pc))
2742 fprintf(of,"bug in call tree");
2745 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2747 while(pc->next && !ispCodeFunction(pc->next)) {
2749 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2750 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2758 /* Re-allocate the registers so that there are no collisions
2759 * between local variables when one function call another */
2761 pic14_deallocateAllRegs();
2763 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2768 fprintf(of,"\n**************\n\na better call tree\n");
2769 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2774 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2775 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));