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 int mnemonics_initialized = 0;
37 //static char *PIC_mnemonics[] = {
38 static char *scpADDLW = "ADDLW";
39 static char *scpADDWF = "ADDWF";
40 static char *scpANDLW = "ANDLW";
41 static char *scpANDWF = "ANDWF";
42 static char *scpBCF = "BCF";
43 static char *scpBSF = "BSF";
44 static char *scpBTFSC = "BTFSC";
45 static char *scpBTFSS = "BTFSS";
46 static char *scpCALL = "CALL";
47 static char *scpCOMF = "COMF";
48 static char *scpCLRF = "CLRF";
49 static char *scpCLRW = "CLRW";
50 static char *scpDECF = "DECF";
51 static char *scpDECFSZ = "DECFSZ";
52 static char *scpGOTO = "GOTO";
53 static char *scpINCF = "INCF";
54 static char *scpINCFSZ = "INCFSZ";
55 static char *scpIORLW = "IORLW";
56 static char *scpIORWF = "IORWF";
57 static char *scpMOVF = "MOVF";
58 static char *scpMOVLW = "MOVLW";
59 static char *scpMOVWF = "MOVWF";
60 static char *scpNEGF = "NEGF";
61 static char *scpRETLW = "RETLW";
62 static char *scpRETURN = "RETURN";
63 static char *scpSUBLW = "SUBLW";
64 static char *scpSUBWF = "SUBWF";
65 static char *scpTRIS = "TRIS";
66 static char *scpXORLW = "XORLW";
67 static char *scpXORWF = "XORWF";
70 static hTab *pic14MnemonicsHash = NULL;
74 static pFile *the_pFile = NULL;
75 static int peepOptimizing = 1;
76 static int GpCodeSequenceNumber = 1;
78 /****************************************************************/
79 /* Forward declarations */
80 /****************************************************************/
82 static void unlinkPC(pCode *pc);
83 static void genericAnalyze(pCode *pc);
84 static void AnalyzeGOTO(pCode *pc);
85 static void AnalyzeSKIP(pCode *pc);
86 static void AnalyzeRETURN(pCode *pc);
88 static void genericDestruct(pCode *pc);
89 static void genericPrint(FILE *of,pCode *pc);
91 static void pCodePrintLabel(FILE *of, pCode *pc);
92 static void pCodePrintFunction(FILE *of, pCode *pc);
93 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
94 static char *get_op( pCodeInstruction *pcc);
95 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
96 int pCodePeepMatchRule(pCode *pc);
99 pCodeInstruction pciADDWF = {
100 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
108 1,0, // dest, bit instruction
109 (PCC_W | PCC_REGISTER), // inCond
110 (PCC_REGISTER | PCC_Z) // outCond
113 pCodeInstruction pciADDFW = {
114 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
122 0,0, // dest, bit instruction
123 (PCC_W | PCC_REGISTER), // inCond
124 (PCC_W | PCC_Z) // outCond
127 pCodeInstruction pciADDLW = {
128 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
136 0,0, // dest, bit instruction
138 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
141 pCodeInstruction pciANDLW = {
142 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
150 0,0, // dest, bit instruction
152 (PCC_W | PCC_Z) // outCond
155 pCodeInstruction pciANDWF = {
156 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
164 1,0, // dest, bit instruction
165 (PCC_W | PCC_REGISTER), // inCond
166 (PCC_REGISTER | PCC_Z) // outCond
169 pCodeInstruction pciANDFW = {
170 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
178 0,0, // dest, bit instruction
179 (PCC_W | PCC_REGISTER), // inCond
180 (PCC_W | PCC_Z) // outCond
183 pCodeInstruction pciBCF = {
184 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
192 0,1, // dest, bit instruction
194 PCC_EXAMINE_PCOP // outCond
197 pCodeInstruction pciBSF = {
198 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
206 0,1, // dest, bit instruction
208 PCC_EXAMINE_PCOP // outCond
211 pCodeInstruction pciBTFSC = {
212 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
220 0,1, // dest, bit instruction
221 PCC_EXAMINE_PCOP, // inCond
225 pCodeInstruction pciBTFSS = {
226 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
234 0,1, // dest, bit instruction
235 PCC_EXAMINE_PCOP, // inCond
239 pCodeInstruction pciCALL = {
240 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
248 0,0, // dest, bit instruction
253 //fixme - need a COMFW instruction.
254 pCodeInstruction pciCOMF = {
255 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
263 0,0, // dest, bit instruction
268 pCodeInstruction pciCLRF = {
269 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
277 0,0, // dest, bit instruction
278 PCC_REGISTER, // inCond
279 PCC_REGISTER // outCond
282 pCodeInstruction pciCLRW = {
283 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
291 0,0, // dest, bit instruction
296 pCodeInstruction pciDECF = {
297 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
305 1,0, // dest, bit instruction
306 PCC_REGISTER, // inCond
307 PCC_REGISTER // outCond
310 pCodeInstruction pciDECFW = {
311 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
319 0,0, // dest, bit instruction
320 PCC_REGISTER, // inCond
324 pCodeInstruction pciDECFSZ = {
325 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
333 1,0, // dest, bit instruction
334 PCC_REGISTER, // inCond
335 PCC_REGISTER // outCond
338 pCodeInstruction pciDECFSZW = {
339 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
347 0,0, // dest, bit instruction
348 PCC_REGISTER, // inCond
352 pCodeInstruction pciGOTO = {
353 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
361 0,0, // dest, bit instruction
367 pCodeInstruction pciINCF = {
368 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
376 1,0, // dest, bit instruction
377 PCC_REGISTER, // inCond
378 PCC_REGISTER // outCond
381 pCodeInstruction pciINCFW = {
382 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
390 0,0, // dest, bit instruction
391 PCC_REGISTER, // inCond
395 pCodeInstruction pciINCFSZ = {
396 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
404 1,0, // dest, bit instruction
405 PCC_REGISTER, // inCond
406 PCC_REGISTER // outCond
409 pCodeInstruction pciINCFSZW = {
410 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
418 0,0, // dest, bit instruction
419 PCC_REGISTER, // inCond
423 pCodeInstruction pciIORWF = {
424 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
432 1,0, // dest, bit instruction
433 (PCC_W | PCC_REGISTER), // inCond
434 (PCC_REGISTER | PCC_Z) // outCond
437 pCodeInstruction pciIORFW = {
438 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
446 0,0, // dest, bit instruction
447 (PCC_W | PCC_REGISTER), // inCond
448 (PCC_W | PCC_Z) // outCond
451 pCodeInstruction pciIORLW = {
452 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
460 0,0, // dest, bit instruction
462 (PCC_W | PCC_Z) // outCond
465 pCodeInstruction pciMOVF = {
466 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
474 1,0, // dest, bit instruction
475 PCC_REGISTER, // inCond
479 pCodeInstruction pciMOVFW = {
480 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
488 0,0, // dest, bit instruction
489 PCC_REGISTER, // inCond
490 (PCC_W | PCC_Z) // outCond
493 pCodeInstruction pciMOVWF = {
494 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
502 0,0, // dest, bit instruction
507 pCodeInstruction pciMOVLW = {
508 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
516 0,0, // dest, bit instruction
521 pCodeInstruction pciNEGF = {
522 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
530 0,0, // dest, bit instruction
531 PCC_REGISTER, // inCond
536 pCodeInstruction pciRETLW = {
537 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
545 0,0, // dest, bit instruction
550 pCodeInstruction pciRETURN = {
551 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
559 0,0, // dest, bit instruction
565 pCodeInstruction pciSUBWF = {
566 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
574 1,0, // dest, bit instruction
575 (PCC_W | PCC_REGISTER), // inCond
576 (PCC_REGISTER | PCC_Z) // outCond
579 pCodeInstruction pciSUBFW = {
580 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
588 0,0, // dest, bit instruction
589 (PCC_W | PCC_REGISTER), // inCond
590 (PCC_W | PCC_Z) // outCond
593 pCodeInstruction pciSUBLW = {
594 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
602 0,0, // dest, bit instruction
604 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
607 pCodeInstruction pciTRIS = {
608 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
616 0,0, // dest, bit instruction
622 pCodeInstruction pciXORWF = {
623 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
631 1,0, // dest, bit instruction
632 (PCC_W | PCC_REGISTER), // inCond
633 (PCC_REGISTER | PCC_Z) // outCond
636 pCodeInstruction pciXORFW = {
637 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
645 0,0, // dest, bit instruction
646 (PCC_W | PCC_REGISTER), // inCond
647 (PCC_W | PCC_Z) // outCond
650 pCodeInstruction pciXORLW = {
651 {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL,
659 0,0, // dest, bit instruction
661 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
665 #define MAX_PIC14MNEMONICS 100
666 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
668 char *Safe_strdup(char *str)
677 fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
685 void pCodeInitRegisters(void)
689 pc_fsr.r = pic14_regWithIdx(4);
693 /*-----------------------------------------------------------------*/
694 /* mnem2key - convert a pic mnemonic into a hash key */
695 /* (BTW - this spreads the mnemonics quite well) */
697 /*-----------------------------------------------------------------*/
699 int mnem2key(char const *mnem)
708 key += toupper(*mnem++) +1;
716 void pic14initMnemonics(void)
721 pCodeInstruction *pci;
723 if(mnemonics_initialized)
726 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
727 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
728 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
729 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
730 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
731 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
732 pic14Mnemonics[POC_BCF] = &pciBCF;
733 pic14Mnemonics[POC_BSF] = &pciBSF;
734 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
735 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
736 pic14Mnemonics[POC_CALL] = &pciCALL;
737 pic14Mnemonics[POC_COMF] = &pciCOMF;
738 pic14Mnemonics[POC_CLRF] = &pciCLRF;
739 pic14Mnemonics[POC_CLRW] = &pciCLRW;
740 pic14Mnemonics[POC_DECF] = &pciDECF;
741 pic14Mnemonics[POC_DECFW] = &pciDECFW;
742 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
743 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
744 pic14Mnemonics[POC_GOTO] = &pciGOTO;
745 pic14Mnemonics[POC_INCF] = &pciINCF;
746 pic14Mnemonics[POC_INCFW] = &pciINCFW;
747 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
748 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
749 pic14Mnemonics[POC_IORLW] = &pciIORLW;
750 pic14Mnemonics[POC_IORWF] = &pciIORWF;
751 pic14Mnemonics[POC_IORFW] = &pciIORFW;
752 pic14Mnemonics[POC_MOVF] = &pciMOVF;
753 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
754 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
755 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
756 pic14Mnemonics[POC_NEGF] = &pciNEGF;
757 pic14Mnemonics[POC_RETLW] = &pciRETLW;
758 pic14Mnemonics[POC_RETURN] = &pciRETURN;
759 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
760 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
761 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
762 pic14Mnemonics[POC_TRIS] = &pciTRIS;
763 pic14Mnemonics[POC_XORLW] = &pciXORLW;
764 pic14Mnemonics[POC_XORWF] = &pciXORWF;
765 pic14Mnemonics[POC_XORFW] = &pciXORFW;
767 for(i=0; i<MAX_PIC14MNEMONICS; i++)
768 if(pic14Mnemonics[i])
769 hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
770 pci = hTabFirstItem(pic14MnemonicsHash, &key);
773 fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
774 pci = hTabNextItem(pic14MnemonicsHash, &key);
777 mnemonics_initialized = 1;
780 int getpCode(char *mnem,int dest)
783 pCodeInstruction *pci;
784 int key = mnem2key(mnem);
786 if(!mnemonics_initialized)
787 pic14initMnemonics();
789 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
793 if(strcasecmp(pci->mnemonic, mnem) == 0) {
794 if((pci->num_ops <= 1) || (pci->dest == dest))
798 pci = hTabNextItemWK (pic14MnemonicsHash);
805 char getpBlock_dbName(pBlock *pb)
811 return pb->cmemmap->dbName;
815 /*-----------------------------------------------------------------*/
816 /* movepBlock2Head - given the dbname of a pBlock, move all */
817 /* instances to the front of the doubly linked */
818 /* list of pBlocks */
819 /*-----------------------------------------------------------------*/
821 void movepBlock2Head(char dbName)
825 pb = the_pFile->pbHead;
829 if(getpBlock_dbName(pb) == dbName) {
830 pBlock *pbn = pb->next;
831 pb->next = the_pFile->pbHead;
832 the_pFile->pbHead->prev = pb;
833 the_pFile->pbHead = pb;
836 pb->prev->next = pbn;
838 // If the pBlock that we just moved was the last
839 // one in the link of all of the pBlocks, then we
840 // need to point the tail to the block just before
842 // Note: if pb->next is NULL, then pb must have
843 // been the last pBlock in the chain.
846 pbn->prev = pb->prev;
848 the_pFile->pbTail = pb->prev;
859 void copypCode(FILE *of, char dbName)
863 if(!of || !the_pFile)
866 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
867 if(getpBlock_dbName(pb) == dbName)
872 void pcode_test(void)
875 printf("pcode is alive!\n");
885 /* create the file name */
886 strcpy(buffer,srcFileName);
889 if( !(pFile = fopen(buffer, "w" ))) {
890 werror(E_FILE_OPEN_ERR,buffer);
894 fprintf(pFile,"pcode dump\n\n");
896 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
897 fprintf(pFile,"\n\tNew pBlock\n\n");
899 fprintf(pFile,"%s",pb->cmemmap->sname);
901 fprintf(pFile,"internal pblock");
903 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
904 printpBlock(pFile,pb);
908 static int RegCond(pCodeOp *pcop)
914 if(pcop->type == PO_BIT && !strcmp(pcop->name, pc_status.pcop.name)) {
915 switch(PCOB(pcop)->bit) {
929 /*-----------------------------------------------------------------*/
930 /* newpCode - create and return a newly initialized pCode */
932 /* fixme - rename this */
934 /* The purpose of this routine is to create a new Instruction */
935 /* pCode. This is called by gen.c while the assembly code is being */
939 /* PIC_OPCODE op - the assembly instruction we wish to create. */
940 /* (note that the op is analogous to but not the */
941 /* same thing as the opcode of the instruction.) */
942 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
945 /* a pointer to the new malloc'd pCode is returned. */
949 /*-----------------------------------------------------------------*/
950 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
952 pCodeInstruction *pci ;
954 if(!mnemonics_initialized)
955 pic14initMnemonics();
957 pci = Safe_calloc(1, sizeof(pCodeInstruction));
959 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
960 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
963 if(pci->inCond == PCC_EXAMINE_PCOP)
964 pci->inCond = RegCond(pcop);
966 if(pci->outCond == PCC_EXAMINE_PCOP)
967 pci->outCond = RegCond(pcop);
972 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
978 /*-----------------------------------------------------------------*/
979 /* newpCodeWild - create a "wild" as in wild card pCode */
981 /* Wild pcodes are used during the peep hole optimizer to serve */
982 /* as place holders for any instruction. When a snippet of code is */
983 /* compared to a peep hole rule, the wild card opcode will match */
984 /* any instruction. However, the optional operand and label are */
985 /* additional qualifiers that must also be matched before the */
986 /* line (of assembly code) is declared matched. Note that the */
987 /* operand may be wild too. */
989 /* Note, a wild instruction is specified just like a wild var: */
990 /* %4 ; A wild instruction, */
991 /* See the peeph.def file for additional examples */
993 /*-----------------------------------------------------------------*/
995 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1000 pcw = Safe_calloc(1,sizeof(pCodeWild));
1002 pcw->pc.type = PC_WILD;
1003 pcw->pc.prev = pcw->pc.next = NULL;
1004 pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1007 pcw->pc.analyze = genericAnalyze;
1008 pcw->pc.destruct = genericDestruct;
1009 pcw->pc.print = genericPrint;
1011 pcw->id = pCodeID; // this is the 'n' in %n
1012 pcw->operand = optional_operand;
1013 pcw->label = optional_label;
1015 return ( (pCode *)pcw);
1019 /*-----------------------------------------------------------------*/
1020 /* newPcodeCharP - create a new pCode from a char string */
1021 /*-----------------------------------------------------------------*/
1023 pCode *newpCodeCharP(char *cP)
1028 pcc = Safe_calloc(1,sizeof(pCodeComment));
1030 pcc->pc.type = PC_COMMENT;
1031 pcc->pc.prev = pcc->pc.next = NULL;
1032 pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1035 pcc->pc.analyze = genericAnalyze;
1036 pcc->pc.destruct = genericDestruct;
1037 pcc->pc.print = genericPrint;
1039 pcc->comment = Safe_strdup(cP);
1041 return ( (pCode *)pcc);
1045 /*-----------------------------------------------------------------*/
1046 /* newpCodeGLabel - create a new global label */
1047 /*-----------------------------------------------------------------*/
1050 pCode *newpCodeFunction(char *mod,char *f)
1054 _ALLOC(pcf,sizeof(pCodeFunction));
1056 pcf->pc.type = PC_FUNCTION;
1057 pcf->pc.prev = pcf->pc.next = NULL;
1058 pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1061 pcf->pc.analyze = genericAnalyze;
1062 pcf->pc.destruct = genericDestruct;
1063 pcf->pc.print = pCodePrintFunction;
1066 _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1067 strcpy(pcf->modname,mod);
1069 pcf->modname = NULL;
1072 _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1073 strcpy(pcf->fname,f);
1077 return ( (pCode *)pcf);
1081 static void pCodeLabelDestruct(pCode *pc)
1090 free(PCL(pc)->label);
1096 pCode *newpCodeLabel(int key)
1102 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1104 pcl->pc.type = PC_LABEL;
1105 pcl->pc.prev = pcl->pc.next = NULL;
1106 pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1109 pcl->pc.analyze = genericAnalyze;
1110 pcl->pc.destruct = pCodeLabelDestruct;
1111 pcl->pc.print = pCodePrintLabel;
1116 sprintf(s,"_%05d_DS_",key);
1117 pcl->label = Safe_strdup(s);
1121 return ( (pCode *)pcl);
1124 pCode *newpCodeLabelStr(char *str)
1126 pCode *pc = newpCodeLabel(-1);
1128 PCL(pc)->label = Safe_strdup(str);
1133 /*-----------------------------------------------------------------*/
1134 /* newpBlock - create and return a pointer to a new pBlock */
1135 /*-----------------------------------------------------------------*/
1136 pBlock *newpBlock(void)
1141 PpB = Safe_calloc(1,sizeof(pBlock) );
1142 PpB->next = PpB->prev = NULL;
1144 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1145 PpB->registers = NULL;
1152 /*-----------------------------------------------------------------*/
1153 /* newpCodeChain - create a new chain of pCodes */
1154 /*-----------------------------------------------------------------*
1156 * This function will create a new pBlock and the pointer to the
1157 * pCode that is passed in will be the first pCode in the block.
1158 *-----------------------------------------------------------------*/
1161 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1164 pBlock *pB = newpBlock();
1166 pB->pcHead = pB->pcTail = pc;
1173 /*-----------------------------------------------------------------*/
1174 /* newpCodeOpLabel - Create a new label given the key */
1175 /* Note, a negative key means that the label is part of wild card */
1176 /* (and hence a wild card label) used in the pCodePeep */
1177 /* optimizations). */
1178 /*-----------------------------------------------------------------*/
1180 pCodeOp *newpCodeOpLabel(int key)
1185 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1186 pcop->type = PO_LABEL;
1189 sprintf(s,"_%05d_DS_",key);
1190 pcop->name = Safe_strdup(s);
1194 ((pCodeOpLabel *)pcop)->key = key;
1199 pCodeOp *newpCodeOpLit(int lit)
1205 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1206 pcop->type = PO_LITERAL;
1208 sprintf(s,"0x%02x",lit);
1209 pcop->name = Safe_strdup(s);
1213 ((pCodeOpLit *)pcop)->lit = lit;
1218 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1224 if(!pcp || !subtype) {
1225 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1229 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1230 pcop->type = PO_WILD;
1231 sprintf(s,"%%%d",id);
1232 pcop->name = Safe_strdup(s);
1234 PCOW(pcop)->id = id;
1235 PCOW(pcop)->pcp = pcp;
1236 PCOW(pcop)->subtype = subtype;
1237 PCOW(pcop)->matched = NULL;
1242 pCodeOp *newpCodeOpBit(char *s, int bit)
1246 pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1247 pcop->type = PO_BIT;
1248 pcop->name = Safe_strdup(s);
1250 PCOB(pcop)->bit = bit;
1252 PCOB(pcop)->inBitSpace = 1;
1254 PCOB(pcop)->inBitSpace = 0;
1259 /*-----------------------------------------------------------------*/
1260 /*-----------------------------------------------------------------*/
1262 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1268 pcop = newpCodeOpBit(name, -1);
1272 pcop = newpCodeOpLit(-1);
1276 pcop = newpCodeOpLabel(-1);
1280 pcop = Safe_calloc(1,sizeof(pCodeOp) );
1282 pcop->name = Safe_strdup(name);
1288 /*-----------------------------------------------------------------*/
1289 /* addpCode2pBlock - place the pCode into the pBlock linked list */
1290 /*-----------------------------------------------------------------*/
1291 void addpCode2pBlock(pBlock *pb, pCode *pc)
1294 pb->pcTail->next = pc;
1295 pc->prev = pb->pcTail;
1301 /*-----------------------------------------------------------------*/
1302 /* addpBlock - place a pBlock into the pFile */
1303 /*-----------------------------------------------------------------*/
1304 void addpBlock(pBlock *pb)
1308 /* First time called, we'll pass through here. */
1309 _ALLOC(the_pFile,sizeof(the_pFile));
1310 the_pFile->pbHead = the_pFile->pbTail = pb;
1311 the_pFile->functions = NULL;
1315 the_pFile->pbTail->next = pb;
1316 pb->prev = the_pFile->pbTail;
1318 the_pFile->pbTail = pb;
1321 /*-----------------------------------------------------------------*/
1322 /* printpCode - write the contents of a pCode to a file */
1323 /*-----------------------------------------------------------------*/
1324 void printpCode(FILE *of, pCode *pc)
1335 fprintf(of,"warning - unable to print pCode\n");
1338 /*-----------------------------------------------------------------*/
1339 /* printpBlock - write the contents of a pBlock to a file */
1340 /*-----------------------------------------------------------------*/
1341 void printpBlock(FILE *of, pBlock *pb)
1351 for(pc = pb->pcHead; pc; pc = pc->next)
1356 /*-----------------------------------------------------------------*/
1358 /* pCode processing */
1362 /*-----------------------------------------------------------------*/
1364 static void unlinkPC(pCode *pc)
1366 if(pc && pc->prev && pc->next) {
1368 pc->prev->next = pc->next;
1369 pc->next->prev = pc->prev;
1372 static void genericDestruct(pCode *pc)
1374 fprintf(stderr,"warning, calling default pCode destructor\n");
1383 void pBlockRegs(FILE *of, pBlock *pb)
1388 r = setFirstItem(pb->registers);
1390 fprintf(of," %s\n",r->name);
1391 r = setNextItem(pb->registers);
1396 static char *get_op( pCodeInstruction *pcc)
1400 if(pcc && pcc->pcop) {
1403 switch(pcc->pcop->type) {
1407 r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1408 fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1409 pBlockRegs(stderr,pcc->pc.pb);
1413 if (pcc->pcop->name)
1414 return pcc->pcop->name;
1419 return "NO operand";
1422 /*-----------------------------------------------------------------*/
1423 /*-----------------------------------------------------------------*/
1424 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1427 fprintf(of,"pcodeopprint\n");
1430 /*-----------------------------------------------------------------*/
1431 /* genericPrint - the contents of a pCode to a file */
1432 /*-----------------------------------------------------------------*/
1433 static void genericPrint(FILE *of, pCode *pc)
1441 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1445 // If the opcode has a label, print that first
1447 pBranch *pbl = pc->label;
1449 if(pbl->pc->type == PC_LABEL)
1450 pCodePrintLabel(of, pbl->pc);
1455 fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
1456 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1458 if(PCI(pc)->bit_inst) {
1459 if(PCI(pc)->pcop->type == PO_BIT) {
1460 if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1461 fprintf(of,"(%s >> 3), (%s & 7)",
1462 PCI(pc)->pcop->name ,
1463 PCI(pc)->pcop->name );
1465 fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1467 fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
1468 //PCI(pc)->pcop->t.bit );
1471 if(PCI(pc)->pcop->type == PO_BIT) {
1472 if( PCI(pc)->num_ops == 2)
1473 fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1475 fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
1478 if( PCI(pc)->num_ops == 2)
1479 fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
1481 fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
1484 fprintf(of,"%s",get_op(PCI(pc)));
1486 if( PCI(pc)->num_ops == 2)
1487 fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1493 pBranch *dpb = pc->to; // debug
1495 switch ( dpb->pc->type) {
1497 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1500 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1503 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1517 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1518 if(PCW(pc)->operand) {
1519 fprintf(of,";\toperand ");
1520 pCodeOpPrint(of,PCW(pc)->operand );
1526 fprintf(of,"unknown pCode type %d\n",pc->type);
1531 /*-----------------------------------------------------------------*/
1532 /* pCodePrintFunction - prints function begin/end */
1533 /*-----------------------------------------------------------------*/
1535 static void pCodePrintFunction(FILE *of, pCode *pc)
1541 if( ((pCodeFunction *)pc)->modname)
1542 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1544 if(PCF(pc)->fname) {
1545 pBranch *exits = pc->to;
1547 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1550 exits = exits->next;
1553 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1557 pc->from->pc->type == PC_FUNCTION &&
1558 PCF(pc->from->pc)->fname)
1559 fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1561 fprintf(of,"; exit point [can't find entry point]\n");
1564 /*-----------------------------------------------------------------*/
1565 /* pCodePrintLabel - prints label */
1566 /*-----------------------------------------------------------------*/
1568 static void pCodePrintLabel(FILE *of, pCode *pc)
1575 fprintf(of,"%s\n",PCL(pc)->label);
1576 else if (PCL(pc)->key >=0)
1577 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1579 fprintf(of,";wild card label\n");
1582 /*-----------------------------------------------------------------*/
1584 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1600 /*-----------------------------------------------------------------*/
1601 /* pBranchLink - given two pcodes, this function will link them */
1602 /* together through their pBranches */
1603 /*-----------------------------------------------------------------*/
1604 static void pBranchLink(pCode *f, pCode *t)
1608 // Declare a new branch object for the 'from' pCode.
1610 _ALLOC(b,sizeof(pBranch));
1611 b->pc = t; // The link to the 'to' pCode.
1614 f->to = pBranchAppend(f->to,b);
1616 // Now do the same for the 'to' pCode.
1618 _ALLOC(b,sizeof(pBranch));
1622 t->from = pBranchAppend(t->from,b);
1627 /*-----------------------------------------------------------------*/
1628 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1630 /*-----------------------------------------------------------------*/
1631 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1644 /*-----------------------------------------------------------------*/
1645 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
1646 /*-----------------------------------------------------------------*/
1647 static void pCodeUnlink(pCode *pc)
1652 if(!pc->prev || !pc->next) {
1653 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1657 /* first remove the pCode from the chain */
1658 pc->prev->next = pc->next;
1659 pc->next->prev = pc->prev;
1661 /* Now for the hard part... */
1663 /* Remove the branches */
1667 pc1 = pb1->pc; /* Get the pCode that branches to the
1668 * one we're unlinking */
1670 /* search for the link back to this pCode (the one we're
1672 if(pb2 = pBranchFind(pc1->to,pc)) {
1673 pb2->pc = pc->to->pc; // make the replacement
1675 /* if the pCode we're unlinking contains multiple 'to'
1676 * branches (e.g. this a skip instruction) then we need
1677 * to copy these extra branches to the chain. */
1679 pBranchAppend(pb2, pc->to->next);
1688 /*-----------------------------------------------------------------*/
1689 /*-----------------------------------------------------------------*/
1690 static void genericAnalyze(pCode *pc)
1700 // Go through the pCodes that are in pCode chain and link
1701 // them together through the pBranches. Note, the pCodes
1702 // are linked together as a contiguous stream like the
1703 // assembly source code lines. The linking here mimics this
1704 // except that comments are not linked in.
1706 pCode *npc = pc->next;
1708 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1709 pBranchLink(pc,npc);
1718 /*-----------------------------------------------------------------*/
1719 /* findLabel - Search the pCode for a particular label */
1720 /*-----------------------------------------------------------------*/
1721 pCode * findLabel(pCodeOpLabel *pcop_label)
1730 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1731 for(pc = pb->pcHead; pc; pc = pc->next) {
1732 if(pc->type == PC_LABEL) {
1733 if( ((pCodeLabel *)pc)->key == pcop_label->key)
1736 if(pc->type == PC_OPCODE) {
1739 if(pbr->pc->type == PC_LABEL) {
1740 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
1750 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1754 /*-----------------------------------------------------------------*/
1755 /* findNextInstruction - given a pCode, find the next instruction */
1756 /* in the linked list */
1757 /*-----------------------------------------------------------------*/
1758 pCode * findNextInstruction(pCode *pc)
1762 if(pc->type == PC_OPCODE)
1768 fprintf(stderr,"Couldn't find instruction\n");
1772 /*-----------------------------------------------------------------*/
1773 /* findFunctionEnd - given a pCode find the end of the function */
1774 /* that contains it t */
1775 /*-----------------------------------------------------------------*/
1776 pCode * findFunctionEnd(pCode *pc)
1780 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
1786 fprintf(stderr,"Couldn't find function end\n");
1791 /*-----------------------------------------------------------------*/
1792 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
1793 /* instruction with which it is associated. */
1794 /*-----------------------------------------------------------------*/
1795 static void AnalyzeLabel(pCode *pc)
1803 static void AnalyzeGOTO(pCode *pc)
1806 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1810 static void AnalyzeSKIP(pCode *pc)
1813 pBranchLink(pc,findNextInstruction(pc->next));
1814 pBranchLink(pc,findNextInstruction(pc->next->next));
1818 static void AnalyzeRETURN(pCode *pc)
1821 // branch_link(pc,findFunctionEnd(pc->next));
1826 void AnalyzepBlock(pBlock *pb)
1833 /* Find all of the registers used in this pBlock */
1834 for(pc = pb->pcHead; pc; pc = pc->next) {
1835 if(pc->type == PC_OPCODE) {
1836 if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1838 /* Loop through all of the registers declared so far in
1839 this block and see if we find this new there */
1841 regs *r = setFirstItem(pb->registers);
1844 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1845 PCOR(PCI(pc)->pcop)->r = r;
1848 r = setNextItem(pb->registers);
1852 /* register wasn't found */
1853 r = Safe_calloc(1, sizeof(regs));
1854 memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1855 addSet(&pb->registers, r);
1856 PCOR(PCI(pc)->pcop)->r = r;
1857 fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1859 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1865 int OptimizepBlock(pBlock *pb)
1870 if(!pb || !peepOptimizing)
1873 fprintf(stderr," Optimizing pBlock\n");
1875 for(pc = pb->pcHead; pc; pc = pc->next)
1876 matches += pCodePeepMatchRule(pc);
1881 /*-----------------------------------------------------------------*/
1882 /* pBlockMergeLabels - remove the pCode labels from the pCode */
1883 /* chain and put them into pBranches that are */
1884 /* associated with the appropriate pCode */
1886 /*-----------------------------------------------------------------*/
1887 void pBlockMergeLabels(pBlock *pb)
1890 pCode *pc, *pcnext=NULL;
1895 for(pc = pb->pcHead; pc; pc = pc->next) {
1897 if(pc->type == PC_LABEL) {
1898 if( !(pcnext = findNextInstruction(pc)) )
1899 return; // Couldn't find an instruction associated with this label
1901 // Unlink the pCode label from it's pCode chain
1903 pc->prev->next = pc->next;
1905 pc->next->prev = pc->prev;
1907 // And link it into the instruction's pBranch labels. (Note, since
1908 // it's possible to have multiple labels associated with one instruction
1909 // we must provide a means to accomodate the additional labels. Thus
1910 // the labels are placed into the singly-linked list "label" as
1911 // opposed to being a single member of the pCodeInstruction.)
1913 _ALLOC(pbr,sizeof(pBranch));
1917 pcnext->label = pBranchAppend(pcnext->label,pbr);
1924 /*-----------------------------------------------------------------*/
1925 /*-----------------------------------------------------------------*/
1926 void OptimizepCode(char dbName)
1928 #define MAX_PASSES 4
1937 fprintf(stderr," Optimizing pCode\n");
1940 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1941 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1942 matches += OptimizepBlock(pb);
1945 while(matches && ++passes < MAX_PASSES);
1949 /*-----------------------------------------------------------------*/
1950 /* AnalyzepCode - parse the pCode that has been generated and form */
1951 /* all of the logical connections. */
1953 /* Essentially what's done here is that the pCode flow is */
1955 /*-----------------------------------------------------------------*/
1957 void AnalyzepCode(char dbName)
1966 fprintf(stderr," Analyzing pCode");
1968 /* First, merge the labels with the instructions */
1969 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1970 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1971 pBlockMergeLabels(pb);
1976 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1977 if('*' == dbName || getpBlock_dbName(pb) == dbName)
1981 /* Now build the call tree.
1982 First we examine all of the pCodes for functions.
1983 Keep in mind that the function boundaries coincide
1984 with pBlock boundaries.
1986 The algorithm goes something like this:
1987 We have two nested loops. The outer loop iterates
1988 through all of the pBlocks/functions. The inner
1989 loop iterates through all of the pCodes for
1990 a given pBlock. When we begin iterating through
1991 a pBlock, the variable pc_fstart, pCode of the start
1992 of a function, is cleared. We then search for pCodes
1993 of type PC_FUNCTION. When one is encountered, we
1994 initialize pc_fstart to this and at the same time
1995 associate a new pBranch object that signifies a
1996 branch entry. If a return is found, then this signifies
1997 a function exit point. We'll link the pCodes of these
1998 returns to the matching pc_fstart.
2000 When we're done, a doubly linked list of pBranches
2001 will exist. The head of this list is stored in
2002 `the_pFile', which is the meta structure for all
2003 of the pCode. Look at the printCallTree function
2004 on how the pBranches are linked together.
2007 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2008 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2009 pCode *pc_fstart=NULL;
2010 for(pc = pb->pcHead; pc; pc = pc->next) {
2011 if(pc->type == PC_FUNCTION) {
2012 if (PCF(pc)->fname) {
2013 // I'm not liking this....
2014 // Found the beginning of a function.
2015 _ALLOC(pbr,sizeof(pBranch));
2016 pbr->pc = pc_fstart = pc;
2019 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2021 // Here's a better way of doing the same:
2022 addSet(&pb->function_entries, pc);
2025 // Found an exit point in a function, e.g. return
2026 // (Note, there may be more than one return per function)
2028 pBranchLink(pc_fstart, pc);
2030 addSet(&pb->function_exits, pc);
2032 } else if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2033 addSet(&pb->function_calls,pc);
2040 /*-----------------------------------------------------------------*/
2041 /* ispCodeFunction - returns true if *pc is the pCode of a */
2043 /*-----------------------------------------------------------------*/
2044 bool ispCodeFunction(pCode *pc)
2047 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2053 /*-----------------------------------------------------------------*/
2054 /* findFunction - Search for a function by name (given the name) */
2055 /* in the set of all functions that are in a pBlock */
2056 /* (note - I expect this to change because I'm planning to limit */
2057 /* pBlock's to just one function declaration */
2058 /*-----------------------------------------------------------------*/
2059 pCode *findFunction(char *fname)
2066 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2068 pc = setFirstItem(pb->function_entries);
2071 if((pc->type == PC_FUNCTION) &&
2073 (strcmp(fname, PCF(pc)->fname)==0))
2076 pc = setNextItem(pb->function_entries);
2084 void MarkUsedRegisters(set *regset)
2089 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2090 r2 = pic14_regWithIdx(r1->rIdx);
2096 void pBlockStats(FILE *of, pBlock *pb)
2102 fprintf(of,"***\n pBlock Stats\n***\n");
2104 // for now just print the first element of each set
2105 pc = setFirstItem(pb->function_entries);
2107 fprintf(of,"entry\n");
2110 pc = setFirstItem(pb->function_exits);
2112 fprintf(of,"has an exit\n");
2116 pc = setFirstItem(pb->function_calls);
2118 fprintf(of,"functions called\n");
2122 pc = setNextItem(pb->function_calls);
2126 r = setFirstItem(pb->registers);
2128 int n = elementsInSet(pb->registers);
2130 fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2133 fprintf(of," %s\n",r->name);
2134 r = setNextItem(pb->registers);
2139 /*-----------------------------------------------------------------*/
2140 /*-----------------------------------------------------------------*/
2141 void sequencepCode(void)
2147 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2149 pb->seq = GpCodeSequenceNumber+1;
2151 for( pc = pb->pcHead; pc; pc = pc->next)
2152 pc->seq = ++GpCodeSequenceNumber;
2157 /*-----------------------------------------------------------------*/
2158 /*-----------------------------------------------------------------*/
2159 set *register_usage(pBlock *pb)
2162 set *registers=NULL;
2163 set *registersInCallPath = NULL;
2165 /* check recursion */
2167 pc = setFirstItem(pb->function_entries);
2174 if(pc->type != PC_FUNCTION)
2175 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2177 pc = setFirstItem(pb->function_calls);
2178 for( ; pc; pc = setNextItem(pb->function_calls)) {
2180 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2181 char *dest = get_op(PCI(pc));
2183 pcn = findFunction(dest);
2185 registersInCallPath = register_usage(pcn->pb);
2187 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2192 pBlockStats(stderr,pb); // debug
2193 if(registersInCallPath) {
2194 /* registers were used in the functions this pBlock has called */
2195 /* so now, we need to see if these collide with the ones we are */
2198 regs *r1,*r2, *newreg;
2200 fprintf(stderr,"comparing registers\n");
2202 r1 = setFirstItem(registersInCallPath);
2205 r2 = setFirstItem(pb->registers);
2209 if(r2->rIdx == r1->rIdx) {
2210 newreg = pic14_findFreeReg();
2214 fprintf(stderr,"Bummer, no more registers.\n");
2218 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2219 r1->rIdx, newreg->rIdx);
2220 r2->rIdx = newreg->rIdx;
2221 //if(r2->name) free(r2->name);
2222 r2->name = Safe_strdup(newreg->name);
2224 newreg->wasUsed = 1;
2226 r2 = setNextItem(pb->registers);
2229 r1 = setNextItem(registersInCallPath);
2232 /* Collisions have been resolved. Now free the registers in the call path */
2233 r1 = setFirstItem(registersInCallPath);
2235 newreg = pic14_regWithIdx(r1->rIdx);
2237 r1 = setNextItem(registersInCallPath);
2241 MarkUsedRegisters(pb->registers);
2243 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2246 fprintf(stderr,"returning regs\n");
2248 fprintf(stderr,"not returning regs\n");
2250 fprintf(stderr,"pBlock after register optim.\n");
2251 pBlockStats(stderr,pb); // debug
2257 /*-----------------------------------------------------------------*/
2258 /* printCallTree - writes the call tree to a file */
2260 /*-----------------------------------------------------------------*/
2261 void pct2(FILE *of,pBlock *pb,int indent)
2265 // set *registersInCallPath = NULL;
2268 return;// registers;
2271 return; // registers; //recursion ?
2273 pc = setFirstItem(pb->function_entries);
2280 for(i=0;i<indent;i++) // Indentation
2283 if(pc->type == PC_FUNCTION)
2284 fprintf(of,"%s\n",PCF(pc)->fname);
2289 pc = setFirstItem(pb->function_calls);
2290 for( ; pc; pc = setNextItem(pb->function_calls)) {
2292 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2293 char *dest = get_op(PCI(pc));
2295 pcn = findFunction(dest);
2297 pct2(of,pcn->pb,indent+1);
2299 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2307 fprintf(stderr,"pBlock before register optim.\n");
2308 pBlockStats(stderr,pb); // debug
2310 if(registersInCallPath) {
2311 /* registers were used in the functions this pBlock has called */
2312 /* so now, we need to see if these collide with the ones we are using here */
2314 regs *r1,*r2, *newreg;
2316 fprintf(stderr,"comparing registers\n");
2318 r1 = setFirstItem(registersInCallPath);
2321 r2 = setFirstItem(pb->registers);
2325 if(r2->rIdx == r1->rIdx) {
2326 newreg = pic14_findFreeReg();
2330 fprintf(stderr,"Bummer, no more registers.\n");
2334 fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2335 r1->rIdx, newreg->rIdx);
2336 r2->rIdx = newreg->rIdx;
2337 //if(r2->name) free(r2->name);
2338 r2->name = Safe_strdup(newreg->name);
2340 newreg->wasUsed = 1;
2342 r2 = setNextItem(pb->registers);
2345 r1 = setNextItem(registersInCallPath);
2348 /* Collisions have been resolved. Now free the registers in the call path */
2349 r1 = setFirstItem(registersInCallPath);
2351 newreg = pic14_regWithIdx(r1->rIdx);
2353 r1 = setNextItem(registersInCallPath);
2357 MarkUsedRegisters(pb->registers);
2359 registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2362 fprintf(stderr,"returning regs\n");
2364 fprintf(stderr,"not returning regs\n");
2366 fprintf(stderr,"pBlock after register optim.\n");
2367 pBlockStats(stderr,pb); // debug
2375 /*-----------------------------------------------------------------*/
2376 /* printCallTree - writes the call tree to a file */
2378 /*-----------------------------------------------------------------*/
2380 void printCallTree(FILE *of)
2392 fprintf(of, "\npBlock statistics\n");
2393 for(pb = the_pFile->pbHead; pb; pb = pb->next )
2394 pBlockStats(stderr,pb);
2398 fprintf(of,"Call Tree\n");
2399 pbr = the_pFile->functions;
2403 if(!ispCodeFunction(pc))
2404 fprintf(of,"bug in call tree");
2407 fprintf(of,"Function: %s\n", PCF(pc)->fname);
2409 while(pc->next && !ispCodeFunction(pc->next)) {
2411 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2412 fprintf(of,"\t%s\n",get_op(PCI(pc)));
2420 /* Re-allocate the registers so that there are no collisions
2421 * between local variables when one function call another */
2423 pic14_deallocateAllRegs();
2425 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2430 fprintf(of,"\n**************\n\na better call tree\n");
2431 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2436 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2437 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));