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
28 #include "pcodeflow.h"
32 pCode *findFunction(char *fname);
34 static void FixRegisterBanking(pBlock *pb);
36 /****************************************************************/
37 /****************************************************************/
39 peepCommand peepCommands[] = {
41 {NOTBITSKIP, "_NOTBITSKIP_"},
42 {BITSKIP, "_BITSKIP_"},
43 {INVERTBITSKIP, "_INVERTBITSKIP_"},
50 // Eventually this will go into device dependent files:
51 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
52 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
53 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
62 static int mnemonics_initialized = 0;
64 static hTab *pic14MnemonicsHash = NULL;
65 static hTab *pic14pCodePeepCommandsHash = NULL;
68 pFile *the_pFile = NULL;
69 static pBlock *pb_dead_pcodes = NULL;
71 /* Hardcoded flags to change the behavior of the PIC port */
72 static int functionInlining = 1; /* inline functions if nonzero */
73 int debug_verbose = 0; /* Set true to inundate .asm file */
75 // static int GpCodeSequenceNumber = 1;
78 /* statistics (code size estimation) */
79 static unsigned int pcode_insns = 0;
80 static unsigned int pcode_doubles = 0;
83 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
84 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
86 extern void RemoveUnusedRegisters(void);
87 extern void RegsUnMapLiveRanges(void);
88 extern void BuildFlowTree(pBlock *pb);
89 extern void pCodeRegOptimizeRegUsage(int level);
90 extern int picIsInitialized(void);
91 extern const char *pCodeOpType(pCodeOp *pcop);
93 /****************************************************************/
94 /* Forward declarations */
95 /****************************************************************/
97 void unlinkpCode(pCode *pc);
99 static void genericAnalyze(pCode *pc);
100 static void AnalyzeGOTO(pCode *pc);
101 static void AnalyzeSKIP(pCode *pc);
102 static void AnalyzeRETURN(pCode *pc);
105 static void genericDestruct(pCode *pc);
106 static void genericPrint(FILE *of,pCode *pc);
108 static void pCodePrintLabel(FILE *of, pCode *pc);
109 static void pCodePrintFunction(FILE *of, pCode *pc);
110 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
111 static char *get_op_from_instruction( pCodeInstruction *pcc);
112 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
113 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
114 int pCodePeepMatchRule(pCode *pc);
115 void pBlockStats(FILE *of, pBlock *pb);
116 pBlock *newpBlock(void);
117 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
118 void pCodeRegMapLiveRanges(pBlock *pb);
120 pBranch * pBranchAppend(pBranch *h, pBranch *n);
123 /****************************************************************/
124 /* PIC Instructions */
125 /****************************************************************/
127 pCodeInstruction pciADDWF = {
128 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
141 1,0, // dest, bit instruction
143 0, // literal operand
145 (PCC_W | PCC_REGISTER), // inCond
146 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
149 pCodeInstruction pciADDFW = {
150 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
163 0,0, // dest, bit instruction
165 0, // literal operand
167 (PCC_W | PCC_REGISTER), // inCond
168 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
171 pCodeInstruction pciADDLW = {
172 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
185 0,0, // dest, bit instruction
187 1, // literal operand
189 (PCC_W | PCC_LITERAL), // inCond
190 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
193 pCodeInstruction pciANDLW = {
194 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
207 0,0, // dest, bit instruction
209 1, // literal operand
211 (PCC_W | PCC_LITERAL), // inCond
212 (PCC_W | PCC_Z) // outCond
215 pCodeInstruction pciANDWF = {
216 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
229 1,0, // dest, bit instruction
231 0, // literal operand
233 (PCC_W | PCC_REGISTER), // inCond
234 (PCC_REGISTER | PCC_Z) // outCond
237 pCodeInstruction pciANDFW = {
238 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
251 0,0, // dest, bit instruction
253 0, // literal operand
255 (PCC_W | PCC_REGISTER), // inCond
256 (PCC_W | PCC_Z) // outCond
259 pCodeInstruction pciBCF = {
260 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
273 1,1, // dest, bit instruction
275 0, // literal operand
277 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
278 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
281 pCodeInstruction pciBSF = {
282 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
295 1,1, // dest, bit instruction
297 0, // literal operand
299 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
300 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
303 pCodeInstruction pciBTFSC = {
304 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
317 0,1, // dest, bit instruction
319 0, // literal operand
321 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
325 pCodeInstruction pciBTFSS = {
326 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
339 0,1, // dest, bit instruction
341 0, // literal operand
343 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
347 pCodeInstruction pciCALL = {
348 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
361 0,0, // dest, bit instruction
363 0, // literal operand
365 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
366 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
369 pCodeInstruction pciCOMF = {
370 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
383 1,0, // dest, bit instruction
385 0, // literal operand
387 PCC_REGISTER, // inCond
388 PCC_REGISTER | PCC_Z // outCond
391 pCodeInstruction pciCOMFW = {
392 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
405 0,0, // dest, bit instruction
407 0, // literal operand
409 PCC_REGISTER, // inCond
410 PCC_W | PCC_Z // outCond
413 pCodeInstruction pciCLRF = {
414 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
427 0,0, // dest, bit instruction
429 0, // literal operand
432 PCC_REGISTER | PCC_Z // outCond
435 pCodeInstruction pciCLRW = {
436 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
449 0,0, // dest, bit instruction
451 0, // literal operand
454 PCC_W | PCC_Z // outCond
457 pCodeInstruction pciCLRWDT = {
458 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
471 0,0, // dest, bit instruction
473 0, // literal operand
479 pCodeInstruction pciDECF = {
480 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
493 1,0, // dest, bit instruction
495 0, // literal operand
497 PCC_REGISTER, // inCond
498 PCC_REGISTER | PCC_Z // outCond
501 pCodeInstruction pciDECFW = {
502 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
515 0,0, // dest, bit instruction
517 0, // literal operand
519 PCC_REGISTER, // inCond
520 PCC_W | PCC_Z // outCond
523 pCodeInstruction pciDECFSZ = {
524 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
537 1,0, // dest, bit instruction
539 0, // literal operand
540 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
541 PCC_REGISTER, // inCond
542 PCC_REGISTER | PCC_Z // outCond
545 pCodeInstruction pciDECFSZW = {
546 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
559 0,0, // dest, bit instruction
561 0, // literal operand
562 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
563 PCC_REGISTER, // inCond
564 PCC_W | PCC_Z // outCond
567 pCodeInstruction pciGOTO = {
568 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
581 0,0, // dest, bit instruction
583 0, // literal operand
589 pCodeInstruction pciINCF = {
590 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
603 1,0, // dest, bit instruction
605 0, // literal operand
607 PCC_REGISTER, // inCond
608 PCC_REGISTER | PCC_Z // outCond
611 pCodeInstruction pciINCFW = {
612 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
625 0,0, // dest, bit instruction
627 0, // literal operand
629 PCC_REGISTER, // inCond
630 PCC_W | PCC_Z // outCond
633 pCodeInstruction pciINCFSZ = {
634 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
647 1,0, // dest, bit instruction
649 0, // literal operand
650 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
651 PCC_REGISTER, // inCond
652 PCC_REGISTER | PCC_Z // outCond
655 pCodeInstruction pciINCFSZW = {
656 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
669 0,0, // dest, bit instruction
671 0, // literal operand
672 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
673 PCC_REGISTER, // inCond
674 PCC_W | PCC_Z // outCond
677 pCodeInstruction pciIORWF = {
678 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
691 1,0, // dest, bit instruction
693 0, // literal operand
695 (PCC_W | PCC_REGISTER), // inCond
696 (PCC_REGISTER | PCC_Z) // outCond
699 pCodeInstruction pciIORFW = {
700 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
713 0,0, // dest, bit instruction
715 0, // literal operand
717 (PCC_W | PCC_REGISTER), // inCond
718 (PCC_W | PCC_Z) // outCond
721 pCodeInstruction pciIORLW = {
722 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
735 0,0, // dest, bit instruction
737 1, // literal operand
739 (PCC_W | PCC_LITERAL), // inCond
740 (PCC_W | PCC_Z) // outCond
743 pCodeInstruction pciMOVF = {
744 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
757 1,0, // dest, bit instruction
759 0, // literal operand
761 PCC_REGISTER, // inCond
765 pCodeInstruction pciMOVFW = {
766 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
779 0,0, // dest, bit instruction
781 0, // literal operand
783 PCC_REGISTER, // inCond
784 (PCC_W | PCC_Z) // outCond
787 pCodeInstruction pciMOVWF = {
788 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
801 0,0, // dest, bit instruction
803 0, // literal operand
806 PCC_REGISTER // outCond
809 pCodeInstruction pciMOVLW = {
810 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
822 0,0, // dest, bit instruction
824 1, // literal operand
826 (PCC_NONE | PCC_LITERAL), // inCond
830 pCodeInstruction pciNOP = {
831 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
843 0,0, // dest, bit instruction
845 0, // literal operand
851 pCodeInstruction pciRETFIE = {
852 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
870 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
873 pCodeInstruction pciRETLW = {
874 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
887 0,0, // dest, bit instruction
889 1, // literal operand
891 PCC_LITERAL, // inCond
892 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
895 pCodeInstruction pciRETURN = {
896 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
909 0,0, // dest, bit instruction
911 0, // literal operand
913 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
914 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
917 pCodeInstruction pciRLF = {
918 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
931 1,0, // dest, bit instruction
933 0, // literal operand
935 (PCC_C | PCC_REGISTER), // inCond
936 (PCC_REGISTER | PCC_C ) // outCond
939 pCodeInstruction pciRLFW = {
940 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
953 0,0, // dest, bit instruction
955 0, // literal operand
957 (PCC_C | PCC_REGISTER), // inCond
958 (PCC_W | PCC_C) // outCond
961 pCodeInstruction pciRRF = {
962 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
975 1,0, // dest, bit instruction
977 0, // literal operand
979 (PCC_C | PCC_REGISTER), // inCond
980 (PCC_REGISTER | PCC_C) // outCond
983 pCodeInstruction pciRRFW = {
984 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
997 0,0, // dest, bit instruction
999 0, // literal operand
1001 (PCC_C | PCC_REGISTER), // inCond
1002 (PCC_W | PCC_C) // outCond
1005 pCodeInstruction pciSUBWF = {
1006 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1012 NULL, // from branch
1019 1,0, // dest, bit instruction
1020 0,0, // branch, skip
1021 0, // literal operand
1023 (PCC_W | PCC_REGISTER), // inCond
1024 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1027 pCodeInstruction pciSUBFW = {
1028 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1034 NULL, // from branch
1041 0,0, // dest, bit instruction
1042 0,0, // branch, skip
1043 0, // literal operand
1045 (PCC_W | PCC_REGISTER), // inCond
1046 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1049 pCodeInstruction pciSUBLW = {
1050 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1056 NULL, // from branch
1063 0,0, // dest, bit instruction
1064 0,0, // branch, skip
1065 1, // literal operand
1067 (PCC_W | PCC_LITERAL), // inCond
1068 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1071 pCodeInstruction pciSWAPF = {
1072 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1078 NULL, // from branch
1085 1,0, // dest, bit instruction
1086 0,0, // branch, skip
1087 0, // literal operand
1089 (PCC_REGISTER), // inCond
1090 (PCC_REGISTER) // outCond
1093 pCodeInstruction pciSWAPFW = {
1094 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1100 NULL, // from branch
1107 0,0, // dest, bit instruction
1108 0,0, // branch, skip
1109 0, // literal operand
1111 (PCC_REGISTER), // inCond
1115 pCodeInstruction pciTRIS = {
1116 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1122 NULL, // from branch
1129 0,0, // dest, bit instruction
1130 0,0, // branch, skip
1131 0, // literal operand
1133 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1134 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1137 pCodeInstruction pciXORWF = {
1138 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1144 NULL, // from branch
1151 1,0, // dest, bit instruction
1152 0,0, // branch, skip
1153 0, // literal operand
1155 (PCC_W | PCC_REGISTER), // inCond
1156 (PCC_REGISTER | PCC_Z) // outCond
1159 pCodeInstruction pciXORFW = {
1160 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1166 NULL, // from branch
1173 0,0, // dest, bit instruction
1174 0,0, // branch, skip
1175 0, // literal operand
1177 (PCC_W | PCC_REGISTER), // inCond
1178 (PCC_W | PCC_Z) // outCond
1181 pCodeInstruction pciXORLW = {
1182 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1188 NULL, // from branch
1195 0,0, // dest, bit instruction
1196 0,0, // branch, skip
1197 1, // literal operand
1199 (PCC_W | PCC_LITERAL), // inCond
1200 (PCC_W | PCC_Z) // outCond
1204 pCodeInstruction pciBANKSEL = {
1205 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1211 NULL, // from branch
1218 0,0, // dest, bit instruction
1219 0,0, // branch, skip
1220 0, // literal operand
1226 pCodeInstruction pciPAGESEL = {
1227 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1233 NULL, // from branch
1240 0,0, // dest, bit instruction
1241 0,0, // branch, skip
1242 0, // literal operand
1248 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1251 /*-----------------------------------------------------------------*/
1252 /* return a unique ID number to assist pCodes debuging */
1253 /*-----------------------------------------------------------------*/
1254 unsigned PCodeID(void) {
1255 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1257 static unsigned int stop;
1258 if (pcodeId == 1448)
1259 stop++; // Place break point here
1264 extern void initStack(int base_address, int size, int shared);
1265 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1266 extern regs *allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias);
1267 extern PIC_device *init_pic(char *);
1269 void pCodeInitRegisters(void)
1271 static int initialized=0;
1272 int shareBankAddress, stkSize, haveShared;
1279 pic = init_pic(port->processor);
1280 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1281 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1282 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1283 * (used for interrupts) to fit into the shared portion of the
1285 stkSize = stkSize - 3;
1286 assert(stkSize >= 0);
1287 initStack(shareBankAddress, stkSize, haveShared);
1289 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1290 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1291 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1292 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1293 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1294 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1295 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1297 pc_status.rIdx = IDX_STATUS;
1298 pc_fsr.rIdx = IDX_FSR;
1299 pc_indf.rIdx = IDX_INDF;
1300 pc_intcon.rIdx = IDX_INTCON;
1301 pc_pcl.rIdx = IDX_PCL;
1302 pc_pclath.rIdx = IDX_PCLATH;
1304 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1305 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1306 /* Interrupt storage for status register. */
1307 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1308 /* Interrupt storage for pclath register. */
1309 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1311 pc_wsave.rIdx = pc_wsave.r->rIdx;
1312 pc_ssave.rIdx = pc_ssave.r->rIdx;
1313 pc_psave.rIdx = pc_psave.r->rIdx;
1315 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1316 pc_wsave.r->address = shareBankAddress-stkSize;
1317 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1318 pc_ssave.r->address = shareBankAddress-stkSize-1;
1319 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1320 pc_psave.r->address = shareBankAddress-stkSize-2;
1322 /* probably should put this in a separate initialization routine */
1323 pb_dead_pcodes = newpBlock();
1327 /*-----------------------------------------------------------------*/
1328 /* mnem2key - convert a pic mnemonic into a hash key */
1329 /* (BTW - this spreads the mnemonics quite well) */
1331 /*-----------------------------------------------------------------*/
1333 int mnem2key(unsigned char const *mnem)
1342 key += toupper(*mnem++) +1;
1346 return (key & 0x1f);
1350 void pic14initMnemonics(void)
1355 pCodeInstruction *pci;
1357 if(mnemonics_initialized)
1360 //FIXME - probably should NULL out the array before making the assignments
1361 //since we check the array contents below this initialization.
1363 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1364 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1365 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1366 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1367 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1368 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1369 pic14Mnemonics[POC_BCF] = &pciBCF;
1370 pic14Mnemonics[POC_BSF] = &pciBSF;
1371 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1372 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1373 pic14Mnemonics[POC_CALL] = &pciCALL;
1374 pic14Mnemonics[POC_COMF] = &pciCOMF;
1375 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1376 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1377 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1378 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1379 pic14Mnemonics[POC_DECF] = &pciDECF;
1380 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1381 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1382 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1383 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1384 pic14Mnemonics[POC_INCF] = &pciINCF;
1385 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1386 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1387 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1388 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1389 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1390 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1391 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1392 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1393 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1394 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1395 pic14Mnemonics[POC_NOP] = &pciNOP;
1396 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1397 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1398 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1399 pic14Mnemonics[POC_RLF] = &pciRLF;
1400 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1401 pic14Mnemonics[POC_RRF] = &pciRRF;
1402 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1403 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1404 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1405 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1406 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1407 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1408 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1409 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1410 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1411 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1412 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1413 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1415 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1416 if(pic14Mnemonics[i])
1417 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1418 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1421 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1422 pci = hTabNextItem(pic14MnemonicsHash, &key);
1425 mnemonics_initialized = 1;
1428 int getpCodePeepCommand(char *cmd);
1430 int getpCode(char *mnem,unsigned dest)
1433 pCodeInstruction *pci;
1434 int key = mnem2key((unsigned char *)mnem);
1436 if(!mnemonics_initialized)
1437 pic14initMnemonics();
1439 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1443 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1444 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1448 pci = hTabNextItemWK (pic14MnemonicsHash);
1455 /*-----------------------------------------------------------------*
1456 * pic14initpCodePeepCommands
1458 *-----------------------------------------------------------------*/
1459 void pic14initpCodePeepCommands(void)
1467 hTabAddItem(&pic14pCodePeepCommandsHash,
1468 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1470 } while (peepCommands[i].cmd);
1472 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1475 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1476 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1481 /*-----------------------------------------------------------------
1484 *-----------------------------------------------------------------*/
1486 int getpCodePeepCommand(char *cmd)
1490 int key = mnem2key((unsigned char *)cmd);
1493 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1496 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1497 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1501 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1508 char getpBlock_dbName(pBlock *pb)
1514 return pb->cmemmap->dbName;
1518 void pBlockConvert2ISR(pBlock *pb)
1529 /*-----------------------------------------------------------------*/
1530 /* movepBlock2Head - given the dbname of a pBlock, move all */
1531 /* instances to the front of the doubly linked */
1532 /* list of pBlocks */
1533 /*-----------------------------------------------------------------*/
1535 void movepBlock2Head(char dbName)
1542 pb = the_pFile->pbHead;
1546 if(getpBlock_dbName(pb) == dbName) {
1547 pBlock *pbn = pb->next;
1548 pb->next = the_pFile->pbHead;
1549 the_pFile->pbHead->prev = pb;
1550 the_pFile->pbHead = pb;
1553 pb->prev->next = pbn;
1555 // If the pBlock that we just moved was the last
1556 // one in the link of all of the pBlocks, then we
1557 // need to point the tail to the block just before
1558 // the one we moved.
1559 // Note: if pb->next is NULL, then pb must have
1560 // been the last pBlock in the chain.
1563 pbn->prev = pb->prev;
1565 the_pFile->pbTail = pb->prev;
1576 void copypCode(FILE *of, char dbName)
1580 if(!of || !the_pFile)
1583 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1584 if(getpBlock_dbName(pb) == dbName) {
1593 void resetpCodeStatistics (void)
1595 pcode_insns = pcode_doubles = 0;
1598 void dumppCodeStatistics (FILE *of)
1600 /* dump statistics */
1602 fprintf (of, ";\tcode size estimation:\n");
1603 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1607 void pcode_test(void)
1610 DFPRINTF((stderr,"pcode is alive!\n"));
1620 /* create the file name */
1621 strcpy(buffer,dstFileName);
1622 strcat(buffer,".p");
1624 if( !(pFile = fopen(buffer, "w" ))) {
1625 werror(E_FILE_OPEN_ERR,buffer);
1629 fprintf(pFile,"pcode dump\n\n");
1631 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1632 fprintf(pFile,"\n\tNew pBlock\n\n");
1634 fprintf(pFile,"%s",pb->cmemmap->sname);
1636 fprintf(pFile,"internal pblock");
1638 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1639 printpBlock(pFile,pb);
1643 /*-----------------------------------------------------------------*/
1644 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1645 /* ister, RegCond will return the bit being referenced. */
1647 /* fixme - why not just OR in the pcop bit field */
1648 /*-----------------------------------------------------------------*/
1650 static int RegCond(pCodeOp *pcop)
1656 if (pcop->type == PO_GPR_BIT) {
1657 char *name = pcop->name;
1659 name = PCOR(pcop)->r->name;
1660 if (strcmp(name, pc_status.pcop.name) == 0)
1662 switch(PCORB(pcop)->bit) {
1676 /*-----------------------------------------------------------------*/
1677 /* newpCode - create and return a newly initialized pCode */
1679 /* fixme - rename this */
1681 /* The purpose of this routine is to create a new Instruction */
1682 /* pCode. This is called by gen.c while the assembly code is being */
1686 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1687 /* (note that the op is analogous to but not the */
1688 /* same thing as the opcode of the instruction.) */
1689 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1692 /* a pointer to the new malloc'd pCode is returned. */
1696 /*-----------------------------------------------------------------*/
1697 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1699 pCodeInstruction *pci ;
1701 if(!mnemonics_initialized)
1702 pic14initMnemonics();
1704 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1706 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1707 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1708 pci->pc.id = PCodeID();
1711 if(pci->inCond & PCC_EXAMINE_PCOP)
1712 pci->inCond |= RegCond(pcop);
1714 if(pci->outCond & PCC_EXAMINE_PCOP)
1715 pci->outCond |= RegCond(pcop);
1717 pci->pc.prev = pci->pc.next = NULL;
1718 return (pCode *)pci;
1721 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1727 /*-----------------------------------------------------------------*/
1728 /* newpCodeWild - create a "wild" as in wild card pCode */
1730 /* Wild pcodes are used during the peep hole optimizer to serve */
1731 /* as place holders for any instruction. When a snippet of code is */
1732 /* compared to a peep hole rule, the wild card opcode will match */
1733 /* any instruction. However, the optional operand and label are */
1734 /* additional qualifiers that must also be matched before the */
1735 /* line (of assembly code) is declared matched. Note that the */
1736 /* operand may be wild too. */
1738 /* Note, a wild instruction is specified just like a wild var: */
1739 /* %4 ; A wild instruction, */
1740 /* See the peeph.def file for additional examples */
1742 /*-----------------------------------------------------------------*/
1744 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1749 pcw = Safe_calloc(1,sizeof(pCodeWild));
1751 pcw->pci.pc.type = PC_WILD;
1752 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1753 pcw->id = PCodeID();
1754 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1755 pcw->pci.pc.pb = NULL;
1757 // pcw->pci.pc.analyze = genericAnalyze;
1758 pcw->pci.pc.destruct = genericDestruct;
1759 pcw->pci.pc.print = genericPrint;
1761 pcw->id = pCodeID; // this is the 'n' in %n
1762 pcw->operand = optional_operand;
1763 pcw->label = optional_label;
1765 pcw->mustBeBitSkipInst = 0;
1766 pcw->mustNotBeBitSkipInst = 0;
1767 pcw->invertBitSkipInst = 0;
1769 return ( (pCode *)pcw);
1773 /*-----------------------------------------------------------------*/
1774 /* newPcodeInlineP - create a new pCode from a char string */
1775 /*-----------------------------------------------------------------*/
1778 pCode *newpCodeInlineP(char *cP)
1783 pcc = Safe_calloc(1,sizeof(pCodeComment));
1785 pcc->pc.type = PC_INLINE;
1786 pcc->pc.prev = pcc->pc.next = NULL;
1787 pcc->pc.id = PCodeID();
1788 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1791 // pcc->pc.analyze = genericAnalyze;
1792 pcc->pc.destruct = genericDestruct;
1793 pcc->pc.print = genericPrint;
1796 pcc->comment = Safe_strdup(cP);
1798 pcc->comment = NULL;
1800 return ( (pCode *)pcc);
1804 /*-----------------------------------------------------------------*/
1805 /* newPcodeCharP - create a new pCode from a char string */
1806 /*-----------------------------------------------------------------*/
1808 pCode *newpCodeCharP(char *cP)
1813 pcc = Safe_calloc(1,sizeof(pCodeComment));
1815 pcc->pc.type = PC_COMMENT;
1816 pcc->pc.prev = pcc->pc.next = NULL;
1817 pcc->pc.id = PCodeID();
1818 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1821 // pcc->pc.analyze = genericAnalyze;
1822 pcc->pc.destruct = genericDestruct;
1823 pcc->pc.print = genericPrint;
1826 pcc->comment = Safe_strdup(cP);
1828 pcc->comment = NULL;
1830 return ( (pCode *)pcc);
1834 /*-----------------------------------------------------------------*/
1835 /* newpCodeFunction - */
1836 /*-----------------------------------------------------------------*/
1839 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1843 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1844 //_ALLOC(pcf,sizeof(pCodeFunction));
1846 pcf->pc.type = PC_FUNCTION;
1847 pcf->pc.prev = pcf->pc.next = NULL;
1848 pcf->pc.id = PCodeID();
1849 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1852 // pcf->pc.analyze = genericAnalyze;
1853 pcf->pc.destruct = genericDestruct;
1854 pcf->pc.print = pCodePrintFunction;
1859 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1860 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1861 strcpy(pcf->modname,mod);
1863 pcf->modname = NULL;
1866 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1867 pcf->fname = Safe_calloc(1,strlen(f)+1);
1868 strcpy(pcf->fname,f);
1872 pcf->isPublic = (unsigned)isPublic;
1874 return ( (pCode *)pcf);
1878 /*-----------------------------------------------------------------*/
1880 /*-----------------------------------------------------------------*/
1881 void destructpCodeFlow(pCode *pc)
1883 if(!pc || !isPCFL(pc))
1892 deleteSet(&PCFL(pc)->registers);
1893 deleteSet(&PCFL(pc)->from);
1894 deleteSet(&PCFL(pc)->to);
1899 pCode *newpCodeFlow(void )
1903 //_ALLOC(pcflow,sizeof(pCodeFlow));
1904 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1906 pcflow->pc.type = PC_FLOW;
1907 pcflow->pc.prev = pcflow->pc.next = NULL;
1908 pcflow->pc.pb = NULL;
1910 // pcflow->pc.analyze = genericAnalyze;
1911 pcflow->pc.destruct = destructpCodeFlow;
1912 pcflow->pc.print = genericPrint;
1914 pcflow->pc.seq = GpcFlowSeq++;
1916 pcflow->from = pcflow->to = NULL;
1918 pcflow->inCond = PCC_NONE;
1919 pcflow->outCond = PCC_NONE;
1921 pcflow->firstBank = 'U'; /* Undetermined */
1922 pcflow->lastBank = 'U'; /* Undetermined */
1924 pcflow->FromConflicts = 0;
1925 pcflow->ToConflicts = 0;
1929 pcflow->registers = newSet();
1931 return ( (pCode *)pcflow);
1935 /*-----------------------------------------------------------------*/
1936 /*-----------------------------------------------------------------*/
1937 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1939 pCodeFlowLink *pcflowLink;
1941 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1943 pcflowLink->pcflow = pcflow;
1944 pcflowLink->bank_conflict = 0;
1949 /*-----------------------------------------------------------------*/
1950 /* newpCodeCSource - create a new pCode Source Symbol */
1951 /*-----------------------------------------------------------------*/
1953 pCode *newpCodeCSource(int ln, char *f, const char *l)
1958 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1960 pccs->pc.type = PC_CSOURCE;
1961 pccs->pc.prev = pccs->pc.next = NULL;
1962 pccs->pc.id = PCodeID();
1965 pccs->pc.destruct = genericDestruct;
1966 pccs->pc.print = genericPrint;
1968 pccs->line_number = ln;
1970 pccs->line = Safe_strdup(l);
1975 pccs->file_name = Safe_strdup(f);
1977 pccs->file_name = NULL;
1979 return ( (pCode *)pccs);
1983 /*******************************************************************/
1984 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
1985 /* added by VR 6-Jun-2003 */
1986 /*******************************************************************/
1988 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
1995 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
1996 pcad->pci.pc.type = PC_ASMDIR;
1997 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
1998 pcad->pci.pc.pb = NULL;
1999 pcad->pci.pc.destruct = genericDestruct;
2000 pcad->pci.pc.print = genericPrint;
2002 if(asdir && *asdir) {
2004 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
2006 pcad->directive = Safe_strdup( asdir );
2009 va_start(ap, argfmt);
2011 memset(buffer, 0, sizeof(buffer));
2012 if(argfmt && *argfmt)
2013 vsprintf(buffer, argfmt, ap);
2017 while(isspace((unsigned char)*lbp))lbp++;
2020 pcad->arg = Safe_strdup( lbp );
2022 return ((pCode *)pcad);
2025 /*-----------------------------------------------------------------*/
2026 /* pCodeLabelDestruct - free memory used by a label. */
2027 /*-----------------------------------------------------------------*/
2028 static void pCodeLabelDestruct(pCode *pc)
2034 if((pc->type == PC_LABEL) && PCL(pc)->label)
2035 free(PCL(pc)->label);
2041 pCode *newpCodeLabel(char *name, int key)
2047 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2049 pcl->pc.type = PC_LABEL;
2050 pcl->pc.prev = pcl->pc.next = NULL;
2051 pcl->pc.id = PCodeID();
2052 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2055 // pcl->pc.analyze = genericAnalyze;
2056 pcl->pc.destruct = pCodeLabelDestruct;
2057 pcl->pc.print = pCodePrintLabel;
2063 sprintf(s,"_%05d_DS_",key);
2068 pcl->label = Safe_strdup(s);
2070 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2071 return ( (pCode *)pcl);
2076 /*-----------------------------------------------------------------*/
2077 /* newpBlock - create and return a pointer to a new pBlock */
2078 /*-----------------------------------------------------------------*/
2079 pBlock *newpBlock(void)
2084 PpB = Safe_calloc(1,sizeof(pBlock) );
2085 PpB->next = PpB->prev = NULL;
2087 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2088 PpB->tregisters = NULL;
2090 PpB->FlowTree = NULL;
2096 /*-----------------------------------------------------------------*/
2097 /* newpCodeChain - create a new chain of pCodes */
2098 /*-----------------------------------------------------------------*
2100 * This function will create a new pBlock and the pointer to the
2101 * pCode that is passed in will be the first pCode in the block.
2102 *-----------------------------------------------------------------*/
2105 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2108 pBlock *pB = newpBlock();
2110 pB->pcHead = pB->pcTail = pc;
2117 /*-----------------------------------------------------------------*/
2118 /* newpCodeOpLabel - Create a new label given the key */
2119 /* Note, a negative key means that the label is part of wild card */
2120 /* (and hence a wild card label) used in the pCodePeep */
2121 /* optimizations). */
2122 /*-----------------------------------------------------------------*/
2124 pCodeOp *newpCodeOpLabel(char *name, int key)
2127 static int label_key=-1;
2131 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2132 pcop->type = PO_LABEL;
2137 sprintf(s=buffer,"_%05d_DS_",key);
2139 s = name, key = label_key--;
2141 PCOLAB(pcop)->offset = 0;
2143 pcop->name = Safe_strdup(s);
2145 ((pCodeOpLabel *)pcop)->key = key;
2147 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2151 /*-----------------------------------------------------------------*/
2152 /*-----------------------------------------------------------------*/
2153 pCodeOp *newpCodeOpLit(int lit)
2159 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2160 pcop->type = PO_LITERAL;
2164 sprintf(s,"0x%02x", (unsigned char)lit);
2166 pcop->name = Safe_strdup(s);
2169 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2174 /*-----------------------------------------------------------------*/
2175 /*-----------------------------------------------------------------*/
2176 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2180 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2181 pcop->type = PO_IMMEDIATE;
2184 pcop->name = Safe_strdup(name);
2187 r = dirregWithName(name);
2191 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2192 PCOI(pcop)->rIdx = r->rIdx;
2194 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2195 PCOI(pcop)->rIdx = -1;
2197 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2202 PCOI(pcop)->index = index;
2203 PCOI(pcop)->offset = offset;
2204 PCOI(pcop)->_const = code_space;
2205 PCOI(pcop)->_function = is_func;
2210 /*-----------------------------------------------------------------*/
2211 /*-----------------------------------------------------------------*/
2212 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2218 if(!pcwb || !subtype) {
2219 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2223 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2224 pcop->type = PO_WILD;
2225 sprintf(s,"%%%d",id);
2226 pcop->name = Safe_strdup(s);
2228 PCOW(pcop)->id = id;
2229 PCOW(pcop)->pcwb = pcwb;
2230 PCOW(pcop)->subtype = subtype;
2231 PCOW(pcop)->matched = NULL;
2235 /*-----------------------------------------------------------------*/
2236 /* Find a symbol with matching name */
2237 /*-----------------------------------------------------------------*/
2238 static symbol *symFindWithName(memmap * map, const char *name)
2242 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2243 if (sym->rname && (strcmp(sym->rname,name)==0))
2249 /*-----------------------------------------------------------------*/
2250 /*-----------------------------------------------------------------*/
2251 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2256 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2257 pcop->type = PO_GPR_BIT;
2259 PCORB(pcop)->bit = ibit;
2260 PCORB(pcop)->inBitSpace = inBitSpace;
2262 if (name) r = regFindWithName(name);
2264 // Register has not been allocated - check for symbol information
2266 sym = symFindWithName(bit, name);
2267 if (!sym) sym = symFindWithName(sfrbit, name);
2268 if (!sym) sym = symFindWithName(sfr, name);
2269 if (!sym) sym = symFindWithName(reg, name);
2270 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2271 // XXX: This ignores nesting levels, but works for globals...
2272 if (!sym) sym = findSym(SymbolTab, NULL, name);
2273 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2275 r = allocNewDirReg(sym->etype,name);
2281 PCOR(pcop)->rIdx = r->rIdx;
2283 pcop->name = Safe_strdup(name);
2284 PCOR(pcop)->r = NULL;
2285 PCOR(pcop)->rIdx = 0;
2291 pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2297 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2298 pcop->name = reg->name;
2299 pcop->type = PO_GPR_BIT;
2300 PCORB(pcop)->bit = ibit;
2301 PCORB(pcop)->inBitSpace = inBitSpace;
2302 PCOR(pcop)->r = reg;
2303 PCOR(pcop)->index = 0;
2304 PCOR(pcop)->rIdx = reg->rIdx;
2309 /*-----------------------------------------------------------------*
2310 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2312 * If rIdx >=0 then a specific register from the set of registers
2313 * will be selected. If rIdx <0, then a new register will be searched
2315 *-----------------------------------------------------------------*/
2317 pCodeOp *newpCodeOpReg(int rIdx)
2321 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2326 PCOR(pcop)->rIdx = rIdx;
2327 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2329 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2332 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2336 pcop->type = PCOR(pcop)->r->pc_type;
2341 pCodeOp *newpCodeOpRegFromStr(char *name)
2345 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2346 PCOR(pcop)->r = allocRegByName(name, 1);
2347 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2348 pcop->type = PCOR(pcop)->r->pc_type;
2349 pcop->name = PCOR(pcop)->r->name;
2354 pCodeOp *newpCodeOpStr(char *name)
2358 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2359 pcop->type = PO_STR;
2360 pcop->name = Safe_strdup(name);
2362 PCOS(pcop)->isPublic = 0;
2368 /*-----------------------------------------------------------------*/
2369 /*-----------------------------------------------------------------*/
2371 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2378 pcop = newpCodeOpBit(name, -1,0);
2382 pcop = newpCodeOpLit(-1);
2386 pcop = newpCodeOpLabel(NULL,-1);
2390 pcop = newpCodeOpReg(-1);
2393 case PO_GPR_POINTER:
2394 case PO_GPR_REGISTER:
2396 pcop = newpCodeOpRegFromStr(name);
2398 pcop = newpCodeOpReg(-1);
2402 pcop = newpCodeOpStr(name);
2406 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2409 pcop->name = Safe_strdup(name);
2417 /*-----------------------------------------------------------------*/
2418 /*-----------------------------------------------------------------*/
2419 void pCodeConstString(char *name, char *value)
2424 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2429 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2433 sprintf(buffer,"; %s = %s",name,value);
2434 for (i=strlen(buffer); i--; ) {
2435 unsigned char c = buffer[i];
2436 if (c=='\r' || c=='\n') {
2437 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2439 if (c=='\r') buffer[i+1] = 'r';
2440 else if (c=='\n') buffer[i+1] = 'n';
2444 addpCode2pBlock(pb,newpCodeCharP(buffer));
2445 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2448 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2454 /*-----------------------------------------------------------------*/
2455 /*-----------------------------------------------------------------*/
2456 void pCodeReadCodeTable(void)
2460 fprintf(stderr, " %s\n",__FUNCTION__);
2462 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2466 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2467 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2468 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2469 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2471 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2472 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2473 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2474 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2479 /*-----------------------------------------------------------------*/
2480 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2481 /*-----------------------------------------------------------------*/
2482 void addpCode2pBlock(pBlock *pb, pCode *pc)
2489 /* If this is the first pcode to be added to a block that
2490 * was initialized with a NULL pcode, then go ahead and
2491 * make this pcode the head and tail */
2492 pb->pcHead = pb->pcTail = pc;
2495 pb->pcTail->next = pc;
2497 pc->prev = pb->pcTail;
2504 /*-----------------------------------------------------------------*/
2505 /* addpBlock - place a pBlock into the pFile */
2506 /*-----------------------------------------------------------------*/
2507 void addpBlock(pBlock *pb)
2509 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2512 /* First time called, we'll pass through here. */
2513 //_ALLOC(the_pFile,sizeof(pFile));
2514 the_pFile = Safe_calloc(1,sizeof(pFile));
2515 the_pFile->pbHead = the_pFile->pbTail = pb;
2516 the_pFile->functions = NULL;
2520 the_pFile->pbTail->next = pb;
2521 pb->prev = the_pFile->pbTail;
2523 the_pFile->pbTail = pb;
2526 /*-----------------------------------------------------------------*/
2527 /* removepBlock - remove a pBlock from the pFile */
2528 /*-----------------------------------------------------------------*/
2529 void removepBlock(pBlock *pb)
2537 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2539 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2542 if(pbs == the_pFile->pbHead)
2543 the_pFile->pbHead = pbs->next;
2545 if (pbs == the_pFile->pbTail)
2546 the_pFile->pbTail = pbs->prev;
2549 pbs->next->prev = pbs->prev;
2552 pbs->prev->next = pbs->next;
2559 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2563 /*-----------------------------------------------------------------*/
2564 /* printpCode - write the contents of a pCode to a file */
2565 /*-----------------------------------------------------------------*/
2566 void printpCode(FILE *of, pCode *pc)
2577 fprintf(of,"warning - unable to print pCode\n");
2580 /*-----------------------------------------------------------------*/
2581 /* printpBlock - write the contents of a pBlock to a file */
2582 /*-----------------------------------------------------------------*/
2583 void printpBlock(FILE *of, pBlock *pb)
2593 for(pc = pb->pcHead; pc; pc = pc->next) {
2598 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2608 /*-----------------------------------------------------------------*/
2610 /* pCode processing */
2614 /*-----------------------------------------------------------------*/
2616 void unlinkpCode(pCode *pc)
2622 fprintf(stderr,"Unlinking: ");
2623 printpCode(stderr, pc);
2626 pc->prev->next = pc->next;
2628 pc->next->prev = pc->prev;
2631 /* RN: I believe this should be right here, but this did not
2632 * cure the bug I was hunting... */
2633 /* must keep labels -- attach to following instruction */
2634 if (isPCI(pc) && PCI(pc)->label && pc->next)
2636 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2639 pBranchAppend (pcnext->label, PCI(pc)->label);
2643 pc->prev = pc->next = NULL;
2647 /*-----------------------------------------------------------------*/
2648 /*-----------------------------------------------------------------*/
2650 static void genericDestruct(pCode *pc)
2656 /* For instructions, tell the register (if there's one used)
2657 * that it's no longer needed */
2658 regs *reg = getRegFromInstruction(pc);
2660 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2663 /* Instead of deleting the memory used by this pCode, mark
2664 * the object as bad so that if there's a pointer to this pCode
2665 * dangling around somewhere then (hopefully) when the type is
2666 * checked we'll catch it.
2671 addpCode2pBlock(pb_dead_pcodes, pc);
2678 /*-----------------------------------------------------------------*/
2679 /* Copies the pCodeInstruction flow pointer from source pCode */
2680 /*-----------------------------------------------------------------*/
2681 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2683 pCodeFlow *pcflow = 0;
2684 for (p=pcs; p; p=p->prev) {
2686 pcflow = PCI(p)->pcflow;
2690 pcflow = (pCodeFlow*)p;
2694 PCI(pcd)->pcflow = pcflow;
2697 /*-----------------------------------------------------------------*/
2698 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2699 /* into the pCode chain containing pc1 */
2700 /*-----------------------------------------------------------------*/
2701 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2707 pc2->next = pc1->next;
2709 pc1->next->prev = pc2;
2715 /* If this is an instrution type propogate the flow */
2717 CopyFlow(PCI(pc2),pc1);
2720 /*------------------------------------------------------------------*/
2721 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2722 /* into the pCode chain containing pc1 */
2723 /*------------------------------------------------------------------*/
2724 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2730 pc2->prev = pc1->prev;
2732 pc1->prev->next = pc2;
2738 /* If this is an instrution type propogate the flow */
2740 CopyFlow(PCI(pc2),pc1);
2743 /*-----------------------------------------------------------------*/
2744 /* pCodeOpCopy - copy a pcode operator */
2745 /*-----------------------------------------------------------------*/
2746 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2748 pCodeOp *pcopnew=NULL;
2753 switch(pcop->type) {
2756 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2757 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2765 case PO_GPR_REGISTER:
2767 case PO_GPR_POINTER:
2768 case PO_SFR_REGISTER:
2772 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2773 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2774 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2775 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2779 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2780 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2781 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2785 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2786 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2792 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2793 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2794 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2798 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2799 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2800 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2804 /* Here we expand the wild card into the appropriate type: */
2805 /* By recursively calling pCodeOpCopy */
2806 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2807 if(PCOW(pcop)->matched)
2808 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2811 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2812 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2813 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2820 assert ( !"unhandled pCodeOp type copied" );
2825 pcopnew->name = Safe_strdup(pcop->name);
2827 pcopnew->name = NULL;
2832 /*-----------------------------------------------------------------*/
2833 /* popCopyReg - copy a pcode operator */
2834 /*-----------------------------------------------------------------*/
2835 pCodeOp *popCopyReg(pCodeOpReg *pc)
2839 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2840 pcor->pcop.type = pc->pcop.type;
2842 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2843 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2845 pcor->pcop.name = NULL;
2847 if (pcor->pcop.type == PO_IMMEDIATE){
2848 PCOL(pcor)->lit = PCOL(pc)->lit;
2851 pcor->rIdx = pc->rIdx;
2855 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2860 /*-----------------------------------------------------------------*/
2861 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2862 /*-----------------------------------------------------------------*/
2863 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2865 pCodeInstruction *new_pci;
2868 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2870 new_pci = PCI(newpCode(pci->op,pci->pcop));
2872 new_pci->pc.pb = pci->pc.pb;
2873 new_pci->from = pci->from;
2874 new_pci->to = pci->to;
2875 new_pci->label = pci->label;
2876 new_pci->pcflow = pci->pcflow;
2878 return PCODE(new_pci);
2881 /*-----------------------------------------------------------------*/
2882 /*-----------------------------------------------------------------*/
2883 void pCodeDeleteChain(pCode *f,pCode *t)
2888 DFPRINTF((stderr,"delete pCode:\n"));
2890 //f->print(stderr,f);
2891 //f->delete(f); this dumps core...
2896 /*-----------------------------------------------------------------*/
2897 /*-----------------------------------------------------------------*/
2898 void pBlockRegs(FILE *of, pBlock *pb)
2903 r = setFirstItem(pb->tregisters);
2905 r = setNextItem(pb->tregisters);
2910 /*-----------------------------------------------------------------*/
2911 /*-----------------------------------------------------------------*/
2912 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2917 int use_buffer = 1; // copy the string to the passed buffer pointer
2922 use_buffer = 0; // Don't bother copying the string to the buffer.
2926 switch(pcop->type) {
2930 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
2936 if (PCOR(pcop)->r->type == REG_STK)
2937 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2939 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2942 SNPRINTF(buffer,size,"%s",r->name);
2951 if(PCOI(pcop)->_const) {
2953 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
2954 switch(PCOI(pcop)->offset) {
2956 SNPRINTF(s,size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
2959 SNPRINTF(s,size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
2962 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
2965 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
2966 assert ( !"offset too large" );
2967 SNPRINTF(s,size,"(((%s+%d) >> %d)&0xff)",
2970 8 * PCOI(pcop)->offset );
2973 SNPRINTF(s,size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
2975 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
2976 SNPRINTF(s,size,"(%s + %d)",
2980 switch(PCOI(pcop)->offset) {
2982 SNPRINTF(s,size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
2985 SNPRINTF(s,size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
2988 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
2991 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
2992 assert ( !"offset too large" );
2993 SNPRINTF(s,size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3003 if( PCOR(pcop)->instance) {
3004 SNPRINTF(s,size,"(%s + %d)",
3006 PCOR(pcop)->instance );
3008 SNPRINTF(s,size,"%s",pcop->name);
3015 if(PCOLAB(pcop)->offset == 1)
3016 SNPRINTF(s,size,"HIGH(%s)",pcop->name);
3018 SNPRINTF(s,size,"%s",pcop->name);
3026 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
3029 return PCOR(pcop)->r->name;
3031 /* fall through to the default case */
3036 SNPRINTF(buffer,size,"%s",pcop->name);
3044 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3045 __FILE__, __LINE__, __FUNCTION__,
3048 return "NO operand";
3052 /*-----------------------------------------------------------------*/
3053 /*-----------------------------------------------------------------*/
3054 static char *get_op_from_instruction( pCodeInstruction *pcc)
3058 return get_op(pcc->pcop,NULL,0);
3060 return ("ERROR Null: get_op_from_instruction");
3064 /*-----------------------------------------------------------------*/
3065 /*-----------------------------------------------------------------*/
3066 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3068 fprintf(of,"pcodeopprint- not implemented\n");
3071 /*-----------------------------------------------------------------*/
3072 /* pCode2str - convert a pCode instruction to string */
3073 /*-----------------------------------------------------------------*/
3074 char *pCode2str(char *str, size_t size, pCode *pc)
3082 SNPRINTF(s,size, "\t%s\t", PCI(pc)->mnemonic);
3086 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3087 if(PCI(pc)->isBitInst) {
3088 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3089 char *name = PCI(pc)->pcop->name;
3091 name = PCOR(PCI(pc)->pcop)->r->name;
3092 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3093 SNPRINTF(s,size,"(%s >> 3), (%s & 7)", name, name);
3095 SNPRINTF(s,size,"%s,%d", name, (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3096 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3097 SNPRINTF(s,size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3099 SNPRINTF(s,size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3101 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3102 if( PCI(pc)->num_ops == 2)
3103 SNPRINTF(s,size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3105 SNPRINTF(s,size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3107 SNPRINTF(s,size,"%s",get_op_from_instruction(PCI(pc)));
3110 if( PCI(pc)->num_ops == 2)
3111 SNPRINTF(s,size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3118 /* assuming that comment ends with a \n */
3119 SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
3123 /* assuming that inline code ends with a \n */
3124 SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
3128 SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3131 SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3134 SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3137 SNPRINTF(s,size,";\t--FLOW change\n");
3140 SNPRINTF(s,size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3143 if(PCAD(pc)->directive) {
3144 SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3145 } else if(PCAD(pc)->arg) {
3146 /* special case to handle inline labels without a tab */
3147 SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
3152 SNPRINTF(s,size,";A bad pCode is being used\n");
3158 /*-----------------------------------------------------------------*/
3159 /* genericPrint - the contents of a pCode to a file */
3160 /*-----------------------------------------------------------------*/
3161 static void genericPrint(FILE *of, pCode *pc)
3168 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3172 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3176 // If the opcode has a label, print that first
3179 pCodeInstruction *pci = PCI(pc);
3180 pBranch *pbl = pci->label;
3181 while(pbl && pbl->pc) {
3182 if(pbl->pc->type == PC_LABEL)
3183 pCodePrintLabel(of, pbl->pc);
3188 genericPrint(of,PCODE(pci->cline));
3191 pCode2str(str, 256, pc);
3193 fprintf(of,"%s",str);
3197 pCodeOpReg *pcor = PCOR(pci->pcop);
3198 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3200 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3201 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3202 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3207 pBranch *dpb = pc->to; // debug
3209 switch ( dpb->pc->type) {
3211 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3214 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3217 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3220 fprintf(of, "\t;flow");
3234 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3235 if(PCW(pc)->pci.label)
3236 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3238 if(PCW(pc)->operand) {
3239 fprintf(of,";\toperand ");
3240 pCodeOpPrint(of,PCW(pc)->operand );
3246 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3247 if(PCFL(pc)->ancestor)
3248 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3250 fprintf(of,"; from: ");
3252 pCodeFlowLink *link;
3253 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3255 fprintf(of,"%03x ",link->pcflow->pc.seq);
3258 fprintf(of,"; to: ");
3260 pCodeFlowLink *link;
3261 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3263 fprintf(of,"%03x ",link->pcflow->pc.seq);
3271 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3272 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3277 pBranch *pbl = PCAD(pc)->pci.label;
3278 while(pbl && pbl->pc) {
3279 if(pbl->pc->type == PC_LABEL)
3280 pCodePrintLabel(of, pbl->pc);
3284 if(PCAD(pc)->directive) {
3285 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3288 /* special case to handle inline labels without tab */
3289 fprintf(of, "%s\n", PCAD(pc)->arg);
3295 fprintf(of,"unknown pCode type %d\n",pc->type);
3299 /*-----------------------------------------------------------------*/
3300 /* pCodePrintFunction - prints function begin/end */
3301 /*-----------------------------------------------------------------*/
3303 static void pCodePrintFunction(FILE *of, pCode *pc)
3309 if( ((pCodeFunction *)pc)->modname)
3310 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3312 if(PCF(pc)->fname) {
3313 pBranch *exits = PCF(pc)->to;
3315 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3318 exits = exits->next;
3321 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3324 if((PCF(pc)->from &&
3325 PCF(pc)->from->pc->type == PC_FUNCTION &&
3326 PCF(PCF(pc)->from->pc)->fname) )
3327 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3329 fprintf(of,"; exit point [can't find entry point]\n");
3332 /*-----------------------------------------------------------------*/
3333 /* pCodePrintLabel - prints label */
3334 /*-----------------------------------------------------------------*/
3336 static void pCodePrintLabel(FILE *of, pCode *pc)
3343 fprintf(of,"%s\n",PCL(pc)->label);
3344 else if (PCL(pc)->key >=0)
3345 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3347 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3351 /*-----------------------------------------------------------------*/
3352 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3353 /* remove it if it is found. */
3354 /*-----------------------------------------------------------------*/
3355 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3361 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3362 b = PCI(pcl)->label;
3364 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3368 //fprintf (stderr, "%s \n",__FUNCTION__);
3369 //pcl->print(stderr,pcl);
3370 //pc->print(stderr,pc);
3373 //fprintf (stderr, "found label\n");
3377 bprev->next = b->next; /* Not first pCode in chain */
3381 PCI(pcl)->label = b->next; /* First pCode in chain */
3384 return; /* A label can't occur more than once */
3391 /*-----------------------------------------------------------------*/
3392 /*-----------------------------------------------------------------*/
3393 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3412 /*-----------------------------------------------------------------*/
3413 /* pBranchLink - given two pcodes, this function will link them */
3414 /* together through their pBranches */
3415 /*-----------------------------------------------------------------*/
3416 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3420 // Declare a new branch object for the 'from' pCode.
3422 //_ALLOC(b,sizeof(pBranch));
3423 b = Safe_calloc(1,sizeof(pBranch));
3424 b->pc = PCODE(t); // The link to the 'to' pCode.
3427 f->to = pBranchAppend(f->to,b);
3429 // Now do the same for the 'to' pCode.
3431 //_ALLOC(b,sizeof(pBranch));
3432 b = Safe_calloc(1,sizeof(pBranch));
3436 t->from = pBranchAppend(t->from,b);
3441 /*-----------------------------------------------------------------*/
3442 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3444 /*-----------------------------------------------------------------*/
3445 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3458 /*-----------------------------------------------------------------*/
3459 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3460 /*-----------------------------------------------------------------*/
3461 static void pCodeUnlink(pCode *pc)
3466 if(!pc->prev || !pc->next) {
3467 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3471 /* first remove the pCode from the chain */
3472 pc->prev->next = pc->next;
3473 pc->next->prev = pc->prev;
3475 /* Now for the hard part... */
3477 /* Remove the branches */
3481 pc1 = pb1->pc; /* Get the pCode that branches to the
3482 * one we're unlinking */
3484 /* search for the link back to this pCode (the one we're
3486 if(pb2 = pBranchFind(pc1->to,pc)) {
3487 pb2->pc = pc->to->pc; // make the replacement
3489 /* if the pCode we're unlinking contains multiple 'to'
3490 * branches (e.g. this a skip instruction) then we need
3491 * to copy these extra branches to the chain. */
3493 pBranchAppend(pb2, pc->to->next);
3502 /*-----------------------------------------------------------------*/
3503 /*-----------------------------------------------------------------*/
3505 static void genericAnalyze(pCode *pc)
3515 // Go through the pCodes that are in pCode chain and link
3516 // them together through the pBranches. Note, the pCodes
3517 // are linked together as a contiguous stream like the
3518 // assembly source code lines. The linking here mimics this
3519 // except that comments are not linked in.
3521 pCode *npc = pc->next;
3523 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3524 pBranchLink(pc,npc);
3529 /* reached the end of the pcode chain without finding
3530 * an instruction we could link to. */
3534 fprintf(stderr,"analyze PC_FLOW\n");
3538 fprintf(stderr,";A bad pCode is being used\n");
3544 /*-----------------------------------------------------------------*/
3545 /*-----------------------------------------------------------------*/
3546 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3550 if(pc->type == PC_LABEL) {
3551 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3554 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3555 pbr = PCI(pc)->label;
3557 if(pbr->pc->type == PC_LABEL) {
3558 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3568 /*-----------------------------------------------------------------*/
3569 /*-----------------------------------------------------------------*/
3570 int checkLabel(pCode *pc)
3574 if(pc && isPCI(pc)) {
3575 pbr = PCI(pc)->label;
3577 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3587 /*-----------------------------------------------------------------*/
3588 /* findLabelinpBlock - Search the pCode for a particular label */
3589 /*-----------------------------------------------------------------*/
3590 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3597 for(pc = pb->pcHead; pc; pc = pc->next)
3598 if(compareLabel(pc,pcop_label))
3604 /*-----------------------------------------------------------------*/
3605 /* findLabel - Search the pCode for a particular label */
3606 /*-----------------------------------------------------------------*/
3607 pCode * findLabel(pCodeOpLabel *pcop_label)
3615 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3616 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3620 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3624 /*-----------------------------------------------------------------*/
3625 /* findNextpCode - given a pCode, find the next of type 'pct' */
3626 /* in the linked list */
3627 /*-----------------------------------------------------------------*/
3628 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3641 /*-----------------------------------------------------------------*/
3642 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3643 /* in the linked list */
3644 /*-----------------------------------------------------------------*/
3645 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3649 if(pc->type == pct) {
3651 static unsigned int stop;
3653 stop++; // Place break point here
3664 /*-----------------------------------------------------------------*/
3665 /* findNextInstruction - given a pCode, find the next instruction */
3666 /* in the linked list */
3667 /*-----------------------------------------------------------------*/
3668 pCode * findNextInstruction(pCode *pci)
3673 if((pc->type == PC_OPCODE)
3674 || (pc->type == PC_WILD)
3675 || (pc->type == PC_ASMDIR))
3679 fprintf(stderr,"findNextInstruction: ");
3680 printpCode(stderr, pc);
3685 //fprintf(stderr,"Couldn't find instruction\n");
3689 /*-----------------------------------------------------------------*/
3690 /* findNextInstruction - given a pCode, find the next instruction */
3691 /* in the linked list */
3692 /*-----------------------------------------------------------------*/
3693 pCode * findPrevInstruction(pCode *pci)
3699 if((pc->type == PC_OPCODE)
3700 || (pc->type == PC_WILD)
3701 || (pc->type == PC_ASMDIR))
3706 fprintf(stderr,"pic16_findPrevInstruction: ");
3707 printpCode(stderr, pc);
3712 //fprintf(stderr,"Couldn't find instruction\n");
3716 /*-----------------------------------------------------------------*/
3717 /* findFunctionEnd - given a pCode find the end of the function */
3718 /* that contains it */
3719 /*-----------------------------------------------------------------*/
3720 pCode * findFunctionEnd(pCode *pc)
3723 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3729 fprintf(stderr,"Couldn't find function end\n");
3734 /*-----------------------------------------------------------------*/
3735 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3736 /* instruction with which it is associated. */
3737 /*-----------------------------------------------------------------*/
3738 static void AnalyzeLabel(pCode *pc)
3747 static void AnalyzeGOTO(pCode *pc)
3750 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3754 static void AnalyzeSKIP(pCode *pc)
3757 pBranchLink(pc,findNextInstruction(pc->next));
3758 pBranchLink(pc,findNextInstruction(pc->next->next));
3762 static void AnalyzeRETURN(pCode *pc)
3765 // branch_link(pc,findFunctionEnd(pc->next));
3771 /*-----------------------------------------------------------------*/
3772 /*-----------------------------------------------------------------*/
3773 regs * getRegFromInstruction(pCode *pc)
3779 PCI(pc)->num_ops == 0 )
3782 switch(PCI(pc)->pcop->type) {
3789 case PO_SFR_REGISTER:
3792 return PCOR(PCI(pc)->pcop)->r;
3794 case PO_GPR_REGISTER:
3797 r = PCOR(PCI(pc)->pcop)->r;
3800 return dirregWithName(PCI(pc)->pcop->name);
3806 r = PCOI(PCI(pc)->pcop)->r;
3809 return dirregWithName(PCI(pc)->pcop->name);
3819 /*-----------------------------------------------------------------*/
3820 /*-----------------------------------------------------------------*/
3822 void AnalyzepBlock(pBlock *pb)
3829 /* Find all of the registers used in this pBlock
3830 * by looking at each instruction and examining it's
3833 for(pc = pb->pcHead; pc; pc = pc->next) {
3835 /* Is this an instruction with operands? */
3836 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3838 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3839 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3841 /* Loop through all of the registers declared so far in
3842 this block and see if we find this one there */
3844 regs *r = setFirstItem(pb->tregisters);
3847 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3848 PCOR(PCI(pc)->pcop)->r = r;
3851 r = setNextItem(pb->tregisters);
3855 /* register wasn't found */
3856 //r = Safe_calloc(1, sizeof(regs));
3857 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3858 //addSet(&pb->tregisters, r);
3859 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3860 //PCOR(PCI(pc)->pcop)->r = r;
3861 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3863 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3866 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3867 if(PCOR(PCI(pc)->pcop)->r) {
3868 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3869 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3871 if(PCI(pc)->pcop->name)
3872 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3874 fprintf(stderr,"ERROR: NULL register\n");
3883 /*-----------------------------------------------------------------*/
3885 /*-----------------------------------------------------------------*/
3886 void InsertpFlow(pCode *pc, pCode **pflow)
3889 PCFL(*pflow)->end = pc;
3891 if(!pc || !pc->next)
3894 *pflow = newpCodeFlow();
3895 pCodeInsertAfter(pc, *pflow);
3898 /*-----------------------------------------------------------------*/
3899 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3900 /* the flow blocks. */
3902 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3903 * point the instruction flow changes.
3905 /*-----------------------------------------------------------------*/
3906 void BuildFlow(pBlock *pb)
3909 pCode *last_pci=NULL;
3916 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3917 /* Insert a pCodeFlow object at the beginning of a pBlock */
3919 InsertpFlow(pb->pcHead, &pflow);
3921 //pflow = newpCodeFlow(); /* Create a new Flow object */
3922 //pflow->next = pb->pcHead; /* Make the current head the next object */
3923 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3924 //pb->pcHead = pflow; /* Make the Flow object the head */
3927 for( pc = findNextInstruction(pb->pcHead);
3929 pc=findNextInstruction(pc)) {
3932 PCI(pc)->pcflow = PCFL(pflow);
3934 //fprintf(stderr," build: ");
3935 //pc->print(stderr, pc);
3936 //pflow->print(stderr,pflow);
3938 if (checkLabel(pc)) {
3940 /* This instruction marks the beginning of a
3941 * new flow segment */
3946 /* If the previous pCode is not a flow object, then
3947 * insert a new flow object. (This check prevents
3948 * two consecutive flow objects from being insert in
3949 * the case where a skip instruction preceeds an
3950 * instruction containing a label.) */
3952 last_pci = findPrevInstruction (pc->prev);
3954 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3955 InsertpFlow(last_pci, &pflow);
3957 PCI(pc)->pcflow = PCFL(pflow);
3961 if(isPCI_SKIP(pc)) {
3963 /* The two instructions immediately following this one
3964 * mark the beginning of a new flow segment */
3966 while(pc && isPCI_SKIP(pc)) {
3968 PCI(pc)->pcflow = PCFL(pflow);
3972 InsertpFlow(pc, &pflow);
3973 pc=findNextInstruction(pc->next);
3981 PCI(pc)->pcflow = PCFL(pflow);
3983 InsertpFlow(pc, &pflow);
3985 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
3987 InsertpFlow(pc, &pflow);
3996 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3998 PCFL(pflow)->end = pb->pcTail;
4001 /*-------------------------------------------------------------------*/
4002 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
4003 /* the flow blocks. */
4005 * unBuildFlow removes pCodeFlow objects from a pCode chain
4007 /*-----------------------------------------------------------------*/
4008 void unBuildFlow(pBlock *pb)
4023 if(PCI(pc)->pcflow) {
4024 //free(PCI(pc)->pcflow);
4025 PCI(pc)->pcflow = NULL;
4028 } else if(isPCFL(pc) )
4037 /*-----------------------------------------------------------------*/
4038 /*-----------------------------------------------------------------*/
4039 void dumpCond(int cond)
4042 static char *pcc_str[] = {
4056 int ncond = sizeof(pcc_str) / sizeof(char *);
4059 fprintf(stderr, "0x%04X\n",cond);
4061 for(i=0,j=1; i<ncond; i++, j<<=1)
4063 fprintf(stderr, " %s\n",pcc_str[i]);
4067 /*-----------------------------------------------------------------*/
4068 /*-----------------------------------------------------------------*/
4069 void FlowStats(pCodeFlow *pcflow)
4077 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4079 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4082 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4087 fprintf(stderr, " FlowStats inCond: ");
4088 dumpCond(pcflow->inCond);
4089 fprintf(stderr, " FlowStats outCond: ");
4090 dumpCond(pcflow->outCond);
4094 /*-----------------------------------------------------------------*
4095 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4096 * if it affects the banking bits.
4098 * return: -1 == Banking bits are unaffected by this pCode.
4100 * return: > 0 == Banking bits are affected.
4102 * If the banking bits are affected, then the returned value describes
4103 * which bits are affected and how they're affected. The lower half
4104 * of the integer maps to the bits that are affected, the upper half
4105 * to whether they're set or cleared.
4107 *-----------------------------------------------------------------*/
4109 #define SET_BANK_BIT (1 << 16)
4110 #define CLR_BANK_BIT 0
4112 static int isBankInstruction(pCode *pc)
4120 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4122 // Check to see if the register banks are changing
4123 if(PCI(pc)->isModReg) {
4125 pCodeOp *pcop = PCI(pc)->pcop;
4126 switch(PCI(pc)->op) {
4129 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4130 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4131 return SET_BANK_BIT | PIC_RP0_BIT;
4134 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4135 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4136 return CLR_BANK_BIT | PIC_RP0_BIT;
4141 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4142 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4143 return CLR_BANK_BIT | PIC_RP1_BIT;
4145 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4146 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4147 return CLR_BANK_BIT | PIC_RP1_BIT;
4151 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4152 //genericPrint(stderr, pc);
4163 /*-----------------------------------------------------------------*/
4164 /*-----------------------------------------------------------------*/
4166 static void FillFlow(pCodeFlow *pcflow)
4174 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4176 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4179 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4186 isBankInstruction(pc);
4188 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4191 fprintf(stderr, " FillFlow - Bad end of flow\n");
4193 fprintf(stderr, " FillFlow - Ending flow with\n ");
4194 pc->print(stderr,pc);
4197 fprintf(stderr, " FillFlow inCond: ");
4198 dumpCond(pcflow->inCond);
4199 fprintf(stderr, " FillFlow outCond: ");
4200 dumpCond(pcflow->outCond);
4205 /*-----------------------------------------------------------------*/
4206 /*-----------------------------------------------------------------*/
4207 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4209 pCodeFlowLink *fromLink, *toLink;
4211 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4212 if (from) from->pc.print(stderr, &from->pc);
4213 else fprintf(stderr, "(null)");
4214 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4215 from && from->pcflow ? from->pcflow->pc.seq : 0,
4216 to && to->pcflow ? to->pcflow->pc.seq : 0);
4217 if (to) to->pc.print(stderr, &to->pc);
4218 else fprintf(stderr, "(null)");
4221 if(!from || !to || !to->pcflow || !from->pcflow)
4224 fromLink = newpCodeFlowLink(from->pcflow);
4225 toLink = newpCodeFlowLink(to->pcflow);
4227 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4228 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4232 /*-----------------------------------------------------------------*
4233 * void LinkFlow(pBlock *pb)
4235 * In BuildFlow, the PIC code has been partitioned into contiguous
4236 * non-branching segments. In LinkFlow, we determine the execution
4237 * order of these segments. For example, if one of the segments ends
4238 * with a skip, then we know that there are two possible flow segments
4239 * to which control may be passed.
4240 *-----------------------------------------------------------------*/
4241 void LinkFlow(pBlock *pb)
4247 //fprintf(stderr,"linkflow \n");
4251 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4253 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4256 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4258 //fprintf(stderr," link: ");
4259 //pcflow->print(stderr,pcflow);
4261 //FillFlow(PCFL(pcflow));
4263 /* find last instruction in flow */
4264 pc = findPrevInstruction (PCFL(pcflow)->end);
4266 fprintf(stderr, "%s: flow without end (%u)?\n",
4267 __FUNCTION__, pcflow->seq );
4271 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4272 //pc->print(stderr, pc);
4273 if(isPCI_SKIP(pc)) {
4274 //fprintf(stderr, "ends with skip\n");
4275 //pc->print(stderr,pc);
4276 pct=findNextInstruction(pc->next);
4277 LinkFlow_pCode(PCI(pc),PCI(pct));
4278 pct=findNextInstruction(pct->next);
4279 LinkFlow_pCode(PCI(pc),PCI(pct));
4283 if(isPCI_BRANCH(pc)) {
4284 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4286 //fprintf(stderr, "ends with branch\n ");
4287 //pc->print(stderr,pc);
4289 if(!(pcol && isPCOLAB(pcol))) {
4290 if((PCI(pc)->op != POC_RETLW)
4291 && (PCI(pc)->op != POC_RETURN)
4292 && (PCI(pc)->op != POC_CALL)
4293 && (PCI(pc)->op != POC_RETFIE) )
4295 pc->print(stderr,pc);
4296 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4300 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4301 LinkFlow_pCode(PCI(pc),PCI(pct));
4303 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4304 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4305 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4307 /* link CALLs to next instruction */
4308 if (PCI(pc)->op != POC_CALL) continue;
4312 //fprintf(stderr, "ends with non-branching instruction:\n");
4313 //pc->print(stderr,pc);
4315 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4321 //fprintf(stderr, "ends with unknown\n");
4322 //pc->print(stderr,pc);
4326 fprintf(stderr, "ends with nothing: ERROR\n");
4330 /*-----------------------------------------------------------------*/
4331 /*-----------------------------------------------------------------*/
4333 /*-----------------------------------------------------------------*/
4334 /*-----------------------------------------------------------------*/
4335 int isPCinFlow(pCode *pc, pCode *pcflow)
4341 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4344 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4350 /*-----------------------------------------------------------------*/
4351 /*-----------------------------------------------------------------*/
4353 static void BanksUsedFlow2(pCode *pcflow)
4362 if(!isPCFL(pcflow)) {
4363 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4367 pc = findNextInstruction(pcflow->next);
4369 PCFL(pcflow)->lastBank = -1;
4371 while(isPCinFlow(pc,pcflow)) {
4373 int bank_selected = isBankInstruction(pc);
4375 //if(PCI(pc)->pcflow)
4376 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4378 if(bank_selected > 0) {
4379 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4381 // This instruction is modifying banking bits before accessing registers
4383 PCFL(pcflow)->firstBank = -1;
4385 if(PCFL(pcflow)->lastBank == -1)
4386 PCFL(pcflow)->lastBank = 0;
4388 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4389 if(bank_selected & SET_BANK_BIT)
4390 PCFL(pcflow)->lastBank |= bank;
4394 reg = getRegFromInstruction(pc);
4396 if(reg && !isREGinBank(reg, bank)) {
4397 int allbanks = REGallBanks(reg);
4399 PCFL(pcflow)->firstBank = allbanks;
4401 PCFL(pcflow)->lastBank = allbanks;
4408 pc = findNextInstruction(pc->next);
4411 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4412 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4415 /*-----------------------------------------------------------------*/
4416 /*-----------------------------------------------------------------*/
4418 static void BanksUsedFlow(pBlock *pb)
4423 //pb->pcHead->print(stderr, pb->pcHead);
4425 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4426 //pcflow->print(stderr,pcflow);
4428 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4430 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4432 BanksUsedFlow2(pcflow);
4438 void pCodeReplace (pCode *old, pCode *new)
4440 pCodeInsertAfter (old, new);
4442 /* special handling for pCodeInstructions */
4443 if (isPCI(new) && isPCI(old))
4445 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4446 PCI(new)->from = PCI(old)->from;
4447 PCI(new)->to = PCI(old)->to;
4448 PCI(new)->label = PCI(old)->label;
4449 PCI(new)->pcflow = PCI(old)->pcflow;
4450 PCI(new)->cline = PCI(old)->cline;
4453 old->destruct (old);
4456 /*-----------------------------------------------------------------*/
4457 /*-----------------------------------------------------------------*/
4458 void addpCodeComment(pCode *pc, const char *fmt, ...)
4465 if (options.verbose || debug_verbose) {
4468 vsprintf(&buffer[2], fmt, ap);
4470 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4471 pCodeInsertAfter(pc, newpc);
4476 void pBlockMergeLabels(pBlock *pb);
4477 /*-----------------------------------------------------------------*/
4478 /* Inserts a new pCodeInstruction before an existing one */
4479 /*-----------------------------------------------------------------*/
4480 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4484 pcprev = findPrevInstruction(pci->pc.prev);
4486 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4488 /* Move the label, if there is one */
4491 new_pci->label = pci->label;
4495 /* Move the C code comment, if there is one */
4498 new_pci->cline = pci->cline;
4502 /* The new instruction has the same pcflow block */
4503 new_pci->pcflow = pci->pcflow;
4505 /* Arrrrg: is pci's previous instruction is a skip, we need to
4506 * change that into a jump (over pci and the new instruction) ... */
4507 if (pcprev && isPCI_SKIP(pcprev))
4509 symbol *lbl = newiTempLabel (NULL);
4510 pCode *label = newpCodeLabel (NULL, lbl->key);
4511 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4513 pCodeInsertAfter (pcprev, jump);
4515 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4516 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4517 switch (PCI(pcprev)->op) {
4522 // These are turned into non-skipping instructions, so
4523 // insert 'BTFSC STATUS, Z' after pcprev
4524 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4527 // no special actions required
4530 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4532 pCodeInsertAfter((pCode*)pci, label);
4533 pBlockMergeLabels(pci->pc.pb);
4537 /*-----------------------------------------------------------------*/
4538 /*-----------------------------------------------------------------*/
4539 static void insertBankSel(pCodeInstruction *pci, const char *name)
4545 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4546 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4548 pcop = popCopyReg(PCOR(pci->pcop));
4549 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4550 if (pcop->name == 0)
4551 pcop->name = strdup(name);
4552 new_pc = newpCode(POC_BANKSEL, pcop);
4554 insertPCodeInstruction(pci, PCI(new_pc));
4558 * isValidIdChar - check if c may be present in an identifier
4560 static int isValidIdChar (char c)
4562 if (c >= 'a' && c <= 'z') return 1;
4563 if (c >= 'A' && c <= 'Z') return 1;
4564 if (c >= '0' && c <= '9') return 1;
4565 if (c == '_') return 1;
4570 * bankcompare - check if two operand string refer to the same register
4571 * This functions handles NAME and (NAME + x) in both operands.
4572 * Returns 1 on same register, 0 on different (or unknown) registers.
4574 static int bankCompare(const char *op1, const char *op2)
4578 if (!op1 && !op2) return 0; // both unknown, might be different though!
4579 if (!op1 || !op2) return 0;
4581 // find start of operand name
4582 while (op1[0] == '(' || op1[0] == ' ') op1++;
4583 while (op2[0] == '(' || op2[0] == ' ') op2++;
4585 // compare till first non-identifier character
4586 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4587 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4589 // play safe---assume different operands
4593 /*-----------------------------------------------------------------*/
4594 /*-----------------------------------------------------------------*/
4595 extern int pic14_operandsAllocatedInSameBank(const char *str1, const char *str2);
4596 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4598 if (!cur_bank) return 0;
4600 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4601 return 1; // if we have address info, we use it for banksel optimization
4603 // regard '(regname + X)' and '(regname + Y)' as equal
4604 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4605 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4607 // check allocation policy from glue.c
4608 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4609 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4611 // seems to be a different operand--might be a different bank
4612 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4616 /*-----------------------------------------------------------------*/
4617 /*-----------------------------------------------------------------*/
4618 void FixRegisterBanking(pBlock *pb)
4621 pCodeInstruction *pci;
4623 regs *previous_reg; // contains the previous variable access info
4624 const char *cur_bank, *new_bank;
4625 unsigned cur_mask, new_mask, max_mask;
4630 max_mask = pic14_getPIC()->bankMask;
4631 cur_mask = max_mask;
4633 previous_reg = NULL;
4635 allRAMmshared = pic14_allRAMShared();
4637 for (pc = pb->pcHead; pc; pc = pc->next)
4639 // this one has a label---might check bank at all jumps here...
4640 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4641 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4642 previous_reg = NULL;
4643 cur_bank = NULL; // start new flow
4644 cur_mask = max_mask;
4647 // this one is/might be a label or BANKSEL---assume nothing
4648 if (isPCL(pc) || isPCASMDIR(pc)) {
4649 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4650 previous_reg = NULL;
4652 cur_mask = max_mask;
4655 // this one modifies STATUS
4656 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4660 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4661 // might need a BANKSEL
4662 reg = getRegFromInstruction(pc);
4665 new_bank = reg->name;
4666 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4667 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4668 new_mask = reg->alias;
4669 } else if (pci->pcop && pci->pcop->name) {
4670 new_bank = pci->pcop->name;
4671 new_mask = 0; // unknown, assume worst case
4673 assert(!"Could not get register from instruction.");
4674 new_bank = "UNKNOWN";
4675 new_mask = 0; // unknown, assume worst case
4679 // XXX: add switch to disable these
4681 // reg present in all banks possibly selected?
4682 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4683 // no BANKSEL required
4684 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4688 // only one bank of memory and no SFR accessed?
4689 // XXX: We can do better with fixed registers.
4690 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4691 // no BANKSEL required
4692 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4696 // restrict cur_mask to cover only the banks this register
4697 // is in (as well as the previous registers)
4698 cur_mask &= new_mask;
4700 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4701 // no BANKSEL required
4702 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4707 cur_mask = new_mask;
4708 cur_bank = new_bank;
4710 insertBankSel(pci, cur_bank);
4716 /*-----------------------------------------------------------------*/
4717 /*-----------------------------------------------------------------*/
4718 int OptimizepBlock(pBlock *pb)
4723 if(!pb || options.nopeep)
4726 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4728 for(pc = pb->pcHead; pc; pc = pc->next)
4729 matches += pCodePeepMatchRule(pc);
4732 pc = findNextInstruction(pb->pcHead);
4740 if(pCodePeepMatchRule(pc)) {
4745 pc = findNextInstruction(pcprev->next);
4747 pc = findNextInstruction(pb->pcHead);
4749 pc = findNextInstruction(pc->next);
4753 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4758 /*-----------------------------------------------------------------*/
4759 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4760 /*-----------------------------------------------------------------*/
4761 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4765 for(pc = pcs; pc; pc = pc->next) {
4767 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4769 (PCI(pc)->pcop->type == PO_LABEL) &&
4770 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4777 /*-----------------------------------------------------------------*/
4778 /*-----------------------------------------------------------------*/
4779 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4786 (PCI(pc)->pcop->type == PO_LABEL)) {
4788 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4790 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4792 free(pcol->pcop.name);
4794 /* If the key is negative, then we (probably) have a label to
4795 * a function and the name is already defined */
4798 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4802 //sprintf(buffer,"_%05d_DS_",pcl->key);
4804 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4806 pcol->pcop.name = Safe_strdup(s);
4807 pcol->key = pcl->key;
4808 //pc->print(stderr,pc);
4815 /*-----------------------------------------------------------------*/
4816 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4817 /* pCode chain if they're not used. */
4818 /*-----------------------------------------------------------------*/
4819 void pBlockRemoveUnusedLabels(pBlock *pb)
4821 pCode *pc; pCodeLabel *pcl;
4823 if(!pb || !pb->pcHead)
4826 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4828 pBranch *pbr = PCI(pc)->label;
4829 if(pbr && pbr->next) {
4830 pCode *pcd = pb->pcHead;
4832 //fprintf(stderr, "multiple labels\n");
4833 //pc->print(stderr,pc);
4838 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4839 //fprintf(stderr,"Used by:\n");
4840 //pcd->print(stderr,pcd);
4842 exchangeLabels(PCL(pbr->pc),pcd);
4851 for(pc = pb->pcHead; pc; pc = pc->next) {
4853 if(isPCL(pc)) // Label pcode
4855 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4856 pcl = PCL(PCI(pc)->label->pc);
4859 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4861 /* This pCode is a label, so search the pBlock to see if anyone
4864 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4865 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4866 /* Couldn't find an instruction that refers to this label
4867 * So, unlink the pCode label from it's pCode chain
4868 * and destroy the label */
4869 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4871 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4872 if(pc->type == PC_LABEL) {
4874 pCodeLabelDestruct(pc);
4876 unlinkpCodeFromBranch(pc, PCODE(pcl));
4877 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4888 /*-----------------------------------------------------------------*/
4889 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4890 /* chain and put them into pBranches that are */
4891 /* associated with the appropriate pCode */
4893 /*-----------------------------------------------------------------*/
4894 void pBlockMergeLabels(pBlock *pb)
4897 pCode *pc, *pcnext=NULL;
4902 /* First, Try to remove any unused labels */
4903 //pBlockRemoveUnusedLabels(pb);
4905 /* Now loop through the pBlock and merge the labels with the opcodes */
4908 // for(pc = pb->pcHead; pc; pc = pc->next) {
4911 pCode *pcn = pc->next;
4913 if(pc->type == PC_LABEL) {
4915 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4916 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4917 if((pcnext = findNextInstruction(pc) )) {
4919 // Unlink the pCode label from it's pCode chain
4922 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4923 // And link it into the instruction's pBranch labels. (Note, since
4924 // it's possible to have multiple labels associated with one instruction
4925 // we must provide a means to accomodate the additional labels. Thus
4926 // the labels are placed into the singly-linked list "label" as
4927 // opposed to being a single member of the pCodeInstruction.)
4929 //_ALLOC(pbr,sizeof(pBranch));
4930 pbr = Safe_calloc(1,sizeof(pBranch));
4934 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4937 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4939 } else if(pc->type == PC_CSOURCE) {
4941 /* merge the source line symbolic info into the next instruction */
4942 if((pcnext = findNextInstruction(pc) )) {
4944 // Unlink the pCode label from it's pCode chain
4946 PCI(pcnext)->cline = PCCS(pc);
4947 //fprintf(stderr, "merging CSRC\n");
4948 //genericPrint(stderr,pcnext);
4954 pBlockRemoveUnusedLabels(pb);
4958 /*-----------------------------------------------------------------*/
4959 /*-----------------------------------------------------------------*/
4960 int OptimizepCode(char dbName)
4962 #define MAX_PASSES 4
4971 DFPRINTF((stderr," Optimizing pCode\n"));
4975 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4976 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4977 matches += OptimizepBlock(pb);
4980 while(matches && ++passes < MAX_PASSES);
4985 /*-----------------------------------------------------------------*/
4986 /* popCopyGPR2Bit - copy a pcode operator */
4987 /*-----------------------------------------------------------------*/
4989 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4993 pcop = newpCodeOpBit(pc->name, bitval, 0);
4995 if( !( (pcop->type == PO_LABEL) ||
4996 (pcop->type == PO_LITERAL) ||
4997 (pcop->type == PO_STR) ))
4998 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5003 /*-----------------------------------------------------------------*/
5004 /*-----------------------------------------------------------------*/
5005 void pBlockDestruct(pBlock *pb)
5016 /*-----------------------------------------------------------------*/
5017 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5018 /* name dbName and combine them */
5019 /* into one block */
5020 /*-----------------------------------------------------------------*/
5021 void mergepBlocks(char dbName)
5024 pBlock *pb, *pbmerged = NULL,*pbn;
5026 pb = the_pFile->pbHead;
5028 //fprintf(stderr," merging blocks named %c\n",dbName);
5032 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5033 if( getpBlock_dbName(pb) == dbName) {
5035 //fprintf(stderr," merged block %c\n",dbName);
5040 addpCode2pBlock(pbmerged, pb->pcHead);
5041 /* addpCode2pBlock doesn't handle the tail: */
5042 pbmerged->pcTail = pb->pcTail;
5044 pb->prev->next = pbn;
5046 pbn->prev = pb->prev;
5051 //printpBlock(stderr, pbmerged);
5058 /*-----------------------------------------------------------------*/
5059 /* AnalyzeFlow - Examine the flow of the code and optimize */
5061 /* level 0 == minimal optimization */
5062 /* optimize registers that are used only by two instructions */
5063 /* level 1 == maximal optimization */
5064 /* optimize by looking at pairs of instructions that use the */
5066 /*-----------------------------------------------------------------*/
5068 void AnalyzeFlow(int level)
5070 static int times_called=0;
5078 /* if this is not the first time this function has been called,
5079 then clean up old flow information */
5080 if(times_called++) {
5081 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5084 RegsUnMapLiveRanges();
5090 /* Phase 2 - Flow Analysis - Register Banking
5092 * In this phase, the individual flow blocks are examined
5093 * and register banking is fixed.
5096 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5097 //FixRegisterBanking(pb);
5099 /* Phase 2 - Flow Analysis
5101 * In this phase, the pCode is partition into pCodeFlow
5102 * blocks. The flow blocks mark the points where a continuous
5103 * stream of instructions changes flow (e.g. because of
5104 * a call or goto or whatever).
5107 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5111 /* Phase 2 - Flow Analysis - linking flow blocks
5113 * In this phase, the individual flow blocks are examined
5114 * to determine their order of excution.
5117 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5120 /* Phase 3 - Flow Analysis - Flow Tree
5122 * In this phase, the individual flow blocks are examined
5123 * to determine their order of excution.
5126 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5130 /* Phase x - Flow Analysis - Used Banks
5132 * In this phase, the individual flow blocks are examined
5133 * to determine the Register Banks they use
5136 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5140 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5141 pCodeRegMapLiveRanges(pb);
5143 RemoveUnusedRegisters();
5145 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5146 pCodeRegOptimizeRegUsage(level);
5151 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5156 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5158 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5159 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5160 pcflow = pcflow->next) {
5162 FillFlow(PCFL(pcflow));
5167 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5169 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5170 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5171 pcflow = pcflow->next) {
5173 FlowStats(PCFL(pcflow));
5179 /*-----------------------------------------------------------------*/
5180 /* AnalyzeBanking - Called after the memory addresses have been */
5181 /* assigned to the registers. */
5183 /*-----------------------------------------------------------------*/
5185 void AnalyzeBanking(void)
5189 if(!picIsInitialized()) {
5190 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5194 if (!the_pFile) return;
5196 /* Phase x - Flow Analysis - Used Banks
5198 * In this phase, the individual flow blocks are examined
5199 * to determine the Register Banks they use
5205 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5206 // BanksUsedFlow(pb);
5207 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5208 FixRegisterBanking(pb);
5215 /*-----------------------------------------------------------------*/
5216 /*-----------------------------------------------------------------*/
5217 DEFSETFUNC (resetrIdx)
5219 regs *r = (regs *)item;
5227 /*-----------------------------------------------------------------*/
5228 /* InitRegReuse - Initialises variables for code analyzer */
5229 /*-----------------------------------------------------------------*/
5230 void InitReuseReg(void)
5232 /* Find end of statically allocated variables for start idx */
5233 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5234 /* XXX: Avoid clashes with fixed registers, start late. */
5235 unsigned maxIdx = 0x1000;
5237 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5238 if (r->type != REG_SFR) {
5239 maxIdx += r->size; /* Increment for all statically allocated variables */
5243 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5246 /*-----------------------------------------------------------------*/
5247 /*-----------------------------------------------------------------*/
5248 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
5252 /* check recursion */
5253 pc = setFirstItem(pb->function_entries);
5258 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5264 DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
5266 if (pb->tregisters) {
5268 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5269 if (r->type == REG_GPR) {
5271 if (r->rIdx < (int)idx) {
5274 // make sure, idx is not yet used in this routine...
5276 regset = pb->tregisters;
5277 // do not touch s->curr ==> outer loop!
5278 while (regset && ((regs *)regset->item)->rIdx != idx) {
5279 regset = regset->next;
5284 if (peakIdx < idx) peakIdx = idx;
5285 sprintf(s,"r0x%02X", r->rIdx);
5286 DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
5288 r->name = Safe_strdup(s);
5294 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5296 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5297 char *dest = get_op_from_instruction(PCI(pc));
5299 pCode *pcn = findFunction(dest);
5301 /* This index increment from subroutines is not required, as all subroutines
5302 * may share registers NOT used by this one (< idx).
5303 * BUT if called functions A and B share a register, which gets assigned
5304 * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
5306 * As an alternative to this "solution" we could check above whether an
5307 * to-be-assigned rIdx is already present in the register set of the
5308 * current function. This would increase the reused registers and make this
5309 * `idx =' irrelevant.
5310 * UPDATE: Implemented above; not fast, but works.
5311 * (Problem shown with regression test src/regression/sub2.c)
5313 /*idx = */register_reassign(pcn->pb,idx,level+1);
5321 /*------------------------------------------------------------------*/
5322 /* ReuseReg were call tree permits */
5324 /* Re-allocate the GPR for optimum reuse for a given pblock */
5325 /* eg if a function m() calls function f1() and f2(), where f1 */
5326 /* allocates a local variable vf1 and f2 allocates a local */
5327 /* variable vf2. Then providing f1 and f2 do not call each other */
5328 /* they may share the same general purpose registers for vf1 and */
5330 /* This is done by first setting the the regs rIdx to start after */
5331 /* all the global variables, then walking through the call tree */
5332 /* renaming the registers to match their new idx and incrementng */
5333 /* it as it goes. If a function has already been called it will */
5334 /* only rename the registers if it has already used up those */
5335 /* registers ie rIdx of the function's registers is lower than the */
5336 /* current rIdx. That way the register will not be reused while */
5337 /* still being used by an eariler function call. */
5339 /* Note for this to work the functions need to be declared static. */
5341 /*------------------------------------------------------------------*/
5345 if (!the_pFile) return;
5347 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5348 /* Non static functions can be called from other modules so their registers must reassign */
5349 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5350 register_reassign(pb,peakIdx,0);
5354 /*-----------------------------------------------------------------*/
5355 /* buildCallTree - look at the flow and extract all of the calls */
5357 /*-----------------------------------------------------------------*/
5359 void buildCallTree(void )
5368 /* Now build the call tree.
5369 First we examine all of the pCodes for functions.
5370 Keep in mind that the function boundaries coincide
5371 with pBlock boundaries.
5373 The algorithm goes something like this:
5374 We have two nested loops. The outer loop iterates
5375 through all of the pBlocks/functions. The inner
5376 loop iterates through all of the pCodes for
5377 a given pBlock. When we begin iterating through
5378 a pBlock, the variable pc_fstart, pCode of the start
5379 of a function, is cleared. We then search for pCodes
5380 of type PC_FUNCTION. When one is encountered, we
5381 initialize pc_fstart to this and at the same time
5382 associate a new pBranch object that signifies a
5383 branch entry. If a return is found, then this signifies
5384 a function exit point. We'll link the pCodes of these
5385 returns to the matching pc_fstart.
5387 When we're done, a doubly linked list of pBranches
5388 will exist. The head of this list is stored in
5389 `the_pFile', which is the meta structure for all
5390 of the pCode. Look at the printCallTree function
5391 on how the pBranches are linked together.
5394 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5395 pCode *pc_fstart=NULL;
5396 for(pc = pb->pcHead; pc; pc = pc->next) {
5398 pCodeFunction *pcf = PCF(pc);
5401 if(STRCASECMP(pcf->fname, "_main") == 0) {
5402 //fprintf(stderr," found main \n");
5403 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5407 pbr = Safe_calloc(1,sizeof(pBranch));
5408 pbr->pc = pc_fstart = pc;
5411 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5413 // Here's a better way of doing the same:
5414 addSet(&pb->function_entries, pc);
5417 // Found an exit point in a function, e.g. return
5418 // (Note, there may be more than one return per function)
5420 pBranchLink(PCF(pc_fstart), pcf);
5422 addSet(&pb->function_exits, pc);
5424 } else if(isCALL(pc)) {
5425 addSet(&pb->function_calls,pc);
5431 /*-----------------------------------------------------------------*/
5432 /* AnalyzepCode - parse the pCode that has been generated and form */
5433 /* all of the logical connections. */
5435 /* Essentially what's done here is that the pCode flow is */
5437 /*-----------------------------------------------------------------*/
5439 void AnalyzepCode(char dbName)
5450 /* Phase 1 - Register allocation and peep hole optimization
5452 * The first part of the analysis is to determine the registers
5453 * that are used in the pCode. Once that is done, the peep rules
5454 * are applied to the code. We continue to loop until no more
5455 * peep rule optimizations are found (or until we exceed the
5456 * MAX_PASSES threshold).
5458 * When done, the required registers will be determined.
5464 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5466 /* First, merge the labels with the instructions */
5467 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5468 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5470 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5471 pBlockMergeLabels(pb);
5474 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5478 changes = OptimizepCode(dbName);
5480 } while(changes && (i++ < MAX_PASSES));
5485 /*-----------------------------------------------------------------*/
5486 /* ispCodeFunction - returns true if *pc is the pCode of a */
5488 /*-----------------------------------------------------------------*/
5489 bool ispCodeFunction(pCode *pc)
5492 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5498 /*-----------------------------------------------------------------*/
5499 /* findFunction - Search for a function by name (given the name) */
5500 /* in the set of all functions that are in a pBlock */
5501 /* (note - I expect this to change because I'm planning to limit */
5502 /* pBlock's to just one function declaration */
5503 /*-----------------------------------------------------------------*/
5504 pCode *findFunction(char *fname)
5511 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5513 pc = setFirstItem(pb->function_entries);
5516 if((pc->type == PC_FUNCTION) &&
5518 (strcmp(fname, PCF(pc)->fname)==0))
5521 pc = setNextItem(pb->function_entries);
5529 void MarkUsedRegisters(set *regset)
5534 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5535 r2 = pic14_regWithIdx(r1->rIdx);
5543 void pBlockStats(FILE *of, pBlock *pb)
5549 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5551 // for now just print the first element of each set
5552 pc = setFirstItem(pb->function_entries);
5554 fprintf(of,";entry: ");
5557 pc = setFirstItem(pb->function_exits);
5559 fprintf(of,";has an exit\n");
5563 pc = setFirstItem(pb->function_calls);
5565 fprintf(of,";functions called:\n");
5568 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5569 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5571 pc = setNextItem(pb->function_calls);
5575 r = setFirstItem(pb->tregisters);
5577 int n = elementsInSet(pb->tregisters);
5579 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5582 fprintf(of,"; %s\n",r->name);
5583 r = setNextItem(pb->tregisters);
5588 /*-----------------------------------------------------------------*/
5589 /*-----------------------------------------------------------------*/
5591 static void sequencepCode(void)
5597 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5599 pb->seq = GpCodeSequenceNumber+1;
5601 for( pc = pb->pcHead; pc; pc = pc->next)
5602 pc->seq = ++GpCodeSequenceNumber;
5608 /*-----------------------------------------------------------------*/
5609 /*-----------------------------------------------------------------*/
5611 set *register_usage(pBlock *pb)
5614 set *registers=NULL;
5615 set *registersInCallPath = NULL;
5617 / * check recursion * /
5619 pc = setFirstItem(pb->function_entries);
5626 if(pc->type != PC_FUNCTION)
5627 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5629 pc = setFirstItem(pb->function_calls);
5630 for( ; pc; pc = setNextItem(pb->function_calls)) {
5632 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5633 char *dest = get_op_from_instruction(PCI(pc));
5635 pcn = findFunction(dest);
5637 registersInCallPath = register_usage(pcn->pb);
5639 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5644 pBlockStats(stderr,pb); // debug
5647 // Mark the registers in this block as used.
5649 MarkUsedRegisters(pb->tregisters);
5650 if(registersInCallPath) {
5651 / * registers were used in the functions this pBlock has called * /
5652 / * so now, we need to see if these collide with the ones we are * /
5655 regs *r1,*r2, *newreg;
5657 DFPRINTF((stderr,"comparing registers\n"));
5659 r1 = setFirstItem(registersInCallPath);
5661 if (r1->type != REG_STK) {
5662 r2 = setFirstItem(pb->tregisters);
5664 while(r2 && (r2->type != REG_STK)) {
5666 if(r2->rIdx == r1->rIdx) {
5667 newreg = pic14_findFreeReg(REG_GPR);
5671 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5675 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5676 r1->rIdx, newreg->rIdx));
5677 r2->rIdx = newreg->rIdx;
5679 r2->name = Safe_strdup(newreg->name);
5683 newreg->wasUsed = 1;
5685 r2 = setNextItem(pb->tregisters);
5689 r1 = setNextItem(registersInCallPath);
5692 / * Collisions have been resolved. Now free the registers in the call path * /
5693 r1 = setFirstItem(registersInCallPath);
5695 newreg = pic14_regWithIdx(r1->rIdx);
5696 if (newreg) newreg->isFree = 1;
5697 r1 = setNextItem(registersInCallPath);
5701 // MarkUsedRegisters(pb->registers);
5703 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5706 DFPRINTF((stderr,"returning regs\n"));
5708 DFPRINTF((stderr,"not returning regs\n"));
5710 DFPRINTF((stderr,"pBlock after register optim.\n"));
5711 pBlockStats(stderr,pb); // debug
5718 /*-----------------------------------------------------------------*/
5719 /* printCallTree - writes the call tree to a file */
5721 /*-----------------------------------------------------------------*/
5722 void pct2(FILE *of,pBlock *pb,int indent)
5726 // set *registersInCallPath = NULL;
5732 return; //recursion ?
5734 pc = setFirstItem(pb->function_entries);
5741 for(i=0;i<indent;i++) // Indentation
5744 if(pc->type == PC_FUNCTION)
5745 fprintf(of,"%s\n",PCF(pc)->fname);
5750 pc = setFirstItem(pb->function_calls);
5751 for( ; pc; pc = setNextItem(pb->function_calls)) {
5753 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5754 char *dest = get_op_from_instruction(PCI(pc));
5756 pcn = findFunction(dest);
5758 pct2(of,pcn->pb,indent+1);
5760 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5768 /*-----------------------------------------------------------------*/
5769 /* printCallTree - writes the call tree to a file */
5771 /*-----------------------------------------------------------------*/
5773 void printCallTree(FILE *of)
5785 fprintf(of, "\npBlock statistics\n");
5786 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5791 fprintf(of,"Call Tree\n");
5792 pbr = the_pFile->functions;
5796 if(!ispCodeFunction(pc))
5797 fprintf(of,"bug in call tree");
5800 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5802 while(pc->next && !ispCodeFunction(pc->next)) {
5804 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5805 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5813 fprintf(of,"\n**************\n\na better call tree\n");
5814 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5819 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5820 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5826 /*-----------------------------------------------------------------*/
5828 /*-----------------------------------------------------------------*/
5830 void InlineFunction(pBlock *pb)
5838 pc = setFirstItem(pb->function_calls);
5840 for( ; pc; pc = setNextItem(pb->function_calls)) {
5843 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5844 pCode *pcp = pc->prev;
5850 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1) && !PCF(pcn)->isPublic && (pcp && (isPCI_BITSKIP(pcp)||!isPCI_SKIP(pcp)))) { /* Bit skips can be inverted other skips can not */
5852 InlineFunction(pcn->pb);
5855 At this point, *pc points to a CALL mnemonic, and
5856 *pcn points to the function that is being called.
5858 To in-line this call, we need to remove the CALL
5859 and RETURN(s), and link the function pCode in with
5866 /* Check if previous instruction was a bit skip */
5867 if (isPCI_BITSKIP(pcp)) {
5869 /* Invert skip instruction and add a goto */
5870 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5872 if(isPCL(pc_call->next)) { // Label pcode
5873 pcl = PCL(pc_call->next);
5874 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5875 pcl = PCL(PCI(pc_call->next)->label->pc);
5877 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5878 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5880 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5883 /* remove callee pBlock from the pBlock linked list */
5884 removepBlock(pcn->pb);
5892 /* Remove the Function pCode */
5893 pct = findNextInstruction(pcn->next);
5895 /* Link the function with the callee */
5896 if (pcp) pcp->next = pcn->next;
5897 pcn->next->prev = pcp;
5899 /* Convert the function name into a label */
5901 pbr = Safe_calloc(1,sizeof(pBranch));
5902 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5904 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5905 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5907 /* turn all of the return's except the last into goto's */
5908 /* check case for 2 instruction pBlocks */
5909 pce = findNextInstruction(pcn->next);
5911 pCode *pce_next = findNextInstruction(pce->next);
5913 if(pce_next == NULL) {
5914 /* found the last return */
5915 pCode *pc_call_next = findNextInstruction(pc_call->next);
5917 //fprintf(stderr,"found last return\n");
5918 //pce->print(stderr,pce);
5919 pce->prev->next = pc_call->next;
5920 pc_call->next->prev = pce->prev;
5921 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5930 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5936 /*-----------------------------------------------------------------*/
5938 /*-----------------------------------------------------------------*/
5940 void InlinepCode(void)
5949 if(!functionInlining)
5952 /* Loop through all of the function definitions and count the
5953 * number of times each one is called */
5954 //fprintf(stderr,"inlining %d\n",__LINE__);
5956 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5958 pc = setFirstItem(pb->function_calls);
5960 for( ; pc; pc = setNextItem(pb->function_calls)) {
5963 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5964 if(pcn && isPCF(pcn)) {
5965 PCF(pcn)->ncalled++;
5968 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5973 //fprintf(stderr,"inlining %d\n",__LINE__);
5975 /* Now, Loop through the function definitions again, but this
5976 * time inline those functions that have only been called once. */
5978 InlineFunction(the_pFile->pbHead);
5979 //fprintf(stderr,"inlining %d\n",__LINE__);
5981 for(pb = the_pFile->pbHead; pb; pb = pb->next)