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 -------------------------------------------------------------------------*/
24 #include "pcodeflow.h"
27 /****************************************************************/
28 /****************************************************************/
30 // Eventually this will go into device dependent files:
31 pCodeOpReg pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
32 pCodeOpReg pc_indf = {{PO_INDF, "INDF"}, -1, NULL,0,NULL};
33 pCodeOpReg pc_fsr = {{PO_FSR, "FSR"}, -1, NULL,0,NULL};
34 pCodeOpReg pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
35 pCodeOpReg pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
36 pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
38 pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
39 pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
40 pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL};
42 pFile *the_pFile = NULL;
45 #define SET_BANK_BIT (1 << 16)
46 #define CLR_BANK_BIT 0
48 static peepCommand peepCommands[] = {
50 {NOTBITSKIP, "_NOTBITSKIP_"},
51 {BITSKIP, "_BITSKIP_"},
52 {INVERTBITSKIP, "_INVERTBITSKIP_"},
57 static int mnemonics_initialized = 0;
59 static hTab *pic14MnemonicsHash = NULL;
60 static hTab *pic14pCodePeepCommandsHash = NULL;
62 static pBlock *pb_dead_pcodes = NULL;
64 /* Hardcoded flags to change the behavior of the PIC port */
65 static int functionInlining = 1; /* inline functions if nonzero */
67 // static int GpCodeSequenceNumber = 1;
68 static int GpcFlowSeq = 1;
70 /* statistics (code size estimation) */
71 static unsigned int pcode_insns = 0;
72 static unsigned int pcode_doubles = 0;
74 static unsigned peakIdx = 0; /* This keeps track of the peak register index for call tree register reuse */
77 /****************************************************************/
78 /* Forward declarations */
79 /****************************************************************/
82 static void genericAnalyze(pCode *pc);
83 static void AnalyzeGOTO(pCode *pc);
84 static void AnalyzeSKIP(pCode *pc);
85 static void AnalyzeRETURN(pCode *pc);
88 static void genericDestruct(pCode *pc);
89 static void genericPrint(FILE *of,pCode *pc);
91 static void pBlockStats(FILE *of, pBlock *pb);
92 static pCode *findFunction(char *fname);
93 static void pCodePrintLabel(FILE *of, pCode *pc);
94 static void pCodePrintFunction(FILE *of, pCode *pc);
95 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
96 static char *get_op_from_instruction( pCodeInstruction *pcc);
97 static pBlock *newpBlock(void);
100 /****************************************************************/
101 /* PIC Instructions */
102 /****************************************************************/
104 static pCodeInstruction pciADDWF = {
105 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
118 1,0, // dest, bit instruction
120 0, // literal operand
122 (PCC_W | PCC_REGISTER), // inCond
123 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
126 static pCodeInstruction pciADDFW = {
127 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
140 0,0, // dest, bit instruction
142 0, // literal operand
144 (PCC_W | PCC_REGISTER), // inCond
145 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
148 static pCodeInstruction pciADDLW = {
149 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
162 0,0, // dest, bit instruction
164 1, // literal operand
166 (PCC_W | PCC_LITERAL), // inCond
167 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
170 static pCodeInstruction pciANDLW = {
171 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
184 0,0, // dest, bit instruction
186 1, // literal operand
188 (PCC_W | PCC_LITERAL), // inCond
189 (PCC_W | PCC_Z) // outCond
192 static pCodeInstruction pciANDWF = {
193 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
206 1,0, // dest, bit instruction
208 0, // literal operand
210 (PCC_W | PCC_REGISTER), // inCond
211 (PCC_REGISTER | PCC_Z) // outCond
214 static pCodeInstruction pciANDFW = {
215 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
228 0,0, // dest, bit instruction
230 0, // literal operand
232 (PCC_W | PCC_REGISTER), // inCond
233 (PCC_W | PCC_Z) // outCond
236 static pCodeInstruction pciBCF = {
237 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
250 1,1, // dest, bit instruction
252 0, // literal operand
254 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
255 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
258 static pCodeInstruction pciBSF = {
259 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
272 1,1, // dest, bit instruction
274 0, // literal operand
276 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
277 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
280 static pCodeInstruction pciBTFSC = {
281 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
294 0,1, // dest, bit instruction
296 0, // literal operand
298 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
302 static pCodeInstruction pciBTFSS = {
303 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
316 0,1, // dest, bit instruction
318 0, // literal operand
320 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
324 static pCodeInstruction pciCALL = {
325 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
338 0,0, // dest, bit instruction
340 0, // literal operand
342 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
343 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
346 static pCodeInstruction pciCOMF = {
347 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
360 1,0, // dest, bit instruction
362 0, // literal operand
364 PCC_REGISTER, // inCond
365 PCC_REGISTER | PCC_Z // outCond
368 static pCodeInstruction pciCOMFW = {
369 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
382 0,0, // dest, bit instruction
384 0, // literal operand
386 PCC_REGISTER, // inCond
387 PCC_W | PCC_Z // outCond
390 static pCodeInstruction pciCLRF = {
391 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
404 0,0, // dest, bit instruction
406 0, // literal operand
409 PCC_REGISTER | PCC_Z // outCond
412 static pCodeInstruction pciCLRW = {
413 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
426 0,0, // dest, bit instruction
428 0, // literal operand
431 PCC_W | PCC_Z // outCond
434 static pCodeInstruction pciCLRWDT = {
435 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
448 0,0, // dest, bit instruction
450 0, // literal operand
456 static pCodeInstruction pciDECF = {
457 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
470 1,0, // dest, bit instruction
472 0, // literal operand
474 PCC_REGISTER, // inCond
475 PCC_REGISTER | PCC_Z // outCond
478 static pCodeInstruction pciDECFW = {
479 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
492 0,0, // dest, bit instruction
494 0, // literal operand
496 PCC_REGISTER, // inCond
497 PCC_W | PCC_Z // outCond
500 static pCodeInstruction pciDECFSZ = {
501 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
514 1,0, // dest, bit instruction
516 0, // literal operand
517 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
518 PCC_REGISTER, // inCond
519 PCC_REGISTER | PCC_Z // outCond
522 static pCodeInstruction pciDECFSZW = {
523 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
536 0,0, // dest, bit instruction
538 0, // literal operand
539 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
540 PCC_REGISTER, // inCond
541 PCC_W | PCC_Z // outCond
544 static pCodeInstruction pciGOTO = {
545 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
558 0,0, // dest, bit instruction
560 0, // literal operand
566 static pCodeInstruction pciINCF = {
567 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
580 1,0, // dest, bit instruction
582 0, // literal operand
584 PCC_REGISTER, // inCond
585 PCC_REGISTER | PCC_Z // outCond
588 static pCodeInstruction pciINCFW = {
589 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
602 0,0, // dest, bit instruction
604 0, // literal operand
606 PCC_REGISTER, // inCond
607 PCC_W | PCC_Z // outCond
610 static pCodeInstruction pciINCFSZ = {
611 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
624 1,0, // dest, bit instruction
626 0, // literal operand
627 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
628 PCC_REGISTER, // inCond
629 PCC_REGISTER | PCC_Z // outCond
632 static pCodeInstruction pciINCFSZW = {
633 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
646 0,0, // dest, bit instruction
648 0, // literal operand
649 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
650 PCC_REGISTER, // inCond
651 PCC_W | PCC_Z // outCond
654 static pCodeInstruction pciIORWF = {
655 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
668 1,0, // dest, bit instruction
670 0, // literal operand
672 (PCC_W | PCC_REGISTER), // inCond
673 (PCC_REGISTER | PCC_Z) // outCond
676 static pCodeInstruction pciIORFW = {
677 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
690 0,0, // dest, bit instruction
692 0, // literal operand
694 (PCC_W | PCC_REGISTER), // inCond
695 (PCC_W | PCC_Z) // outCond
698 static pCodeInstruction pciIORLW = {
699 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
712 0,0, // dest, bit instruction
714 1, // literal operand
716 (PCC_W | PCC_LITERAL), // inCond
717 (PCC_W | PCC_Z) // outCond
720 static pCodeInstruction pciMOVF = {
721 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
734 1,0, // dest, bit instruction
736 0, // literal operand
738 PCC_REGISTER, // inCond
742 static pCodeInstruction pciMOVFW = {
743 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
756 0,0, // dest, bit instruction
758 0, // literal operand
760 PCC_REGISTER, // inCond
761 (PCC_W | PCC_Z) // outCond
764 static pCodeInstruction pciMOVWF = {
765 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
778 0,0, // dest, bit instruction
780 0, // literal operand
783 PCC_REGISTER // outCond
786 static pCodeInstruction pciMOVLW = {
787 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
799 0,0, // dest, bit instruction
801 1, // literal operand
803 (PCC_NONE | PCC_LITERAL), // inCond
807 static pCodeInstruction pciNOP = {
808 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
820 0,0, // dest, bit instruction
822 0, // literal operand
828 static pCodeInstruction pciRETFIE = {
829 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
842 0,0, // dest, bit instruction
844 0, // literal operand
847 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
850 static pCodeInstruction pciRETLW = {
851 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
864 0,0, // dest, bit instruction
866 1, // literal operand
868 PCC_LITERAL, // inCond
869 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
872 static pCodeInstruction pciRETURN = {
873 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
886 0,0, // dest, bit instruction
888 0, // literal operand
890 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
891 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
894 static pCodeInstruction pciRLF = {
895 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
908 1,0, // dest, bit instruction
910 0, // literal operand
912 (PCC_C | PCC_REGISTER), // inCond
913 (PCC_REGISTER | PCC_C ) // outCond
916 static pCodeInstruction pciRLFW = {
917 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
930 0,0, // dest, bit instruction
932 0, // literal operand
934 (PCC_C | PCC_REGISTER), // inCond
935 (PCC_W | PCC_C) // outCond
938 static pCodeInstruction pciRRF = {
939 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
952 1,0, // dest, bit instruction
954 0, // literal operand
956 (PCC_C | PCC_REGISTER), // inCond
957 (PCC_REGISTER | PCC_C) // outCond
960 static pCodeInstruction pciRRFW = {
961 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
974 0,0, // dest, bit instruction
976 0, // literal operand
978 (PCC_C | PCC_REGISTER), // inCond
979 (PCC_W | PCC_C) // outCond
982 static pCodeInstruction pciSUBWF = {
983 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
996 1,0, // dest, bit instruction
998 0, // literal operand
1000 (PCC_W | PCC_REGISTER), // inCond
1001 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
1004 static pCodeInstruction pciSUBFW = {
1005 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1011 NULL, // from branch
1018 0,0, // dest, bit instruction
1019 0,0, // branch, skip
1020 0, // literal operand
1022 (PCC_W | PCC_REGISTER), // inCond
1023 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
1026 static pCodeInstruction pciSUBLW = {
1027 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1033 NULL, // from branch
1040 0,0, // dest, bit instruction
1041 0,0, // branch, skip
1042 1, // literal operand
1044 (PCC_W | PCC_LITERAL), // inCond
1045 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1048 static pCodeInstruction pciSWAPF = {
1049 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1055 NULL, // from branch
1062 1,0, // dest, bit instruction
1063 0,0, // branch, skip
1064 0, // literal operand
1066 (PCC_REGISTER), // inCond
1067 (PCC_REGISTER) // outCond
1070 static pCodeInstruction pciSWAPFW = {
1071 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1077 NULL, // from branch
1084 0,0, // dest, bit instruction
1085 0,0, // branch, skip
1086 0, // literal operand
1088 (PCC_REGISTER), // inCond
1092 static pCodeInstruction pciTRIS = {
1093 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1099 NULL, // from branch
1106 0,0, // dest, bit instruction
1107 0,0, // branch, skip
1108 0, // literal operand
1110 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1111 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1114 static pCodeInstruction pciXORWF = {
1115 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1121 NULL, // from branch
1128 1,0, // dest, bit instruction
1129 0,0, // branch, skip
1130 0, // literal operand
1132 (PCC_W | PCC_REGISTER), // inCond
1133 (PCC_REGISTER | PCC_Z) // outCond
1136 static pCodeInstruction pciXORFW = {
1137 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1143 NULL, // from branch
1150 0,0, // dest, bit instruction
1151 0,0, // branch, skip
1152 0, // literal operand
1154 (PCC_W | PCC_REGISTER), // inCond
1155 (PCC_W | PCC_Z) // outCond
1158 static pCodeInstruction pciXORLW = {
1159 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1165 NULL, // from branch
1172 0,0, // dest, bit instruction
1173 0,0, // branch, skip
1174 1, // literal operand
1176 (PCC_W | PCC_LITERAL), // inCond
1177 (PCC_W | PCC_Z) // outCond
1181 static pCodeInstruction pciBANKSEL = {
1182 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1188 NULL, // from branch
1195 0,0, // dest, bit instruction
1196 0,0, // branch, skip
1197 0, // literal operand
1203 static pCodeInstruction pciPAGESEL = {
1204 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1210 NULL, // from branch
1217 0,0, // dest, bit instruction
1218 0,0, // branch, skip
1219 0, // literal operand
1225 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1228 /*-----------------------------------------------------------------*/
1229 /* return a unique ID number to assist pCodes debuging */
1230 /*-----------------------------------------------------------------*/
1231 static unsigned PCodeID(void) {
1232 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1234 static unsigned int stop;
1235 if (pcodeId == 1448)
1236 stop++; // Place break point here
1241 void pCodeInitRegisters(void)
1243 static int initialized=0;
1244 int shareBankAddress, stkSize, haveShared;
1251 pic = init_pic(port->processor);
1252 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1253 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1254 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1255 * (used for interrupts) to fit into the shared portion of the
1257 stkSize = stkSize - 3;
1258 assert(stkSize >= 0);
1259 initStack(shareBankAddress, stkSize, haveShared);
1261 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1262 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1263 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1264 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1265 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1266 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1267 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1269 pc_status.rIdx = IDX_STATUS;
1270 pc_fsr.rIdx = IDX_FSR;
1271 pc_indf.rIdx = IDX_INDF;
1272 pc_intcon.rIdx = IDX_INTCON;
1273 pc_pcl.rIdx = IDX_PCL;
1274 pc_pclath.rIdx = IDX_PCLATH;
1276 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1277 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1278 /* Interrupt storage for status register. */
1279 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1280 /* Interrupt storage for pclath register. */
1281 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1283 pc_wsave.rIdx = pc_wsave.r->rIdx;
1284 pc_ssave.rIdx = pc_ssave.r->rIdx;
1285 pc_psave.rIdx = pc_psave.r->rIdx;
1287 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1288 pc_wsave.r->address = shareBankAddress-stkSize;
1289 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1290 pc_ssave.r->address = shareBankAddress-stkSize-1;
1291 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1292 pc_psave.r->address = shareBankAddress-stkSize-2;
1294 /* probably should put this in a separate initialization routine */
1295 pb_dead_pcodes = newpBlock();
1299 /*-----------------------------------------------------------------*/
1300 /* mnem2key - convert a pic mnemonic into a hash key */
1301 /* (BTW - this spreads the mnemonics quite well) */
1303 /*-----------------------------------------------------------------*/
1305 static int mnem2key(unsigned char const *mnem)
1314 key += toupper(*mnem++) +1;
1318 return (key & 0x1f);
1322 static void pic14initMnemonics(void)
1327 pCodeInstruction *pci;
1329 if(mnemonics_initialized)
1332 //FIXME - probably should NULL out the array before making the assignments
1333 //since we check the array contents below this initialization.
1335 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1336 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1337 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1338 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1339 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1340 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1341 pic14Mnemonics[POC_BCF] = &pciBCF;
1342 pic14Mnemonics[POC_BSF] = &pciBSF;
1343 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1344 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1345 pic14Mnemonics[POC_CALL] = &pciCALL;
1346 pic14Mnemonics[POC_COMF] = &pciCOMF;
1347 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1348 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1349 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1350 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1351 pic14Mnemonics[POC_DECF] = &pciDECF;
1352 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1353 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1354 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1355 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1356 pic14Mnemonics[POC_INCF] = &pciINCF;
1357 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1358 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1359 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1360 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1361 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1362 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1363 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1364 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1365 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1366 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1367 pic14Mnemonics[POC_NOP] = &pciNOP;
1368 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1369 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1370 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1371 pic14Mnemonics[POC_RLF] = &pciRLF;
1372 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1373 pic14Mnemonics[POC_RRF] = &pciRRF;
1374 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1375 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1376 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1377 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1378 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1379 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1380 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1381 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1382 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1383 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1384 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1385 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1387 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1388 if(pic14Mnemonics[i])
1389 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1390 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1393 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1394 pci = hTabNextItem(pic14MnemonicsHash, &key);
1397 mnemonics_initialized = 1;
1400 int getpCode(char *mnem,unsigned dest)
1403 pCodeInstruction *pci;
1404 int key = mnem2key((unsigned char *)mnem);
1406 if(!mnemonics_initialized)
1407 pic14initMnemonics();
1409 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1413 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1414 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1418 pci = hTabNextItemWK (pic14MnemonicsHash);
1425 /*-----------------------------------------------------------------*
1426 * pic14initpCodePeepCommands
1428 *-----------------------------------------------------------------*/
1429 void pic14initpCodePeepCommands(void)
1437 hTabAddItem(&pic14pCodePeepCommandsHash,
1438 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1440 } while (peepCommands[i].cmd);
1442 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1445 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1446 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1451 /*-----------------------------------------------------------------
1454 *-----------------------------------------------------------------*/
1456 int getpCodePeepCommand(char *cmd)
1460 int key = mnem2key((unsigned char *)cmd);
1463 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1466 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1467 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1471 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1478 static char getpBlock_dbName(pBlock *pb)
1484 return pb->cmemmap->dbName;
1488 void pBlockConvert2ISR(pBlock *pb)
1499 /*-----------------------------------------------------------------*/
1500 /* movepBlock2Head - given the dbname of a pBlock, move all */
1501 /* instances to the front of the doubly linked */
1502 /* list of pBlocks */
1503 /*-----------------------------------------------------------------*/
1505 void movepBlock2Head(char dbName)
1512 pb = the_pFile->pbHead;
1516 if(getpBlock_dbName(pb) == dbName) {
1517 pBlock *pbn = pb->next;
1518 pb->next = the_pFile->pbHead;
1519 the_pFile->pbHead->prev = pb;
1520 the_pFile->pbHead = pb;
1523 pb->prev->next = pbn;
1525 // If the pBlock that we just moved was the last
1526 // one in the link of all of the pBlocks, then we
1527 // need to point the tail to the block just before
1528 // the one we moved.
1529 // Note: if pb->next is NULL, then pb must have
1530 // been the last pBlock in the chain.
1533 pbn->prev = pb->prev;
1535 the_pFile->pbTail = pb->prev;
1546 void copypCode(FILE *of, char dbName)
1550 if(!of || !the_pFile)
1553 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1554 if(getpBlock_dbName(pb) == dbName) {
1563 void resetpCodeStatistics (void)
1565 pcode_insns = pcode_doubles = 0;
1568 void dumppCodeStatistics (FILE *of)
1570 /* dump statistics */
1572 fprintf (of, ";\tcode size estimation:\n");
1573 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1577 void pcode_test(void)
1580 DFPRINTF((stderr,"pcode is alive!\n"));
1590 /* create the file name */
1591 strcpy(buffer,dstFileName);
1592 strcat(buffer,".p");
1594 if( !(pFile = fopen(buffer, "w" ))) {
1595 werror(E_FILE_OPEN_ERR,buffer);
1599 fprintf(pFile,"pcode dump\n\n");
1601 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1602 fprintf(pFile,"\n\tNew pBlock\n\n");
1604 fprintf(pFile,"%s",pb->cmemmap->sname);
1606 fprintf(pFile,"internal pblock");
1608 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1609 printpBlock(pFile,pb);
1613 /*-----------------------------------------------------------------*/
1614 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1615 /* ister, RegCond will return the bit being referenced. */
1617 /* fixme - why not just OR in the pcop bit field */
1618 /*-----------------------------------------------------------------*/
1620 static int RegCond(pCodeOp *pcop)
1626 if (pcop->type == PO_GPR_BIT) {
1627 char *name = pcop->name;
1629 name = PCOR(pcop)->r->name;
1630 if (strcmp(name, pc_status.pcop.name) == 0)
1632 switch(PCORB(pcop)->bit) {
1646 /*-----------------------------------------------------------------*/
1647 /* newpCode - create and return a newly initialized pCode */
1649 /* fixme - rename this */
1651 /* The purpose of this routine is to create a new Instruction */
1652 /* pCode. This is called by gen.c while the assembly code is being */
1656 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1657 /* (note that the op is analogous to but not the */
1658 /* same thing as the opcode of the instruction.) */
1659 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1662 /* a pointer to the new malloc'd pCode is returned. */
1666 /*-----------------------------------------------------------------*/
1667 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1669 pCodeInstruction *pci ;
1671 if(!mnemonics_initialized)
1672 pic14initMnemonics();
1674 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1676 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1677 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1678 pci->pc.id = PCodeID();
1681 if(pci->inCond & PCC_EXAMINE_PCOP)
1682 pci->inCond |= RegCond(pcop);
1684 if(pci->outCond & PCC_EXAMINE_PCOP)
1685 pci->outCond |= RegCond(pcop);
1687 pci->pc.prev = pci->pc.next = NULL;
1688 return (pCode *)pci;
1691 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1697 /*-----------------------------------------------------------------*/
1698 /* newpCodeWild - create a "wild" as in wild card pCode */
1700 /* Wild pcodes are used during the peep hole optimizer to serve */
1701 /* as place holders for any instruction. When a snippet of code is */
1702 /* compared to a peep hole rule, the wild card opcode will match */
1703 /* any instruction. However, the optional operand and label are */
1704 /* additional qualifiers that must also be matched before the */
1705 /* line (of assembly code) is declared matched. Note that the */
1706 /* operand may be wild too. */
1708 /* Note, a wild instruction is specified just like a wild var: */
1709 /* %4 ; A wild instruction, */
1710 /* See the peeph.def file for additional examples */
1712 /*-----------------------------------------------------------------*/
1714 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1719 pcw = Safe_calloc(1,sizeof(pCodeWild));
1721 pcw->pci.pc.type = PC_WILD;
1722 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1723 pcw->id = PCodeID();
1724 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1725 pcw->pci.pc.pb = NULL;
1727 // pcw->pci.pc.analyze = genericAnalyze;
1728 pcw->pci.pc.destruct = genericDestruct;
1729 pcw->pci.pc.print = genericPrint;
1731 pcw->id = pCodeID; // this is the 'n' in %n
1732 pcw->operand = optional_operand;
1733 pcw->label = optional_label;
1735 pcw->mustBeBitSkipInst = 0;
1736 pcw->mustNotBeBitSkipInst = 0;
1737 pcw->invertBitSkipInst = 0;
1739 return ( (pCode *)pcw);
1743 /*-----------------------------------------------------------------*/
1744 /* newPcodeInlineP - create a new pCode from a char string */
1745 /*-----------------------------------------------------------------*/
1748 static pCode *newpCodeInlineP(char *cP)
1753 pcc = Safe_calloc(1,sizeof(pCodeComment));
1755 pcc->pc.type = PC_INLINE;
1756 pcc->pc.prev = pcc->pc.next = NULL;
1757 pcc->pc.id = PCodeID();
1758 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1761 // pcc->pc.analyze = genericAnalyze;
1762 pcc->pc.destruct = genericDestruct;
1763 pcc->pc.print = genericPrint;
1766 pcc->comment = Safe_strdup(cP);
1768 pcc->comment = NULL;
1770 return ( (pCode *)pcc);
1775 /*-----------------------------------------------------------------*/
1776 /* newPcodeCharP - create a new pCode from a char string */
1777 /*-----------------------------------------------------------------*/
1779 pCode *newpCodeCharP(char *cP)
1784 pcc = Safe_calloc(1,sizeof(pCodeComment));
1786 pcc->pc.type = PC_COMMENT;
1787 pcc->pc.prev = pcc->pc.next = NULL;
1788 pcc->pc.id = PCodeID();
1789 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1792 // pcc->pc.analyze = genericAnalyze;
1793 pcc->pc.destruct = genericDestruct;
1794 pcc->pc.print = genericPrint;
1797 pcc->comment = Safe_strdup(cP);
1799 pcc->comment = NULL;
1801 return ( (pCode *)pcc);
1805 /*-----------------------------------------------------------------*/
1806 /* newpCodeFunction - */
1807 /*-----------------------------------------------------------------*/
1810 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1814 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1815 //_ALLOC(pcf,sizeof(pCodeFunction));
1817 pcf->pc.type = PC_FUNCTION;
1818 pcf->pc.prev = pcf->pc.next = NULL;
1819 pcf->pc.id = PCodeID();
1820 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1823 // pcf->pc.analyze = genericAnalyze;
1824 pcf->pc.destruct = genericDestruct;
1825 pcf->pc.print = pCodePrintFunction;
1830 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1831 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1832 strcpy(pcf->modname,mod);
1834 pcf->modname = NULL;
1837 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1838 pcf->fname = Safe_calloc(1,strlen(f)+1);
1839 strcpy(pcf->fname,f);
1843 pcf->isPublic = (unsigned)isPublic;
1845 return ( (pCode *)pcf);
1849 /*-----------------------------------------------------------------*/
1851 /*-----------------------------------------------------------------*/
1852 static void destructpCodeFlow(pCode *pc)
1854 if(!pc || !isPCFL(pc))
1863 deleteSet(&PCFL(pc)->registers);
1864 deleteSet(&PCFL(pc)->from);
1865 deleteSet(&PCFL(pc)->to);
1870 static pCode *newpCodeFlow(void )
1874 //_ALLOC(pcflow,sizeof(pCodeFlow));
1875 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1877 pcflow->pc.type = PC_FLOW;
1878 pcflow->pc.prev = pcflow->pc.next = NULL;
1879 pcflow->pc.pb = NULL;
1881 // pcflow->pc.analyze = genericAnalyze;
1882 pcflow->pc.destruct = destructpCodeFlow;
1883 pcflow->pc.print = genericPrint;
1885 pcflow->pc.seq = GpcFlowSeq++;
1887 pcflow->from = pcflow->to = NULL;
1889 pcflow->inCond = PCC_NONE;
1890 pcflow->outCond = PCC_NONE;
1892 pcflow->firstBank = 'U'; /* Undetermined */
1893 pcflow->lastBank = 'U'; /* Undetermined */
1895 pcflow->FromConflicts = 0;
1896 pcflow->ToConflicts = 0;
1900 pcflow->registers = newSet();
1902 return ( (pCode *)pcflow);
1906 /*-----------------------------------------------------------------*/
1907 /*-----------------------------------------------------------------*/
1908 static pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1910 pCodeFlowLink *pcflowLink;
1912 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1914 pcflowLink->pcflow = pcflow;
1915 pcflowLink->bank_conflict = 0;
1920 /*-----------------------------------------------------------------*/
1921 /* newpCodeCSource - create a new pCode Source Symbol */
1922 /*-----------------------------------------------------------------*/
1924 pCode *newpCodeCSource(int ln, char *f, const char *l)
1929 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1931 pccs->pc.type = PC_CSOURCE;
1932 pccs->pc.prev = pccs->pc.next = NULL;
1933 pccs->pc.id = PCodeID();
1936 pccs->pc.destruct = genericDestruct;
1937 pccs->pc.print = genericPrint;
1939 pccs->line_number = ln;
1941 pccs->line = Safe_strdup(l);
1946 pccs->file_name = Safe_strdup(f);
1948 pccs->file_name = NULL;
1950 return ( (pCode *)pccs);
1954 /*******************************************************************/
1955 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
1956 /* added by VR 6-Jun-2003 */
1957 /*******************************************************************/
1959 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
1966 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
1967 pcad->pci.pc.type = PC_ASMDIR;
1968 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
1969 pcad->pci.pc.pb = NULL;
1970 pcad->pci.pc.destruct = genericDestruct;
1971 pcad->pci.pc.print = genericPrint;
1973 if(asdir && *asdir) {
1975 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
1977 pcad->directive = Safe_strdup( asdir );
1980 va_start(ap, argfmt);
1982 memset(buffer, 0, sizeof(buffer));
1983 if(argfmt && *argfmt)
1984 vsprintf(buffer, argfmt, ap);
1988 while(isspace((unsigned char)*lbp))lbp++;
1991 pcad->arg = Safe_strdup( lbp );
1993 return ((pCode *)pcad);
1996 /*-----------------------------------------------------------------*/
1997 /* pCodeLabelDestruct - free memory used by a label. */
1998 /*-----------------------------------------------------------------*/
1999 static void pCodeLabelDestruct(pCode *pc)
2005 if((pc->type == PC_LABEL) && PCL(pc)->label)
2006 free(PCL(pc)->label);
2012 pCode *newpCodeLabel(char *name, int key)
2018 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2020 pcl->pc.type = PC_LABEL;
2021 pcl->pc.prev = pcl->pc.next = NULL;
2022 pcl->pc.id = PCodeID();
2023 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2026 // pcl->pc.analyze = genericAnalyze;
2027 pcl->pc.destruct = pCodeLabelDestruct;
2028 pcl->pc.print = pCodePrintLabel;
2034 sprintf(s,"_%05d_DS_",key);
2039 pcl->label = Safe_strdup(s);
2041 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2042 return ( (pCode *)pcl);
2047 /*-----------------------------------------------------------------*/
2048 /* newpBlock - create and return a pointer to a new pBlock */
2049 /*-----------------------------------------------------------------*/
2050 static pBlock *newpBlock(void)
2055 PpB = Safe_calloc(1,sizeof(pBlock) );
2056 PpB->next = PpB->prev = NULL;
2058 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2059 PpB->tregisters = NULL;
2061 PpB->FlowTree = NULL;
2067 /*-----------------------------------------------------------------*/
2068 /* newpCodeChain - create a new chain of pCodes */
2069 /*-----------------------------------------------------------------*
2071 * This function will create a new pBlock and the pointer to the
2072 * pCode that is passed in will be the first pCode in the block.
2073 *-----------------------------------------------------------------*/
2076 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2079 pBlock *pB = newpBlock();
2081 pB->pcHead = pB->pcTail = pc;
2088 /*-----------------------------------------------------------------*/
2089 /* newpCodeOpLabel - Create a new label given the key */
2090 /* Note, a negative key means that the label is part of wild card */
2091 /* (and hence a wild card label) used in the pCodePeep */
2092 /* optimizations). */
2093 /*-----------------------------------------------------------------*/
2095 pCodeOp *newpCodeOpLabel(char *name, int key)
2098 static int label_key=-1;
2102 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2103 pcop->type = PO_LABEL;
2108 sprintf(s=buffer,"_%05d_DS_",key);
2110 s = name, key = label_key--;
2112 PCOLAB(pcop)->offset = 0;
2114 pcop->name = Safe_strdup(s);
2116 ((pCodeOpLabel *)pcop)->key = key;
2118 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2122 /*-----------------------------------------------------------------*/
2123 /*-----------------------------------------------------------------*/
2124 pCodeOp *newpCodeOpLit(int lit)
2130 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2131 pcop->type = PO_LITERAL;
2135 sprintf(s,"0x%02x", (unsigned char)lit);
2137 pcop->name = Safe_strdup(s);
2140 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2145 /*-----------------------------------------------------------------*/
2146 /*-----------------------------------------------------------------*/
2147 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2151 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2152 pcop->type = PO_IMMEDIATE;
2155 pcop->name = Safe_strdup(name);
2158 r = dirregWithName(name);
2162 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2163 PCOI(pcop)->rIdx = r->rIdx;
2165 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2166 PCOI(pcop)->rIdx = -1;
2168 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2173 PCOI(pcop)->index = index;
2174 PCOI(pcop)->offset = offset;
2175 PCOI(pcop)->_const = code_space;
2176 PCOI(pcop)->_function = is_func;
2181 /*-----------------------------------------------------------------*/
2182 /*-----------------------------------------------------------------*/
2183 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2189 if(!pcwb || !subtype) {
2190 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2194 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2195 pcop->type = PO_WILD;
2196 sprintf(s,"%%%d",id);
2197 pcop->name = Safe_strdup(s);
2199 PCOW(pcop)->id = id;
2200 PCOW(pcop)->pcwb = pcwb;
2201 PCOW(pcop)->subtype = subtype;
2202 PCOW(pcop)->matched = NULL;
2206 /*-----------------------------------------------------------------*/
2207 /* Find a symbol with matching name */
2208 /*-----------------------------------------------------------------*/
2209 static symbol *symFindWithName(memmap * map, const char *name)
2213 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2214 if (sym->rname && (strcmp(sym->rname,name)==0))
2220 /*-----------------------------------------------------------------*/
2221 /*-----------------------------------------------------------------*/
2222 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2227 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2228 pcop->type = PO_GPR_BIT;
2230 PCORB(pcop)->bit = ibit;
2231 PCORB(pcop)->inBitSpace = inBitSpace;
2233 if (name) r = regFindWithName(name);
2235 // Register has not been allocated - check for symbol information
2237 sym = symFindWithName(bit, name);
2238 if (!sym) sym = symFindWithName(sfrbit, name);
2239 if (!sym) sym = symFindWithName(sfr, name);
2240 if (!sym) sym = symFindWithName(reg, name);
2241 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2242 // XXX: This ignores nesting levels, but works for globals...
2243 if (!sym) sym = findSym(SymbolTab, NULL, name);
2244 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2246 r = allocNewDirReg(sym->etype,name);
2252 PCOR(pcop)->rIdx = r->rIdx;
2254 pcop->name = Safe_strdup(name);
2255 PCOR(pcop)->r = NULL;
2256 PCOR(pcop)->rIdx = 0;
2262 static pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2268 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2269 pcop->name = reg->name;
2270 pcop->type = PO_GPR_BIT;
2271 PCORB(pcop)->bit = ibit;
2272 PCORB(pcop)->inBitSpace = inBitSpace;
2273 PCOR(pcop)->r = reg;
2274 PCOR(pcop)->index = 0;
2275 PCOR(pcop)->rIdx = reg->rIdx;
2280 /*-----------------------------------------------------------------*
2281 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2283 * If rIdx >=0 then a specific register from the set of registers
2284 * will be selected. If rIdx <0, then a new register will be searched
2286 *-----------------------------------------------------------------*/
2288 static pCodeOp *newpCodeOpReg(int rIdx)
2292 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2297 PCOR(pcop)->rIdx = rIdx;
2298 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2300 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2303 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2307 pcop->type = PCOR(pcop)->r->pc_type;
2312 pCodeOp *newpCodeOpRegFromStr(char *name)
2316 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2317 PCOR(pcop)->r = allocRegByName(name, 1);
2318 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2319 pcop->type = PCOR(pcop)->r->pc_type;
2320 pcop->name = PCOR(pcop)->r->name;
2325 static pCodeOp *newpCodeOpStr(char *name)
2329 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2330 pcop->type = PO_STR;
2331 pcop->name = Safe_strdup(name);
2333 PCOS(pcop)->isPublic = 0;
2339 /*-----------------------------------------------------------------*/
2340 /*-----------------------------------------------------------------*/
2342 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2349 pcop = newpCodeOpBit(name, -1,0);
2353 pcop = newpCodeOpLit(-1);
2357 pcop = newpCodeOpLabel(NULL,-1);
2361 pcop = newpCodeOpReg(-1);
2364 case PO_GPR_POINTER:
2365 case PO_GPR_REGISTER:
2367 pcop = newpCodeOpRegFromStr(name);
2369 pcop = newpCodeOpReg(-1);
2373 pcop = newpCodeOpStr(name);
2377 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2380 pcop->name = Safe_strdup(name);
2389 /*-----------------------------------------------------------------*/
2390 /*-----------------------------------------------------------------*/
2391 static void pCodeConstString(char *name, char *value)
2396 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
2401 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2405 sprintf(buffer,"; %s = %s",name,value);
2406 for (i=strlen(buffer); i--; ) {
2407 unsigned char c = buffer[i];
2408 if (c=='\r' || c=='\n') {
2409 memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2411 if (c=='\r') buffer[i+1] = 'r';
2412 else if (c=='\n') buffer[i+1] = 'n';
2416 addpCode2pBlock(pb,newpCodeCharP(buffer));
2417 addpCode2pBlock(pb,newpCodeLabel(name,-1));
2420 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2426 /*-----------------------------------------------------------------*/
2427 /*-----------------------------------------------------------------*/
2428 static void pCodeReadCodeTable(void)
2432 fprintf(stderr, " %s\n",__FUNCTION__);
2434 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2438 addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2439 addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2440 addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2441 addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2443 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2444 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2445 addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2446 addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2452 /*-----------------------------------------------------------------*/
2453 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2454 /*-----------------------------------------------------------------*/
2455 void addpCode2pBlock(pBlock *pb, pCode *pc)
2462 /* If this is the first pcode to be added to a block that
2463 * was initialized with a NULL pcode, then go ahead and
2464 * make this pcode the head and tail */
2465 pb->pcHead = pb->pcTail = pc;
2468 pb->pcTail->next = pc;
2470 pc->prev = pb->pcTail;
2477 /*-----------------------------------------------------------------*/
2478 /* addpBlock - place a pBlock into the pFile */
2479 /*-----------------------------------------------------------------*/
2480 void addpBlock(pBlock *pb)
2482 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2485 /* First time called, we'll pass through here. */
2486 //_ALLOC(the_pFile,sizeof(pFile));
2487 the_pFile = Safe_calloc(1,sizeof(pFile));
2488 the_pFile->pbHead = the_pFile->pbTail = pb;
2489 the_pFile->functions = NULL;
2493 the_pFile->pbTail->next = pb;
2494 pb->prev = the_pFile->pbTail;
2496 the_pFile->pbTail = pb;
2499 /*-----------------------------------------------------------------*/
2500 /* removepBlock - remove a pBlock from the pFile */
2501 /*-----------------------------------------------------------------*/
2502 static void removepBlock(pBlock *pb)
2510 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2512 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2515 if(pbs == the_pFile->pbHead)
2516 the_pFile->pbHead = pbs->next;
2518 if (pbs == the_pFile->pbTail)
2519 the_pFile->pbTail = pbs->prev;
2522 pbs->next->prev = pbs->prev;
2525 pbs->prev->next = pbs->next;
2532 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2536 /*-----------------------------------------------------------------*/
2537 /* printpCode - write the contents of a pCode to a file */
2538 /*-----------------------------------------------------------------*/
2539 void printpCode(FILE *of, pCode *pc)
2550 fprintf(of,"warning - unable to print pCode\n");
2553 /*-----------------------------------------------------------------*/
2554 /* printpBlock - write the contents of a pBlock to a file */
2555 /*-----------------------------------------------------------------*/
2556 void printpBlock(FILE *of, pBlock *pb)
2566 for(pc = pb->pcHead; pc; pc = pc->next) {
2571 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2581 /*-----------------------------------------------------------------*/
2583 /* pCode processing */
2587 /*-----------------------------------------------------------------*/
2589 void unlinkpCode(pCode *pc)
2595 fprintf(stderr,"Unlinking: ");
2596 printpCode(stderr, pc);
2599 pc->prev->next = pc->next;
2601 pc->next->prev = pc->prev;
2604 /* RN: I believe this should be right here, but this did not
2605 * cure the bug I was hunting... */
2606 /* must keep labels -- attach to following instruction */
2607 if (isPCI(pc) && PCI(pc)->label && pc->next)
2609 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2612 pBranchAppend (pcnext->label, PCI(pc)->label);
2616 pc->prev = pc->next = NULL;
2620 /*-----------------------------------------------------------------*/
2621 /*-----------------------------------------------------------------*/
2623 static void genericDestruct(pCode *pc)
2629 /* For instructions, tell the register (if there's one used)
2630 * that it's no longer needed */
2631 regs *reg = getRegFromInstruction(pc);
2633 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2636 /* Instead of deleting the memory used by this pCode, mark
2637 * the object as bad so that if there's a pointer to this pCode
2638 * dangling around somewhere then (hopefully) when the type is
2639 * checked we'll catch it.
2644 addpCode2pBlock(pb_dead_pcodes, pc);
2651 /*-----------------------------------------------------------------*/
2652 /* Copies the pCodeInstruction flow pointer from source pCode */
2653 /*-----------------------------------------------------------------*/
2654 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2656 pCodeFlow *pcflow = 0;
2657 for (p=pcs; p; p=p->prev) {
2659 pcflow = PCI(p)->pcflow;
2663 pcflow = (pCodeFlow*)p;
2667 PCI(pcd)->pcflow = pcflow;
2670 /*-----------------------------------------------------------------*/
2671 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2672 /* into the pCode chain containing pc1 */
2673 /*-----------------------------------------------------------------*/
2674 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2680 pc2->next = pc1->next;
2682 pc1->next->prev = pc2;
2688 /* If this is an instrution type propogate the flow */
2690 CopyFlow(PCI(pc2),pc1);
2693 /*------------------------------------------------------------------*/
2694 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2695 /* into the pCode chain containing pc1 */
2696 /*------------------------------------------------------------------*/
2697 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2703 pc2->prev = pc1->prev;
2705 pc1->prev->next = pc2;
2711 /* If this is an instrution type propogate the flow */
2713 CopyFlow(PCI(pc2),pc1);
2716 /*-----------------------------------------------------------------*/
2717 /* pCodeOpCopy - copy a pcode operator */
2718 /*-----------------------------------------------------------------*/
2719 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2721 pCodeOp *pcopnew=NULL;
2726 switch(pcop->type) {
2729 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2730 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2738 case PO_GPR_REGISTER:
2740 case PO_GPR_POINTER:
2741 case PO_SFR_REGISTER:
2745 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2746 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2747 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2748 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2752 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2753 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2754 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2758 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2759 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2765 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2766 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2767 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2771 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2772 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2773 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2777 /* Here we expand the wild card into the appropriate type: */
2778 /* By recursively calling pCodeOpCopy */
2779 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2780 if(PCOW(pcop)->matched)
2781 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2784 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2785 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2786 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2793 assert ( !"unhandled pCodeOp type copied" );
2798 pcopnew->name = Safe_strdup(pcop->name);
2800 pcopnew->name = NULL;
2805 /*-----------------------------------------------------------------*/
2806 /* popCopyReg - copy a pcode operator */
2807 /*-----------------------------------------------------------------*/
2808 pCodeOp *popCopyReg(pCodeOpReg *pc)
2812 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2813 pcor->pcop.type = pc->pcop.type;
2815 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2816 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2818 pcor->pcop.name = NULL;
2820 if (pcor->pcop.type == PO_IMMEDIATE){
2821 PCOL(pcor)->lit = PCOL(pc)->lit;
2824 pcor->rIdx = pc->rIdx;
2828 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2833 /*-----------------------------------------------------------------*/
2834 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2835 /*-----------------------------------------------------------------*/
2836 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2838 pCodeInstruction *new_pci;
2841 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2843 new_pci = PCI(newpCode(pci->op,pci->pcop));
2845 new_pci->pc.pb = pci->pc.pb;
2846 new_pci->from = pci->from;
2847 new_pci->to = pci->to;
2848 new_pci->label = pci->label;
2849 new_pci->pcflow = pci->pcflow;
2851 return PCODE(new_pci);
2854 /*-----------------------------------------------------------------*/
2855 /*-----------------------------------------------------------------*/
2856 void pCodeDeleteChain(pCode *f,pCode *t)
2861 DFPRINTF((stderr,"delete pCode:\n"));
2863 //f->print(stderr,f);
2864 //f->delete(f); this dumps core...
2870 /*-----------------------------------------------------------------*/
2871 /*-----------------------------------------------------------------*/
2872 static void pBlockRegs(FILE *of, pBlock *pb)
2877 r = setFirstItem(pb->tregisters);
2879 r = setNextItem(pb->tregisters);
2884 /*-----------------------------------------------------------------*/
2885 /*-----------------------------------------------------------------*/
2886 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2891 int use_buffer = 1; // copy the string to the passed buffer pointer
2896 use_buffer = 0; // Don't bother copying the string to the buffer.
2900 switch(pcop->type) {
2904 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
2910 if (PCOR(pcop)->r->type == REG_STK)
2911 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2913 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2916 SNPRINTF(buffer,size,"%s",r->name);
2925 if(PCOI(pcop)->_const) {
2927 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
2928 switch(PCOI(pcop)->offset) {
2930 SNPRINTF(s,size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
2933 SNPRINTF(s,size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
2936 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
2939 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
2940 assert ( !"offset too large" );
2941 SNPRINTF(s,size,"(((%s+%d) >> %d)&0xff)",
2944 8 * PCOI(pcop)->offset );
2947 SNPRINTF(s,size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
2949 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
2950 SNPRINTF(s,size,"(%s + %d)",
2954 switch(PCOI(pcop)->offset) {
2956 SNPRINTF(s,size,"(%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/mutable/offset=%d\n", PCOI(pcop)->offset);
2966 assert ( !"offset too large" );
2967 SNPRINTF(s,size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
2977 if( PCOR(pcop)->instance) {
2978 SNPRINTF(s,size,"(%s + %d)",
2980 PCOR(pcop)->instance );
2982 SNPRINTF(s,size,"%s",pcop->name);
2989 if(PCOLAB(pcop)->offset == 1)
2990 SNPRINTF(s,size,"HIGH(%s)",pcop->name);
2992 SNPRINTF(s,size,"%s",pcop->name);
3000 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
3003 return PCOR(pcop)->r->name;
3005 /* fall through to the default case */
3010 SNPRINTF(buffer,size,"%s",pcop->name);
3018 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3019 __FILE__, __LINE__, __FUNCTION__,
3022 return "NO operand";
3026 /*-----------------------------------------------------------------*/
3027 /*-----------------------------------------------------------------*/
3028 static char *get_op_from_instruction( pCodeInstruction *pcc)
3032 return get_op(pcc->pcop,NULL,0);
3034 return ("ERROR Null: get_op_from_instruction");
3038 /*-----------------------------------------------------------------*/
3039 /*-----------------------------------------------------------------*/
3040 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3042 fprintf(of,"pcodeopprint- not implemented\n");
3045 /*-----------------------------------------------------------------*/
3046 /* pCode2str - convert a pCode instruction to string */
3047 /*-----------------------------------------------------------------*/
3048 char *pCode2str(char *str, size_t size, pCode *pc)
3056 SNPRINTF(s,size, "\t%s\t", PCI(pc)->mnemonic);
3060 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3061 if(PCI(pc)->isBitInst) {
3062 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3063 char *name = PCI(pc)->pcop->name;
3065 name = PCOR(PCI(pc)->pcop)->r->name;
3066 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3067 SNPRINTF(s,size,"(%s >> 3), (%s & 7)", name, name);
3069 SNPRINTF(s,size,"%s,%d", name, (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3070 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3071 SNPRINTF(s,size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3073 SNPRINTF(s,size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3075 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3076 if( PCI(pc)->num_ops == 2)
3077 SNPRINTF(s,size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3079 SNPRINTF(s,size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3081 SNPRINTF(s,size,"%s",get_op_from_instruction(PCI(pc)));
3084 if( PCI(pc)->num_ops == 2)
3085 SNPRINTF(s,size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3092 /* assuming that comment ends with a \n */
3093 SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
3097 /* assuming that inline code ends with a \n */
3098 SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
3102 SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3105 SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3108 SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3111 SNPRINTF(s,size,";\t--FLOW change\n");
3114 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);
3117 if(PCAD(pc)->directive) {
3118 SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3119 } else if(PCAD(pc)->arg) {
3120 /* special case to handle inline labels without a tab */
3121 SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
3126 SNPRINTF(s,size,";A bad pCode is being used\n");
3132 /*-----------------------------------------------------------------*/
3133 /* genericPrint - the contents of a pCode to a file */
3134 /*-----------------------------------------------------------------*/
3135 static void genericPrint(FILE *of, pCode *pc)
3142 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3146 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3150 // If the opcode has a label, print that first
3153 pCodeInstruction *pci = PCI(pc);
3154 pBranch *pbl = pci->label;
3155 while(pbl && pbl->pc) {
3156 if(pbl->pc->type == PC_LABEL)
3157 pCodePrintLabel(of, pbl->pc);
3162 genericPrint(of,PCODE(pci->cline));
3165 pCode2str(str, 256, pc);
3167 fprintf(of,"%s",str);
3171 pCodeOpReg *pcor = PCOR(pci->pcop);
3172 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3174 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3175 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3176 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3181 pBranch *dpb = pc->to; // debug
3183 switch ( dpb->pc->type) {
3185 fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3188 fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3191 fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3194 fprintf(of, "\t;flow");
3208 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3209 if(PCW(pc)->pci.label)
3210 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3212 if(PCW(pc)->operand) {
3213 fprintf(of,";\toperand ");
3214 pCodeOpPrint(of,PCW(pc)->operand );
3220 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3221 if(PCFL(pc)->ancestor)
3222 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3224 fprintf(of,"; from: ");
3226 pCodeFlowLink *link;
3227 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3229 fprintf(of,"%03x ",link->pcflow->pc.seq);
3232 fprintf(of,"; to: ");
3234 pCodeFlowLink *link;
3235 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3237 fprintf(of,"%03x ",link->pcflow->pc.seq);
3245 // fprintf(of,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3246 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3251 pBranch *pbl = PCAD(pc)->pci.label;
3252 while(pbl && pbl->pc) {
3253 if(pbl->pc->type == PC_LABEL)
3254 pCodePrintLabel(of, pbl->pc);
3258 if(PCAD(pc)->directive) {
3259 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3262 /* special case to handle inline labels without tab */
3263 fprintf(of, "%s\n", PCAD(pc)->arg);
3269 fprintf(of,"unknown pCode type %d\n",pc->type);
3273 /*-----------------------------------------------------------------*/
3274 /* pCodePrintFunction - prints function begin/end */
3275 /*-----------------------------------------------------------------*/
3277 static void pCodePrintFunction(FILE *of, pCode *pc)
3283 if( ((pCodeFunction *)pc)->modname)
3284 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3286 if(PCF(pc)->fname) {
3287 pBranch *exits = PCF(pc)->to;
3289 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3292 exits = exits->next;
3295 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3298 if((PCF(pc)->from &&
3299 PCF(pc)->from->pc->type == PC_FUNCTION &&
3300 PCF(PCF(pc)->from->pc)->fname) )
3301 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3303 fprintf(of,"; exit point [can't find entry point]\n");
3306 /*-----------------------------------------------------------------*/
3307 /* pCodePrintLabel - prints label */
3308 /*-----------------------------------------------------------------*/
3310 static void pCodePrintLabel(FILE *of, pCode *pc)
3317 fprintf(of,"%s\n",PCL(pc)->label);
3318 else if (PCL(pc)->key >=0)
3319 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3321 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3325 /*-----------------------------------------------------------------*/
3326 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3327 /* remove it if it is found. */
3328 /*-----------------------------------------------------------------*/
3329 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3335 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3336 b = PCI(pcl)->label;
3338 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3342 //fprintf (stderr, "%s \n",__FUNCTION__);
3343 //pcl->print(stderr,pcl);
3344 //pc->print(stderr,pc);
3347 //fprintf (stderr, "found label\n");
3351 bprev->next = b->next; /* Not first pCode in chain */
3355 PCI(pcl)->label = b->next; /* First pCode in chain */
3358 return; /* A label can't occur more than once */
3365 /*-----------------------------------------------------------------*/
3366 /*-----------------------------------------------------------------*/
3367 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3386 /*-----------------------------------------------------------------*/
3387 /* pBranchLink - given two pcodes, this function will link them */
3388 /* together through their pBranches */
3389 /*-----------------------------------------------------------------*/
3390 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3394 // Declare a new branch object for the 'from' pCode.
3396 //_ALLOC(b,sizeof(pBranch));
3397 b = Safe_calloc(1,sizeof(pBranch));
3398 b->pc = PCODE(t); // The link to the 'to' pCode.
3401 f->to = pBranchAppend(f->to,b);
3403 // Now do the same for the 'to' pCode.
3405 //_ALLOC(b,sizeof(pBranch));
3406 b = Safe_calloc(1,sizeof(pBranch));
3410 t->from = pBranchAppend(t->from,b);
3415 /*-----------------------------------------------------------------*/
3416 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3418 /*-----------------------------------------------------------------*/
3419 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3432 /*-----------------------------------------------------------------*/
3433 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
3434 /*-----------------------------------------------------------------*/
3435 static void pCodeUnlink(pCode *pc)
3440 if(!pc->prev || !pc->next) {
3441 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3445 /* first remove the pCode from the chain */
3446 pc->prev->next = pc->next;
3447 pc->next->prev = pc->prev;
3449 /* Now for the hard part... */
3451 /* Remove the branches */
3455 pc1 = pb1->pc; /* Get the pCode that branches to the
3456 * one we're unlinking */
3458 /* search for the link back to this pCode (the one we're
3460 if(pb2 = pBranchFind(pc1->to,pc)) {
3461 pb2->pc = pc->to->pc; // make the replacement
3463 /* if the pCode we're unlinking contains multiple 'to'
3464 * branches (e.g. this a skip instruction) then we need
3465 * to copy these extra branches to the chain. */
3467 pBranchAppend(pb2, pc->to->next);
3476 /*-----------------------------------------------------------------*/
3477 /*-----------------------------------------------------------------*/
3479 static void genericAnalyze(pCode *pc)
3489 // Go through the pCodes that are in pCode chain and link
3490 // them together through the pBranches. Note, the pCodes
3491 // are linked together as a contiguous stream like the
3492 // assembly source code lines. The linking here mimics this
3493 // except that comments are not linked in.
3495 pCode *npc = pc->next;
3497 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3498 pBranchLink(pc,npc);
3503 /* reached the end of the pcode chain without finding
3504 * an instruction we could link to. */
3508 fprintf(stderr,"analyze PC_FLOW\n");
3512 fprintf(stderr,";A bad pCode is being used\n");
3518 /*-----------------------------------------------------------------*/
3519 /*-----------------------------------------------------------------*/
3520 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3524 if(pc->type == PC_LABEL) {
3525 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3528 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3529 pbr = PCI(pc)->label;
3531 if(pbr->pc->type == PC_LABEL) {
3532 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3542 /*-----------------------------------------------------------------*/
3543 /*-----------------------------------------------------------------*/
3544 static int checkLabel(pCode *pc)
3548 if(pc && isPCI(pc)) {
3549 pbr = PCI(pc)->label;
3551 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3561 /*-----------------------------------------------------------------*/
3562 /* findLabelinpBlock - Search the pCode for a particular label */
3563 /*-----------------------------------------------------------------*/
3564 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3571 for(pc = pb->pcHead; pc; pc = pc->next)
3572 if(compareLabel(pc,pcop_label))
3579 /*-----------------------------------------------------------------*/
3580 /* findLabel - Search the pCode for a particular label */
3581 /*-----------------------------------------------------------------*/
3582 static pCode * findLabel(pCodeOpLabel *pcop_label)
3590 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3591 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3595 fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3600 /*-----------------------------------------------------------------*/
3601 /* findNextpCode - given a pCode, find the next of type 'pct' */
3602 /* in the linked list */
3603 /*-----------------------------------------------------------------*/
3604 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3618 /*-----------------------------------------------------------------*/
3619 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3620 /* in the linked list */
3621 /*-----------------------------------------------------------------*/
3622 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3626 if(pc->type == pct) {
3628 static unsigned int stop;
3630 stop++; // Place break point here
3642 /*-----------------------------------------------------------------*/
3643 /* findNextInstruction - given a pCode, find the next instruction */
3644 /* in the linked list */
3645 /*-----------------------------------------------------------------*/
3646 pCode * findNextInstruction(pCode *pci)
3651 if((pc->type == PC_OPCODE)
3652 || (pc->type == PC_WILD)
3653 || (pc->type == PC_ASMDIR))
3657 fprintf(stderr,"findNextInstruction: ");
3658 printpCode(stderr, pc);
3663 //fprintf(stderr,"Couldn't find instruction\n");
3667 /*-----------------------------------------------------------------*/
3668 /* findNextInstruction - given a pCode, find the next instruction */
3669 /* in the linked list */
3670 /*-----------------------------------------------------------------*/
3671 pCode * findPrevInstruction(pCode *pci)
3677 if((pc->type == PC_OPCODE)
3678 || (pc->type == PC_WILD)
3679 || (pc->type == PC_ASMDIR))
3684 fprintf(stderr,"pic16_findPrevInstruction: ");
3685 printpCode(stderr, pc);
3690 //fprintf(stderr,"Couldn't find instruction\n");
3695 /*-----------------------------------------------------------------*/
3696 /* findFunctionEnd - given a pCode find the end of the function */
3697 /* that contains it */
3698 /*-----------------------------------------------------------------*/
3699 static pCode * findFunctionEnd(pCode *pc)
3702 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
3708 fprintf(stderr,"Couldn't find function end\n");
3714 /*-----------------------------------------------------------------*/
3715 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
3716 /* instruction with which it is associated. */
3717 /*-----------------------------------------------------------------*/
3718 static void AnalyzeLabel(pCode *pc)
3727 static void AnalyzeGOTO(pCode *pc)
3730 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3734 static void AnalyzeSKIP(pCode *pc)
3737 pBranchLink(pc,findNextInstruction(pc->next));
3738 pBranchLink(pc,findNextInstruction(pc->next->next));
3742 static void AnalyzeRETURN(pCode *pc)
3745 // branch_link(pc,findFunctionEnd(pc->next));
3751 /*-----------------------------------------------------------------*/
3752 /*-----------------------------------------------------------------*/
3753 regs * getRegFromInstruction(pCode *pc)
3759 PCI(pc)->num_ops == 0 )
3762 switch(PCI(pc)->pcop->type) {
3769 case PO_SFR_REGISTER:
3772 return PCOR(PCI(pc)->pcop)->r;
3774 case PO_GPR_REGISTER:
3777 r = PCOR(PCI(pc)->pcop)->r;
3780 return dirregWithName(PCI(pc)->pcop->name);
3786 r = PCOI(PCI(pc)->pcop)->r;
3789 return dirregWithName(PCI(pc)->pcop->name);
3799 /*-----------------------------------------------------------------*/
3800 /*-----------------------------------------------------------------*/
3802 static void AnalyzepBlock(pBlock *pb)
3809 /* Find all of the registers used in this pBlock
3810 * by looking at each instruction and examining it's
3813 for(pc = pb->pcHead; pc; pc = pc->next) {
3815 /* Is this an instruction with operands? */
3816 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3818 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3819 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3821 /* Loop through all of the registers declared so far in
3822 this block and see if we find this one there */
3824 regs *r = setFirstItem(pb->tregisters);
3827 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3828 PCOR(PCI(pc)->pcop)->r = r;
3831 r = setNextItem(pb->tregisters);
3835 /* register wasn't found */
3836 //r = Safe_calloc(1, sizeof(regs));
3837 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3838 //addSet(&pb->tregisters, r);
3839 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3840 //PCOR(PCI(pc)->pcop)->r = r;
3841 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3843 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3846 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3847 if(PCOR(PCI(pc)->pcop)->r) {
3848 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3849 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3851 if(PCI(pc)->pcop->name)
3852 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3854 fprintf(stderr,"ERROR: NULL register\n");
3863 /*-----------------------------------------------------------------*/
3865 /*-----------------------------------------------------------------*/
3866 static void InsertpFlow(pCode *pc, pCode **pflow)
3869 PCFL(*pflow)->end = pc;
3871 if(!pc || !pc->next)
3874 *pflow = newpCodeFlow();
3875 pCodeInsertAfter(pc, *pflow);
3878 /*-----------------------------------------------------------------*/
3879 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3880 /* the flow blocks. */
3882 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3883 * point the instruction flow changes.
3885 /*-----------------------------------------------------------------*/
3886 static void BuildFlow(pBlock *pb)
3889 pCode *last_pci=NULL;
3896 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3897 /* Insert a pCodeFlow object at the beginning of a pBlock */
3899 InsertpFlow(pb->pcHead, &pflow);
3901 //pflow = newpCodeFlow(); /* Create a new Flow object */
3902 //pflow->next = pb->pcHead; /* Make the current head the next object */
3903 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3904 //pb->pcHead = pflow; /* Make the Flow object the head */
3907 for( pc = findNextInstruction(pb->pcHead);
3909 pc=findNextInstruction(pc)) {
3912 PCI(pc)->pcflow = PCFL(pflow);
3914 //fprintf(stderr," build: ");
3915 //pc->print(stderr, pc);
3916 //pflow->print(stderr,pflow);
3918 if (checkLabel(pc)) {
3920 /* This instruction marks the beginning of a
3921 * new flow segment */
3926 /* If the previous pCode is not a flow object, then
3927 * insert a new flow object. (This check prevents
3928 * two consecutive flow objects from being insert in
3929 * the case where a skip instruction preceeds an
3930 * instruction containing a label.) */
3932 last_pci = findPrevInstruction (pc->prev);
3934 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3935 InsertpFlow(last_pci, &pflow);
3937 PCI(pc)->pcflow = PCFL(pflow);
3941 if(isPCI_SKIP(pc)) {
3943 /* The two instructions immediately following this one
3944 * mark the beginning of a new flow segment */
3946 while(pc && isPCI_SKIP(pc)) {
3948 PCI(pc)->pcflow = PCFL(pflow);
3952 InsertpFlow(pc, &pflow);
3953 pc=findNextInstruction(pc->next);
3961 PCI(pc)->pcflow = PCFL(pflow);
3963 InsertpFlow(pc, &pflow);
3965 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
3967 InsertpFlow(pc, &pflow);
3976 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3978 PCFL(pflow)->end = pb->pcTail;
3981 /*-------------------------------------------------------------------*/
3982 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3983 /* the flow blocks. */
3985 * unBuildFlow removes pCodeFlow objects from a pCode chain
3987 /*-----------------------------------------------------------------*/
3988 static void unBuildFlow(pBlock *pb)
4003 if(PCI(pc)->pcflow) {
4004 //free(PCI(pc)->pcflow);
4005 PCI(pc)->pcflow = NULL;
4008 } else if(isPCFL(pc) )
4018 /*-----------------------------------------------------------------*/
4019 /*-----------------------------------------------------------------*/
4020 static void dumpCond(int cond)
4023 static char *pcc_str[] = {
4037 int ncond = sizeof(pcc_str) / sizeof(char *);
4040 fprintf(stderr, "0x%04X\n",cond);
4042 for(i=0,j=1; i<ncond; i++, j<<=1)
4044 fprintf(stderr, " %s\n",pcc_str[i]);
4050 /*-----------------------------------------------------------------*/
4051 /*-----------------------------------------------------------------*/
4052 static void FlowStats(pCodeFlow *pcflow)
4060 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4062 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4065 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4070 fprintf(stderr, " FlowStats inCond: ");
4071 dumpCond(pcflow->inCond);
4072 fprintf(stderr, " FlowStats outCond: ");
4073 dumpCond(pcflow->outCond);
4078 /*-----------------------------------------------------------------*
4079 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4080 * if it affects the banking bits.
4082 * return: -1 == Banking bits are unaffected by this pCode.
4084 * return: > 0 == Banking bits are affected.
4086 * If the banking bits are affected, then the returned value describes
4087 * which bits are affected and how they're affected. The lower half
4088 * of the integer maps to the bits that are affected, the upper half
4089 * to whether they're set or cleared.
4091 *-----------------------------------------------------------------*/
4093 static int isBankInstruction(pCode *pc)
4101 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4103 // Check to see if the register banks are changing
4104 if(PCI(pc)->isModReg) {
4106 pCodeOp *pcop = PCI(pc)->pcop;
4107 switch(PCI(pc)->op) {
4110 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4111 //fprintf(stderr, " isBankInstruction - Set RP0\n");
4112 return SET_BANK_BIT | PIC_RP0_BIT;
4115 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4116 //fprintf(stderr, " isBankInstruction - Set RP1\n");
4117 return CLR_BANK_BIT | PIC_RP0_BIT;
4122 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4123 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
4124 return CLR_BANK_BIT | PIC_RP1_BIT;
4126 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4127 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
4128 return CLR_BANK_BIT | PIC_RP1_BIT;
4132 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
4133 //genericPrint(stderr, pc);
4144 /*-----------------------------------------------------------------*/
4145 /*-----------------------------------------------------------------*/
4147 static void FillFlow(pCodeFlow *pcflow)
4155 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4157 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
4160 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4167 isBankInstruction(pc);
4169 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4172 fprintf(stderr, " FillFlow - Bad end of flow\n");
4174 fprintf(stderr, " FillFlow - Ending flow with\n ");
4175 pc->print(stderr,pc);
4178 fprintf(stderr, " FillFlow inCond: ");
4179 dumpCond(pcflow->inCond);
4180 fprintf(stderr, " FillFlow outCond: ");
4181 dumpCond(pcflow->outCond);
4186 /*-----------------------------------------------------------------*/
4187 /*-----------------------------------------------------------------*/
4188 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4190 pCodeFlowLink *fromLink, *toLink;
4192 fprintf(stderr, "%s: linking ", __FUNCTION__ );
4193 if (from) from->pc.print(stderr, &from->pc);
4194 else fprintf(stderr, "(null)");
4195 fprintf(stderr, " -(%u)-> with -(%u)-> ",
4196 from && from->pcflow ? from->pcflow->pc.seq : 0,
4197 to && to->pcflow ? to->pcflow->pc.seq : 0);
4198 if (to) to->pc.print(stderr, &to->pc);
4199 else fprintf(stderr, "(null)");
4202 if(!from || !to || !to->pcflow || !from->pcflow)
4205 fromLink = newpCodeFlowLink(from->pcflow);
4206 toLink = newpCodeFlowLink(to->pcflow);
4208 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
4209 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4213 /*-----------------------------------------------------------------*
4214 * void LinkFlow(pBlock *pb)
4216 * In BuildFlow, the PIC code has been partitioned into contiguous
4217 * non-branching segments. In LinkFlow, we determine the execution
4218 * order of these segments. For example, if one of the segments ends
4219 * with a skip, then we know that there are two possible flow segments
4220 * to which control may be passed.
4221 *-----------------------------------------------------------------*/
4222 static void LinkFlow(pBlock *pb)
4228 //fprintf(stderr,"linkflow \n");
4232 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4234 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4237 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4239 //fprintf(stderr," link: ");
4240 //pcflow->print(stderr,pcflow);
4242 //FillFlow(PCFL(pcflow));
4244 /* find last instruction in flow */
4245 pc = findPrevInstruction (PCFL(pcflow)->end);
4247 fprintf(stderr, "%s: flow without end (%u)?\n",
4248 __FUNCTION__, pcflow->seq );
4252 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4253 //pc->print(stderr, pc);
4254 if(isPCI_SKIP(pc)) {
4255 //fprintf(stderr, "ends with skip\n");
4256 //pc->print(stderr,pc);
4257 pct=findNextInstruction(pc->next);
4258 LinkFlow_pCode(PCI(pc),PCI(pct));
4259 pct=findNextInstruction(pct->next);
4260 LinkFlow_pCode(PCI(pc),PCI(pct));
4264 if(isPCI_BRANCH(pc)) {
4265 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4267 //fprintf(stderr, "ends with branch\n ");
4268 //pc->print(stderr,pc);
4270 if(!(pcol && isPCOLAB(pcol))) {
4271 if((PCI(pc)->op != POC_RETLW)
4272 && (PCI(pc)->op != POC_RETURN)
4273 && (PCI(pc)->op != POC_CALL)
4274 && (PCI(pc)->op != POC_RETFIE) )
4276 pc->print(stderr,pc);
4277 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4281 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4282 LinkFlow_pCode(PCI(pc),PCI(pct));
4284 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4285 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4286 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4288 /* link CALLs to next instruction */
4289 if (PCI(pc)->op != POC_CALL) continue;
4293 //fprintf(stderr, "ends with non-branching instruction:\n");
4294 //pc->print(stderr,pc);
4296 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4302 //fprintf(stderr, "ends with unknown\n");
4303 //pc->print(stderr,pc);
4307 fprintf(stderr, "ends with nothing: ERROR\n");
4311 /*-----------------------------------------------------------------*/
4312 /*-----------------------------------------------------------------*/
4315 /*-----------------------------------------------------------------*/
4316 /*-----------------------------------------------------------------*/
4317 static int isPCinFlow(pCode *pc, pCode *pcflow)
4323 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4326 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4334 static int isREGinBank(regs *reg, int bank)
4340 if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank)
4346 static int REGallBanks(regs *reg)
4352 return ((reg->address | reg->alias) & pic->bankMask);
4357 /*-----------------------------------------------------------------*/
4358 /*-----------------------------------------------------------------*/
4360 static void BanksUsedFlow2(pCode *pcflow)
4369 if(!isPCFL(pcflow)) {
4370 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4374 pc = findNextInstruction(pcflow->next);
4376 PCFL(pcflow)->lastBank = -1;
4378 while(isPCinFlow(pc,pcflow)) {
4380 int bank_selected = isBankInstruction(pc);
4382 //if(PCI(pc)->pcflow)
4383 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4385 if(bank_selected > 0) {
4386 //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4388 // This instruction is modifying banking bits before accessing registers
4390 PCFL(pcflow)->firstBank = -1;
4392 if(PCFL(pcflow)->lastBank == -1)
4393 PCFL(pcflow)->lastBank = 0;
4395 bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4396 if(bank_selected & SET_BANK_BIT)
4397 PCFL(pcflow)->lastBank |= bank;
4401 reg = getRegFromInstruction(pc);
4403 if(reg && !isREGinBank(reg, bank)) {
4404 int allbanks = REGallBanks(reg);
4406 PCFL(pcflow)->firstBank = allbanks;
4408 PCFL(pcflow)->lastBank = allbanks;
4415 pc = findNextInstruction(pc->next);
4418 // fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4419 // pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4422 /*-----------------------------------------------------------------*/
4423 /*-----------------------------------------------------------------*/
4425 static void BanksUsedFlow(pBlock *pb)
4430 //pb->pcHead->print(stderr, pb->pcHead);
4432 pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4433 //pcflow->print(stderr,pcflow);
4435 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4437 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4439 BanksUsedFlow2(pcflow);
4445 static void pCodeReplace (pCode *old, pCode *new)
4447 pCodeInsertAfter (old, new);
4449 /* special handling for pCodeInstructions */
4450 if (isPCI(new) && isPCI(old))
4452 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4453 PCI(new)->from = PCI(old)->from;
4454 PCI(new)->to = PCI(old)->to;
4455 PCI(new)->label = PCI(old)->label;
4456 PCI(new)->pcflow = PCI(old)->pcflow;
4457 PCI(new)->cline = PCI(old)->cline;
4460 old->destruct (old);
4463 /*-----------------------------------------------------------------*/
4464 /*-----------------------------------------------------------------*/
4465 static void addpCodeComment(pCode *pc, const char *fmt, ...)
4472 if (options.verbose || debug_verbose) {
4475 vsprintf(&buffer[2], fmt, ap);
4477 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4478 pCodeInsertAfter(pc, newpc);
4483 /*-----------------------------------------------------------------*/
4484 /* Inserts a new pCodeInstruction before an existing one */
4485 /*-----------------------------------------------------------------*/
4486 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4490 pcprev = findPrevInstruction(pci->pc.prev);
4492 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4494 /* Move the label, if there is one */
4497 new_pci->label = pci->label;
4501 /* Move the C code comment, if there is one */
4504 new_pci->cline = pci->cline;
4508 /* The new instruction has the same pcflow block */
4509 new_pci->pcflow = pci->pcflow;
4511 /* Arrrrg: is pci's previous instruction is a skip, we need to
4512 * change that into a jump (over pci and the new instruction) ... */
4513 if (pcprev && isPCI_SKIP(pcprev))
4515 symbol *lbl = newiTempLabel (NULL);
4516 pCode *label = newpCodeLabel (NULL, lbl->key);
4517 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4519 pCodeInsertAfter (pcprev, jump);
4521 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4522 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4523 switch (PCI(pcprev)->op) {
4528 // These are turned into non-skipping instructions, so
4529 // insert 'BTFSC STATUS, Z' after pcprev
4530 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4533 // no special actions required
4536 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4538 pCodeInsertAfter((pCode*)pci, label);
4539 pBlockMergeLabels(pci->pc.pb);
4543 /*-----------------------------------------------------------------*/
4544 /*-----------------------------------------------------------------*/
4545 static void insertBankSel(pCodeInstruction *pci, const char *name)
4551 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4552 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4554 pcop = popCopyReg(PCOR(pci->pcop));
4555 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4556 if (pcop->name == 0)
4557 pcop->name = strdup(name);
4558 new_pc = newpCode(POC_BANKSEL, pcop);
4560 insertPCodeInstruction(pci, PCI(new_pc));
4564 * isValidIdChar - check if c may be present in an identifier
4566 static int isValidIdChar (char c)
4568 if (c >= 'a' && c <= 'z') return 1;
4569 if (c >= 'A' && c <= 'Z') return 1;
4570 if (c >= '0' && c <= '9') return 1;
4571 if (c == '_') return 1;
4576 * bankcompare - check if two operand string refer to the same register
4577 * This functions handles NAME and (NAME + x) in both operands.
4578 * Returns 1 on same register, 0 on different (or unknown) registers.
4580 static int bankCompare(const char *op1, const char *op2)
4584 if (!op1 && !op2) return 0; // both unknown, might be different though!
4585 if (!op1 || !op2) return 0;
4587 // find start of operand name
4588 while (op1[0] == '(' || op1[0] == ' ') op1++;
4589 while (op2[0] == '(' || op2[0] == ' ') op2++;
4591 // compare till first non-identifier character
4592 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4593 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4595 // play safe---assume different operands
4600 * Interface to BANKSEL generation.
4601 * This function should return != 0 iff str1 and str2 denote operands that
4602 * are known to be allocated into the same bank. Consequently, there will
4603 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
4604 * select the current bank just previously.
4606 * If in doubt, return 0.
4609 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
4610 // see glue.c(pic14printLocals)
4612 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
4613 // no clustering applied, each register resides in its own bank
4615 // check whether BOTH names are local registers
4616 // XXX: This is some kind of shortcut, should be safe...
4617 // In this model, all r0xXXXX are allocated into a single section
4618 // per file, so no BANKSEL required if accessing a r0xXXXX after a
4619 // (different) r0xXXXX. Works great for multi-byte operands.
4620 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
4623 // assume operands in different banks
4627 /*-----------------------------------------------------------------*/
4628 /*-----------------------------------------------------------------*/
4629 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4631 if (!cur_bank) return 0;
4633 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4634 return 1; // if we have address info, we use it for banksel optimization
4636 // regard '(regname + X)' and '(regname + Y)' as equal
4637 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4638 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4640 // check allocation policy from glue.c
4641 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4642 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4644 // seems to be a different operand--might be a different bank
4645 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4649 /*-----------------------------------------------------------------*/
4650 /*-----------------------------------------------------------------*/
4651 static void FixRegisterBanking(pBlock *pb)
4654 pCodeInstruction *pci;
4656 regs *previous_reg; // contains the previous variable access info
4657 const char *cur_bank, *new_bank;
4658 unsigned cur_mask, new_mask, max_mask;
4663 max_mask = pic14_getPIC()->bankMask;
4664 cur_mask = max_mask;
4666 previous_reg = NULL;
4668 allRAMmshared = pic14_allRAMShared();
4670 for (pc = pb->pcHead; pc; pc = pc->next)
4672 // this one has a label---might check bank at all jumps here...
4673 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4674 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4675 previous_reg = NULL;
4676 cur_bank = NULL; // start new flow
4677 cur_mask = max_mask;
4680 // this one is/might be a label or BANKSEL---assume nothing
4681 if (isPCL(pc) || isPCASMDIR(pc)) {
4682 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4683 previous_reg = NULL;
4685 cur_mask = max_mask;
4688 // this one modifies STATUS
4689 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4693 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4694 // might need a BANKSEL
4695 reg = getRegFromInstruction(pc);
4698 new_bank = reg->name;
4699 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4700 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4701 new_mask = reg->alias;
4702 } else if (pci->pcop && pci->pcop->name) {
4703 new_bank = pci->pcop->name;
4704 new_mask = 0; // unknown, assume worst case
4706 assert(!"Could not get register from instruction.");
4707 new_bank = "UNKNOWN";
4708 new_mask = 0; // unknown, assume worst case
4712 // XXX: add switch to disable these
4714 // reg present in all banks possibly selected?
4715 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4716 // no BANKSEL required
4717 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4721 // only one bank of memory and no SFR accessed?
4722 // XXX: We can do better with fixed registers.
4723 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4724 // no BANKSEL required
4725 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4729 // restrict cur_mask to cover only the banks this register
4730 // is in (as well as the previous registers)
4731 cur_mask &= new_mask;
4733 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4734 // no BANKSEL required
4735 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4740 cur_mask = new_mask;
4741 cur_bank = new_bank;
4743 insertBankSel(pci, cur_bank);
4749 /*-----------------------------------------------------------------*/
4750 /*-----------------------------------------------------------------*/
4751 static int OptimizepBlock(pBlock *pb)
4756 if(!pb || options.nopeep)
4759 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4761 for(pc = pb->pcHead; pc; pc = pc->next)
4762 matches += pCodePeepMatchRule(pc);
4765 pc = findNextInstruction(pb->pcHead);
4773 if(pCodePeepMatchRule(pc)) {
4778 pc = findNextInstruction(pcprev->next);
4780 pc = findNextInstruction(pb->pcHead);
4782 pc = findNextInstruction(pc->next);
4786 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4791 /*-----------------------------------------------------------------*/
4792 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4793 /*-----------------------------------------------------------------*/
4794 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4798 for(pc = pcs; pc; pc = pc->next) {
4800 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4802 (PCI(pc)->pcop->type == PO_LABEL) &&
4803 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4810 /*-----------------------------------------------------------------*/
4811 /*-----------------------------------------------------------------*/
4812 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4819 (PCI(pc)->pcop->type == PO_LABEL)) {
4821 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4823 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4825 free(pcol->pcop.name);
4827 /* If the key is negative, then we (probably) have a label to
4828 * a function and the name is already defined */
4831 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4835 //sprintf(buffer,"_%05d_DS_",pcl->key);
4837 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4839 pcol->pcop.name = Safe_strdup(s);
4840 pcol->key = pcl->key;
4841 //pc->print(stderr,pc);
4848 /*-----------------------------------------------------------------*/
4849 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4850 /* pCode chain if they're not used. */
4851 /*-----------------------------------------------------------------*/
4852 static void pBlockRemoveUnusedLabels(pBlock *pb)
4854 pCode *pc; pCodeLabel *pcl;
4856 if(!pb || !pb->pcHead)
4859 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4861 pBranch *pbr = PCI(pc)->label;
4862 if(pbr && pbr->next) {
4863 pCode *pcd = pb->pcHead;
4865 //fprintf(stderr, "multiple labels\n");
4866 //pc->print(stderr,pc);
4871 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4872 //fprintf(stderr,"Used by:\n");
4873 //pcd->print(stderr,pcd);
4875 exchangeLabels(PCL(pbr->pc),pcd);
4884 for(pc = pb->pcHead; pc; pc = pc->next) {
4886 if(isPCL(pc)) // Label pcode
4888 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4889 pcl = PCL(PCI(pc)->label->pc);
4892 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4894 /* This pCode is a label, so search the pBlock to see if anyone
4897 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4898 /* Couldn't find an instruction that refers to this label
4899 * So, unlink the pCode label from it's pCode chain
4900 * and destroy the label */
4901 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4903 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4904 if(pc->type == PC_LABEL) {
4906 pCodeLabelDestruct(pc);
4908 unlinkpCodeFromBranch(pc, PCODE(pcl));
4909 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4920 /*-----------------------------------------------------------------*/
4921 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4922 /* chain and put them into pBranches that are */
4923 /* associated with the appropriate pCode */
4925 /*-----------------------------------------------------------------*/
4926 void pBlockMergeLabels(pBlock *pb)
4929 pCode *pc, *pcnext=NULL;
4934 /* First, Try to remove any unused labels */
4935 //pBlockRemoveUnusedLabels(pb);
4937 /* Now loop through the pBlock and merge the labels with the opcodes */
4942 pCode *pcn = pc->next;
4944 if(pc->type == PC_LABEL) {
4946 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4947 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4948 if((pcnext = findNextInstruction(pc) )) {
4950 // Unlink the pCode label from it's pCode chain
4953 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4954 // And link it into the instruction's pBranch labels. (Note, since
4955 // it's possible to have multiple labels associated with one instruction
4956 // we must provide a means to accomodate the additional labels. Thus
4957 // the labels are placed into the singly-linked list "label" as
4958 // opposed to being a single member of the pCodeInstruction.)
4960 //_ALLOC(pbr,sizeof(pBranch));
4961 pbr = Safe_calloc(1,sizeof(pBranch));
4965 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4968 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4970 } else if(pc->type == PC_CSOURCE) {
4972 /* merge the source line symbolic info into the next instruction */
4973 if((pcnext = findNextInstruction(pc) )) {
4975 // Unlink the pCode label from it's pCode chain
4977 PCI(pcnext)->cline = PCCS(pc);
4978 //fprintf(stderr, "merging CSRC\n");
4979 //genericPrint(stderr,pcnext);
4985 pBlockRemoveUnusedLabels(pb);
4989 /*-----------------------------------------------------------------*/
4990 /*-----------------------------------------------------------------*/
4991 static int OptimizepCode(char dbName)
4993 #define MAX_PASSES 4
5002 DFPRINTF((stderr," Optimizing pCode\n"));
5006 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5007 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5008 matches += OptimizepBlock(pb);
5011 while(matches && ++passes < MAX_PASSES);
5016 /*-----------------------------------------------------------------*/
5017 /* popCopyGPR2Bit - copy a pcode operator */
5018 /*-----------------------------------------------------------------*/
5020 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5024 pcop = newpCodeOpBit(pc->name, bitval, 0);
5026 if( !( (pcop->type == PO_LABEL) ||
5027 (pcop->type == PO_LITERAL) ||
5028 (pcop->type == PO_STR) ))
5029 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5034 /*-----------------------------------------------------------------*/
5035 /*-----------------------------------------------------------------*/
5036 static void pBlockDestruct(pBlock *pb)
5047 /*-----------------------------------------------------------------*/
5048 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5049 /* name dbName and combine them */
5050 /* into one block */
5051 /*-----------------------------------------------------------------*/
5052 static void mergepBlocks(char dbName)
5055 pBlock *pb, *pbmerged = NULL,*pbn;
5057 pb = the_pFile->pbHead;
5059 //fprintf(stderr," merging blocks named %c\n",dbName);
5063 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5064 if( getpBlock_dbName(pb) == dbName) {
5066 //fprintf(stderr," merged block %c\n",dbName);
5071 addpCode2pBlock(pbmerged, pb->pcHead);
5072 /* addpCode2pBlock doesn't handle the tail: */
5073 pbmerged->pcTail = pb->pcTail;
5075 pb->prev->next = pbn;
5077 pbn->prev = pb->prev;
5082 //printpBlock(stderr, pbmerged);
5089 /*-----------------------------------------------------------------*/
5090 /* AnalyzeFlow - Examine the flow of the code and optimize */
5092 /* level 0 == minimal optimization */
5093 /* optimize registers that are used only by two instructions */
5094 /* level 1 == maximal optimization */
5095 /* optimize by looking at pairs of instructions that use the */
5097 /*-----------------------------------------------------------------*/
5099 static void AnalyzeFlow(int level)
5101 static int times_called=0;
5109 /* if this is not the first time this function has been called,
5110 then clean up old flow information */
5111 if(times_called++) {
5112 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5115 RegsUnMapLiveRanges();
5121 /* Phase 2 - Flow Analysis - Register Banking
5123 * In this phase, the individual flow blocks are examined
5124 * and register banking is fixed.
5127 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5128 //FixRegisterBanking(pb);
5130 /* Phase 2 - Flow Analysis
5132 * In this phase, the pCode is partition into pCodeFlow
5133 * blocks. The flow blocks mark the points where a continuous
5134 * stream of instructions changes flow (e.g. because of
5135 * a call or goto or whatever).
5138 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5142 /* Phase 2 - Flow Analysis - linking flow blocks
5144 * In this phase, the individual flow blocks are examined
5145 * to determine their order of excution.
5148 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5151 /* Phase 3 - Flow Analysis - Flow Tree
5153 * In this phase, the individual flow blocks are examined
5154 * to determine their order of excution.
5157 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5161 /* Phase x - Flow Analysis - Used Banks
5163 * In this phase, the individual flow blocks are examined
5164 * to determine the Register Banks they use
5167 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5171 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5172 pCodeRegMapLiveRanges(pb);
5174 RemoveUnusedRegisters();
5176 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5177 pCodeRegOptimizeRegUsage(level);
5182 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5187 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5189 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5190 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5191 pcflow = pcflow->next) {
5193 FillFlow(PCFL(pcflow));
5198 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5200 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
5201 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5202 pcflow = pcflow->next) {
5204 FlowStats(PCFL(pcflow));
5210 /*-----------------------------------------------------------------*/
5211 /* AnalyzeBanking - Called after the memory addresses have been */
5212 /* assigned to the registers. */
5214 /*-----------------------------------------------------------------*/
5216 void AnalyzeBanking(void)
5220 if(!picIsInitialized()) {
5221 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5225 if (!the_pFile) return;
5227 /* Phase x - Flow Analysis - Used Banks
5229 * In this phase, the individual flow blocks are examined
5230 * to determine the Register Banks they use
5236 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
5237 // BanksUsedFlow(pb);
5238 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5239 FixRegisterBanking(pb);
5246 /*-----------------------------------------------------------------*/
5247 /*-----------------------------------------------------------------*/
5248 static DEFSETFUNC (resetrIdx)
5250 regs *r = (regs *)item;
5258 /*-----------------------------------------------------------------*/
5259 /* InitRegReuse - Initialises variables for code analyzer */
5260 /*-----------------------------------------------------------------*/
5261 static void InitReuseReg(void)
5263 /* Find end of statically allocated variables for start idx */
5264 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5265 /* XXX: Avoid clashes with fixed registers, start late. */
5266 unsigned maxIdx = 0x1000;
5268 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5269 if (r->type != REG_SFR) {
5270 maxIdx += r->size; /* Increment for all statically allocated variables */
5274 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5277 /*-----------------------------------------------------------------*/
5278 /*-----------------------------------------------------------------*/
5279 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
5283 /* check recursion */
5284 pc = setFirstItem(pb->function_entries);
5289 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5295 DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
5297 if (pb->tregisters) {
5299 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5300 if (r->type == REG_GPR) {
5302 if (r->rIdx < (int)idx) {
5305 // make sure, idx is not yet used in this routine...
5307 regset = pb->tregisters;
5308 // do not touch s->curr ==> outer loop!
5309 while (regset && ((regs *)regset->item)->rIdx != idx) {
5310 regset = regset->next;
5315 if (peakIdx < idx) peakIdx = idx;
5316 sprintf(s,"r0x%02X", r->rIdx);
5317 DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
5319 r->name = Safe_strdup(s);
5325 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5327 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5328 char *dest = get_op_from_instruction(PCI(pc));
5330 pCode *pcn = findFunction(dest);
5332 /* This index increment from subroutines is not required, as all subroutines
5333 * may share registers NOT used by this one (< idx).
5334 * BUT if called functions A and B share a register, which gets assigned
5335 * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
5337 * As an alternative to this "solution" we could check above whether an
5338 * to-be-assigned rIdx is already present in the register set of the
5339 * current function. This would increase the reused registers and make this
5340 * `idx =' irrelevant.
5341 * UPDATE: Implemented above; not fast, but works.
5342 * (Problem shown with regression test src/regression/sub2.c)
5344 /*idx = */register_reassign(pcn->pb,idx,level+1);
5352 /*------------------------------------------------------------------*/
5353 /* ReuseReg were call tree permits */
5355 /* Re-allocate the GPR for optimum reuse for a given pblock */
5356 /* eg if a function m() calls function f1() and f2(), where f1 */
5357 /* allocates a local variable vf1 and f2 allocates a local */
5358 /* variable vf2. Then providing f1 and f2 do not call each other */
5359 /* they may share the same general purpose registers for vf1 and */
5361 /* This is done by first setting the the regs rIdx to start after */
5362 /* all the global variables, then walking through the call tree */
5363 /* renaming the registers to match their new idx and incrementng */
5364 /* it as it goes. If a function has already been called it will */
5365 /* only rename the registers if it has already used up those */
5366 /* registers ie rIdx of the function's registers is lower than the */
5367 /* current rIdx. That way the register will not be reused while */
5368 /* still being used by an eariler function call. */
5370 /* Note for this to work the functions need to be declared static. */
5372 /*------------------------------------------------------------------*/
5376 if (options.noOverlay || !the_pFile) return;
5378 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5379 /* Non static functions can be called from other modules so their registers must reassign */
5380 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5381 register_reassign(pb,peakIdx,0);
5385 /*-----------------------------------------------------------------*/
5386 /* buildCallTree - look at the flow and extract all of the calls */
5388 /*-----------------------------------------------------------------*/
5390 static void buildCallTree(void)
5399 /* Now build the call tree.
5400 First we examine all of the pCodes for functions.
5401 Keep in mind that the function boundaries coincide
5402 with pBlock boundaries.
5404 The algorithm goes something like this:
5405 We have two nested loops. The outer loop iterates
5406 through all of the pBlocks/functions. The inner
5407 loop iterates through all of the pCodes for
5408 a given pBlock. When we begin iterating through
5409 a pBlock, the variable pc_fstart, pCode of the start
5410 of a function, is cleared. We then search for pCodes
5411 of type PC_FUNCTION. When one is encountered, we
5412 initialize pc_fstart to this and at the same time
5413 associate a new pBranch object that signifies a
5414 branch entry. If a return is found, then this signifies
5415 a function exit point. We'll link the pCodes of these
5416 returns to the matching pc_fstart.
5418 When we're done, a doubly linked list of pBranches
5419 will exist. The head of this list is stored in
5420 `the_pFile', which is the meta structure for all
5421 of the pCode. Look at the printCallTree function
5422 on how the pBranches are linked together.
5425 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5426 pCode *pc_fstart=NULL;
5427 for(pc = pb->pcHead; pc; pc = pc->next) {
5429 pCodeFunction *pcf = PCF(pc);
5432 if(STRCASECMP(pcf->fname, "_main") == 0) {
5433 //fprintf(stderr," found main \n");
5434 pb->cmemmap = NULL; /* FIXME do we need to free ? */
5438 pbr = Safe_calloc(1,sizeof(pBranch));
5439 pbr->pc = pc_fstart = pc;
5442 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5444 // Here's a better way of doing the same:
5445 addSet(&pb->function_entries, pc);
5448 // Found an exit point in a function, e.g. return
5449 // (Note, there may be more than one return per function)
5451 pBranchLink(PCF(pc_fstart), pcf);
5453 addSet(&pb->function_exits, pc);
5455 } else if(isCALL(pc)) {
5456 addSet(&pb->function_calls,pc);
5462 /*-----------------------------------------------------------------*/
5463 /* AnalyzepCode - parse the pCode that has been generated and form */
5464 /* all of the logical connections. */
5466 /* Essentially what's done here is that the pCode flow is */
5468 /*-----------------------------------------------------------------*/
5470 void AnalyzepCode(char dbName)
5481 /* Phase 1 - Register allocation and peep hole optimization
5483 * The first part of the analysis is to determine the registers
5484 * that are used in the pCode. Once that is done, the peep rules
5485 * are applied to the code. We continue to loop until no more
5486 * peep rule optimizations are found (or until we exceed the
5487 * MAX_PASSES threshold).
5489 * When done, the required registers will be determined.
5495 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5497 /* First, merge the labels with the instructions */
5498 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5499 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5501 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5502 pBlockMergeLabels(pb);
5505 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5509 changes = OptimizepCode(dbName);
5511 } while(changes && (i++ < MAX_PASSES));
5517 /*-----------------------------------------------------------------*/
5518 /* ispCodeFunction - returns true if *pc is the pCode of a */
5520 /*-----------------------------------------------------------------*/
5521 static bool ispCodeFunction(pCode *pc)
5524 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5531 /*-----------------------------------------------------------------*/
5532 /* findFunction - Search for a function by name (given the name) */
5533 /* in the set of all functions that are in a pBlock */
5534 /* (note - I expect this to change because I'm planning to limit */
5535 /* pBlock's to just one function declaration */
5536 /*-----------------------------------------------------------------*/
5537 static pCode *findFunction(char *fname)
5544 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5546 pc = setFirstItem(pb->function_entries);
5549 if((pc->type == PC_FUNCTION) &&
5551 (strcmp(fname, PCF(pc)->fname)==0))
5554 pc = setNextItem(pb->function_entries);
5563 static void MarkUsedRegisters(set *regset)
5568 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5569 r2 = pic14_regWithIdx(r1->rIdx);
5578 static void pBlockStats(FILE *of, pBlock *pb)
5584 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5586 // for now just print the first element of each set
5587 pc = setFirstItem(pb->function_entries);
5589 fprintf(of,";entry: ");
5592 pc = setFirstItem(pb->function_exits);
5594 fprintf(of,";has an exit\n");
5598 pc = setFirstItem(pb->function_calls);
5600 fprintf(of,";functions called:\n");
5603 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5604 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5606 pc = setNextItem(pb->function_calls);
5610 r = setFirstItem(pb->tregisters);
5612 int n = elementsInSet(pb->tregisters);
5614 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5617 fprintf(of,"; %s\n",r->name);
5618 r = setNextItem(pb->tregisters);
5623 /*-----------------------------------------------------------------*/
5624 /*-----------------------------------------------------------------*/
5626 static void sequencepCode(void)
5632 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5634 pb->seq = GpCodeSequenceNumber+1;
5636 for( pc = pb->pcHead; pc; pc = pc->next)
5637 pc->seq = ++GpCodeSequenceNumber;
5643 /*-----------------------------------------------------------------*/
5644 /*-----------------------------------------------------------------*/
5646 static set *register_usage(pBlock *pb)
5649 set *registers=NULL;
5650 set *registersInCallPath = NULL;
5652 / * check recursion * /
5654 pc = setFirstItem(pb->function_entries);
5661 if(pc->type != PC_FUNCTION)
5662 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5664 pc = setFirstItem(pb->function_calls);
5665 for( ; pc; pc = setNextItem(pb->function_calls)) {
5667 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5668 char *dest = get_op_from_instruction(PCI(pc));
5670 pcn = findFunction(dest);
5672 registersInCallPath = register_usage(pcn->pb);
5674 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5679 pBlockStats(stderr,pb); // debug
5682 // Mark the registers in this block as used.
5684 MarkUsedRegisters(pb->tregisters);
5685 if(registersInCallPath) {
5686 / * registers were used in the functions this pBlock has called * /
5687 / * so now, we need to see if these collide with the ones we are * /
5690 regs *r1,*r2, *newreg;
5692 DFPRINTF((stderr,"comparing registers\n"));
5694 r1 = setFirstItem(registersInCallPath);
5696 if (r1->type != REG_STK) {
5697 r2 = setFirstItem(pb->tregisters);
5699 while(r2 && (r2->type != REG_STK)) {
5701 if(r2->rIdx == r1->rIdx) {
5702 newreg = pic14_findFreeReg(REG_GPR);
5706 DFPRINTF((stderr,"Bummer, no more registers.\n"));
5710 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5711 r1->rIdx, newreg->rIdx));
5712 r2->rIdx = newreg->rIdx;
5714 r2->name = Safe_strdup(newreg->name);
5718 newreg->wasUsed = 1;
5720 r2 = setNextItem(pb->tregisters);
5724 r1 = setNextItem(registersInCallPath);
5727 / * Collisions have been resolved. Now free the registers in the call path * /
5728 r1 = setFirstItem(registersInCallPath);
5730 newreg = pic14_regWithIdx(r1->rIdx);
5731 if (newreg) newreg->isFree = 1;
5732 r1 = setNextItem(registersInCallPath);
5736 // MarkUsedRegisters(pb->registers);
5738 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5741 DFPRINTF((stderr,"returning regs\n"));
5743 DFPRINTF((stderr,"not returning regs\n"));
5745 DFPRINTF((stderr,"pBlock after register optim.\n"));
5746 pBlockStats(stderr,pb); // debug
5753 /*-----------------------------------------------------------------*/
5754 /* printCallTree - writes the call tree to a file */
5756 /*-----------------------------------------------------------------*/
5757 static void pct2(FILE *of,pBlock *pb,int indent)
5761 // set *registersInCallPath = NULL;
5767 return; //recursion ?
5769 pc = setFirstItem(pb->function_entries);
5776 for(i=0;i<indent;i++) // Indentation
5779 if(pc->type == PC_FUNCTION)
5780 fprintf(of,"%s\n",PCF(pc)->fname);
5785 pc = setFirstItem(pb->function_calls);
5786 for( ; pc; pc = setNextItem(pb->function_calls)) {
5788 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5789 char *dest = get_op_from_instruction(PCI(pc));
5791 pcn = findFunction(dest);
5793 pct2(of,pcn->pb,indent+1);
5795 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5803 /*-----------------------------------------------------------------*/
5804 /* printCallTree - writes the call tree to a file */
5806 /*-----------------------------------------------------------------*/
5808 static void printCallTree(FILE *of)
5820 fprintf(of, "\npBlock statistics\n");
5821 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5826 fprintf(of,"Call Tree\n");
5827 pbr = the_pFile->functions;
5831 if(!ispCodeFunction(pc))
5832 fprintf(of,"bug in call tree");
5835 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5837 while(pc->next && !ispCodeFunction(pc->next)) {
5839 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5840 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5848 fprintf(of,"\n**************\n\na better call tree\n");
5849 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5854 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5855 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5861 /*-----------------------------------------------------------------*/
5863 /*-----------------------------------------------------------------*/
5865 static void InlineFunction(pBlock *pb)
5873 pc = setFirstItem(pb->function_calls);
5875 for( ; pc; pc = setNextItem(pb->function_calls)) {
5878 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5879 pCode *pcp = pc->prev;
5885 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 */
5887 InlineFunction(pcn->pb);
5890 At this point, *pc points to a CALL mnemonic, and
5891 *pcn points to the function that is being called.
5893 To in-line this call, we need to remove the CALL
5894 and RETURN(s), and link the function pCode in with
5901 /* Check if previous instruction was a bit skip */
5902 if (isPCI_BITSKIP(pcp)) {
5904 /* Invert skip instruction and add a goto */
5905 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5907 if(isPCL(pc_call->next)) { // Label pcode
5908 pcl = PCL(pc_call->next);
5909 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5910 pcl = PCL(PCI(pc_call->next)->label->pc);
5912 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5913 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5915 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5918 /* remove callee pBlock from the pBlock linked list */
5919 removepBlock(pcn->pb);
5927 /* Remove the Function pCode */
5928 pct = findNextInstruction(pcn->next);
5930 /* Link the function with the callee */
5931 if (pcp) pcp->next = pcn->next;
5932 pcn->next->prev = pcp;
5934 /* Convert the function name into a label */
5936 pbr = Safe_calloc(1,sizeof(pBranch));
5937 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5939 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5940 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5942 /* turn all of the return's except the last into goto's */
5943 /* check case for 2 instruction pBlocks */
5944 pce = findNextInstruction(pcn->next);
5946 pCode *pce_next = findNextInstruction(pce->next);
5948 if(pce_next == NULL) {
5949 /* found the last return */
5950 pCode *pc_call_next = findNextInstruction(pc_call->next);
5952 //fprintf(stderr,"found last return\n");
5953 //pce->print(stderr,pce);
5954 pce->prev->next = pc_call->next;
5955 pc_call->next->prev = pce->prev;
5956 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5965 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5971 /*-----------------------------------------------------------------*/
5973 /*-----------------------------------------------------------------*/
5975 void InlinepCode(void)
5984 if(!functionInlining)
5987 /* Loop through all of the function definitions and count the
5988 * number of times each one is called */
5989 //fprintf(stderr,"inlining %d\n",__LINE__);
5991 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5993 pc = setFirstItem(pb->function_calls);
5995 for( ; pc; pc = setNextItem(pb->function_calls)) {
5998 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5999 if(pcn && isPCF(pcn)) {
6000 PCF(pcn)->ncalled++;
6003 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6008 //fprintf(stderr,"inlining %d\n",__LINE__);
6010 /* Now, Loop through the function definitions again, but this
6011 * time inline those functions that have only been called once. */
6013 InlineFunction(the_pFile->pbHead);
6014 //fprintf(stderr,"inlining %d\n",__LINE__);
6016 for(pb = the_pFile->pbHead; pb; pb = pb->next)