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
29 // Eventually this will go into device dependent files:
30 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,NULL};
31 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,NULL};
32 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,NULL};
34 //static char *PIC_mnemonics[] = {
35 static char *scpADDLW = "ADDLW";
36 static char *scpADDWF = "ADDWF";
37 static char *scpANDLW = "ANDLW";
38 static char *scpANDWF = "ANDWF";
39 static char *scpBCF = "BCF";
40 static char *scpBSF = "BSF";
41 static char *scpBTFSC = "BTFSC";
42 static char *scpBTFSS = "BTFSS";
43 static char *scpCALL = "CALL";
44 static char *scpCOMF = "COMF";
45 static char *scpCLRF = "CLRF";
46 static char *scpCLRW = "CLRW";
47 static char *scpDECF = "DECF";
48 static char *scpDECFSZ = "DECFSZ";
49 static char *scpGOTO = "GOTO";
50 static char *scpINCF = "INCF";
51 static char *scpINCFSZ = "INCFSZ";
52 static char *scpIORLW = "IORLW";
53 static char *scpIORWF = "IORWF";
54 static char *scpMOVF = "MOVF";
55 static char *scpMOVLW = "MOVLW";
56 static char *scpMOVWF = "MOVWF";
57 static char *scpNEGF = "NEGF";
58 static char *scpRETLW = "RETLW";
59 static char *scpRETURN = "RETURN";
60 static char *scpSUBLW = "SUBLW";
61 static char *scpSUBWF = "SUBWF";
62 static char *scpTRIS = "TRIS";
63 static char *scpXORLW = "XORLW";
64 static char *scpXORWF = "XORWF";
67 static pFile *the_pFile = NULL;
68 static int peepOptimizing = 1;
69 static int GpCodeSequenceNumber = 1;
71 /****************************************************************/
72 /* Forward declarations */
73 /****************************************************************/
75 static void unlinkPC(pCode *pc);
76 static void genericAnalyze(pCode *pc);
77 static void AnalyzeGOTO(pCode *pc);
78 static void AnalyzeSKIP(pCode *pc);
79 static void AnalyzeRETURN(pCode *pc);
81 static void genericDestruct(pCode *pc);
82 static void genericPrint(FILE *of,pCode *pc);
84 static void pCodePrintLabel(FILE *of, pCode *pc);
85 static void pCodePrintFunction(FILE *of, pCode *pc);
86 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
87 static char *get_op( pCodeInstruction *pcc);
88 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
89 int pCodePeepMatchRule(pCode *pc);
92 char *Safe_strdup(char *str)
101 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
109 void pCodeInitRegisters(void)
113 pc_fsr.r = pic14_regWithIdx(4);
117 char getpBlock_dbName(pBlock *pb)
123 return pb->cmemmap->dbName;
127 /*-----------------------------------------------------------------*/
128 /* movepBlock2Head - given the dbname of a pBlock, move all */
129 /* instances to the front of the doubly linked */
130 /* list of pBlocks */
131 /*-----------------------------------------------------------------*/
133 void movepBlock2Head(char dbName)
137 pb = the_pFile->pbHead;
141 if(getpBlock_dbName(pb) == dbName) {
142 pBlock *pbn = pb->next;
143 pb->next = the_pFile->pbHead;
144 the_pFile->pbHead->prev = pb;
145 the_pFile->pbHead = pb;
148 pb->prev->next = pbn;
150 // If the pBlock that we just moved was the last
151 // one in the link of all of the pBlocks, then we
152 // need to point the tail to the block just before
154 // Note: if pb->next is NULL, then pb must have
155 // been the last pBlock in the chain.
158 pbn->prev = pb->prev;
160 the_pFile->pbTail = pb->prev;
171 void copypCode(FILE *of, char dbName)
175 if(!of || !the_pFile)
178 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
179 if(getpBlock_dbName(pb) == dbName)
184 void pcode_test(void)
187 printf("pcode is alive!\n");
195 /* create the file name */
196 strcpy(buffer,srcFileName);
199 if( !(pFile = fopen(buffer, "w" ))) {
200 werror(E_FILE_OPEN_ERR,buffer);
204 fprintf(pFile,"pcode dump\n\n");
206 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
207 fprintf(pFile,"\n\tNew pBlock\n\n");
209 fprintf(pFile,"%s",pb->cmemmap->sname);
211 fprintf(pFile,"internal pblock");
213 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
214 printpBlock(pFile,pb);
218 static int RegCond(pCodeOp *pcop)
224 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
225 switch(PCOB(pcop)->bit) {
239 /*-----------------------------------------------------------------*/
240 /* newpCode - create and return a newly initialized pCode */
242 /* fixme - rename this */
244 /* The purpose of this routine is to create a new Instruction */
245 /* pCode. This is called by gen.c while the assembly code is being */
249 /* PIC_OPCODE op - the assembly instruction we wish to create. */
250 /* (note that the op is analogous to but not the */
251 /* same thing as the opcode of the instruction.) */
252 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
255 /* a pointer to the new malloc'd pCode is returned. */
259 /*-----------------------------------------------------------------*/
260 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
262 pCodeInstruction *pci ;
265 pci = Safe_calloc(1, sizeof(pCodeInstruction));
267 pci->pc.analyze = genericAnalyze; // pointers to the generic functions, it
268 pci->pc.destruct = genericDestruct; // doesn't hurt to think about C++ virtual
269 pci->pc.print = genericPrint; // functions here.
270 pci->pc.type = PC_OPCODE; //
271 pci->op = op; // the "opcode" for the instruction.
272 pci->pc.prev = pci->pc.next = NULL; // The pCode gets linked in later
273 pci->pcop = pcop; // The operand of the instruction
274 pci->dest = 0; // e.g. W or F
275 pci->bit_inst = 0; // e.g. btfxx instructions
276 pci->num_ops = 2; // Most instructions have two ops...
277 pci->inCond = pci->outCond = PCC_NONE; /* input/output conditions. This is used during
278 * optimization to ascertain instruction dependencies.
279 * For example, if an instruction affects the Z bit,
280 * then the output condition for this instruction
281 * is "z bit is affected". The "conditions" are bit
282 * constants defined in pcode.h. */
283 pci->pc.from = pci->pc.to = NULL; // Flow linkages are defined later
284 pci->pc.label = NULL; // Labels get merged into instructions here.
285 pci->pc.pb = NULL; // The pBlock to which this instruction belongs
287 if(pcop && pcop->name)
288 printf("newpCode operand name %s\n",pcop->name);
290 // The most pic dependent portion of the pCode logic:
295 pci->outCond = PCC_W | PCC_Z;
296 pci->mnemonic = scpANDLW;
301 pci->inCond = PCC_W | PCC_REGISTER;
302 pci->outCond = PCC_REGISTER | PCC_Z;
303 pci->mnemonic = scpANDWF;
306 pci->inCond = PCC_W | PCC_REGISTER;
307 pci->outCond = PCC_W | PCC_Z;
308 pci->mnemonic = scpANDWF;
313 pci->outCond = PCC_W | PCC_Z | PCC_C | PCC_DC;
314 pci->mnemonic = scpADDLW;
319 pci->inCond = PCC_W | PCC_REGISTER;
320 pci->outCond = PCC_REGISTER | PCC_Z | PCC_C | PCC_DC;
321 pci->mnemonic = scpADDWF;
324 pci->inCond = PCC_W | PCC_REGISTER;
325 pci->outCond = PCC_W | PCC_Z | PCC_C | PCC_DC;
326 pci->mnemonic = scpADDWF;
331 pci->mnemonic = scpBCF;
332 pci->outCond = RegCond(pcop);
336 pci->mnemonic = scpBSF;
337 pci->outCond = RegCond(pcop);
341 pci->mnemonic = scpBTFSC;
342 pci->pc.analyze = AnalyzeSKIP;
343 pci->inCond = RegCond(pcop);
347 pci->mnemonic = scpBTFSS;
348 pci->pc.analyze = AnalyzeSKIP;
349 pci->inCond = RegCond(pcop);
353 pci->mnemonic = scpCALL;
356 pci->mnemonic = scpCOMF;
360 pci->mnemonic = scpCLRF;
364 pci->mnemonic = scpCLRW;
369 pci->mnemonic = scpDECF;
374 pci->mnemonic = scpDECFSZ;
375 pci->pc.analyze = AnalyzeSKIP;
379 pci->mnemonic = scpGOTO;
380 pci->pc.analyze = AnalyzeGOTO;
385 pci->mnemonic = scpINCF;
390 pci->mnemonic = scpINCFSZ;
391 pci->pc.analyze = AnalyzeSKIP;
395 pci->mnemonic = scpIORLW;
400 pci->mnemonic = scpIORWF;
405 pci->mnemonic = scpMOVF;
409 pci->mnemonic = scpMOVLW;
413 pci->mnemonic = scpMOVWF;
416 pci->mnemonic = scpNEGF;
420 pci->mnemonic = scpRETLW;
421 pci->pc.analyze = AnalyzeRETURN;
425 pci->mnemonic = scpRETURN;
426 pci->pc.analyze = AnalyzeRETURN;
429 pci->mnemonic = scpSUBLW;
435 pci->mnemonic = scpSUBWF;
438 pci->mnemonic = scpTRIS;
442 pci->mnemonic = scpXORLW;
447 pci->mnemonic = scpXORWF;
451 pci->pc.print = genericPrint;
457 /*-----------------------------------------------------------------*/
458 /* newpCodeWild - create a "wild" as in wild card pCode */
460 /* Wild pcodes are used during the peep hole optimizer to serve */
461 /* as place holders for any instruction. When a snippet of code is */
462 /* compared to a peep hole rule, the wild card opcode will match */
463 /* any instruction. However, the optional operand and label are */
464 /* additional qualifiers that must also be matched before the */
465 /* line (of assembly code) is declared matched. Note that the */
466 /* operand may be wild too. */
468 /*-----------------------------------------------------------------*/
470 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
475 pcw = Safe_calloc(1,sizeof(pCodeWild));
477 pcw->pc.type = PC_WILD;
478 pcw->pc.prev = pcw->pc.next = NULL;
479 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
482 pcw->pc.analyze = genericAnalyze;
483 pcw->pc.destruct = genericDestruct;
484 pcw->pc.print = genericPrint;
487 pcw->operand = optional_operand;
488 pcw->label = optional_label;
490 return ( (pCode *)pcw);
494 /*-----------------------------------------------------------------*/
495 /* newPcodeCharP - create a new pCode from a char string */
496 /*-----------------------------------------------------------------*/
498 pCode *newpCodeCharP(char *cP)
503 pcc = Safe_calloc(1,sizeof(pCodeComment));
505 pcc->pc.type = PC_COMMENT;
506 pcc->pc.prev = pcc->pc.next = NULL;
507 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
510 pcc->pc.analyze = genericAnalyze;
511 pcc->pc.destruct = genericDestruct;
512 pcc->pc.print = genericPrint;
514 pcc->comment = Safe_strdup(cP);
516 return ( (pCode *)pcc);
520 /*-----------------------------------------------------------------*/
521 /* newpCodeGLabel - create a new global label */
522 /*-----------------------------------------------------------------*/
525 pCode *newpCodeFunction(char *mod,char *f)
529 _ALLOC(pcf,sizeof(pCodeFunction));
531 pcf->pc.type = PC_FUNCTION;
532 pcf->pc.prev = pcf->pc.next = NULL;
533 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
536 pcf->pc.analyze = genericAnalyze;
537 pcf->pc.destruct = genericDestruct;
538 pcf->pc.print = pCodePrintFunction;
541 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
542 strcpy(pcf->modname,mod);
547 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
548 strcpy(pcf->fname,f);
552 return ( (pCode *)pcf);
557 pCode *newpCodeLabel(int key)
563 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
565 pcl->pc.type = PC_LABEL;
566 pcl->pc.prev = pcl->pc.next = NULL;
567 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
570 pcl->pc.analyze = genericAnalyze;
571 pcl->pc.destruct = genericDestruct;
572 pcl->pc.print = pCodePrintLabel;
577 sprintf(s,"_%05d_DS_",key);
578 pcl->label = Safe_strdup(s);
582 return ( (pCode *)pcl);
585 pCode *newpCodeLabelStr(char *str)
587 pCode *pc = newpCodeLabel(-1);
589 PCL(pc)->label = Safe_strdup(str);
594 /*-----------------------------------------------------------------*/
595 /* newpBlock - create and return a pointer to a new pBlock */
596 /*-----------------------------------------------------------------*/
597 pBlock *newpBlock(void)
602 _ALLOC(PpB,sizeof(pBlock));
603 PpB->next = PpB->prev = NULL;
605 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
606 PpB->registers = NULL;
613 /*-----------------------------------------------------------------*/
614 /* newpCodeChain - create a new chain of pCodes */
615 /*-----------------------------------------------------------------*
617 * This function will create a new pBlock and the pointer to the
618 * pCode that is passed in will be the first pCode in the block.
619 *-----------------------------------------------------------------*/
622 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
625 pBlock *pB = newpBlock();
627 pB->pcHead = pB->pcTail = pc;
634 /*-----------------------------------------------------------------*/
635 /*-----------------------------------------------------------------*/
637 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
641 pcop = Safe_calloc(1,sizeof(pCodeOp) );
643 pcop->name = Safe_strdup(name);
648 /*-----------------------------------------------------------------*/
649 /* newpCodeOpLabel - Create a new label given the key */
650 /* Note, a negative key means that the label is part of wild card */
651 /* (and hence a wild card label) used in the pCodePeep */
652 /* optimizations). */
653 /*-----------------------------------------------------------------*/
655 pCodeOp *newpCodeOpLabel(int key)
660 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
661 pcop->type = PO_LABEL;
664 sprintf(s,"_%05d_DS_",key);
665 pcop->name = Safe_strdup(s);
669 ((pCodeOpLabel *)pcop)->key = key;
674 pCodeOp *newpCodeOpLit(int lit)
680 _ALLOC(pcop,sizeof(pCodeOpLit) );
681 pcop->type = PO_LITERAL;
682 sprintf(s,"0x%02x",lit);
683 _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
684 strcpy(pcop->name,s);
685 ((pCodeOpLit *)pcop)->lit = lit;
690 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
696 if(!pcp || !subtype) {
697 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
701 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
702 pcop->type = PO_WILD;
703 sprintf(s,"%%%d",id);
704 pcop->name = Safe_strdup(s);
707 PCOW(pcop)->pcp = pcp;
708 PCOW(pcop)->subtype = subtype;
709 PCOW(pcop)->matched = NULL;
714 pCodeOp *newpCodeOpBit(char *s, int bit)
718 _ALLOC(pcop,sizeof(pCodeOpBit) );
720 pcop->name = Safe_strdup(s);
721 PCOB(pcop)->bit = bit;
723 PCOB(pcop)->inBitSpace = 1;
725 PCOB(pcop)->inBitSpace = 0;
730 /*-----------------------------------------------------------------*/
731 /* addpCode2pBlock - place the pCode into the pBlock linked list */
732 /*-----------------------------------------------------------------*/
733 void addpCode2pBlock(pBlock *pb, pCode *pc)
736 pb->pcTail->next = pc;
737 pc->prev = pb->pcTail;
743 /*-----------------------------------------------------------------*/
744 /* addpBlock - place a pBlock into the pFile */
745 /*-----------------------------------------------------------------*/
746 void addpBlock(pBlock *pb)
750 /* First time called, we'll pass through here. */
751 _ALLOC(the_pFile,sizeof(the_pFile));
752 the_pFile->pbHead = the_pFile->pbTail = pb;
753 the_pFile->functions = NULL;
757 the_pFile->pbTail->next = pb;
758 pb->prev = the_pFile->pbTail;
760 the_pFile->pbTail = pb;
763 /*-----------------------------------------------------------------*/
764 /* printpCode - write the contents of a pCode to a file */
765 /*-----------------------------------------------------------------*/
766 void printpCode(FILE *of, pCode *pc)
777 fprintf(of,"warning - unable to print pCode\n");
780 /*-----------------------------------------------------------------*/
781 /* printpBlock - write the contents of a pBlock to a file */
782 /*-----------------------------------------------------------------*/
783 void printpBlock(FILE *of, pBlock *pb)
793 for(pc = pb->pcHead; pc; pc = pc->next)
798 /*-----------------------------------------------------------------*/
800 /* pCode processing */
804 /*-----------------------------------------------------------------*/
806 static void unlinkPC(pCode *pc)
808 if(pc && pc->prev && pc->next) {
810 pc->prev->next = pc->next;
811 pc->next->prev = pc->prev;
814 static void genericDestruct(pCode *pc)
818 fprintf(stderr,"warning, calling default pCode destructor\n");
823 void pBlockRegs(FILE *of, pBlock *pb)
828 r = setFirstItem(pb->registers);
830 fprintf(of," %s\n",r->name);
831 r = setNextItem(pb->registers);
836 static char *get_op( pCodeInstruction *pcc)
840 if(pcc && pcc->pcop) {
843 switch(pcc->pcop->type) {
847 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
848 fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
849 pBlockRegs(stderr,pcc->pc.pb);
854 return pcc->pcop->name;
862 /*-----------------------------------------------------------------*/
863 /*-----------------------------------------------------------------*/
864 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
867 fprintf(of,"pcodeopprint\n");
870 /*-----------------------------------------------------------------*/
871 /* genericPrint - the contents of a pCode to a file */
872 /*-----------------------------------------------------------------*/
873 static void genericPrint(FILE *of, pCode *pc)
881 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
885 // If the opcode has a label, print that first
887 pBranch *pbl = pc->label;
889 if(pbl->pc->type == PC_LABEL)
890 pCodePrintLabel(of, pbl->pc);
895 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
896 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
898 if(PCI(pc)->bit_inst) {
899 if(PCI(pc)->pcop->type == PO_BIT) {
900 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
901 fprintf(of,"(%s >> 3), (%s & 7)",
902 PCI(pc)->pcop->name ,
903 PCI(pc)->pcop->name );
905 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
907 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
908 //PCI(pc)->pcop->t.bit );
911 if(PCI(pc)->pcop->type == PO_BIT) {
912 if( PCI(pc)->num_ops == 2)
913 fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
915 fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
918 if( PCI(pc)->num_ops == 2)
919 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
921 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
924 fprintf(of,"%s",get_op(PCI(pc)));
926 if( PCI(pc)->num_ops == 2)
927 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
933 pBranch *dpb = pc->to; // debug
935 switch ( dpb->pc->type) {
937 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
940 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
943 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
957 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
958 if(PCW(pc)->operand) {
959 fprintf(of,";\toperand ");
960 pCodeOpPrint(of,PCW(pc)->operand );
966 fprintf(of,"unknown pCode type %d\n",pc->type);
971 /*-----------------------------------------------------------------*/
972 /* pCodePrintFunction - prints function begin/end */
973 /*-----------------------------------------------------------------*/
975 static void pCodePrintFunction(FILE *of, pCode *pc)
981 if( ((pCodeFunction *)pc)->modname)
982 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
985 pBranch *exits = pc->to;
987 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
993 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
997 pc->from->pc->type == PC_FUNCTION &&
998 PCF(pc->from->pc)->fname)
999 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1001 fprintf(of,"; exit point [can't find entry point]\n");
1004 /*-----------------------------------------------------------------*/
1005 /* pCodePrintLabel - prints label */
1006 /*-----------------------------------------------------------------*/
1008 static void pCodePrintLabel(FILE *of, pCode *pc)
1015 fprintf(of,"%s\n",PCL(pc)->label);
1016 else if (PCL(pc)->key >=0)
1017 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1019 fprintf(of,";wild card label\n");
1022 /*-----------------------------------------------------------------*/
1024 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1040 /*-----------------------------------------------------------------*/
1041 /* pBranchLink - given two pcodes, this function will link them */
1042 /* together through their pBranches */
1043 /*-----------------------------------------------------------------*/
1044 static void pBranchLink(pCode *f, pCode *t)
1048 // Declare a new branch object for the 'from' pCode.
1050 _ALLOC(b,sizeof(pBranch));
1051 b->pc = t; // The link to the 'to' pCode.
1054 f->to = pBranchAppend(f->to,b);
1056 // Now do the same for the 'to' pCode.
1058 _ALLOC(b,sizeof(pBranch));
1062 t->from = pBranchAppend(t->from,b);
1067 /*-----------------------------------------------------------------*/
1068 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1070 /*-----------------------------------------------------------------*/
1071 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1084 /*-----------------------------------------------------------------*/
1085 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1086 /*-----------------------------------------------------------------*/
1087 static void pCodeUnlink(pCode *pc)
1092 if(!pc->prev || !pc->next) {
1093 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1097 /* first remove the pCode from the chain */
1098 pc->prev->next = pc->next;
1099 pc->next->prev = pc->prev;
1101 /* Now for the hard part... */
1103 /* Remove the branches */
1107 pc1 = pb1->pc; /* Get the pCode that branches to the
1108 * one we're unlinking */
1110 /* search for the link back to this pCode (the one we're
1112 if(pb2 = pBranchFind(pc1->to,pc)) {
1113 pb2->pc = pc->to->pc; // make the replacement
1115 /* if the pCode we're unlinking contains multiple 'to'
1116 * branches (e.g. this a skip instruction) then we need
1117 * to copy these extra branches to the chain. */
1119 pBranchAppend(pb2, pc->to->next);
1128 /*-----------------------------------------------------------------*/
1129 /*-----------------------------------------------------------------*/
1130 static void genericAnalyze(pCode *pc)
1140 // Go through the pCodes that are in pCode chain and link
1141 // them together through the pBranches. Note, the pCodes
1142 // are linked together as a contiguous stream like the
1143 // assembly source code lines. The linking here mimics this
1144 // except that comments are not linked in.
1146 pCode *npc = pc->next;
1148 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1149 pBranchLink(pc,npc);
1158 /*-----------------------------------------------------------------*/
1159 /* findLabel - Search the pCode for a particular label */
1160 /*-----------------------------------------------------------------*/
1161 pCode * findLabel(pCodeOpLabel *pcop_label)
1170 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1171 for(pc = pb->pcHead; pc; pc = pc->next) {
1172 if(pc->type == PC_LABEL) {
1173 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1176 if(pc->type == PC_OPCODE) {
1179 if(pbr->pc->type == PC_LABEL) {
1180 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1190 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1194 /*-----------------------------------------------------------------*/
1195 /* findNextInstruction - given a pCode, find the next instruction */
1196 /* in the linked list */
1197 /*-----------------------------------------------------------------*/
1198 pCode * findNextInstruction(pCode *pc)
1202 if(pc->type == PC_OPCODE)
1208 fprintf(stderr,"Couldn't find instruction\n");
1212 /*-----------------------------------------------------------------*/
1213 /* findFunctionEnd - given a pCode find the end of the function */
1214 /* that contains it t */
1215 /*-----------------------------------------------------------------*/
1216 pCode * findFunctionEnd(pCode *pc)
1220 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1226 fprintf(stderr,"Couldn't find function end\n");
1231 /*-----------------------------------------------------------------*/
1232 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1233 /* instruction with which it is associated. */
1234 /*-----------------------------------------------------------------*/
1235 static void AnalyzeLabel(pCode *pc)
1243 static void AnalyzeGOTO(pCode *pc)
1246 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1250 static void AnalyzeSKIP(pCode *pc)
1253 pBranchLink(pc,findNextInstruction(pc->next));
1254 pBranchLink(pc,findNextInstruction(pc->next->next));
1258 static void AnalyzeRETURN(pCode *pc)
1261 // branch_link(pc,findFunctionEnd(pc->next));
1266 void AnalyzepBlock(pBlock *pb)
1273 /* Find all of the registers used in this pBlock */
1274 for(pc = pb->pcHead; pc; pc = pc->next) {
1275 if(pc->type == PC_OPCODE) {
1276 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1278 /* Loop through all of the registers declared so far in
1279 this block and see if we find this new there */
1281 regs *r = setFirstItem(pb->registers);
1284 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1285 PCOR(PCI(pc)->pcop)->r = r;
1288 r = setNextItem(pb->registers);
1292 /* register wasn't found */
1293 r = Safe_calloc(1, sizeof(regs));
1294 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1295 addSet(&pb->registers, r);
1296 PCOR(PCI(pc)->pcop)->r = r;
1297 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1299 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1305 int OptimizepBlock(pBlock *pb)
1310 if(!pb || !peepOptimizing)
1313 fprintf(stderr," Optimizing pBlock\n");
1315 for(pc = pb->pcHead; pc; pc = pc->next)
1316 matches += pCodePeepMatchRule(pc);
1321 /*-----------------------------------------------------------------*/
1322 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1323 /* chain and put them into pBranches that are */
1324 /* associated with the appropriate pCode */
1326 /*-----------------------------------------------------------------*/
1327 void pBlockMergeLabels(pBlock *pb)
1330 pCode *pc, *pcnext=NULL;
1335 for(pc = pb->pcHead; pc; pc = pc->next) {
1337 if(pc->type == PC_LABEL) {
1338 if( !(pcnext = findNextInstruction(pc)) )
1339 return; // Couldn't find an instruction associated with this label
1341 // Unlink the pCode label from it's pCode chain
1343 pc->prev->next = pc->next;
1345 pc->next->prev = pc->prev;
1347 // And link it into the instruction's pBranch labels. (Note, since
1348 // it's possible to have multiple labels associated with one instruction
1349 // we must provide a means to accomodate the additional labels. Thus
1350 // the labels are placed into the singly-linked list "label" as
1351 // opposed to being a single member of the pCodeInstruction.)
1353 _ALLOC(pbr,sizeof(pBranch));
1357 pcnext->label = pBranchAppend(pcnext->label,pbr);
1364 /*-----------------------------------------------------------------*/
1365 /*-----------------------------------------------------------------*/
1366 void OptimizepCode(char dbName)
1368 #define MAX_PASSES 4
1377 fprintf(stderr," Optimizing pCode\n");
1380 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1381 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1382 matches += OptimizepBlock(pb);
1385 while(matches && ++passes < MAX_PASSES);
1389 /*-----------------------------------------------------------------*/
1390 /* AnalyzepCode - parse the pCode that has been generated and form */
1391 /* all of the logical connections. */
1393 /* Essentially what's done here is that the pCode flow is */
1395 /*-----------------------------------------------------------------*/
1397 void AnalyzepCode(char dbName)
1406 fprintf(stderr," Analyzing pCode");
1408 /* First, merge the labels with the instructions */
1409 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1410 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1411 pBlockMergeLabels(pb);
1416 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1417 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1421 /* Now build the call tree.
1422 First we examine all of the pCodes for functions.
1423 Keep in mind that the function boundaries coincide
1424 with pBlock boundaries.
1426 The algorithm goes something like this:
1427 We have two nested loops. The outer loop iterates
1428 through all of the pBlocks/functions. The inner
1429 loop iterates through all of the pCodes for
1430 a given pBlock. When we begin iterating through
1431 a pBlock, the variable pc_fstart, pCode of the start
1432 of a function, is cleared. We then search for pCodes
1433 of type PC_FUNCTION. When one is encountered, we
1434 initialize pc_fstart to this and at the same time
1435 associate a new pBranch object that signifies a
1436 branch entry. If a return is found, then this signifies
1437 a function exit point. We'll link the pCodes of these
1438 returns to the matching pc_fstart.
1440 When we're done, a doubly linked list of pBranches
1441 will exist. The head of this list is stored in
1442 `the_pFile', which is the meta structure for all
1443 of the pCode. Look at the printCallTree function
1444 on how the pBranches are linked together.
1447 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1448 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1449 pCode *pc_fstart=NULL;
1450 for(pc = pb->pcHead; pc; pc = pc->next) {
1451 if(pc->type == PC_FUNCTION) {
1452 if (PCF(pc)->fname) {
1453 // I'm not liking this....
1454 // Found the beginning of a function.
1455 _ALLOC(pbr,sizeof(pBranch));
1456 pbr->pc = pc_fstart = pc;
1459 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1461 // Here's a better way of doing the same:
1462 addSet(&pb->function_entries, pc);
1465 // Found an exit point in a function, e.g. return
1466 // (Note, there may be more than one return per function)
1468 pBranchLink(pc_fstart, pc);
1470 addSet(&pb->function_exits, pc);
1472 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1473 addSet(&pb->function_calls,pc);
1480 /*-----------------------------------------------------------------*/
1481 /* ispCodeFunction - returns true if *pc is the pCode of a */
1483 /*-----------------------------------------------------------------*/
1484 bool ispCodeFunction(pCode *pc)
1487 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
1493 /*-----------------------------------------------------------------*/
1494 /* findFunction - Search for a function by name (given the name) */
1495 /* in the set of all functions that are in a pBlock */
1496 /* (note - I expect this to change because I'm planning to limit */
1497 /* pBlock's to just one function declaration */
1498 /*-----------------------------------------------------------------*/
1499 pCode *findFunction(char *fname)
1506 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1508 pc = setFirstItem(pb->function_entries);
1511 if((pc->type == PC_FUNCTION) &&
1513 (strcmp(fname, PCF(pc)->fname)==0))
1516 pc = setNextItem(pb->function_entries);
1524 void MarkUsedRegisters(set *regset)
1529 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
1530 r2 = pic14_regWithIdx(r1->rIdx);
1536 void pBlockStats(FILE *of, pBlock *pb)
1542 fprintf(of,"***\n pBlock Stats\n***\n");
1544 // for now just print the first element of each set
1545 pc = setFirstItem(pb->function_entries);
1547 fprintf(of,"entry\n");
1550 pc = setFirstItem(pb->function_exits);
1552 fprintf(of,"has an exit\n");
1556 pc = setFirstItem(pb->function_calls);
1558 fprintf(of,"functions called\n");
1562 pc = setNextItem(pb->function_calls);
1566 r = setFirstItem(pb->registers);
1568 int n = elementsInSet(pb->registers);
1570 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
1573 fprintf(of," %s\n",r->name);
1574 r = setNextItem(pb->registers);
1579 /*-----------------------------------------------------------------*/
1580 /*-----------------------------------------------------------------*/
1581 void sequencepCode(void)
1587 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1589 pb->seq = GpCodeSequenceNumber+1;
1591 for( pc = pb->pcHead; pc; pc = pc->next)
1592 pc->seq = ++GpCodeSequenceNumber;
1597 /*-----------------------------------------------------------------*/
1598 /*-----------------------------------------------------------------*/
1599 set *register_usage(pBlock *pb)
1602 set *registers=NULL;
1603 set *registersInCallPath = NULL;
1605 /* check recursion */
1607 pc = setFirstItem(pb->function_entries);
1614 if(pc->type != PC_FUNCTION)
1615 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
1617 pc = setFirstItem(pb->function_calls);
1618 for( ; pc; pc = setNextItem(pb->function_calls)) {
1620 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1621 char *dest = get_op(PCI(pc));
1623 pcn = findFunction(dest);
1625 registersInCallPath = register_usage(pcn->pb);
1627 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1632 pBlockStats(stderr,pb); // debug
1633 if(registersInCallPath) {
1634 /* registers were used in the functions this pBlock has called */
1635 /* so now, we need to see if these collide with the ones we are */
1638 regs *r1,*r2, *newreg;
1640 fprintf(stderr,"comparing registers\n");
1642 r1 = setFirstItem(registersInCallPath);
1645 r2 = setFirstItem(pb->registers);
1649 if(r2->rIdx == r1->rIdx) {
1650 newreg = pic14_findFreeReg();
1654 fprintf(stderr,"Bummer, no more registers.\n");
1658 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1659 r1->rIdx, newreg->rIdx);
1660 r2->rIdx = newreg->rIdx;
1661 //if(r2->name) free(r2->name);
1662 r2->name = Safe_strdup(newreg->name);
1664 newreg->wasUsed = 1;
1666 r2 = setNextItem(pb->registers);
1669 r1 = setNextItem(registersInCallPath);
1672 /* Collisions have been resolved. Now free the registers in the call path */
1673 r1 = setFirstItem(registersInCallPath);
1675 newreg = pic14_regWithIdx(r1->rIdx);
1677 r1 = setNextItem(registersInCallPath);
1681 MarkUsedRegisters(pb->registers);
1683 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1686 fprintf(stderr,"returning regs\n");
1688 fprintf(stderr,"not returning regs\n");
1690 fprintf(stderr,"pBlock after register optim.\n");
1691 pBlockStats(stderr,pb); // debug
1697 /*-----------------------------------------------------------------*/
1698 /* printCallTree - writes the call tree to a file */
1700 /*-----------------------------------------------------------------*/
1701 void pct2(FILE *of,pBlock *pb,int indent)
1705 // set *registersInCallPath = NULL;
1708 return;// registers;
1711 return; // registers; //recursion ?
1713 pc = setFirstItem(pb->function_entries);
1720 for(i=0;i<indent;i++) // Indentation
1723 if(pc->type == PC_FUNCTION)
1724 fprintf(of,"%s\n",PCF(pc)->fname);
1729 pc = setFirstItem(pb->function_calls);
1730 for( ; pc; pc = setNextItem(pb->function_calls)) {
1732 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1733 char *dest = get_op(PCI(pc));
1735 pcn = findFunction(dest);
1737 pct2(of,pcn->pb,indent+1);
1739 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1747 fprintf(stderr,"pBlock before register optim.\n");
1748 pBlockStats(stderr,pb); // debug
1750 if(registersInCallPath) {
1751 /* registers were used in the functions this pBlock has called */
1752 /* so now, we need to see if these collide with the ones we are using here */
1754 regs *r1,*r2, *newreg;
1756 fprintf(stderr,"comparing registers\n");
1758 r1 = setFirstItem(registersInCallPath);
1761 r2 = setFirstItem(pb->registers);
1765 if(r2->rIdx == r1->rIdx) {
1766 newreg = pic14_findFreeReg();
1770 fprintf(stderr,"Bummer, no more registers.\n");
1774 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1775 r1->rIdx, newreg->rIdx);
1776 r2->rIdx = newreg->rIdx;
1777 //if(r2->name) free(r2->name);
1778 r2->name = Safe_strdup(newreg->name);
1780 newreg->wasUsed = 1;
1782 r2 = setNextItem(pb->registers);
1785 r1 = setNextItem(registersInCallPath);
1788 /* Collisions have been resolved. Now free the registers in the call path */
1789 r1 = setFirstItem(registersInCallPath);
1791 newreg = pic14_regWithIdx(r1->rIdx);
1793 r1 = setNextItem(registersInCallPath);
1797 MarkUsedRegisters(pb->registers);
1799 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1802 fprintf(stderr,"returning regs\n");
1804 fprintf(stderr,"not returning regs\n");
1806 fprintf(stderr,"pBlock after register optim.\n");
1807 pBlockStats(stderr,pb); // debug
1815 /*-----------------------------------------------------------------*/
1816 /* printCallTree - writes the call tree to a file */
1818 /*-----------------------------------------------------------------*/
1820 void printCallTree(FILE *of)
1832 fprintf(of, "\npBlock statistics\n");
1833 for(pb = the_pFile->pbHead; pb; pb = pb->next )
1834 pBlockStats(stderr,pb);
1838 fprintf(of,"Call Tree\n");
1839 pbr = the_pFile->functions;
1843 if(!ispCodeFunction(pc))
1844 fprintf(of,"bug in call tree");
1847 fprintf(of,"Function: %s\n", PCF(pc)->fname);
1849 while(pc->next && !ispCodeFunction(pc->next)) {
1851 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
1852 fprintf(of,"\t%s\n",get_op(PCI(pc)));
1860 /* Re-allocate the registers so that there are no collisions
1861 * between local variables when one function call another */
1863 pic14_deallocateAllRegs();
1865 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1870 fprintf(of,"\n**************\n\na better call tree\n");
1871 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1876 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1877 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));