1 /*-------------------------------------------------------------------------
3 pcode.h - 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
28 // Eventually this will go into device dependent files:
29 pCodeOp pc_status = {PO_STATUS, "STATUS"};
30 pCodeOp pc_indf = {PO_INDF, "INDF"};
31 pCodeOp pc_fsr = {PO_FSR, "FSR"};
33 //static char *PIC_mnemonics[] = {
34 static char *scpADDLW = "ADDLW";
35 static char *scpADDWF = "ADDWF";
36 static char *scpANDLW = "ANDLW";
37 static char *scpANDWF = "ANDWF";
38 static char *scpBCF = "BCF";
39 static char *scpBSF = "BSF";
40 static char *scpBTFSC = "BTFSC";
41 static char *scpBTFSS = "BTFSS";
42 static char *scpCALL = "CALL";
43 static char *scpCOMF = "COMF";
44 static char *scpCLRF = "CLRF";
45 static char *scpCLRW = "CLRW";
46 static char *scpDECF = "DECF";
47 static char *scpDECFSZ = "DECFSZ";
48 static char *scpGOTO = "GOTO";
49 static char *scpINCF = "INCF";
50 static char *scpINCFSZ = "INCFSZ";
51 static char *scpIORLW = "IORLW";
52 static char *scpIORWF = "IORWF";
53 static char *scpMOVF = "MOVF";
54 static char *scpMOVLW = "MOVLW";
55 static char *scpMOVWF = "MOVWF";
56 static char *scpNEGF = "NEGF";
57 static char *scpRETLW = "RETLW";
58 static char *scpRETURN = "RETURN";
59 static char *scpSUBLW = "SUBLW";
60 static char *scpSUBWF = "SUBWF";
61 static char *scpTRIS = "TRIS";
62 static char *scpXORLW = "XORLW";
63 static char *scpXORWF = "XORWF";
66 static pFile *the_pFile = NULL;
67 static int peepOptimizing = 1;
69 /****************************************************************/
70 /****************************************************************/
78 typedef struct pCodePeepSnippets
85 static pCodePeepSnippets *peepSnippets=NULL;
87 /****************************************************************/
88 /* Forward declarations */
89 /****************************************************************/
91 static void unlink(pCode *pc);
92 static void genericAnalyze(pCode *pc);
93 static void AnalyzeGOTO(pCode *pc);
94 static void AnalyzeSKIP(pCode *pc);
95 static void AnalyzeRETURN(pCode *pc);
97 static void genericDestruct(pCode *pc);
98 static void genericPrint(FILE *of,pCode *pc);
100 static void pCodePrintLabel(FILE *of, pCode *pc);
101 static void pCodePrintFunction(FILE *of, pCode *pc);
102 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
103 static char *get_op( pCodeInstruction *pcc);
104 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
105 int pCodePeepMatchRule(pCode *pc);
108 char *Safe_strdup(char *str)
117 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
125 void copypCode(FILE *of, char dbName)
129 if(!of || !the_pFile)
132 fprintf(of,";dumping pcode to a file");
134 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
135 if(pb->cmemmap->dbName == dbName)
140 void pcode_test(void)
143 printf("pcode is alive!\n");
151 /* create the file name */
152 strcpy(buffer,srcFileName);
155 if( !(pFile = fopen(buffer, "w" ))) {
156 werror(E_FILE_OPEN_ERR,buffer);
160 fprintf(pFile,"pcode dump\n\n");
162 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
163 fprintf(pFile,"\n\tNew pBlock\n\n");
164 fprintf(pFile,"%s, dbName =%c\n",pb->cmemmap->sname,pb->cmemmap->dbName);
165 printpBlock(pFile,pb);
170 /*-----------------------------------------------------------------*/
171 /* newpCode - create and return a newly initialized pCode */
172 /*-----------------------------------------------------------------*/
173 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
175 pCodeInstruction *pci ;
178 pci = Safe_calloc(1, sizeof(pCodeInstruction));
179 pci->pc.analyze = genericAnalyze;
180 pci->pc.destruct = genericDestruct;
181 pci->pc.type = PC_OPCODE;
183 pci->pc.prev = pci->pc.next = NULL;
188 pci->inCond = pci->outCond = PCC_NONE;
189 pci->pc.print = genericPrint;
190 pci->pc.from = pci->pc.to = pci->pc.label = NULL;
192 if(pcop && pcop->name)
193 printf("newpCode operand name %s\n",pcop->name);
199 pci->outCond = PCC_W | PCC_Z;
200 pci->mnemonic = scpANDLW;
205 pci->inCond = PCC_W | PCC_REGISTER;
206 pci->outCond = PCC_REGISTER | PCC_Z;
207 pci->mnemonic = scpANDWF;
210 pci->inCond = PCC_W | PCC_REGISTER;
211 pci->outCond = PCC_W | PCC_Z;
212 pci->mnemonic = scpANDWF;
217 pci->outCond = PCC_W | PCC_Z | PCC_C | PCC_DC;
218 pci->mnemonic = scpADDLW;
223 pci->inCond = PCC_W | PCC_REGISTER;
224 pci->outCond = PCC_REGISTER | PCC_Z | PCC_C | PCC_DC;
225 pci->mnemonic = scpADDWF;
228 pci->inCond = PCC_W | PCC_REGISTER;
229 pci->outCond = PCC_W | PCC_Z | PCC_C | PCC_DC;
230 pci->mnemonic = scpADDWF;
235 pci->mnemonic = scpBCF;
239 pci->mnemonic = scpBSF;
243 pci->mnemonic = scpBTFSC;
244 pci->pc.analyze = AnalyzeSKIP;
248 pci->mnemonic = scpBTFSS;
249 pci->pc.analyze = AnalyzeSKIP;
253 pci->mnemonic = scpCALL;
256 pci->mnemonic = scpCOMF;
260 pci->mnemonic = scpCLRF;
264 pci->mnemonic = scpCLRW;
269 pci->mnemonic = scpDECF;
274 pci->mnemonic = scpDECFSZ;
275 pci->pc.analyze = AnalyzeSKIP;
279 pci->mnemonic = scpGOTO;
280 pci->pc.analyze = AnalyzeGOTO;
285 pci->mnemonic = scpINCF;
290 pci->mnemonic = scpINCFSZ;
291 pci->pc.analyze = AnalyzeSKIP;
295 pci->mnemonic = scpIORLW;
300 pci->mnemonic = scpIORWF;
305 pci->mnemonic = scpMOVF;
309 pci->mnemonic = scpMOVLW;
313 pci->mnemonic = scpMOVWF;
316 pci->mnemonic = scpNEGF;
320 pci->mnemonic = scpRETLW;
321 pci->pc.analyze = AnalyzeRETURN;
325 pci->mnemonic = scpRETURN;
326 pci->pc.analyze = AnalyzeRETURN;
329 pci->mnemonic = scpSUBLW;
335 pci->mnemonic = scpSUBWF;
338 pci->mnemonic = scpTRIS;
342 pci->mnemonic = scpXORLW;
347 pci->mnemonic = scpXORWF;
351 pci->pc.print = genericPrint;
357 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
362 pcw = Safe_calloc(1,sizeof(pCodeWild));
364 pcw->pc.type = PC_WILD;
365 pcw->pc.prev = pcw->pc.next = NULL;
366 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
368 pcw->pc.analyze = genericAnalyze;
369 pcw->pc.destruct = genericDestruct;
370 pcw->pc.print = genericPrint;
373 pcw->operand = optional_operand;
374 pcw->label = optional_label;
376 return ( (pCode *)pcw);
380 /*-----------------------------------------------------------------*/
381 /* newPcodeCharP - create a new pCode from a char string */
382 /*-----------------------------------------------------------------*/
384 pCode *newpCodeCharP(char *cP)
389 pcc = Safe_calloc(1,sizeof(pCodeComment));
391 pcc->pc.type = PC_COMMENT;
392 pcc->pc.prev = pcc->pc.next = NULL;
393 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
395 pcc->pc.analyze = genericAnalyze;
396 pcc->pc.destruct = genericDestruct;
397 pcc->pc.print = genericPrint;
399 pcc->comment = Safe_strdup(cP);
401 return ( (pCode *)pcc);
405 /*-----------------------------------------------------------------*/
406 /* newpCodeGLabel - create a new global label */
407 /*-----------------------------------------------------------------*/
410 pCode *newpCodeFunction(char *mod,char *f)
414 _ALLOC(pcf,sizeof(pCodeFunction));
416 pcf->pc.type = PC_FUNCTION;
417 pcf->pc.prev = pcf->pc.next = NULL;
418 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
420 pcf->pc.analyze = genericAnalyze;
421 pcf->pc.destruct = genericDestruct;
422 pcf->pc.print = pCodePrintFunction;
425 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
426 strcpy(pcf->modname,mod);
431 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
432 strcpy(pcf->fname,f);
436 return ( (pCode *)pcf);
441 pCode *newpCodeLabel(int key)
447 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
449 pcl->pc.type = PC_LABEL;
450 pcl->pc.prev = pcl->pc.next = NULL;
451 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
453 pcl->pc.analyze = genericAnalyze;
454 pcl->pc.destruct = genericDestruct;
455 pcl->pc.print = pCodePrintLabel;
460 sprintf(s,"_%05d_DS_",key);
461 pcl->label = Safe_strdup(s);
465 return ( (pCode *)pcl);
469 /*-----------------------------------------------------------------*/
470 /* newpBlock - create and return a pointer to a new pBlock */
471 /*-----------------------------------------------------------------*/
472 pBlock *newpBlock(void)
477 _ALLOC(PpB,sizeof(pBlock));
478 PpB->next = PpB->prev = NULL;
484 /*-----------------------------------------------------------------*/
485 /* newpCodeChain - create a new chain of pCodes */
486 /*-----------------------------------------------------------------*
488 * This function will create a new pBlock and the pointer to the
489 * pCode that is passed in will be the first pCode in the block.
490 *-----------------------------------------------------------------*/
493 pBlock *newpCodeChain(memmap *cm,pCode *pc)
496 pBlock *pB = newpBlock();
498 pB->pcHead = pB->pcTail = pc;
504 /*-----------------------------------------------------------------*/
505 /*-----------------------------------------------------------------*/
507 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
511 pcop = Safe_calloc(1,sizeof(pCodeOp) );
513 pcop->name = Safe_strdup(name);
518 /*-----------------------------------------------------------------*/
519 /* newpCodeOpLabel - Create a new label given the key */
520 /* Note, a negative key means that the label is part of wild card */
521 /* (and hence a wild card label) used in the pCodePeep */
522 /* optimizations). */
523 /*-----------------------------------------------------------------*/
525 pCodeOp *newpCodeOpLabel(int key)
530 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
531 pcop->type = PO_LABEL;
534 sprintf(s,"_%05d_DS_",key);
535 pcop->name = Safe_strdup(s);
539 ((pCodeOpLabel *)pcop)->key = key;
544 pCodeOp *newpCodeOpLit(int lit)
550 _ALLOC(pcop,sizeof(pCodeOpLit) );
551 pcop->type = PO_LITERAL;
552 sprintf(s,"0x%02x",lit);
553 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
554 strcpy(pcop->name,s);
555 ((pCodeOpLit *)pcop)->lit = lit;
560 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
566 if(!pcp || !subtype) {
567 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
571 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
572 pcop->type = PO_WILD;
573 sprintf(s,"%%%d",id);
574 pcop->name = Safe_strdup(s);
577 PCOW(pcop)->pcp = pcp;
578 PCOW(pcop)->subtype = subtype;
583 pCodeOp *newpCodeOpBit(char *s, int bit)
587 _ALLOC(pcop,sizeof(pCodeOpBit) );
589 pcop->name = Safe_strdup(s);
590 PCOB(pcop)->bit = bit;
591 PCOB(pcop)->inBitSpace = 1;
596 /*-----------------------------------------------------------------*/
597 /* addpCode2pBlock - place the pCode into the pBlock linked list */
598 /*-----------------------------------------------------------------*/
599 void addpCode2pBlock(pBlock *pb, pCode *pc)
602 pb->pcTail->next = pc;
603 pc->prev = pb->pcTail;
608 /*-----------------------------------------------------------------*/
609 /* addpBlock - place a pBlock into the pFile */
610 /*-----------------------------------------------------------------*/
611 void addpBlock(pBlock *pb)
615 /* First time called, we'll pass through here. */
616 _ALLOC(the_pFile,sizeof(the_pFile));
617 the_pFile->pbHead = the_pFile->pbTail = pb;
618 the_pFile->functions = NULL;
622 the_pFile->pbTail->next = pb;
623 pb->prev = the_pFile->pbTail;
625 the_pFile->pbTail = pb;
628 void printpCodeString(FILE *of, pCode *pc, int max)
632 while(pc && (i++<max)) {
637 /*-----------------------------------------------------------------*/
638 /* printpCode - write the contents of a pCode to a file */
639 /*-----------------------------------------------------------------*/
640 void printpCode(FILE *of, pCode *pc)
651 fprintf(of,"warning - unable to print pCode\n");
654 /*-----------------------------------------------------------------*/
655 /* printpBlock - write the contents of a pBlock to a file */
656 /*-----------------------------------------------------------------*/
657 void printpBlock(FILE *of, pBlock *pb)
667 for(pc = pb->pcHead; pc; pc = pc->next)
672 /*-----------------------------------------------------------------*/
674 /* pCode processing */
676 /* The stuff that follows is very PIC specific! */
681 /*-----------------------------------------------------------------*/
683 static void unlink(pCode *pc)
685 if(pc && pc->prev && pc->next) {
687 pc->prev->next = pc->next;
688 pc->next->prev = pc->prev;
691 static void genericDestruct(pCode *pc)
695 fprintf(stderr,"warning, calling default pCode destructor\n");
699 static char *get_op( pCodeInstruction *pcc)
701 if(pcc && pcc->pcop && pcc->pcop->name)
702 return pcc->pcop->name;
706 /*-----------------------------------------------------------------*/
707 /*-----------------------------------------------------------------*/
708 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
711 fprintf(of,"pcodeopprint\n");
714 /*-----------------------------------------------------------------*/
715 /* genericPrint - the contents of a pCode to a file */
716 /*-----------------------------------------------------------------*/
717 static void genericPrint(FILE *of, pCode *pc)
725 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
729 // If the opcode has a label, print that first
731 pBranch *pbl = pc->label;
733 if(pbl->pc->type == PC_LABEL)
734 pCodePrintLabel(of, pbl->pc);
739 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
740 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
742 if(PCI(pc)->bit_inst) {
743 if(PCI(pc)->pcop->type == PO_BIT) {
744 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
745 fprintf(of,"(%s >> 3), (%s & 7)",
746 PCI(pc)->pcop->name ,
747 PCI(pc)->pcop->name );
749 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
751 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
752 //PCI(pc)->pcop->t.bit );
755 if(PCI(pc)->pcop->type == PO_BIT) {
756 if( PCI(pc)->num_ops == 2)
757 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
759 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
761 fprintf(of,"%s",get_op(PCI(pc)));
763 if( PCI(pc)->num_ops == 2)
764 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
770 pBranch *dpb = pc->to; // debug
772 switch ( dpb->pc->type) {
774 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
777 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
780 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
794 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
795 if(PCW(pc)->operand) {
796 fprintf(of,";\toperand ");
797 pCodeOpPrint(of,PCW(pc)->operand );
803 fprintf(of,"unknown pCode type %d\n",pc->type);
808 /*-----------------------------------------------------------------*/
809 /* pCodePrintFunction - prints function begin/end */
810 /*-----------------------------------------------------------------*/
812 static void pCodePrintFunction(FILE *of, pCode *pc)
818 if( ((pCodeFunction *)pc)->modname)
819 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
822 pBranch *exits = pc->to;
824 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
830 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
834 pc->from->pc->type == PC_FUNCTION &&
835 PCF(pc->from->pc)->fname)
836 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
838 fprintf(of,"; exit point [can't find entry point]\n");
841 /*-----------------------------------------------------------------*/
842 /* pCodePrintLabel - prints label */
843 /*-----------------------------------------------------------------*/
845 static void pCodePrintLabel(FILE *of, pCode *pc)
852 fprintf(of,"%s\n",PCL(pc)->label);
853 else if (PCL(pc)->key >=0)
854 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
856 fprintf(of,";wild card label\n");
860 /*-----------------------------------------------------------------*/
861 /* _DLL * DLL_append */
863 /* Append a _DLL object to the end of a _DLL (doubly linked list) */
864 /* If The list to which we want to append is non-existant then one */
865 /* is created. Other wise, the end of the list is sought out and */
866 /* a new DLL object is appended to it. In either case, the void */
867 /* *data is added to the newly created DLL object. */
868 /*-----------------------------------------------------------------*/
870 static void * DLL_append(_DLL *list, _DLL *next)
875 /* If there's no list, then create one: */
877 next->next = next->prev = NULL;
882 /* Search for the end of the list. */
887 /* Now append the new DLL object */
896 /*-----------------------------------------------------------------*/
898 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
914 /*-----------------------------------------------------------------*/
915 /* pBranchLink - given two pcodes, this function will link them */
916 /* together through their pBranches */
917 /*-----------------------------------------------------------------*/
918 static void pBranchLink(pCode *f, pCode *t)
922 // Declare a new branch object for the 'from' pCode.
924 _ALLOC(b,sizeof(pBranch));
925 b->pc = t; // The link to the 'to' pCode.
928 f->to = pBranchAppend(f->to,b);
930 // Now do the same for the 'to' pCode.
932 _ALLOC(b,sizeof(pBranch));
936 t->from = pBranchAppend(t->from,b);
941 /*-----------------------------------------------------------------*/
942 /* pBranchFind - find the pBranch in a pBranch chain that contains */
944 /*-----------------------------------------------------------------*/
945 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
958 /*-----------------------------------------------------------------*/
959 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
960 /*-----------------------------------------------------------------*/
961 static void pCodeUnlink(pCode *pc)
966 if(!pc->prev || !pc->next) {
967 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
971 /* first remove the pCode from the chain */
972 pc->prev->next = pc->next;
973 pc->next->prev = pc->prev;
975 /* Now for the hard part... */
977 /* Remove the branches */
981 pc1 = pb1->pc; /* Get the pCode that branches to the
982 * one we're unlinking */
984 /* search for the link back to this pCode (the one we're
986 if(pb2 = pBranchFind(pc1->to,pc)) {
987 pb2->pc = pc->to->pc; // make the replacement
989 /* if the pCode we're unlinking contains multiple 'to'
990 * branches (e.g. this a skip instruction) then we need
991 * to copy these extra branches to the chain. */
993 pBranchAppend(pb2, pc->to->next);
1002 /*-----------------------------------------------------------------*/
1003 /*-----------------------------------------------------------------*/
1004 static void genericAnalyze(pCode *pc)
1014 // Go through the pCodes that are in pCode chain and link
1015 // them together through the pBranches. Note, the pCodes
1016 // are linked together as a contiguous stream like the
1017 // assembly source code lines. The linking here mimics this
1018 // except that comments are not linked in.
1020 pCode *npc = pc->next;
1022 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1023 pBranchLink(pc,npc);
1032 /*-----------------------------------------------------------------*/
1033 /* findLabel - Search the pCode for a particular label */
1034 /*-----------------------------------------------------------------*/
1035 pCode * findLabel(pCodeOpLabel *pcop_label)
1044 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1045 for(pc = pb->pcHead; pc; pc = pc->next) {
1046 if(pc->type == PC_LABEL) {
1047 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1050 if(pc->type == PC_OPCODE) {
1053 if(pbr->pc->type == PC_LABEL) {
1054 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1064 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1068 /*-----------------------------------------------------------------*/
1069 /* findNextInstruction - given a pCode, find the next instruction */
1070 /* in the linked list */
1071 /*-----------------------------------------------------------------*/
1072 pCode * findNextInstruction(pCode *pc)
1076 if(pc->type == PC_OPCODE)
1082 fprintf(stderr,"Couldn't find instruction\n");
1086 /*-----------------------------------------------------------------*/
1087 /* findFunctionEnd - given a pCode find the end of the function */
1088 /* that contains it t */
1089 /*-----------------------------------------------------------------*/
1090 pCode * findFunctionEnd(pCode *pc)
1094 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1100 fprintf(stderr,"Couldn't find function end\n");
1105 /*-----------------------------------------------------------------*/
1106 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1107 /* instruction with which it is associated. */
1108 /*-----------------------------------------------------------------*/
1109 static void AnalyzeLabel(pCode *pc)
1117 static void AnalyzeGOTO(pCode *pc)
1120 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1124 static void AnalyzeSKIP(pCode *pc)
1127 pBranchLink(pc,findNextInstruction(pc->next));
1128 pBranchLink(pc,findNextInstruction(pc->next->next));
1132 static void AnalyzeRETURN(pCode *pc)
1135 // branch_link(pc,findFunctionEnd(pc->next));
1140 void AnalyzepBlock(pBlock *pb)
1147 for(pc = pb->pcHead; pc; pc = pc->next)
1152 int OptimizepBlock(pBlock *pb)
1157 if(!pb || !peepOptimizing)
1160 fprintf(stderr," Optimizing pBlock\n");
1162 for(pc = pb->pcHead; pc; pc = pc->next)
1163 matches += pCodePeepMatchRule(pc);
1168 /*-----------------------------------------------------------------*/
1169 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1170 /* chain and put them into pBranches that are */
1171 /* associated with the appropriate pCode */
1173 /*-----------------------------------------------------------------*/
1174 void pBlockMergeLabels(pBlock *pb)
1177 pCode *pc, *pcnext=NULL;
1182 for(pc = pb->pcHead; pc; pc = pc->next) {
1184 if(pc->type == PC_LABEL) {
1185 if( !(pcnext = findNextInstruction(pc)) )
1186 return; // Couldn't find an instruction associated with this label
1188 // Unlink the pCode label from it's pCode chain
1190 pc->prev->next = pc->next;
1192 pc->next->prev = pc->prev;
1194 // And link it into the instruction's pBranch labels. (Note, since
1195 // it's possible to have multiple labels associated with one instruction
1196 // we must provide a means to accomodate the additional labels. Thus
1197 // the labels are placed into the singly-linked list "label" as
1198 // opposed to being a single member of the pCodeInstruction.)
1200 _ALLOC(pbr,sizeof(pBranch));
1204 pcnext->label = pBranchAppend(pcnext->label,pbr);
1211 /*-----------------------------------------------------------------*/
1212 /*-----------------------------------------------------------------*/
1213 void OptimizepCode(char dbName)
1215 #define MAX_PASSES 4
1224 fprintf(stderr," Optimizing pCode\n");
1227 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1228 if(pb->cmemmap->dbName == dbName)
1229 matches += OptimizepBlock(pb);
1232 while(matches && ++passes < MAX_PASSES);
1236 /*-----------------------------------------------------------------*/
1237 /* AnalyzepCode - parse the pCode that has been generated and form */
1238 /* all of the logical connections. */
1240 /* Essentially what's done here is that the pCode flow is */
1242 /*-----------------------------------------------------------------*/
1244 void AnalyzepCode(char dbName)
1253 fprintf(stderr," Analyzing pCode");
1255 /* First, merge the labels with the instructions */
1256 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1257 if(pb->cmemmap->dbName == dbName)
1258 pBlockMergeLabels(pb);
1261 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1262 if(pb->cmemmap->dbName == dbName)
1266 /* Now build the call tree.
1267 First we examine all of the pCodes for functions.
1270 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1271 if(pb->cmemmap->dbName == dbName) {
1272 pCode *pc_fstart=NULL;
1273 for(pc = pb->pcHead; pc; pc = pc->next) {
1274 if(pc->type == PC_FUNCTION) {
1275 if (PCF(pc)->fname) {
1276 // Found the beginning of a function.
1277 _ALLOC(pbr,sizeof(pBranch));
1278 pbr->pc = pc_fstart = pc;
1281 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1283 // Found an exit point in a function, e.g. return
1284 // (Note, there may be more than one return per function)
1286 pBranchLink(pc_fstart, pc);
1294 /*-----------------------------------------------------------------*/
1295 /* ispCodeFunction - returns true if *pc is the pCode of a */
1297 /*-----------------------------------------------------------------*/
1298 bool ispCodeFunction(pCode *pc)
1301 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
1307 void printCallTree(FILE *of)
1317 pbr = the_pFile->functions;
1319 fprintf(of,"Call Tree\n");
1322 pCode *pc = pbr->pc;
1323 if(!ispCodeFunction(pc))
1324 fprintf(of,"bug in call tree");
1327 fprintf(of,"Function: %s\n", PCF(pc)->fname);
1329 while(pc->next && !ispCodeFunction(pc->next)) {
1331 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
1332 fprintf(of,"\t%s\n",get_op(PCI(pc)));
1339 /*-----------------------------------------------------------------
1341 pCode peephole optimization
1344 The pCode "peep hole" optimization is not too unlike the peep hole
1345 optimization in SDCCpeeph.c. The major difference is that here we
1346 use pCode's whereas there we use ASCII strings. The advantage with
1347 pCode's is that we can ascertain flow information in the instructions
1351 <FIX ME> - elaborate...
1353 -----------------------------------------------------------------*/
1356 /*-----------------------------------------------------------------*/
1358 /*-----------------------------------------------------------------*/
1359 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1361 pCode *pcfrom,*pcto;
1364 for( pcto=pcp->target; pcto; pcto=pcto->next) {
1366 pcfrom = findNextInstruction(pcfrom);
1369 (PCI(pcfrom)->op == PCI(pcto)->op ||
1370 PCI(pcto)->op == POC_WILD))
1377 /*-----------------------------------------------------------------*/
1379 /*-----------------------------------------------------------------*/
1380 void pCodePeepSearch(pCodePeep *snippet)
1388 /* compare the chain to the pCode that we've
1389 got so far. If a match is found, then replace
1392 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1393 for(pc = pb->pcHead; pc; pc = pc->next) {
1394 pCodePeepCompare(pc,snippet);
1402 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1419 void pCodePeepInit(void)
1424 pCodePeepSnippets *pcps;
1426 /* Declare a peep code snippet */
1427 /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1428 /* e.g. I could put the DLL into the pCodePeep structure */
1429 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1430 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1431 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1434 pb = newpCodeChain(NULL, newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1435 addpCode2pBlock( pb, newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1439 pcp->replace = newpCodeChain(NULL, newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
1441 /* Allocate space to store pointers to the wildcard variables */
1443 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1444 pcp->nwildpCodes = 0;
1445 pcp->wildpCodes = NULL;
1447 pcp->postFalseCond = PCC_Z;
1448 pcp->postTrueCond = PCC_NONE;
1450 fprintf(stderr,"Peep rule\nTarget:\n");
1451 printpCodeString(stderr,pcp->target->pcHead, 10);
1452 fprintf(stderr,"Replaced with:\n");
1453 printpCodeString(stderr,pcp->replace->pcHead, 10);
1455 /* Now for another peep example */
1456 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1457 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1458 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1464 pb = newpCodeChain(NULL, newpCode(POC_BTFSC, newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1))) );
1466 pcl = newpCodeOpLabel(-1);
1467 pcw = newpCodeOpWild(1, pcp, pcl);
1468 addpCode2pBlock( pb, newpCode(POC_GOTO, pcw));
1469 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1470 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1475 pb = newpCodeChain(NULL, newpCode(POC_BTFSS, newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1))) );
1476 addpCode2pBlock( pb, newpCodeWild(0,NULL,NULL));
1477 addpCode2pBlock( pb, newpCodeWild(1,NULL,pcw));
1481 /* Allocate space to store pointers to the wildcard variables */
1483 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1484 pcp->nwildpCodes = 2;
1485 pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
1487 pcp->postFalseCond = PCC_NONE;
1488 pcp->postTrueCond = PCC_NONE;
1502 /* Now for another peep example */
1503 pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
1504 pcp = pcps->peep = Safe_calloc(1,sizeof(pCodePeep));
1505 peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
1510 pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
1512 pb = newpCodeChain(NULL, newpCode(POC_MOVWF, pcw));
1513 addpCode2pBlock( pb, newpCode(POC_MOVWF, pcw));
1517 pb = newpCodeChain(NULL, newpCode(POC_MOVWF, pcw));
1521 /* Allocate space to store pointers to the wildcard variables */
1523 pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
1524 pcp->nwildpCodes = 0;
1525 pcp->wildpCodes = NULL;
1527 pcp->postFalseCond = PCC_NONE;
1528 pcp->postTrueCond = PCC_NONE;
1536 /*-----------------------------------------------------------------*/
1537 /* pCodeSearchCondition - Search a pCode chain for a 'condition' */
1539 /* return conditions */
1540 /* 1 - The Condition was found for a pCode's input */
1541 /* 0 - No matching condition was found for the whole chain */
1542 /* -1 - The Condition was found for a pCode's output */
1544 /*-----------------------------------------------------------------*/
1545 int pCodeSearchCondition(pCode *pc, unsigned int cond)
1550 /* If we reach a function end (presumably an end since we most
1551 probably began the search in the middle of a function), then
1552 the condition was not found. */
1553 if(pc->type == PC_FUNCTION)
1556 if(pc->type == PC_OPCODE) {
1557 if(PCI(pc)->inCond & cond)
1559 if(PCI(pc)->outCond & cond)
1568 /*-----------------------------------------------------------------*/
1569 /* pCodePeepMatchLine - Compare source and destination pCodes to */
1570 /* see they're the same. */
1571 /*-----------------------------------------------------------------*/
1572 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
1574 int index; // index into wild card arrays
1576 if(pcs->type == pcd->type) {
1578 if(pcs->type == PC_OPCODE) {
1580 /* If the opcodes don't match then the line doesn't match */
1581 if(PCI(pcs)->op != PCI(pcd)->op)
1584 fprintf(stderr,"%s comparing\n",__FUNCTION__);
1585 pcs->print(stderr,pcs);
1586 pcd->print(stderr,pcd);
1588 /* Compare the operands */
1589 if(PCI(pcd)->pcop) {
1590 if (PCI(pcd)->pcop->type == PO_WILD) {
1591 index = PCOW(PCI(pcd)->pcop)->id;
1593 #ifdef DEBUG_PCODEPEEP
1594 if (index > peepBlock->nvars) {
1595 fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
1599 if(peepBlock->vars[index])
1600 return (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1602 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1607 /* The pcd has no operand. Lines match if pcs has no operand either*/
1608 return (PCI(pcs)->pcop == NULL);
1613 if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
1617 index = PCW(pcd)->id;
1619 fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
1620 pcs->print(stderr,pcs);
1621 pcd->print(stderr,pcd);
1623 peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
1625 /* Check for a label associated with this wild pCode */
1626 // If the wild card has a label, make sure the source code does too.
1627 if(PCW(pcd)->label) {
1631 labindex = PCOW(PCW(pcd)->label)->id;
1632 if(peepBlock->vars[labindex] == NULL) {
1633 // First time to encounter this label
1634 peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
1635 fprintf(stderr,"first time for a label\n");
1637 if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
1638 fprintf(stderr,"labels don't match\n");
1641 fprintf(stderr,"matched a label\n");
1646 if(PCW(pcd)->operand) {
1647 if(peepBlock->vars[index]) {
1648 int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
1650 fprintf(stderr," (matched)\n");
1652 fprintf(stderr," (no match: wild card operand mismatch\n");
1653 fprintf(stderr," peepblock= %s, pcodeop= %s\n",
1654 peepBlock->vars[index],
1655 PCI(pcs)->pcop->name);
1659 peepBlock->vars[index] = PCI(pcs)->pcop->name;
1664 pcs = findNextInstruction(pcs->next);
1665 fprintf(stderr," (next to match)\n");
1666 pcs->print(stderr,pcs);
1667 return 1; /* wild card matches */
1673 /*-----------------------------------------------------------------*/
1674 /*-----------------------------------------------------------------*/
1675 void pCodePeepClrVars(pCodePeep *pcp)
1680 for(i=0;i<pcp->nvars; i++)
1681 pcp->vars[i] = NULL;
1685 /*-----------------------------------------------------------------*/
1686 /*-----------------------------------------------------------------*/
1687 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
1693 pc2->next = pc1->next;
1695 pc1->next->prev = pc2;
1702 /*-----------------------------------------------------------------*/
1703 /* pCodeOpCopy - copy a pcode operator */
1704 /*-----------------------------------------------------------------*/
1705 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
1707 pCodeOp *pcopnew=NULL;
1712 switch(pcop->type) {
1715 pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
1716 PCOB(pcopnew)->bit = PCOB(pcop)->bit;
1717 PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
1722 /* Here we expand the wild card into the appropriate type: */
1723 /* By recursively calling pCodeOpCopy */
1724 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
1725 pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
1730 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
1731 PCOLAB(pcopnew)->key = PCOLAB(pcop)->key;
1736 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
1737 PCOL(pcopnew)->lit = PCOL(pcop)->lit;
1740 case PO_GPR_REGISTER:
1741 case PO_SFR_REGISTER:
1750 pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
1754 pcopnew->type = pcop->type;
1755 pcopnew->name = Safe_strdup(pcop->name);
1761 /*-----------------------------------------------------------------*/
1762 /* pCodeCopy - copy a pcode */
1763 /*-----------------------------------------------------------------*/
1764 static pCode *pCodeCopy(pCode *pc)
1769 pcnew = newpCode(pc->type,pc->pcop);
1772 /*-----------------------------------------------------------------*/
1773 /*-----------------------------------------------------------------*/
1774 void pCodeDeleteChain(pCode *f,pCode *t)
1779 fprintf(stderr,"delete pCode:\n");
1787 /*-----------------------------------------------------------------*/
1788 /*-----------------------------------------------------------------*/
1789 int pCodePeepMatchRule(pCode *pc)
1791 pCodePeep *peepBlock;
1796 peeprules = (_DLL *)peepSnippets;
1799 peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
1800 pCodePeepClrVars(peepBlock);
1803 pct = peepBlock->target->pcHead;
1805 while(pct && pcin) {
1807 if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
1810 pcin = findNextInstruction(pcin->next);
1813 fprintf(stderr," matched\n");
1815 fprintf(stderr," end of code\n");
1817 fprintf(stderr," end of rule\n");
1822 /* So far we matched the rule up to the point of the conditions .
1823 * In other words, all of the opcodes match. Now we need to see
1824 * if the post conditions are satisfied.
1825 * First we check the 'postFalseCond'. This means that we check
1826 * to see if any of the subsequent pCode's in the pCode chain
1827 * following the point just past where we have matched depend on
1828 * the `postFalseCond' as input then we abort the match
1830 fprintf(stderr," matched rule so far, now checking conditions\n");
1831 if (peepBlock->postFalseCond &&
1832 (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
1842 /* We matched a rule! Now we have to go through and remove the
1843 inefficient code with the optimized version */
1845 fprintf(stderr, "Found a pcode peep match:\nRule:\n");
1846 printpCodeString(stderr,peepBlock->target->pcHead,10);
1847 fprintf(stderr,"first thing matched\n");
1848 pc->print(stderr,pc);
1849 fprintf(stderr,"last thing matched\n");
1850 pcin->print(stderr,pcin);
1853 /* Unlink the original code */
1855 pcprev->next = pcin;
1856 pcin->prev = pc->prev;
1857 pCodeDeleteChain(pc,pcin);
1859 /* Generate the replacement code */
1861 pcr = peepBlock->replace->pcHead; // This is the replacement code
1864 /* If the replace pcode is an instruction with an operand, */
1865 /* then duplicate the operand (and expand wild cards in the process. */
1866 if(pcr->type == PC_OPCODE) {
1868 pcop = pCodeOpCopy(PCI(pcr)->pcop);
1870 pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
1871 } else if (pcr->type == PC_WILD) {
1872 pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
1882 peeprules = peeprules->next;