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 /****************************************************************/
81 static void genericDestruct(pCode *pc);
82 static void genericPrint(FILE *of,pCode *pc);
84 static void pBlockStats(FILE *of, pBlock *pb);
85 static pCode *findFunction(char *fname);
86 static void pCodePrintLabel(FILE *of, pCode *pc);
87 static void pCodePrintFunction(FILE *of, pCode *pc);
88 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
89 static char *get_op_from_instruction( pCodeInstruction *pcc);
90 static pBlock *newpBlock(void);
93 /****************************************************************/
94 /* PIC Instructions */
95 /****************************************************************/
97 static pCodeInstruction pciADDWF = {
98 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
110 1,0, // dest, bit instruction
112 0, // literal operand
114 (PCC_W | PCC_REGISTER), // inCond
115 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
118 static pCodeInstruction pciADDFW = {
119 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
131 0,0, // dest, bit instruction
133 0, // literal operand
135 (PCC_W | PCC_REGISTER), // inCond
136 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
139 static pCodeInstruction pciADDLW = {
140 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
152 0,0, // dest, bit instruction
154 1, // literal operand
156 (PCC_W | PCC_LITERAL), // inCond
157 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
160 static pCodeInstruction pciANDLW = {
161 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
173 0,0, // dest, bit instruction
175 1, // literal operand
177 (PCC_W | PCC_LITERAL), // inCond
178 (PCC_W | PCC_Z) // outCond
181 static pCodeInstruction pciANDWF = {
182 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
194 1,0, // dest, bit instruction
196 0, // literal operand
198 (PCC_W | PCC_REGISTER), // inCond
199 (PCC_REGISTER | PCC_Z) // outCond
202 static pCodeInstruction pciANDFW = {
203 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
215 0,0, // dest, bit instruction
217 0, // literal operand
219 (PCC_W | PCC_REGISTER), // inCond
220 (PCC_W | PCC_Z) // outCond
223 static pCodeInstruction pciBCF = {
224 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
236 1,1, // dest, bit instruction
238 0, // literal operand
240 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
241 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
244 static pCodeInstruction pciBSF = {
245 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
257 1,1, // dest, bit instruction
259 0, // literal operand
261 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
262 (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
265 static pCodeInstruction pciBTFSC = {
266 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
278 0,1, // dest, bit instruction
280 0, // literal operand
282 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
286 static pCodeInstruction pciBTFSS = {
287 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
299 0,1, // dest, bit instruction
301 0, // literal operand
303 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
307 static pCodeInstruction pciCALL = {
308 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
320 0,0, // dest, bit instruction
322 0, // literal operand
324 (PCC_NONE | PCC_W), // inCond, reads argument from WREG
325 (PCC_NONE | PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond, flags are destroyed by called function
328 static pCodeInstruction pciCOMF = {
329 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
341 1,0, // dest, bit instruction
343 0, // literal operand
345 PCC_REGISTER, // inCond
346 PCC_REGISTER | PCC_Z // outCond
349 static pCodeInstruction pciCOMFW = {
350 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
362 0,0, // dest, bit instruction
364 0, // literal operand
366 PCC_REGISTER, // inCond
367 PCC_W | PCC_Z // outCond
370 static pCodeInstruction pciCLRF = {
371 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
383 0,0, // dest, bit instruction
385 0, // literal operand
388 PCC_REGISTER | PCC_Z // outCond
391 static pCodeInstruction pciCLRW = {
392 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
404 0,0, // dest, bit instruction
406 0, // literal operand
409 PCC_W | PCC_Z // outCond
412 static pCodeInstruction pciCLRWDT = {
413 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
425 0,0, // dest, bit instruction
427 0, // literal operand
433 static pCodeInstruction pciDECF = {
434 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
446 1,0, // dest, bit instruction
448 0, // literal operand
450 PCC_REGISTER, // inCond
451 PCC_REGISTER | PCC_Z // outCond
454 static pCodeInstruction pciDECFW = {
455 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
467 0,0, // dest, bit instruction
469 0, // literal operand
471 PCC_REGISTER, // inCond
472 PCC_W | PCC_Z // outCond
475 static pCodeInstruction pciDECFSZ = {
476 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
488 1,0, // dest, bit instruction
490 0, // literal operand
491 POC_DECF, // followed by BTFSC STATUS, Z --> also kills STATUS
492 PCC_REGISTER, // inCond
493 PCC_REGISTER | PCC_Z // outCond
496 static pCodeInstruction pciDECFSZW = {
497 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
509 0,0, // dest, bit instruction
511 0, // literal operand
512 POC_DECFW, // followed by BTFSC STATUS, Z --> also kills STATUS
513 PCC_REGISTER, // inCond
514 PCC_W | PCC_Z // outCond
517 static pCodeInstruction pciGOTO = {
518 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
530 0,0, // dest, bit instruction
532 0, // literal operand
538 static pCodeInstruction pciINCF = {
539 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
551 1,0, // dest, bit instruction
553 0, // literal operand
555 PCC_REGISTER, // inCond
556 PCC_REGISTER | PCC_Z // outCond
559 static pCodeInstruction pciINCFW = {
560 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
572 0,0, // dest, bit instruction
574 0, // literal operand
576 PCC_REGISTER, // inCond
577 PCC_W | PCC_Z // outCond
580 static pCodeInstruction pciINCFSZ = {
581 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
593 1,0, // dest, bit instruction
595 0, // literal operand
596 POC_INCF, // followed by BTFSC STATUS, Z --> also kills STATUS
597 PCC_REGISTER, // inCond
598 PCC_REGISTER | PCC_Z // outCond
601 static pCodeInstruction pciINCFSZW = {
602 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
614 0,0, // dest, bit instruction
616 0, // literal operand
617 POC_INCFW, // followed by BTFSC STATUS, Z --> also kills STATUS
618 PCC_REGISTER, // inCond
619 PCC_W | PCC_Z // outCond
622 static pCodeInstruction pciIORWF = {
623 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
635 1,0, // dest, bit instruction
637 0, // literal operand
639 (PCC_W | PCC_REGISTER), // inCond
640 (PCC_REGISTER | PCC_Z) // outCond
643 static pCodeInstruction pciIORFW = {
644 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
656 0,0, // dest, bit instruction
658 0, // literal operand
660 (PCC_W | PCC_REGISTER), // inCond
661 (PCC_W | PCC_Z) // outCond
664 static pCodeInstruction pciIORLW = {
665 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
677 0,0, // dest, bit instruction
679 1, // literal operand
681 (PCC_W | PCC_LITERAL), // inCond
682 (PCC_W | PCC_Z) // outCond
685 static pCodeInstruction pciMOVF = {
686 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
698 1,0, // dest, bit instruction
700 0, // literal operand
702 PCC_REGISTER, // inCond
706 static pCodeInstruction pciMOVFW = {
707 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
719 0,0, // dest, bit instruction
721 0, // literal operand
723 PCC_REGISTER, // inCond
724 (PCC_W | PCC_Z) // outCond
727 static pCodeInstruction pciMOVWF = {
728 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
740 0,0, // dest, bit instruction
742 0, // literal operand
745 PCC_REGISTER // outCond
748 static pCodeInstruction pciMOVLW = {
749 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
761 0,0, // dest, bit instruction
763 1, // literal operand
765 (PCC_NONE | PCC_LITERAL), // inCond
769 static pCodeInstruction pciNOP = {
770 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
782 0,0, // dest, bit instruction
784 0, // literal operand
790 static pCodeInstruction pciRETFIE = {
791 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
803 0,0, // dest, bit instruction
805 0, // literal operand
808 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond (not true... affects the GIE bit too), STATUS bit are retored
811 static pCodeInstruction pciRETLW = {
812 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
824 0,0, // dest, bit instruction
826 1, // literal operand
828 PCC_LITERAL, // inCond
829 (PCC_W| PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETLW
832 static pCodeInstruction pciRETURN = {
833 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
845 0,0, // dest, bit instruction
847 0, // literal operand
849 PCC_NONE | PCC_W, // inCond, return value is possibly present in W
850 (PCC_NONE | PCC_C | PCC_DC | PCC_Z) // outCond, STATUS bits are irrelevant after RETURN
853 static pCodeInstruction pciRLF = {
854 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
866 1,0, // dest, bit instruction
868 0, // literal operand
870 (PCC_C | PCC_REGISTER), // inCond
871 (PCC_REGISTER | PCC_C ) // outCond
874 static pCodeInstruction pciRLFW = {
875 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
887 0,0, // dest, bit instruction
889 0, // literal operand
891 (PCC_C | PCC_REGISTER), // inCond
892 (PCC_W | PCC_C) // outCond
895 static pCodeInstruction pciRRF = {
896 {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 pciRRFW = {
917 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
929 0,0, // dest, bit instruction
931 0, // literal operand
933 (PCC_C | PCC_REGISTER), // inCond
934 (PCC_W | PCC_C) // outCond
937 static pCodeInstruction pciSUBWF = {
938 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
950 1,0, // dest, bit instruction
952 0, // literal operand
954 (PCC_W | PCC_REGISTER), // inCond
955 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z) // outCond
958 static pCodeInstruction pciSUBFW = {
959 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
971 0,0, // dest, bit instruction
973 0, // literal operand
975 (PCC_W | PCC_REGISTER), // inCond
976 (PCC_W | PCC_C | PCC_DC | PCC_Z) // outCond
979 static pCodeInstruction pciSUBLW = {
980 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
992 0,0, // dest, bit instruction
994 1, // literal operand
996 (PCC_W | PCC_LITERAL), // inCond
997 (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1000 static pCodeInstruction pciSWAPF = {
1001 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1006 NULL, // from branch
1013 1,0, // dest, bit instruction
1014 0,0, // branch, skip
1015 0, // literal operand
1017 (PCC_REGISTER), // inCond
1018 (PCC_REGISTER) // outCond
1021 static pCodeInstruction pciSWAPFW = {
1022 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1027 NULL, // from branch
1034 0,0, // dest, bit instruction
1035 0,0, // branch, skip
1036 0, // literal operand
1038 (PCC_REGISTER), // inCond
1042 static pCodeInstruction pciTRIS = {
1043 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1048 NULL, // from branch
1055 0,0, // dest, bit instruction
1056 0,0, // branch, skip
1057 0, // literal operand
1059 PCC_NONE, // inCond /* FIXME: what's TRIS doing? */
1060 PCC_REGISTER // outCond /* FIXME: what's TRIS doing */
1063 static pCodeInstruction pciXORWF = {
1064 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1069 NULL, // from branch
1076 1,0, // dest, bit instruction
1077 0,0, // branch, skip
1078 0, // literal operand
1080 (PCC_W | PCC_REGISTER), // inCond
1081 (PCC_REGISTER | PCC_Z) // outCond
1084 static pCodeInstruction pciXORFW = {
1085 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1090 NULL, // from branch
1097 0,0, // dest, bit instruction
1098 0,0, // branch, skip
1099 0, // literal operand
1101 (PCC_W | PCC_REGISTER), // inCond
1102 (PCC_W | PCC_Z) // outCond
1105 static pCodeInstruction pciXORLW = {
1106 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1111 NULL, // from branch
1118 0,0, // dest, bit instruction
1119 0,0, // branch, skip
1120 1, // literal operand
1122 (PCC_W | PCC_LITERAL), // inCond
1123 (PCC_W | PCC_Z) // outCond
1127 static pCodeInstruction pciBANKSEL = {
1128 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1133 NULL, // from branch
1140 0,0, // dest, bit instruction
1141 0,0, // branch, skip
1142 0, // literal operand
1148 static pCodeInstruction pciPAGESEL = {
1149 {PC_OPCODE, NULL, NULL, 0, 0, NULL,
1154 NULL, // from branch
1161 0,0, // dest, bit instruction
1162 0,0, // branch, skip
1163 0, // literal operand
1169 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1172 /*-----------------------------------------------------------------*/
1173 /* return a unique ID number to assist pCodes debuging */
1174 /*-----------------------------------------------------------------*/
1175 static unsigned PCodeID(void) {
1176 static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1178 static unsigned int stop;
1179 if (pcodeId == 1448)
1180 stop++; // Place break point here
1185 void pCodeInitRegisters(void)
1187 static int initialized=0;
1188 int shareBankAddress, stkSize, haveShared;
1195 pic = init_pic(port->processor);
1196 haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1197 /* Set pseudo stack size to SHAREBANKSIZE - 3.
1198 * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1199 * (used for interrupts) to fit into the shared portion of the
1201 stkSize = stkSize - 3;
1202 assert(stkSize >= 0);
1203 initStack(shareBankAddress, stkSize, haveShared);
1205 /* TODO: Read aliases for SFRs from regmap lines in device description. */
1206 pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1207 pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1208 pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1209 pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1210 pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1211 pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1213 pc_status.rIdx = IDX_STATUS;
1214 pc_fsr.rIdx = IDX_FSR;
1215 pc_indf.rIdx = IDX_INDF;
1216 pc_intcon.rIdx = IDX_INTCON;
1217 pc_pcl.rIdx = IDX_PCL;
1218 pc_pclath.rIdx = IDX_PCLATH;
1220 /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1221 pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1222 /* Interrupt storage for status register. */
1223 pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1224 /* Interrupt storage for pclath register. */
1225 pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1227 pc_wsave.rIdx = pc_wsave.r->rIdx;
1228 pc_ssave.rIdx = pc_ssave.r->rIdx;
1229 pc_psave.rIdx = pc_psave.r->rIdx;
1231 pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1232 pc_wsave.r->address = shareBankAddress-stkSize;
1233 pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1234 pc_ssave.r->address = shareBankAddress-stkSize-1;
1235 pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1236 pc_psave.r->address = shareBankAddress-stkSize-2;
1238 /* probably should put this in a separate initialization routine */
1239 pb_dead_pcodes = newpBlock();
1243 /*-----------------------------------------------------------------*/
1244 /* mnem2key - convert a pic mnemonic into a hash key */
1245 /* (BTW - this spreads the mnemonics quite well) */
1247 /*-----------------------------------------------------------------*/
1249 static int mnem2key(unsigned char const *mnem)
1258 key += toupper(*mnem++) +1;
1262 return (key & 0x1f);
1266 static void pic14initMnemonics(void)
1271 pCodeInstruction *pci;
1273 if(mnemonics_initialized)
1276 //FIXME - probably should NULL out the array before making the assignments
1277 //since we check the array contents below this initialization.
1279 pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1280 pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1281 pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1282 pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1283 pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1284 pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1285 pic14Mnemonics[POC_BCF] = &pciBCF;
1286 pic14Mnemonics[POC_BSF] = &pciBSF;
1287 pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1288 pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1289 pic14Mnemonics[POC_CALL] = &pciCALL;
1290 pic14Mnemonics[POC_COMF] = &pciCOMF;
1291 pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1292 pic14Mnemonics[POC_CLRF] = &pciCLRF;
1293 pic14Mnemonics[POC_CLRW] = &pciCLRW;
1294 pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1295 pic14Mnemonics[POC_DECF] = &pciDECF;
1296 pic14Mnemonics[POC_DECFW] = &pciDECFW;
1297 pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1298 pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1299 pic14Mnemonics[POC_GOTO] = &pciGOTO;
1300 pic14Mnemonics[POC_INCF] = &pciINCF;
1301 pic14Mnemonics[POC_INCFW] = &pciINCFW;
1302 pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1303 pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1304 pic14Mnemonics[POC_IORLW] = &pciIORLW;
1305 pic14Mnemonics[POC_IORWF] = &pciIORWF;
1306 pic14Mnemonics[POC_IORFW] = &pciIORFW;
1307 pic14Mnemonics[POC_MOVF] = &pciMOVF;
1308 pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1309 pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1310 pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1311 pic14Mnemonics[POC_NOP] = &pciNOP;
1312 pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1313 pic14Mnemonics[POC_RETLW] = &pciRETLW;
1314 pic14Mnemonics[POC_RETURN] = &pciRETURN;
1315 pic14Mnemonics[POC_RLF] = &pciRLF;
1316 pic14Mnemonics[POC_RLFW] = &pciRLFW;
1317 pic14Mnemonics[POC_RRF] = &pciRRF;
1318 pic14Mnemonics[POC_RRFW] = &pciRRFW;
1319 pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1320 pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1321 pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1322 pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1323 pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1324 pic14Mnemonics[POC_TRIS] = &pciTRIS;
1325 pic14Mnemonics[POC_XORLW] = &pciXORLW;
1326 pic14Mnemonics[POC_XORWF] = &pciXORWF;
1327 pic14Mnemonics[POC_XORFW] = &pciXORFW;
1328 pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1329 pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1331 for(i=0; i<MAX_PIC14MNEMONICS; i++)
1332 if(pic14Mnemonics[i])
1333 hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1334 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1337 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1338 pci = hTabNextItem(pic14MnemonicsHash, &key);
1341 mnemonics_initialized = 1;
1344 int getpCode(char *mnem,unsigned dest)
1347 pCodeInstruction *pci;
1348 int key = mnem2key((unsigned char *)mnem);
1350 if(!mnemonics_initialized)
1351 pic14initMnemonics();
1353 pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1357 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1358 if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1362 pci = hTabNextItemWK (pic14MnemonicsHash);
1369 /*-----------------------------------------------------------------*
1370 * pic14initpCodePeepCommands
1372 *-----------------------------------------------------------------*/
1373 void pic14initpCodePeepCommands(void)
1381 hTabAddItem(&pic14pCodePeepCommandsHash,
1382 mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1384 } while (peepCommands[i].cmd);
1386 pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1389 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
1390 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1395 /*-----------------------------------------------------------------
1398 *-----------------------------------------------------------------*/
1400 int getpCodePeepCommand(char *cmd)
1404 int key = mnem2key((unsigned char *)cmd);
1407 pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1410 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1411 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1415 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1422 static char getpBlock_dbName(pBlock *pb)
1428 return pb->cmemmap->dbName;
1433 void pBlockConvert2ISR(pBlock *pb)
1444 /*-----------------------------------------------------------------*/
1445 /* movepBlock2Head - given the dbname of a pBlock, move all */
1446 /* instances to the front of the doubly linked */
1447 /* list of pBlocks */
1448 /*-----------------------------------------------------------------*/
1450 void movepBlock2Head(char dbName)
1457 pb = the_pFile->pbHead;
1461 if(getpBlock_dbName(pb) == dbName) {
1462 pBlock *pbn = pb->next;
1463 pb->next = the_pFile->pbHead;
1464 the_pFile->pbHead->prev = pb;
1465 the_pFile->pbHead = pb;
1468 pb->prev->next = pbn;
1470 // If the pBlock that we just moved was the last
1471 // one in the link of all of the pBlocks, then we
1472 // need to point the tail to the block just before
1473 // the one we moved.
1474 // Note: if pb->next is NULL, then pb must have
1475 // been the last pBlock in the chain.
1478 pbn->prev = pb->prev;
1480 the_pFile->pbTail = pb->prev;
1491 void copypCode(FILE *of, char dbName)
1495 if(!of || !the_pFile)
1498 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1499 if(getpBlock_dbName(pb) == dbName) {
1508 void resetpCodeStatistics (void)
1510 pcode_insns = pcode_doubles = 0;
1513 void dumppCodeStatistics (FILE *of)
1515 /* dump statistics */
1517 fprintf (of, ";\tcode size estimation:\n");
1518 fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1522 void pcode_test(void)
1525 DFPRINTF((stderr,"pcode is alive!\n"));
1535 /* create the file name */
1536 strcpy(buffer,dstFileName);
1537 strcat(buffer,".p");
1539 if( !(pFile = fopen(buffer, "w" ))) {
1540 werror(E_FILE_OPEN_ERR,buffer);
1544 fprintf(pFile,"pcode dump\n\n");
1546 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1547 fprintf(pFile,"\n\tNew pBlock\n\n");
1549 fprintf(pFile,"%s",pb->cmemmap->sname);
1551 fprintf(pFile,"internal pblock");
1553 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1554 printpBlock(pFile,pb);
1559 /*-----------------------------------------------------------------*/
1560 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
1561 /* ister, RegCond will return the bit being referenced. */
1563 /* fixme - why not just OR in the pcop bit field */
1564 /*-----------------------------------------------------------------*/
1566 static int RegCond(pCodeOp *pcop)
1572 if (pcop->type == PO_GPR_BIT) {
1573 char *name = pcop->name;
1575 name = PCOR(pcop)->r->name;
1576 if (strcmp(name, pc_status.pcop.name) == 0)
1578 switch(PCORB(pcop)->bit) {
1592 /*-----------------------------------------------------------------*/
1593 /* newpCode - create and return a newly initialized pCode */
1595 /* fixme - rename this */
1597 /* The purpose of this routine is to create a new Instruction */
1598 /* pCode. This is called by gen.c while the assembly code is being */
1602 /* PIC_OPCODE op - the assembly instruction we wish to create. */
1603 /* (note that the op is analogous to but not the */
1604 /* same thing as the opcode of the instruction.) */
1605 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
1608 /* a pointer to the new malloc'd pCode is returned. */
1612 /*-----------------------------------------------------------------*/
1613 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1615 pCodeInstruction *pci ;
1617 if(!mnemonics_initialized)
1618 pic14initMnemonics();
1620 pci = Safe_calloc(1, sizeof(pCodeInstruction));
1622 if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1623 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1624 pci->pc.id = PCodeID();
1627 if(pci->inCond & PCC_EXAMINE_PCOP)
1628 pci->inCond |= RegCond(pcop);
1630 if(pci->outCond & PCC_EXAMINE_PCOP)
1631 pci->outCond |= RegCond(pcop);
1633 pci->pc.prev = pci->pc.next = NULL;
1634 return (pCode *)pci;
1637 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1643 /*-----------------------------------------------------------------*/
1644 /* newpCodeWild - create a "wild" as in wild card pCode */
1646 /* Wild pcodes are used during the peep hole optimizer to serve */
1647 /* as place holders for any instruction. When a snippet of code is */
1648 /* compared to a peep hole rule, the wild card opcode will match */
1649 /* any instruction. However, the optional operand and label are */
1650 /* additional qualifiers that must also be matched before the */
1651 /* line (of assembly code) is declared matched. Note that the */
1652 /* operand may be wild too. */
1654 /* Note, a wild instruction is specified just like a wild var: */
1655 /* %4 ; A wild instruction, */
1656 /* See the peeph.def file for additional examples */
1658 /*-----------------------------------------------------------------*/
1660 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1665 pcw = Safe_calloc(1,sizeof(pCodeWild));
1667 pcw->pci.pc.type = PC_WILD;
1668 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1669 pcw->id = PCodeID();
1670 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1671 pcw->pci.pc.pb = NULL;
1673 pcw->pci.pc.destruct = genericDestruct;
1674 pcw->pci.pc.print = genericPrint;
1676 pcw->id = pCodeID; // this is the 'n' in %n
1677 pcw->operand = optional_operand;
1678 pcw->label = optional_label;
1680 pcw->mustBeBitSkipInst = 0;
1681 pcw->mustNotBeBitSkipInst = 0;
1682 pcw->invertBitSkipInst = 0;
1684 return ( (pCode *)pcw);
1688 /*-----------------------------------------------------------------*/
1689 /* newPcodeCharP - create a new pCode from a char string */
1690 /*-----------------------------------------------------------------*/
1692 pCode *newpCodeCharP(char *cP)
1697 pcc = Safe_calloc(1,sizeof(pCodeComment));
1699 pcc->pc.type = PC_COMMENT;
1700 pcc->pc.prev = pcc->pc.next = NULL;
1701 pcc->pc.id = PCodeID();
1702 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1705 pcc->pc.destruct = genericDestruct;
1706 pcc->pc.print = genericPrint;
1709 pcc->comment = Safe_strdup(cP);
1711 pcc->comment = NULL;
1713 return ( (pCode *)pcc);
1717 /*-----------------------------------------------------------------*/
1718 /* newpCodeFunction - */
1719 /*-----------------------------------------------------------------*/
1722 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1726 pcf = Safe_calloc(1,sizeof(pCodeFunction));
1727 //_ALLOC(pcf,sizeof(pCodeFunction));
1729 pcf->pc.type = PC_FUNCTION;
1730 pcf->pc.prev = pcf->pc.next = NULL;
1731 pcf->pc.id = PCodeID();
1732 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1735 pcf->pc.destruct = genericDestruct;
1736 pcf->pc.print = pCodePrintFunction;
1741 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1742 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1743 strcpy(pcf->modname,mod);
1745 pcf->modname = NULL;
1748 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1749 pcf->fname = Safe_calloc(1,strlen(f)+1);
1750 strcpy(pcf->fname,f);
1754 pcf->isPublic = (unsigned)isPublic;
1756 return ( (pCode *)pcf);
1760 /*-----------------------------------------------------------------*/
1762 /*-----------------------------------------------------------------*/
1763 static void destructpCodeFlow(pCode *pc)
1765 if(!pc || !isPCFL(pc))
1774 deleteSet(&PCFL(pc)->registers);
1775 deleteSet(&PCFL(pc)->from);
1776 deleteSet(&PCFL(pc)->to);
1781 static pCode *newpCodeFlow(void )
1785 //_ALLOC(pcflow,sizeof(pCodeFlow));
1786 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1788 pcflow->pc.type = PC_FLOW;
1789 pcflow->pc.prev = pcflow->pc.next = NULL;
1790 pcflow->pc.pb = NULL;
1792 pcflow->pc.destruct = destructpCodeFlow;
1793 pcflow->pc.print = genericPrint;
1795 pcflow->pc.seq = GpcFlowSeq++;
1797 pcflow->from = pcflow->to = NULL;
1799 pcflow->inCond = PCC_NONE;
1800 pcflow->outCond = PCC_NONE;
1802 pcflow->firstBank = 'U'; /* Undetermined */
1803 pcflow->lastBank = 'U'; /* Undetermined */
1805 pcflow->FromConflicts = 0;
1806 pcflow->ToConflicts = 0;
1810 pcflow->registers = newSet();
1812 return ( (pCode *)pcflow);
1816 /*-----------------------------------------------------------------*/
1817 /*-----------------------------------------------------------------*/
1818 static pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1820 pCodeFlowLink *pcflowLink;
1822 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1824 pcflowLink->pcflow = pcflow;
1825 pcflowLink->bank_conflict = 0;
1830 /*-----------------------------------------------------------------*/
1831 /* newpCodeCSource - create a new pCode Source Symbol */
1832 /*-----------------------------------------------------------------*/
1834 pCode *newpCodeCSource(int ln, char *f, const char *l)
1839 pccs = Safe_calloc(1,sizeof(pCodeCSource));
1841 pccs->pc.type = PC_CSOURCE;
1842 pccs->pc.prev = pccs->pc.next = NULL;
1843 pccs->pc.id = PCodeID();
1846 pccs->pc.destruct = genericDestruct;
1847 pccs->pc.print = genericPrint;
1849 pccs->line_number = ln;
1851 pccs->line = Safe_strdup(l);
1856 pccs->file_name = Safe_strdup(f);
1858 pccs->file_name = NULL;
1860 return ( (pCode *)pccs);
1864 /*******************************************************************/
1865 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
1866 /* added by VR 6-Jun-2003 */
1867 /*******************************************************************/
1869 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
1876 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
1877 pcad->pci.pc.type = PC_ASMDIR;
1878 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
1879 pcad->pci.pc.pb = NULL;
1880 pcad->pci.pc.destruct = genericDestruct;
1881 pcad->pci.pc.print = genericPrint;
1883 if(asdir && *asdir) {
1885 while(isspace((unsigned char)*asdir))asdir++; // strip any white space from the beginning
1887 pcad->directive = Safe_strdup( asdir );
1890 va_start(ap, argfmt);
1892 memset(buffer, 0, sizeof(buffer));
1893 if(argfmt && *argfmt)
1894 vsprintf(buffer, argfmt, ap);
1898 while(isspace((unsigned char)*lbp))lbp++;
1901 pcad->arg = Safe_strdup( lbp );
1903 return ((pCode *)pcad);
1906 /*-----------------------------------------------------------------*/
1907 /* pCodeLabelDestruct - free memory used by a label. */
1908 /*-----------------------------------------------------------------*/
1909 static void pCodeLabelDestruct(pCode *pc)
1915 if((pc->type == PC_LABEL) && PCL(pc)->label)
1916 free(PCL(pc)->label);
1922 pCode *newpCodeLabel(char *name, int key)
1928 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1930 pcl->pc.type = PC_LABEL;
1931 pcl->pc.prev = pcl->pc.next = NULL;
1932 pcl->pc.id = PCodeID();
1933 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1936 pcl->pc.destruct = pCodeLabelDestruct;
1937 pcl->pc.print = pCodePrintLabel;
1943 sprintf(s,"_%05d_DS_",key);
1948 pcl->label = Safe_strdup(s);
1950 //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
1951 return ( (pCode *)pcl);
1956 /*-----------------------------------------------------------------*/
1957 /* newpBlock - create and return a pointer to a new pBlock */
1958 /*-----------------------------------------------------------------*/
1959 static pBlock *newpBlock(void)
1964 PpB = Safe_calloc(1,sizeof(pBlock) );
1965 PpB->next = PpB->prev = NULL;
1967 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1968 PpB->tregisters = NULL;
1970 PpB->FlowTree = NULL;
1976 /*-----------------------------------------------------------------*/
1977 /* newpCodeChain - create a new chain of pCodes */
1978 /*-----------------------------------------------------------------*
1980 * This function will create a new pBlock and the pointer to the
1981 * pCode that is passed in will be the first pCode in the block.
1982 *-----------------------------------------------------------------*/
1985 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1988 pBlock *pB = newpBlock();
1990 pB->pcHead = pB->pcTail = pc;
1997 /*-----------------------------------------------------------------*/
1998 /* newpCodeOpLabel - Create a new label given the key */
1999 /* Note, a negative key means that the label is part of wild card */
2000 /* (and hence a wild card label) used in the pCodePeep */
2001 /* optimizations). */
2002 /*-----------------------------------------------------------------*/
2004 pCodeOp *newpCodeOpLabel(char *name, int key)
2007 static int label_key=-1;
2011 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2012 pcop->type = PO_LABEL;
2017 sprintf(s=buffer,"_%05d_DS_",key);
2019 s = name, key = label_key--;
2021 PCOLAB(pcop)->offset = 0;
2023 pcop->name = Safe_strdup(s);
2025 ((pCodeOpLabel *)pcop)->key = key;
2027 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2031 /*-----------------------------------------------------------------*/
2032 /*-----------------------------------------------------------------*/
2033 pCodeOp *newpCodeOpLit(int lit)
2039 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2040 pcop->type = PO_LITERAL;
2044 sprintf(s,"0x%02x", (unsigned char)lit);
2046 pcop->name = Safe_strdup(s);
2049 ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2054 /*-----------------------------------------------------------------*/
2055 /*-----------------------------------------------------------------*/
2056 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2060 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2061 pcop->type = PO_IMMEDIATE;
2064 pcop->name = Safe_strdup(name);
2067 r = dirregWithName(name);
2071 //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2072 PCOI(pcop)->rIdx = r->rIdx;
2074 //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2075 PCOI(pcop)->rIdx = -1;
2077 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2082 PCOI(pcop)->index = index;
2083 PCOI(pcop)->offset = offset;
2084 PCOI(pcop)->_const = code_space;
2085 PCOI(pcop)->_function = is_func;
2090 /*-----------------------------------------------------------------*/
2091 /*-----------------------------------------------------------------*/
2092 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2098 if(!pcwb || !subtype) {
2099 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2103 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2104 pcop->type = PO_WILD;
2105 sprintf(s,"%%%d",id);
2106 pcop->name = Safe_strdup(s);
2108 PCOW(pcop)->id = id;
2109 PCOW(pcop)->pcwb = pcwb;
2110 PCOW(pcop)->subtype = subtype;
2111 PCOW(pcop)->matched = NULL;
2115 /*-----------------------------------------------------------------*/
2116 /* Find a symbol with matching name */
2117 /*-----------------------------------------------------------------*/
2118 static symbol *symFindWithName(memmap * map, const char *name)
2122 for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2123 if (sym->rname && (strcmp(sym->rname,name)==0))
2129 /*-----------------------------------------------------------------*/
2130 /*-----------------------------------------------------------------*/
2131 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2136 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2137 pcop->type = PO_GPR_BIT;
2139 PCORB(pcop)->bit = ibit;
2140 PCORB(pcop)->inBitSpace = inBitSpace;
2142 if (name) r = regFindWithName(name);
2144 // Register has not been allocated - check for symbol information
2146 sym = symFindWithName(bit, name);
2147 if (!sym) sym = symFindWithName(sfrbit, name);
2148 if (!sym) sym = symFindWithName(sfr, name);
2149 if (!sym) sym = symFindWithName(reg, name);
2150 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2151 // XXX: This ignores nesting levels, but works for globals...
2152 if (!sym) sym = findSym(SymbolTab, NULL, name);
2153 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2155 r = allocNewDirReg(sym->etype,name);
2161 PCOR(pcop)->rIdx = r->rIdx;
2163 pcop->name = Safe_strdup(name);
2164 PCOR(pcop)->r = NULL;
2165 PCOR(pcop)->rIdx = 0;
2170 /*-----------------------------------------------------------------*
2171 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2173 * If rIdx >=0 then a specific register from the set of registers
2174 * will be selected. If rIdx <0, then a new register will be searched
2176 *-----------------------------------------------------------------*/
2178 static pCodeOp *newpCodeOpReg(int rIdx)
2182 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2187 PCOR(pcop)->rIdx = rIdx;
2188 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2190 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2193 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2197 pcop->type = PCOR(pcop)->r->pc_type;
2202 pCodeOp *newpCodeOpRegFromStr(char *name)
2206 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2207 PCOR(pcop)->r = allocRegByName(name, 1);
2208 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2209 pcop->type = PCOR(pcop)->r->pc_type;
2210 pcop->name = PCOR(pcop)->r->name;
2215 static pCodeOp *newpCodeOpStr(char *name)
2219 pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2220 pcop->type = PO_STR;
2221 pcop->name = Safe_strdup(name);
2223 PCOS(pcop)->isPublic = 0;
2229 /*-----------------------------------------------------------------*/
2230 /*-----------------------------------------------------------------*/
2232 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2239 pcop = newpCodeOpBit(name, -1,0);
2243 pcop = newpCodeOpLit(-1);
2247 pcop = newpCodeOpLabel(NULL,-1);
2251 pcop = newpCodeOpReg(-1);
2254 case PO_GPR_POINTER:
2255 case PO_GPR_REGISTER:
2257 pcop = newpCodeOpRegFromStr(name);
2259 pcop = newpCodeOpReg(-1);
2263 pcop = newpCodeOpStr(name);
2267 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2270 pcop->name = Safe_strdup(name);
2278 /*-----------------------------------------------------------------*/
2279 /* addpCode2pBlock - place the pCode into the pBlock linked list */
2280 /*-----------------------------------------------------------------*/
2281 void addpCode2pBlock(pBlock *pb, pCode *pc)
2288 /* If this is the first pcode to be added to a block that
2289 * was initialized with a NULL pcode, then go ahead and
2290 * make this pcode the head and tail */
2291 pb->pcHead = pb->pcTail = pc;
2294 pb->pcTail->next = pc;
2296 pc->prev = pb->pcTail;
2303 /*-----------------------------------------------------------------*/
2304 /* addpBlock - place a pBlock into the pFile */
2305 /*-----------------------------------------------------------------*/
2306 void addpBlock(pBlock *pb)
2308 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2311 /* First time called, we'll pass through here. */
2312 //_ALLOC(the_pFile,sizeof(pFile));
2313 the_pFile = Safe_calloc(1,sizeof(pFile));
2314 the_pFile->pbHead = the_pFile->pbTail = pb;
2315 the_pFile->functions = NULL;
2319 the_pFile->pbTail->next = pb;
2320 pb->prev = the_pFile->pbTail;
2322 the_pFile->pbTail = pb;
2325 /*-----------------------------------------------------------------*/
2326 /* removepBlock - remove a pBlock from the pFile */
2327 /*-----------------------------------------------------------------*/
2328 static void removepBlock(pBlock *pb)
2336 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2338 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2341 if(pbs == the_pFile->pbHead)
2342 the_pFile->pbHead = pbs->next;
2344 if (pbs == the_pFile->pbTail)
2345 the_pFile->pbTail = pbs->prev;
2348 pbs->next->prev = pbs->prev;
2351 pbs->prev->next = pbs->next;
2358 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2362 /*-----------------------------------------------------------------*/
2363 /* printpCode - write the contents of a pCode to a file */
2364 /*-----------------------------------------------------------------*/
2365 void printpCode(FILE *of, pCode *pc)
2376 fprintf(of,"warning - unable to print pCode\n");
2379 /*-----------------------------------------------------------------*/
2380 /* printpBlock - write the contents of a pBlock to a file */
2381 /*-----------------------------------------------------------------*/
2382 void printpBlock(FILE *of, pBlock *pb)
2392 for(pc = pb->pcHead; pc; pc = pc->next) {
2397 if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2407 /*-----------------------------------------------------------------*/
2409 /* pCode processing */
2413 /*-----------------------------------------------------------------*/
2415 void unlinkpCode(pCode *pc)
2421 fprintf(stderr,"Unlinking: ");
2422 printpCode(stderr, pc);
2425 pc->prev->next = pc->next;
2427 pc->next->prev = pc->prev;
2430 /* RN: I believe this should be right here, but this did not
2431 * cure the bug I was hunting... */
2432 /* must keep labels -- attach to following instruction */
2433 if (isPCI(pc) && PCI(pc)->label && pc->next)
2435 pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2438 pBranchAppend (pcnext->label, PCI(pc)->label);
2442 pc->prev = pc->next = NULL;
2446 /*-----------------------------------------------------------------*/
2447 /*-----------------------------------------------------------------*/
2449 static void genericDestruct(pCode *pc)
2455 /* For instructions, tell the register (if there's one used)
2456 * that it's no longer needed */
2457 regs *reg = getRegFromInstruction(pc);
2459 deleteSetItem (&(reg->reglives.usedpCodes),pc);
2462 /* Instead of deleting the memory used by this pCode, mark
2463 * the object as bad so that if there's a pointer to this pCode
2464 * dangling around somewhere then (hopefully) when the type is
2465 * checked we'll catch it.
2470 addpCode2pBlock(pb_dead_pcodes, pc);
2477 /*-----------------------------------------------------------------*/
2478 /* Copies the pCodeInstruction flow pointer from source pCode */
2479 /*-----------------------------------------------------------------*/
2480 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2482 pCodeFlow *pcflow = 0;
2483 for (p=pcs; p; p=p->prev) {
2485 pcflow = PCI(p)->pcflow;
2489 pcflow = (pCodeFlow*)p;
2493 PCI(pcd)->pcflow = pcflow;
2496 /*-----------------------------------------------------------------*/
2497 /* pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2498 /* into the pCode chain containing pc1 */
2499 /*-----------------------------------------------------------------*/
2500 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2506 pc2->next = pc1->next;
2508 pc1->next->prev = pc2;
2514 /* If this is an instrution type propogate the flow */
2516 CopyFlow(PCI(pc2),pc1);
2519 /*------------------------------------------------------------------*/
2520 /* pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2521 /* into the pCode chain containing pc1 */
2522 /*------------------------------------------------------------------*/
2523 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2529 pc2->prev = pc1->prev;
2531 pc1->prev->next = pc2;
2537 /* If this is an instrution type propogate the flow */
2539 CopyFlow(PCI(pc2),pc1);
2542 /*-----------------------------------------------------------------*/
2543 /* pCodeOpCopy - copy a pcode operator */
2544 /*-----------------------------------------------------------------*/
2545 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2547 pCodeOp *pcopnew=NULL;
2552 switch(pcop->type) {
2555 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2556 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2564 case PO_GPR_REGISTER:
2566 case PO_GPR_POINTER:
2567 case PO_SFR_REGISTER:
2571 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2572 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2573 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2574 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2578 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2579 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2580 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2584 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2585 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2591 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2592 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2593 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2597 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2598 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2599 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2603 /* Here we expand the wild card into the appropriate type: */
2604 /* By recursively calling pCodeOpCopy */
2605 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2606 if(PCOW(pcop)->matched)
2607 pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2610 pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2611 pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2612 //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2619 assert ( !"unhandled pCodeOp type copied" );
2624 pcopnew->name = Safe_strdup(pcop->name);
2626 pcopnew->name = NULL;
2631 /*-----------------------------------------------------------------*/
2632 /* popCopyReg - copy a pcode operator */
2633 /*-----------------------------------------------------------------*/
2634 pCodeOp *popCopyReg(pCodeOpReg *pc)
2638 pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2639 pcor->pcop.type = pc->pcop.type;
2641 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2642 fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2644 pcor->pcop.name = NULL;
2646 if (pcor->pcop.type == PO_IMMEDIATE){
2647 PCOL(pcor)->lit = PCOL(pc)->lit;
2650 pcor->rIdx = pc->rIdx;
2654 //DEBUGpic14_emitcode ("; ***","%s , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2659 /*-----------------------------------------------------------------*/
2660 /* pCodeInstructionCopy - copy a pCodeInstructionCopy */
2661 /*-----------------------------------------------------------------*/
2662 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2664 pCodeInstruction *new_pci;
2667 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2669 new_pci = PCI(newpCode(pci->op,pci->pcop));
2671 new_pci->pc.pb = pci->pc.pb;
2672 new_pci->from = pci->from;
2673 new_pci->to = pci->to;
2674 new_pci->label = pci->label;
2675 new_pci->pcflow = pci->pcflow;
2677 return PCODE(new_pci);
2680 /*-----------------------------------------------------------------*/
2681 /*-----------------------------------------------------------------*/
2682 void pCodeDeleteChain(pCode *f,pCode *t)
2687 DFPRINTF((stderr,"delete pCode:\n"));
2689 //f->print(stderr,f);
2690 //f->delete(f); this dumps core...
2695 /*-----------------------------------------------------------------*/
2696 /*-----------------------------------------------------------------*/
2697 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2702 int use_buffer = 1; // copy the string to the passed buffer pointer
2707 use_buffer = 0; // Don't bother copying the string to the buffer.
2711 switch(pcop->type) {
2715 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
2721 if (PCOR(pcop)->r->type == REG_STK)
2722 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2724 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2727 SNPRINTF(buffer,size,"%s",r->name);
2736 if(PCOI(pcop)->_const) {
2738 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
2739 switch(PCOI(pcop)->offset) {
2741 SNPRINTF(s,size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
2744 SNPRINTF(s,size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
2747 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
2750 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
2751 assert ( !"offset too large" );
2752 SNPRINTF(s,size,"(((%s+%d) >> %d)&0xff)",
2755 8 * PCOI(pcop)->offset );
2758 SNPRINTF(s,size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
2760 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
2761 SNPRINTF(s,size,"(%s + %d)",
2765 switch(PCOI(pcop)->offset) {
2767 SNPRINTF(s,size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
2770 SNPRINTF(s,size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
2773 SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
2776 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
2777 assert ( !"offset too large" );
2778 SNPRINTF(s,size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
2788 if( PCOR(pcop)->instance) {
2789 SNPRINTF(s,size,"(%s + %d)",
2791 PCOR(pcop)->instance );
2793 SNPRINTF(s,size,"%s",pcop->name);
2800 if(PCOLAB(pcop)->offset == 1)
2801 SNPRINTF(s,size,"HIGH(%s)",pcop->name);
2803 SNPRINTF(s,size,"%s",pcop->name);
2811 SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
2814 return PCOR(pcop)->r->name;
2816 /* fall through to the default case */
2821 SNPRINTF(buffer,size,"%s",pcop->name);
2829 printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
2830 __FILE__, __LINE__, __FUNCTION__,
2833 return "NO operand";
2837 /*-----------------------------------------------------------------*/
2838 /*-----------------------------------------------------------------*/
2839 static char *get_op_from_instruction( pCodeInstruction *pcc)
2843 return get_op(pcc->pcop,NULL,0);
2845 return ("ERROR Null: get_op_from_instruction");
2849 /*-----------------------------------------------------------------*/
2850 /*-----------------------------------------------------------------*/
2851 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2853 fprintf(of,"pcodeopprint- not implemented\n");
2856 /*-----------------------------------------------------------------*/
2857 /* pCode2str - convert a pCode instruction to string */
2858 /*-----------------------------------------------------------------*/
2859 char *pCode2str(char *str, size_t size, pCode *pc)
2867 SNPRINTF(s,size, "\t%s\t", PCI(pc)->mnemonic);
2871 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2872 if(PCI(pc)->isBitInst) {
2873 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2874 char *name = PCI(pc)->pcop->name;
2876 name = PCOR(PCI(pc)->pcop)->r->name;
2877 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2878 SNPRINTF(s,size,"(%s >> 3), (%s & 7)", name, name);
2880 SNPRINTF(s,size,"%s,%d", name, (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
2881 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2882 SNPRINTF(s,size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2884 SNPRINTF(s,size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2886 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2887 if( PCI(pc)->num_ops == 2)
2888 SNPRINTF(s,size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2890 SNPRINTF(s,size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2892 SNPRINTF(s,size,"%s",get_op_from_instruction(PCI(pc)));
2895 if( PCI(pc)->num_ops == 2)
2896 SNPRINTF(s,size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2903 /* assuming that comment ends with a \n */
2904 SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
2908 /* assuming that inline code ends with a \n */
2909 SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
2913 SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2916 SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2919 SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2922 SNPRINTF(s,size,";\t--FLOW change\n");
2925 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);
2928 if(PCAD(pc)->directive) {
2929 SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
2930 } else if(PCAD(pc)->arg) {
2931 /* special case to handle inline labels without a tab */
2932 SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
2937 SNPRINTF(s,size,";A bad pCode is being used\n");
2943 /*-----------------------------------------------------------------*/
2944 /* genericPrint - the contents of a pCode to a file */
2945 /*-----------------------------------------------------------------*/
2946 static void genericPrint(FILE *of, pCode *pc)
2953 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2957 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2961 // If the opcode has a label, print that first
2964 pCodeInstruction *pci = PCI(pc);
2965 pBranch *pbl = pci->label;
2966 while(pbl && pbl->pc) {
2967 if(pbl->pc->type == PC_LABEL)
2968 pCodePrintLabel(of, pbl->pc);
2973 genericPrint(of,PCODE(pci->cline));
2976 pCode2str(str, 256, pc);
2978 fprintf(of,"%s",str);
2982 pCodeOpReg *pcor = PCOR(pci->pcop);
2983 fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
2985 fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
2986 if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
2987 fprintf(of,",rIdx=r0x%X",pcor->rIdx);
2994 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2995 if(PCW(pc)->pci.label)
2996 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2998 if(PCW(pc)->operand) {
2999 fprintf(of,";\toperand ");
3000 pCodeOpPrint(of,PCW(pc)->operand );
3006 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3007 if(PCFL(pc)->ancestor)
3008 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3010 fprintf(of,"; from: ");
3012 pCodeFlowLink *link;
3013 for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3015 fprintf(of,"%03x ",link->pcflow->pc.seq);
3018 fprintf(of,"; to: ");
3020 pCodeFlowLink *link;
3021 for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3023 fprintf(of,"%03x ",link->pcflow->pc.seq);
3031 fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3036 pBranch *pbl = PCAD(pc)->pci.label;
3037 while(pbl && pbl->pc) {
3038 if(pbl->pc->type == PC_LABEL)
3039 pCodePrintLabel(of, pbl->pc);
3043 if(PCAD(pc)->directive) {
3044 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3047 /* special case to handle inline labels without tab */
3048 fprintf(of, "%s\n", PCAD(pc)->arg);
3054 fprintf(of,"unknown pCode type %d\n",pc->type);
3058 /*-----------------------------------------------------------------*/
3059 /* pCodePrintFunction - prints function begin/end */
3060 /*-----------------------------------------------------------------*/
3062 static void pCodePrintFunction(FILE *of, pCode *pc)
3068 if( ((pCodeFunction *)pc)->modname)
3069 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3071 if(PCF(pc)->fname) {
3072 pBranch *exits = PCF(pc)->to;
3074 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3077 exits = exits->next;
3080 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3083 if((PCF(pc)->from &&
3084 PCF(pc)->from->pc->type == PC_FUNCTION &&
3085 PCF(PCF(pc)->from->pc)->fname) )
3086 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3088 fprintf(of,"; exit point [can't find entry point]\n");
3092 /*-----------------------------------------------------------------*/
3093 /* pCodePrintLabel - prints label */
3094 /*-----------------------------------------------------------------*/
3096 static void pCodePrintLabel(FILE *of, pCode *pc)
3103 fprintf(of,"%s\n",PCL(pc)->label);
3104 else if (PCL(pc)->key >=0)
3105 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3107 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3111 /*-----------------------------------------------------------------*/
3112 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
3113 /* remove it if it is found. */
3114 /*-----------------------------------------------------------------*/
3115 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3121 if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3122 b = PCI(pcl)->label;
3124 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3128 //fprintf (stderr, "%s \n",__FUNCTION__);
3129 //pcl->print(stderr,pcl);
3130 //pc->print(stderr,pc);
3133 //fprintf (stderr, "found label\n");
3137 bprev->next = b->next; /* Not first pCode in chain */
3141 PCI(pcl)->label = b->next; /* First pCode in chain */
3144 return; /* A label can't occur more than once */
3151 /*-----------------------------------------------------------------*/
3152 /*-----------------------------------------------------------------*/
3153 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3173 /*-----------------------------------------------------------------*/
3174 /* pBranchLink - given two pcodes, this function will link them */
3175 /* together through their pBranches */
3176 /*-----------------------------------------------------------------*/
3177 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3181 // Declare a new branch object for the 'from' pCode.
3183 //_ALLOC(b,sizeof(pBranch));
3184 b = Safe_calloc(1,sizeof(pBranch));
3185 b->pc = PCODE(t); // The link to the 'to' pCode.
3188 f->to = pBranchAppend(f->to,b);
3190 // Now do the same for the 'to' pCode.
3192 //_ALLOC(b,sizeof(pBranch));
3193 b = Safe_calloc(1,sizeof(pBranch));
3197 t->from = pBranchAppend(t->from,b);
3201 /*-----------------------------------------------------------------*/
3202 /*-----------------------------------------------------------------*/
3203 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3207 if(pc->type == PC_LABEL) {
3208 if( ((pCodeLabel *)pc)->key == pcop_label->key)
3211 if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3212 pbr = PCI(pc)->label;
3214 if(pbr->pc->type == PC_LABEL) {
3215 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
3225 /*-----------------------------------------------------------------*/
3226 /*-----------------------------------------------------------------*/
3227 static int checkLabel(pCode *pc)
3231 if(pc && isPCI(pc)) {
3232 pbr = PCI(pc)->label;
3234 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3244 /*-----------------------------------------------------------------*/
3245 /* findLabelinpBlock - Search the pCode for a particular label */
3246 /*-----------------------------------------------------------------*/
3247 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3254 for(pc = pb->pcHead; pc; pc = pc->next)
3255 if(compareLabel(pc,pcop_label))
3261 /*-----------------------------------------------------------------*/
3262 /* findNextpCode - given a pCode, find the next of type 'pct' */
3263 /* in the linked list */
3264 /*-----------------------------------------------------------------*/
3265 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3279 /*-----------------------------------------------------------------*/
3280 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
3281 /* in the linked list */
3282 /*-----------------------------------------------------------------*/
3283 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3287 if(pc->type == pct) {
3289 static unsigned int stop;
3291 stop++; // Place break point here
3303 /*-----------------------------------------------------------------*/
3304 /* findNextInstruction - given a pCode, find the next instruction */
3305 /* in the linked list */
3306 /*-----------------------------------------------------------------*/
3307 pCode * findNextInstruction(pCode *pci)
3312 if((pc->type == PC_OPCODE)
3313 || (pc->type == PC_WILD)
3314 || (pc->type == PC_ASMDIR))
3318 fprintf(stderr,"findNextInstruction: ");
3319 printpCode(stderr, pc);
3324 //fprintf(stderr,"Couldn't find instruction\n");
3328 /*-----------------------------------------------------------------*/
3329 /* findNextInstruction - given a pCode, find the next instruction */
3330 /* in the linked list */
3331 /*-----------------------------------------------------------------*/
3332 pCode * findPrevInstruction(pCode *pci)
3338 if((pc->type == PC_OPCODE)
3339 || (pc->type == PC_WILD)
3340 || (pc->type == PC_ASMDIR))
3345 fprintf(stderr,"pic16_findPrevInstruction: ");
3346 printpCode(stderr, pc);
3351 //fprintf(stderr,"Couldn't find instruction\n");
3355 /*-----------------------------------------------------------------*/
3356 /*-----------------------------------------------------------------*/
3357 regs * getRegFromInstruction(pCode *pc)
3363 PCI(pc)->num_ops == 0 )
3366 switch(PCI(pc)->pcop->type) {
3373 case PO_SFR_REGISTER:
3376 return PCOR(PCI(pc)->pcop)->r;
3378 case PO_GPR_REGISTER:
3381 r = PCOR(PCI(pc)->pcop)->r;
3384 return dirregWithName(PCI(pc)->pcop->name);
3390 r = PCOI(PCI(pc)->pcop)->r;
3393 return dirregWithName(PCI(pc)->pcop->name);
3403 /*-----------------------------------------------------------------*/
3404 /*-----------------------------------------------------------------*/
3406 static void AnalyzepBlock(pBlock *pb)
3413 /* Find all of the registers used in this pBlock
3414 * by looking at each instruction and examining it's
3417 for(pc = pb->pcHead; pc; pc = pc->next) {
3419 /* Is this an instruction with operands? */
3420 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3422 if((PCI(pc)->pcop->type == PO_GPR_TEMP)
3423 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3425 /* Loop through all of the registers declared so far in
3426 this block and see if we find this one there */
3428 regs *r = setFirstItem(pb->tregisters);
3431 if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3432 PCOR(PCI(pc)->pcop)->r = r;
3435 r = setNextItem(pb->tregisters);
3439 /* register wasn't found */
3440 //r = Safe_calloc(1, sizeof(regs));
3441 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3442 //addSet(&pb->tregisters, r);
3443 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3444 //PCOR(PCI(pc)->pcop)->r = r;
3445 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3447 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3450 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3451 if(PCOR(PCI(pc)->pcop)->r) {
3452 pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3453 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3455 if(PCI(pc)->pcop->name)
3456 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3458 fprintf(stderr,"ERROR: NULL register\n");
3467 /*-----------------------------------------------------------------*/
3469 /*-----------------------------------------------------------------*/
3470 static void InsertpFlow(pCode *pc, pCode **pflow)
3473 PCFL(*pflow)->end = pc;
3475 if(!pc || !pc->next)
3478 *pflow = newpCodeFlow();
3479 pCodeInsertAfter(pc, *pflow);
3482 /*-----------------------------------------------------------------*/
3483 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3484 /* the flow blocks. */
3486 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3487 * point the instruction flow changes.
3489 /*-----------------------------------------------------------------*/
3490 static void BuildFlow(pBlock *pb)
3493 pCode *last_pci=NULL;
3500 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
3501 /* Insert a pCodeFlow object at the beginning of a pBlock */
3503 InsertpFlow(pb->pcHead, &pflow);
3505 //pflow = newpCodeFlow(); /* Create a new Flow object */
3506 //pflow->next = pb->pcHead; /* Make the current head the next object */
3507 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
3508 //pb->pcHead = pflow; /* Make the Flow object the head */
3511 for( pc = findNextInstruction(pb->pcHead);
3513 pc=findNextInstruction(pc)) {
3516 PCI(pc)->pcflow = PCFL(pflow);
3518 //fprintf(stderr," build: ");
3519 //pc->print(stderr, pc);
3520 //pflow->print(stderr,pflow);
3522 if (checkLabel(pc)) {
3524 /* This instruction marks the beginning of a
3525 * new flow segment */
3530 /* If the previous pCode is not a flow object, then
3531 * insert a new flow object. (This check prevents
3532 * two consecutive flow objects from being insert in
3533 * the case where a skip instruction preceeds an
3534 * instruction containing a label.) */
3536 last_pci = findPrevInstruction (pc->prev);
3538 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3539 InsertpFlow(last_pci, &pflow);
3541 PCI(pc)->pcflow = PCFL(pflow);
3545 if(isPCI_SKIP(pc)) {
3547 /* The two instructions immediately following this one
3548 * mark the beginning of a new flow segment */
3550 while(pc && isPCI_SKIP(pc)) {
3552 PCI(pc)->pcflow = PCFL(pflow);
3556 InsertpFlow(pc, &pflow);
3557 pc=findNextInstruction(pc->next);
3565 PCI(pc)->pcflow = PCFL(pflow);
3567 InsertpFlow(pc, &pflow);
3569 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next))) {
3571 InsertpFlow(pc, &pflow);
3580 //fprintf (stderr,",end seq %d",GpcFlowSeq);
3582 PCFL(pflow)->end = pb->pcTail;
3585 /*-------------------------------------------------------------------*/
3586 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
3587 /* the flow blocks. */
3589 * unBuildFlow removes pCodeFlow objects from a pCode chain
3591 /*-----------------------------------------------------------------*/
3592 static void unBuildFlow(pBlock *pb)
3607 if(PCI(pc)->pcflow) {
3608 //free(PCI(pc)->pcflow);
3609 PCI(pc)->pcflow = NULL;
3612 } else if(isPCFL(pc) )
3622 /*-----------------------------------------------------------------*/
3623 /*-----------------------------------------------------------------*/
3624 static void dumpCond(int cond)
3627 static char *pcc_str[] = {
3641 int ncond = sizeof(pcc_str) / sizeof(char *);
3644 fprintf(stderr, "0x%04X\n",cond);
3646 for(i=0,j=1; i<ncond; i++, j<<=1)
3648 fprintf(stderr, " %s\n",pcc_str[i]);
3654 /*-----------------------------------------------------------------*/
3655 /*-----------------------------------------------------------------*/
3656 static void FlowStats(pCodeFlow *pcflow)
3664 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3666 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3669 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3674 fprintf(stderr, " FlowStats inCond: ");
3675 dumpCond(pcflow->inCond);
3676 fprintf(stderr, " FlowStats outCond: ");
3677 dumpCond(pcflow->outCond);
3682 /*-----------------------------------------------------------------*
3683 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3684 * if it affects the banking bits.
3686 * return: -1 == Banking bits are unaffected by this pCode.
3688 * return: > 0 == Banking bits are affected.
3690 * If the banking bits are affected, then the returned value describes
3691 * which bits are affected and how they're affected. The lower half
3692 * of the integer maps to the bits that are affected, the upper half
3693 * to whether they're set or cleared.
3695 *-----------------------------------------------------------------*/
3697 static int isBankInstruction(pCode *pc)
3705 if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3707 // Check to see if the register banks are changing
3708 if(PCI(pc)->isModReg) {
3710 pCodeOp *pcop = PCI(pc)->pcop;
3711 switch(PCI(pc)->op) {
3714 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3715 //fprintf(stderr, " isBankInstruction - Set RP0\n");
3716 return SET_BANK_BIT | PIC_RP0_BIT;
3719 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3720 //fprintf(stderr, " isBankInstruction - Set RP1\n");
3721 return CLR_BANK_BIT | PIC_RP0_BIT;
3726 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3727 //fprintf(stderr, " isBankInstruction - Clr RP0\n");
3728 return CLR_BANK_BIT | PIC_RP1_BIT;
3730 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3731 //fprintf(stderr, " isBankInstruction - Clr RP1\n");
3732 return CLR_BANK_BIT | PIC_RP1_BIT;
3736 //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n");
3737 //genericPrint(stderr, pc);
3748 /*-----------------------------------------------------------------*/
3749 /*-----------------------------------------------------------------*/
3751 static void FillFlow(pCodeFlow *pcflow)
3759 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3761 pc = findNextpCode(PCODE(pcflow), PC_OPCODE);
3764 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3771 isBankInstruction(pc);
3773 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3776 fprintf(stderr, " FillFlow - Bad end of flow\n");
3778 fprintf(stderr, " FillFlow - Ending flow with\n ");
3779 pc->print(stderr,pc);
3782 fprintf(stderr, " FillFlow inCond: ");
3783 dumpCond(pcflow->inCond);
3784 fprintf(stderr, " FillFlow outCond: ");
3785 dumpCond(pcflow->outCond);
3790 /*-----------------------------------------------------------------*/
3791 /*-----------------------------------------------------------------*/
3792 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3794 pCodeFlowLink *fromLink, *toLink;
3796 fprintf(stderr, "%s: linking ", __FUNCTION__ );
3797 if (from) from->pc.print(stderr, &from->pc);
3798 else fprintf(stderr, "(null)");
3799 fprintf(stderr, " -(%u)-> with -(%u)-> ",
3800 from && from->pcflow ? from->pcflow->pc.seq : 0,
3801 to && to->pcflow ? to->pcflow->pc.seq : 0);
3802 if (to) to->pc.print(stderr, &to->pc);
3803 else fprintf(stderr, "(null)");
3806 if(!from || !to || !to->pcflow || !from->pcflow)
3809 fromLink = newpCodeFlowLink(from->pcflow);
3810 toLink = newpCodeFlowLink(to->pcflow);
3812 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
3813 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3817 /*-----------------------------------------------------------------*
3818 * void LinkFlow(pBlock *pb)
3820 * In BuildFlow, the PIC code has been partitioned into contiguous
3821 * non-branching segments. In LinkFlow, we determine the execution
3822 * order of these segments. For example, if one of the segments ends
3823 * with a skip, then we know that there are two possible flow segments
3824 * to which control may be passed.
3825 *-----------------------------------------------------------------*/
3826 static void LinkFlow(pBlock *pb)
3832 //fprintf(stderr,"linkflow \n");
3836 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3838 pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3841 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3843 //fprintf(stderr," link: ");
3844 //pcflow->print(stderr,pcflow);
3846 //FillFlow(PCFL(pcflow));
3848 /* find last instruction in flow */
3849 pc = findPrevInstruction (PCFL(pcflow)->end);
3851 fprintf(stderr, "%s: flow without end (%u)?\n",
3852 __FUNCTION__, pcflow->seq );
3856 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3857 //pc->print(stderr, pc);
3858 if(isPCI_SKIP(pc)) {
3859 //fprintf(stderr, "ends with skip\n");
3860 //pc->print(stderr,pc);
3861 pct=findNextInstruction(pc->next);
3862 LinkFlow_pCode(PCI(pc),PCI(pct));
3863 pct=findNextInstruction(pct->next);
3864 LinkFlow_pCode(PCI(pc),PCI(pct));
3868 if(isPCI_BRANCH(pc)) {
3869 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3871 //fprintf(stderr, "ends with branch\n ");
3872 //pc->print(stderr,pc);
3874 if(!(pcol && isPCOLAB(pcol))) {
3875 if((PCI(pc)->op != POC_RETLW)
3876 && (PCI(pc)->op != POC_RETURN)
3877 && (PCI(pc)->op != POC_CALL)
3878 && (PCI(pc)->op != POC_RETFIE) )
3880 pc->print(stderr,pc);
3881 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3885 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3886 LinkFlow_pCode(PCI(pc),PCI(pct));
3888 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
3889 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
3890 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3892 /* link CALLs to next instruction */
3893 if (PCI(pc)->op != POC_CALL) continue;
3897 //fprintf(stderr, "ends with non-branching instruction:\n");
3898 //pc->print(stderr,pc);
3900 LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3906 //fprintf(stderr, "ends with unknown\n");
3907 //pc->print(stderr,pc);
3911 fprintf(stderr, "ends with nothing: ERROR\n");
3916 static void pCodeReplace (pCode *old, pCode *new)
3918 pCodeInsertAfter (old, new);
3920 /* special handling for pCodeInstructions */
3921 if (isPCI(new) && isPCI(old))
3923 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
3924 PCI(new)->from = PCI(old)->from;
3925 PCI(new)->to = PCI(old)->to;
3926 PCI(new)->label = PCI(old)->label;
3927 PCI(new)->pcflow = PCI(old)->pcflow;
3928 PCI(new)->cline = PCI(old)->cline;
3931 old->destruct (old);
3934 /*-----------------------------------------------------------------*/
3935 /*-----------------------------------------------------------------*/
3936 static void addpCodeComment(pCode *pc, const char *fmt, ...)
3943 if (options.verbose || debug_verbose) {
3946 vsprintf(&buffer[2], fmt, ap);
3948 newpc = newpCodeCharP(&buffer[0]); // strdup's the string
3949 pCodeInsertAfter(pc, newpc);
3954 /*-----------------------------------------------------------------*/
3955 /* Inserts a new pCodeInstruction before an existing one */
3956 /*-----------------------------------------------------------------*/
3957 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
3961 pcprev = findPrevInstruction(pci->pc.prev);
3963 pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
3965 /* Move the label, if there is one */
3968 new_pci->label = pci->label;
3972 /* Move the C code comment, if there is one */
3975 new_pci->cline = pci->cline;
3979 /* The new instruction has the same pcflow block */
3980 new_pci->pcflow = pci->pcflow;
3982 /* Arrrrg: is pci's previous instruction is a skip, we need to
3983 * change that into a jump (over pci and the new instruction) ... */
3984 if (pcprev && isPCI_SKIP(pcprev))
3986 symbol *lbl = newiTempLabel (NULL);
3987 pCode *label = newpCodeLabel (NULL, lbl->key);
3988 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
3990 pCodeInsertAfter (pcprev, jump);
3992 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
3993 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
3994 switch (PCI(pcprev)->op) {
3999 // These are turned into non-skipping instructions, so
4000 // insert 'BTFSC STATUS, Z' after pcprev
4001 pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4004 // no special actions required
4007 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4009 pCodeInsertAfter((pCode*)pci, label);
4010 pBlockMergeLabels(pci->pc.pb);
4014 /*-----------------------------------------------------------------*/
4015 /*-----------------------------------------------------------------*/
4016 static void insertBankSel(pCodeInstruction *pci, const char *name)
4022 // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4023 if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4025 pcop = popCopyReg(PCOR(pci->pcop));
4026 pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4027 if (pcop->name == 0)
4028 pcop->name = strdup(name);
4029 new_pc = newpCode(POC_BANKSEL, pcop);
4031 insertPCodeInstruction(pci, PCI(new_pc));
4035 * isValidIdChar - check if c may be present in an identifier
4037 static int isValidIdChar (char c)
4039 if (c >= 'a' && c <= 'z') return 1;
4040 if (c >= 'A' && c <= 'Z') return 1;
4041 if (c >= '0' && c <= '9') return 1;
4042 if (c == '_') return 1;
4047 * bankcompare - check if two operand string refer to the same register
4048 * This functions handles NAME and (NAME + x) in both operands.
4049 * Returns 1 on same register, 0 on different (or unknown) registers.
4051 static int bankCompare(const char *op1, const char *op2)
4055 if (!op1 && !op2) return 0; // both unknown, might be different though!
4056 if (!op1 || !op2) return 0;
4058 // find start of operand name
4059 while (op1[0] == '(' || op1[0] == ' ') op1++;
4060 while (op2[0] == '(' || op2[0] == ' ') op2++;
4062 // compare till first non-identifier character
4063 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4064 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4066 // play safe---assume different operands
4071 * Interface to BANKSEL generation.
4072 * This function should return != 0 iff str1 and str2 denote operands that
4073 * are known to be allocated into the same bank. Consequently, there will
4074 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
4075 * select the current bank just previously.
4077 * If in doubt, return 0.
4080 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
4081 // see glue.c(pic14printLocals)
4083 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
4084 // no clustering applied, each register resides in its own bank
4086 // check whether BOTH names are local registers
4087 // XXX: This is some kind of shortcut, should be safe...
4088 // In this model, all r0xXXXX are allocated into a single section
4089 // per file, so no BANKSEL required if accessing a r0xXXXX after a
4090 // (different) r0xXXXX. Works great for multi-byte operands.
4091 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
4094 // assume operands in different banks
4098 /*-----------------------------------------------------------------*/
4099 /*-----------------------------------------------------------------*/
4100 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4102 if (!cur_bank) return 0;
4104 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4105 return 1; // if we have address info, we use it for banksel optimization
4107 // regard '(regname + X)' and '(regname + Y)' as equal
4108 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4109 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4111 // check allocation policy from glue.c
4112 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4113 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4115 // seems to be a different operand--might be a different bank
4116 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4120 /*-----------------------------------------------------------------*/
4121 /*-----------------------------------------------------------------*/
4122 static void FixRegisterBanking(pBlock *pb)
4125 pCodeInstruction *pci;
4127 regs *previous_reg; // contains the previous variable access info
4128 const char *cur_bank, *new_bank;
4129 unsigned cur_mask, new_mask, max_mask;
4134 max_mask = pic14_getPIC()->bankMask;
4135 cur_mask = max_mask;
4137 previous_reg = NULL;
4139 allRAMmshared = pic14_allRAMShared();
4141 for (pc = pb->pcHead; pc; pc = pc->next)
4143 // this one has a label---might check bank at all jumps here...
4144 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4145 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4146 previous_reg = NULL;
4147 cur_bank = NULL; // start new flow
4148 cur_mask = max_mask;
4151 // this one is/might be a label or BANKSEL---assume nothing
4152 if (isPCL(pc) || isPCASMDIR(pc)) {
4153 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4154 previous_reg = NULL;
4156 cur_mask = max_mask;
4159 // this one modifies STATUS
4160 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4164 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4165 // might need a BANKSEL
4166 reg = getRegFromInstruction(pc);
4169 new_bank = reg->name;
4170 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4171 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4172 new_mask = reg->alias;
4173 } else if (pci->pcop && pci->pcop->name) {
4174 new_bank = pci->pcop->name;
4175 new_mask = 0; // unknown, assume worst case
4177 assert(!"Could not get register from instruction.");
4178 new_bank = "UNKNOWN";
4179 new_mask = 0; // unknown, assume worst case
4183 // XXX: add switch to disable these
4185 // reg present in all banks possibly selected?
4186 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4187 // no BANKSEL required
4188 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4192 // only one bank of memory and no SFR accessed?
4193 // XXX: We can do better with fixed registers.
4194 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4195 // no BANKSEL required
4196 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4200 // restrict cur_mask to cover only the banks this register
4201 // is in (as well as the previous registers)
4202 cur_mask &= new_mask;
4204 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4205 // no BANKSEL required
4206 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4211 cur_mask = new_mask;
4212 cur_bank = new_bank;
4214 insertBankSel(pci, cur_bank);
4220 /*-----------------------------------------------------------------*/
4221 /*-----------------------------------------------------------------*/
4222 static int OptimizepBlock(pBlock *pb)
4227 if(!pb || options.nopeep)
4230 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4232 for(pc = pb->pcHead; pc; pc = pc->next)
4233 matches += pCodePeepMatchRule(pc);
4236 pc = findNextInstruction(pb->pcHead);
4244 if(pCodePeepMatchRule(pc)) {
4249 pc = findNextInstruction(pcprev->next);
4251 pc = findNextInstruction(pb->pcHead);
4253 pc = findNextInstruction(pc->next);
4257 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4262 /*-----------------------------------------------------------------*/
4263 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4264 /*-----------------------------------------------------------------*/
4265 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4269 for(pc = pcs; pc; pc = pc->next) {
4271 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4273 (PCI(pc)->pcop->type == PO_LABEL) &&
4274 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4281 /*-----------------------------------------------------------------*/
4282 /*-----------------------------------------------------------------*/
4283 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4290 (PCI(pc)->pcop->type == PO_LABEL)) {
4292 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4294 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4296 free(pcol->pcop.name);
4298 /* If the key is negative, then we (probably) have a label to
4299 * a function and the name is already defined */
4302 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4306 //sprintf(buffer,"_%05d_DS_",pcl->key);
4308 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4310 pcol->pcop.name = Safe_strdup(s);
4311 pcol->key = pcl->key;
4312 //pc->print(stderr,pc);
4319 /*-----------------------------------------------------------------*/
4320 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4321 /* pCode chain if they're not used. */
4322 /*-----------------------------------------------------------------*/
4323 static void pBlockRemoveUnusedLabels(pBlock *pb)
4325 pCode *pc; pCodeLabel *pcl;
4327 if(!pb || !pb->pcHead)
4330 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4332 pBranch *pbr = PCI(pc)->label;
4333 if(pbr && pbr->next) {
4334 pCode *pcd = pb->pcHead;
4336 //fprintf(stderr, "multiple labels\n");
4337 //pc->print(stderr,pc);
4342 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4343 //fprintf(stderr,"Used by:\n");
4344 //pcd->print(stderr,pcd);
4346 exchangeLabels(PCL(pbr->pc),pcd);
4355 for(pc = pb->pcHead; pc; pc = pc->next) {
4357 if(isPCL(pc)) // Label pcode
4359 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4360 pcl = PCL(PCI(pc)->label->pc);
4363 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4365 /* This pCode is a label, so search the pBlock to see if anyone
4368 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4369 /* Couldn't find an instruction that refers to this label
4370 * So, unlink the pCode label from it's pCode chain
4371 * and destroy the label */
4372 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4374 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4375 if(pc->type == PC_LABEL) {
4377 pCodeLabelDestruct(pc);
4379 unlinkpCodeFromBranch(pc, PCODE(pcl));
4380 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4391 /*-----------------------------------------------------------------*/
4392 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4393 /* chain and put them into pBranches that are */
4394 /* associated with the appropriate pCode */
4396 /*-----------------------------------------------------------------*/
4397 void pBlockMergeLabels(pBlock *pb)
4400 pCode *pc, *pcnext=NULL;
4405 /* First, Try to remove any unused labels */
4406 //pBlockRemoveUnusedLabels(pb);
4408 /* Now loop through the pBlock and merge the labels with the opcodes */
4413 pCode *pcn = pc->next;
4415 if(pc->type == PC_LABEL) {
4417 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4418 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4419 if((pcnext = findNextInstruction(pc) )) {
4421 // Unlink the pCode label from it's pCode chain
4424 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4425 // And link it into the instruction's pBranch labels. (Note, since
4426 // it's possible to have multiple labels associated with one instruction
4427 // we must provide a means to accomodate the additional labels. Thus
4428 // the labels are placed into the singly-linked list "label" as
4429 // opposed to being a single member of the pCodeInstruction.)
4431 //_ALLOC(pbr,sizeof(pBranch));
4432 pbr = Safe_calloc(1,sizeof(pBranch));
4436 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4439 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4441 } else if(pc->type == PC_CSOURCE) {
4443 /* merge the source line symbolic info into the next instruction */
4444 if((pcnext = findNextInstruction(pc) )) {
4446 // Unlink the pCode label from it's pCode chain
4448 PCI(pcnext)->cline = PCCS(pc);
4449 //fprintf(stderr, "merging CSRC\n");
4450 //genericPrint(stderr,pcnext);
4456 pBlockRemoveUnusedLabels(pb);
4460 /*-----------------------------------------------------------------*/
4461 /*-----------------------------------------------------------------*/
4462 static int OptimizepCode(char dbName)
4464 #define MAX_PASSES 4
4473 DFPRINTF((stderr," Optimizing pCode\n"));
4477 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4478 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4479 matches += OptimizepBlock(pb);
4482 while(matches && ++passes < MAX_PASSES);
4487 /*-----------------------------------------------------------------*/
4488 /* popCopyGPR2Bit - copy a pcode operator */
4489 /*-----------------------------------------------------------------*/
4491 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4495 pcop = newpCodeOpBit(pc->name, bitval, 0);
4497 if( !( (pcop->type == PO_LABEL) ||
4498 (pcop->type == PO_LITERAL) ||
4499 (pcop->type == PO_STR) ))
4500 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4505 /*-----------------------------------------------------------------*/
4506 /*-----------------------------------------------------------------*/
4507 static void pBlockDestruct(pBlock *pb)
4518 /*-----------------------------------------------------------------*/
4519 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4520 /* name dbName and combine them */
4521 /* into one block */
4522 /*-----------------------------------------------------------------*/
4523 static void mergepBlocks(char dbName)
4526 pBlock *pb, *pbmerged = NULL,*pbn;
4528 pb = the_pFile->pbHead;
4530 //fprintf(stderr," merging blocks named %c\n",dbName);
4534 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4535 if( getpBlock_dbName(pb) == dbName) {
4537 //fprintf(stderr," merged block %c\n",dbName);
4542 addpCode2pBlock(pbmerged, pb->pcHead);
4543 /* addpCode2pBlock doesn't handle the tail: */
4544 pbmerged->pcTail = pb->pcTail;
4546 pb->prev->next = pbn;
4548 pbn->prev = pb->prev;
4553 //printpBlock(stderr, pbmerged);
4560 /*-----------------------------------------------------------------*/
4561 /* AnalyzeFlow - Examine the flow of the code and optimize */
4563 /* level 0 == minimal optimization */
4564 /* optimize registers that are used only by two instructions */
4565 /* level 1 == maximal optimization */
4566 /* optimize by looking at pairs of instructions that use the */
4568 /*-----------------------------------------------------------------*/
4570 static void AnalyzeFlow(int level)
4572 static int times_called=0;
4580 /* if this is not the first time this function has been called,
4581 then clean up old flow information */
4582 if(times_called++) {
4583 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4586 RegsUnMapLiveRanges();
4592 /* Phase 2 - Flow Analysis - Register Banking
4594 * In this phase, the individual flow blocks are examined
4595 * and register banking is fixed.
4598 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4599 //FixRegisterBanking(pb);
4601 /* Phase 2 - Flow Analysis
4603 * In this phase, the pCode is partition into pCodeFlow
4604 * blocks. The flow blocks mark the points where a continuous
4605 * stream of instructions changes flow (e.g. because of
4606 * a call or goto or whatever).
4609 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4613 /* Phase 2 - Flow Analysis - linking flow blocks
4615 * In this phase, the individual flow blocks are examined
4616 * to determine their order of excution.
4619 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4622 /* Phase 3 - Flow Analysis - Flow Tree
4624 * In this phase, the individual flow blocks are examined
4625 * to determine their order of excution.
4628 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4632 /* Phase x - Flow Analysis - Used Banks
4634 * In this phase, the individual flow blocks are examined
4635 * to determine the Register Banks they use
4638 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4642 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4643 pCodeRegMapLiveRanges(pb);
4645 RemoveUnusedRegisters();
4647 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4648 pCodeRegOptimizeRegUsage(level);
4653 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4658 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4660 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4661 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4662 pcflow = pcflow->next) {
4664 FillFlow(PCFL(pcflow));
4669 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4671 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4672 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4673 pcflow = pcflow->next) {
4675 FlowStats(PCFL(pcflow));
4681 /*-----------------------------------------------------------------*/
4682 /* AnalyzeBanking - Called after the memory addresses have been */
4683 /* assigned to the registers. */
4685 /*-----------------------------------------------------------------*/
4687 void AnalyzeBanking(void)
4691 if(!picIsInitialized()) {
4692 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
4696 if (!the_pFile) return;
4698 /* Phase x - Flow Analysis - Used Banks
4700 * In this phase, the individual flow blocks are examined
4701 * to determine the Register Banks they use
4707 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4708 FixRegisterBanking(pb);
4715 /*-----------------------------------------------------------------*/
4716 /*-----------------------------------------------------------------*/
4717 static DEFSETFUNC (resetrIdx)
4719 regs *r = (regs *)item;
4727 /*-----------------------------------------------------------------*/
4728 /* InitRegReuse - Initialises variables for code analyzer */
4729 /*-----------------------------------------------------------------*/
4730 static void InitReuseReg(void)
4732 /* Find end of statically allocated variables for start idx */
4733 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
4734 /* XXX: Avoid clashes with fixed registers, start late. */
4735 unsigned maxIdx = 0x1000;
4737 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
4738 if (r->type != REG_SFR) {
4739 maxIdx += r->size; /* Increment for all statically allocated variables */
4743 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
4746 /*-----------------------------------------------------------------*/
4747 /*-----------------------------------------------------------------*/
4748 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
4752 /* check recursion */
4753 pc = setFirstItem(pb->function_entries);
4758 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
4764 DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
4766 if (pb->tregisters) {
4768 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
4769 if (r->type == REG_GPR) {
4771 if (r->rIdx < (int)idx) {
4774 // make sure, idx is not yet used in this routine...
4776 regset = pb->tregisters;
4777 // do not touch s->curr ==> outer loop!
4778 while (regset && ((regs *)regset->item)->rIdx != idx) {
4779 regset = regset->next;
4784 if (peakIdx < idx) peakIdx = idx;
4785 sprintf(s,"r0x%02X", r->rIdx);
4786 DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
4788 r->name = Safe_strdup(s);
4794 for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
4796 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4797 char *dest = get_op_from_instruction(PCI(pc));
4799 pCode *pcn = findFunction(dest);
4801 /* This index increment from subroutines is not required, as all subroutines
4802 * may share registers NOT used by this one (< idx).
4803 * BUT if called functions A and B share a register, which gets assigned
4804 * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
4806 * As an alternative to this "solution" we could check above whether an
4807 * to-be-assigned rIdx is already present in the register set of the
4808 * current function. This would increase the reused registers and make this
4809 * `idx =' irrelevant.
4810 * UPDATE: Implemented above; not fast, but works.
4811 * (Problem shown with regression test src/regression/sub2.c)
4813 /*idx = */register_reassign(pcn->pb,idx,level+1);
4821 /*------------------------------------------------------------------*/
4822 /* ReuseReg were call tree permits */
4824 /* Re-allocate the GPR for optimum reuse for a given pblock */
4825 /* eg if a function m() calls function f1() and f2(), where f1 */
4826 /* allocates a local variable vf1 and f2 allocates a local */
4827 /* variable vf2. Then providing f1 and f2 do not call each other */
4828 /* they may share the same general purpose registers for vf1 and */
4830 /* This is done by first setting the the regs rIdx to start after */
4831 /* all the global variables, then walking through the call tree */
4832 /* renaming the registers to match their new idx and incrementng */
4833 /* it as it goes. If a function has already been called it will */
4834 /* only rename the registers if it has already used up those */
4835 /* registers ie rIdx of the function's registers is lower than the */
4836 /* current rIdx. That way the register will not be reused while */
4837 /* still being used by an eariler function call. */
4839 /* Note for this to work the functions need to be declared static. */
4841 /*------------------------------------------------------------------*/
4845 if (options.noOverlay || !the_pFile) return;
4847 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4848 /* Non static functions can be called from other modules so their registers must reassign */
4849 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
4850 register_reassign(pb,peakIdx,0);
4854 /*-----------------------------------------------------------------*/
4855 /* buildCallTree - look at the flow and extract all of the calls */
4857 /*-----------------------------------------------------------------*/
4859 static void buildCallTree(void)
4868 /* Now build the call tree.
4869 First we examine all of the pCodes for functions.
4870 Keep in mind that the function boundaries coincide
4871 with pBlock boundaries.
4873 The algorithm goes something like this:
4874 We have two nested loops. The outer loop iterates
4875 through all of the pBlocks/functions. The inner
4876 loop iterates through all of the pCodes for
4877 a given pBlock. When we begin iterating through
4878 a pBlock, the variable pc_fstart, pCode of the start
4879 of a function, is cleared. We then search for pCodes
4880 of type PC_FUNCTION. When one is encountered, we
4881 initialize pc_fstart to this and at the same time
4882 associate a new pBranch object that signifies a
4883 branch entry. If a return is found, then this signifies
4884 a function exit point. We'll link the pCodes of these
4885 returns to the matching pc_fstart.
4887 When we're done, a doubly linked list of pBranches
4888 will exist. The head of this list is stored in
4889 `the_pFile', which is the meta structure for all
4890 of the pCode. Look at the printCallTree function
4891 on how the pBranches are linked together.
4894 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4895 pCode *pc_fstart=NULL;
4896 for(pc = pb->pcHead; pc; pc = pc->next) {
4898 pCodeFunction *pcf = PCF(pc);
4901 if(STRCASECMP(pcf->fname, "_main") == 0) {
4902 //fprintf(stderr," found main \n");
4903 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4907 pbr = Safe_calloc(1,sizeof(pBranch));
4908 pbr->pc = pc_fstart = pc;
4911 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4913 // Here's a better way of doing the same:
4914 addSet(&pb->function_entries, pc);
4917 // Found an exit point in a function, e.g. return
4918 // (Note, there may be more than one return per function)
4920 pBranchLink(PCF(pc_fstart), pcf);
4922 addSet(&pb->function_exits, pc);
4924 } else if(isCALL(pc)) {
4925 addSet(&pb->function_calls,pc);
4931 /*-----------------------------------------------------------------*/
4932 /* AnalyzepCode - parse the pCode that has been generated and form */
4933 /* all of the logical connections. */
4935 /* Essentially what's done here is that the pCode flow is */
4937 /*-----------------------------------------------------------------*/
4939 void AnalyzepCode(char dbName)
4950 /* Phase 1 - Register allocation and peep hole optimization
4952 * The first part of the analysis is to determine the registers
4953 * that are used in the pCode. Once that is done, the peep rules
4954 * are applied to the code. We continue to loop until no more
4955 * peep rule optimizations are found (or until we exceed the
4956 * MAX_PASSES threshold).
4958 * When done, the required registers will be determined.
4964 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4966 /* First, merge the labels with the instructions */
4967 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4968 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4970 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4971 pBlockMergeLabels(pb);
4974 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
4978 changes = OptimizepCode(dbName);
4980 } while(changes && (i++ < MAX_PASSES));
4985 /*-----------------------------------------------------------------*/
4986 /* findFunction - Search for a function by name (given the name) */
4987 /* in the set of all functions that are in a pBlock */
4988 /* (note - I expect this to change because I'm planning to limit */
4989 /* pBlock's to just one function declaration */
4990 /*-----------------------------------------------------------------*/
4991 static pCode *findFunction(char *fname)
4998 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5000 pc = setFirstItem(pb->function_entries);
5003 if((pc->type == PC_FUNCTION) &&
5005 (strcmp(fname, PCF(pc)->fname)==0))
5008 pc = setNextItem(pb->function_entries);
5016 static void pBlockStats(FILE *of, pBlock *pb)
5022 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5024 // for now just print the first element of each set
5025 pc = setFirstItem(pb->function_entries);
5027 fprintf(of,";entry: ");
5030 pc = setFirstItem(pb->function_exits);
5032 fprintf(of,";has an exit\n");
5036 pc = setFirstItem(pb->function_calls);
5038 fprintf(of,";functions called:\n");
5041 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5042 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5044 pc = setNextItem(pb->function_calls);
5048 r = setFirstItem(pb->tregisters);
5050 int n = elementsInSet(pb->tregisters);
5052 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5055 fprintf(of,"; %s\n",r->name);
5056 r = setNextItem(pb->tregisters);
5062 /*-----------------------------------------------------------------*/
5063 /* printCallTree - writes the call tree to a file */
5065 /*-----------------------------------------------------------------*/
5066 static void pct2(FILE *of,pBlock *pb,int indent)
5070 // set *registersInCallPath = NULL;
5076 return; //recursion ?
5078 pc = setFirstItem(pb->function_entries);
5085 for(i=0;i<indent;i++) // Indentation
5088 if(pc->type == PC_FUNCTION)
5089 fprintf(of,"%s\n",PCF(pc)->fname);
5094 pc = setFirstItem(pb->function_calls);
5095 for( ; pc; pc = setNextItem(pb->function_calls)) {
5097 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5098 char *dest = get_op_from_instruction(PCI(pc));
5100 pcn = findFunction(dest);
5102 pct2(of,pcn->pb,indent+1);
5104 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5113 /*-----------------------------------------------------------------*/
5114 /* ispCodeFunction - returns true if *pc is the pCode of a */
5116 /*-----------------------------------------------------------------*/
5117 static bool ispCodeFunction(pCode *pc)
5120 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5126 /*-----------------------------------------------------------------*/
5127 /* printCallTree - writes the call tree to a file */
5129 /*-----------------------------------------------------------------*/
5131 static void printCallTree(FILE *of)
5143 fprintf(of, "\npBlock statistics\n");
5144 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5149 fprintf(of,"Call Tree\n");
5150 pbr = the_pFile->functions;
5154 if(!ispCodeFunction(pc))
5155 fprintf(of,"bug in call tree");
5158 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5160 while(pc->next && !ispCodeFunction(pc->next)) {
5162 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5163 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5171 fprintf(of,"\n**************\n\na better call tree\n");
5172 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5177 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5178 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5184 /*-----------------------------------------------------------------*/
5186 /*-----------------------------------------------------------------*/
5188 static void InlineFunction(pBlock *pb)
5196 pc = setFirstItem(pb->function_calls);
5198 for( ; pc; pc = setNextItem(pb->function_calls)) {
5201 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5202 pCode *pcp = pc->prev;
5208 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 */
5210 InlineFunction(pcn->pb);
5213 At this point, *pc points to a CALL mnemonic, and
5214 *pcn points to the function that is being called.
5216 To in-line this call, we need to remove the CALL
5217 and RETURN(s), and link the function pCode in with
5224 /* Check if previous instruction was a bit skip */
5225 if (isPCI_BITSKIP(pcp)) {
5227 /* Invert skip instruction and add a goto */
5228 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5230 if(isPCL(pc_call->next)) { // Label pcode
5231 pcl = PCL(pc_call->next);
5232 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5233 pcl = PCL(PCI(pc_call->next)->label->pc);
5235 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5236 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5238 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5241 /* remove callee pBlock from the pBlock linked list */
5242 removepBlock(pcn->pb);
5250 /* Remove the Function pCode */
5251 pct = findNextInstruction(pcn->next);
5253 /* Link the function with the callee */
5254 if (pcp) pcp->next = pcn->next;
5255 pcn->next->prev = pcp;
5257 /* Convert the function name into a label */
5259 pbr = Safe_calloc(1,sizeof(pBranch));
5260 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5262 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5263 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5265 /* turn all of the return's except the last into goto's */
5266 /* check case for 2 instruction pBlocks */
5267 pce = findNextInstruction(pcn->next);
5269 pCode *pce_next = findNextInstruction(pce->next);
5271 if(pce_next == NULL) {
5272 /* found the last return */
5273 pCode *pc_call_next = findNextInstruction(pc_call->next);
5275 //fprintf(stderr,"found last return\n");
5276 //pce->print(stderr,pce);
5277 pce->prev->next = pc_call->next;
5278 pc_call->next->prev = pce->prev;
5279 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5288 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5294 /*-----------------------------------------------------------------*/
5296 /*-----------------------------------------------------------------*/
5298 void InlinepCode(void)
5307 if(!functionInlining)
5310 /* Loop through all of the function definitions and count the
5311 * number of times each one is called */
5312 //fprintf(stderr,"inlining %d\n",__LINE__);
5314 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5316 pc = setFirstItem(pb->function_calls);
5318 for( ; pc; pc = setNextItem(pb->function_calls)) {
5321 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5322 if(pcn && isPCF(pcn)) {
5323 PCF(pcn)->ncalled++;
5326 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5331 //fprintf(stderr,"inlining %d\n",__LINE__);
5333 /* Now, Loop through the function definitions again, but this
5334 * time inline those functions that have only been called once. */
5336 InlineFunction(the_pFile->pbHead);
5337 //fprintf(stderr,"inlining %d\n",__LINE__);
5339 for(pb = the_pFile->pbHead; pb; pb = pb->next)