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 int 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 0;
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));
4036 * isValidIdChar - check if c may be present in an identifier
4038 static int isValidIdChar (char c)
4040 if (c >= 'a' && c <= 'z') return 1;
4041 if (c >= 'A' && c <= 'Z') return 1;
4042 if (c >= '0' && c <= '9') return 1;
4043 if (c == '_') return 1;
4048 * bankcompare - check if two operand string refer to the same register
4049 * This functions handles NAME and (NAME + x) in both operands.
4050 * Returns 1 on same register, 0 on different (or unknown) registers.
4052 static int bankCompare(const char *op1, const char *op2)
4056 if (!op1 && !op2) return 0; // both unknown, might be different though!
4057 if (!op1 || !op2) return 0;
4059 // find start of operand name
4060 while (op1[0] == '(' || op1[0] == ' ') op1++;
4061 while (op2[0] == '(' || op2[0] == ' ') op2++;
4063 // compare till first non-identifier character
4064 for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
4065 if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
4067 // play safe---assume different operands
4072 * Interface to BANKSEL generation.
4073 * This function should return != 0 iff str1 and str2 denote operands that
4074 * are known to be allocated into the same bank. Consequently, there will
4075 * be no BANKSEL emitted if str2 is accessed while str1 has been used to
4076 * select the current bank just previously.
4078 * If in doubt, return 0.
4081 pic14_operandsAllocatedInSameBank(const char *str1, const char *str2) {
4082 // see glue.c(pic14printLocals)
4084 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
4085 // no clustering applied, each register resides in its own bank
4087 // check whether BOTH names are local registers
4088 // XXX: This is some kind of shortcut, should be safe...
4089 // In this model, all r0xXXXX are allocated into a single section
4090 // per file, so no BANKSEL required if accessing a r0xXXXX after a
4091 // (different) r0xXXXX. Works great for multi-byte operands.
4092 if (str1 && str2 && str1[0] == 'r' && str2[0] == 'r') return (1);
4095 // assume operands in different banks
4099 /*-----------------------------------------------------------------*/
4100 /*-----------------------------------------------------------------*/
4101 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4103 if (!cur_bank) return 0;
4105 if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
4106 return 1; // if we have address info, we use it for banksel optimization
4108 // regard '(regname + X)' and '(regname + Y)' as equal
4109 if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
4110 if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
4112 // check allocation policy from glue.c
4113 if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
4114 if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
4116 // seems to be a different operand--might be a different bank
4117 //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
4121 /*-----------------------------------------------------------------*/
4122 /*-----------------------------------------------------------------*/
4123 static void FixRegisterBanking(pBlock *pb)
4126 pCodeInstruction *pci;
4128 regs *previous_reg; // contains the previous variable access info
4129 const char *cur_bank, *new_bank;
4130 unsigned cur_mask, new_mask, max_mask;
4135 max_mask = pic14_getPIC()->bankMask;
4136 cur_mask = max_mask;
4138 previous_reg = NULL;
4140 allRAMmshared = pic14_allRAMShared();
4142 for (pc = pb->pcHead; pc; pc = pc->next)
4144 // this one has a label---might check bank at all jumps here...
4145 if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4146 addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4147 previous_reg = NULL;
4148 cur_bank = NULL; // start new flow
4149 cur_mask = max_mask;
4152 // this one is/might be a label or BANKSEL---assume nothing
4153 if (isPCL(pc) || isPCASMDIR(pc)) {
4154 addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4155 previous_reg = NULL;
4157 cur_mask = max_mask;
4160 // this one modifies STATUS
4161 // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4165 if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4166 // might need a BANKSEL
4167 reg = getRegFromInstruction(pc);
4170 new_bank = reg->name;
4171 // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4172 // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4173 new_mask = reg->alias;
4174 } else if (pci->pcop && pci->pcop->name) {
4175 new_bank = pci->pcop->name;
4176 new_mask = 0; // unknown, assume worst case
4178 assert(!"Could not get register from instruction.");
4179 new_bank = "UNKNOWN";
4180 new_mask = 0; // unknown, assume worst case
4184 // XXX: add switch to disable these
4186 // reg present in all banks possibly selected?
4187 if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4188 // no BANKSEL required
4189 addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4193 // only one bank of memory and no SFR accessed?
4194 // XXX: We can do better with fixed registers.
4195 if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4196 // no BANKSEL required
4197 addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all (of %s's) banks", new_bank, cur_bank);
4201 if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4202 // no BANKSEL required
4203 addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4208 if (insertBankSel(pci, new_bank)) {
4209 cur_mask = new_mask;
4210 cur_bank = new_bank;
4218 /*-----------------------------------------------------------------*/
4219 /*-----------------------------------------------------------------*/
4220 static int OptimizepBlock(pBlock *pb)
4225 if(!pb || options.nopeep)
4228 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4230 for(pc = pb->pcHead; pc; pc = pc->next)
4231 matches += pCodePeepMatchRule(pc);
4234 pc = findNextInstruction(pb->pcHead);
4242 if(pCodePeepMatchRule(pc)) {
4247 pc = findNextInstruction(pcprev->next);
4249 pc = findNextInstruction(pb->pcHead);
4251 pc = findNextInstruction(pc->next);
4255 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4260 /*-----------------------------------------------------------------*/
4261 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4262 /*-----------------------------------------------------------------*/
4263 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4267 for(pc = pcs; pc; pc = pc->next) {
4269 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4271 (PCI(pc)->pcop->type == PO_LABEL) &&
4272 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4279 /*-----------------------------------------------------------------*/
4280 /*-----------------------------------------------------------------*/
4281 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4288 (PCI(pc)->pcop->type == PO_LABEL)) {
4290 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4292 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4294 free(pcol->pcop.name);
4296 /* If the key is negative, then we (probably) have a label to
4297 * a function and the name is already defined */
4300 sprintf(s=buffer,"_%05d_DS_",pcl->key);
4304 //sprintf(buffer,"_%05d_DS_",pcl->key);
4306 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4308 pcol->pcop.name = Safe_strdup(s);
4309 pcol->key = pcl->key;
4310 //pc->print(stderr,pc);
4317 /*-----------------------------------------------------------------*/
4318 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
4319 /* pCode chain if they're not used. */
4320 /*-----------------------------------------------------------------*/
4321 static void pBlockRemoveUnusedLabels(pBlock *pb)
4323 pCode *pc; pCodeLabel *pcl;
4325 if(!pb || !pb->pcHead)
4328 for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4330 pBranch *pbr = PCI(pc)->label;
4331 if(pbr && pbr->next) {
4332 pCode *pcd = pb->pcHead;
4334 //fprintf(stderr, "multiple labels\n");
4335 //pc->print(stderr,pc);
4340 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4341 //fprintf(stderr,"Used by:\n");
4342 //pcd->print(stderr,pcd);
4344 exchangeLabels(PCL(pbr->pc),pcd);
4353 for(pc = pb->pcHead; pc; pc = pc->next) {
4355 if(isPCL(pc)) // Label pcode
4357 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4358 pcl = PCL(PCI(pc)->label->pc);
4361 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4363 /* This pCode is a label, so search the pBlock to see if anyone
4366 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4367 /* Couldn't find an instruction that refers to this label
4368 * So, unlink the pCode label from it's pCode chain
4369 * and destroy the label */
4370 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4372 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4373 if(pc->type == PC_LABEL) {
4375 pCodeLabelDestruct(pc);
4377 unlinkpCodeFromBranch(pc, PCODE(pcl));
4378 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4389 /*-----------------------------------------------------------------*/
4390 /* pBlockMergeLabels - remove the pCode labels from the pCode */
4391 /* chain and put them into pBranches that are */
4392 /* associated with the appropriate pCode */
4394 /*-----------------------------------------------------------------*/
4395 void pBlockMergeLabels(pBlock *pb)
4398 pCode *pc, *pcnext=NULL;
4403 /* First, Try to remove any unused labels */
4404 //pBlockRemoveUnusedLabels(pb);
4406 /* Now loop through the pBlock and merge the labels with the opcodes */
4411 pCode *pcn = pc->next;
4413 if(pc->type == PC_LABEL) {
4415 //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4416 //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4417 if((pcnext = findNextInstruction(pc) )) {
4419 // Unlink the pCode label from it's pCode chain
4422 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4423 // And link it into the instruction's pBranch labels. (Note, since
4424 // it's possible to have multiple labels associated with one instruction
4425 // we must provide a means to accomodate the additional labels. Thus
4426 // the labels are placed into the singly-linked list "label" as
4427 // opposed to being a single member of the pCodeInstruction.)
4429 //_ALLOC(pbr,sizeof(pBranch));
4430 pbr = Safe_calloc(1,sizeof(pBranch));
4434 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4437 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4439 } else if(pc->type == PC_CSOURCE) {
4441 /* merge the source line symbolic info into the next instruction */
4442 if((pcnext = findNextInstruction(pc) )) {
4444 // Unlink the pCode label from it's pCode chain
4446 PCI(pcnext)->cline = PCCS(pc);
4447 //fprintf(stderr, "merging CSRC\n");
4448 //genericPrint(stderr,pcnext);
4454 pBlockRemoveUnusedLabels(pb);
4458 /*-----------------------------------------------------------------*/
4459 /*-----------------------------------------------------------------*/
4460 static int OptimizepCode(char dbName)
4462 #define MAX_PASSES 4
4471 DFPRINTF((stderr," Optimizing pCode\n"));
4475 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4476 if('*' == dbName || getpBlock_dbName(pb) == dbName)
4477 matches += OptimizepBlock(pb);
4480 while(matches && ++passes < MAX_PASSES);
4485 /*-----------------------------------------------------------------*/
4486 /* popCopyGPR2Bit - copy a pcode operator */
4487 /*-----------------------------------------------------------------*/
4489 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4493 pcop = newpCodeOpBit(pc->name, bitval, 0);
4495 if( !( (pcop->type == PO_LABEL) ||
4496 (pcop->type == PO_LITERAL) ||
4497 (pcop->type == PO_STR) ))
4498 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
4503 /*-----------------------------------------------------------------*/
4504 /*-----------------------------------------------------------------*/
4505 static void pBlockDestruct(pBlock *pb)
4516 /*-----------------------------------------------------------------*/
4517 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4518 /* name dbName and combine them */
4519 /* into one block */
4520 /*-----------------------------------------------------------------*/
4521 static void mergepBlocks(char dbName)
4524 pBlock *pb, *pbmerged = NULL,*pbn;
4526 pb = the_pFile->pbHead;
4528 //fprintf(stderr," merging blocks named %c\n",dbName);
4532 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4533 if( getpBlock_dbName(pb) == dbName) {
4535 //fprintf(stderr," merged block %c\n",dbName);
4540 addpCode2pBlock(pbmerged, pb->pcHead);
4541 /* addpCode2pBlock doesn't handle the tail: */
4542 pbmerged->pcTail = pb->pcTail;
4544 pb->prev->next = pbn;
4546 pbn->prev = pb->prev;
4551 //printpBlock(stderr, pbmerged);
4558 /*-----------------------------------------------------------------*/
4559 /* AnalyzeFlow - Examine the flow of the code and optimize */
4561 /* level 0 == minimal optimization */
4562 /* optimize registers that are used only by two instructions */
4563 /* level 1 == maximal optimization */
4564 /* optimize by looking at pairs of instructions that use the */
4566 /*-----------------------------------------------------------------*/
4568 static void AnalyzeFlow(int level)
4570 static int times_called=0;
4578 /* if this is not the first time this function has been called,
4579 then clean up old flow information */
4580 if(times_called++) {
4581 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4584 RegsUnMapLiveRanges();
4590 /* Phase 2 - Flow Analysis - Register Banking
4592 * In this phase, the individual flow blocks are examined
4593 * and register banking is fixed.
4596 //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4597 //FixRegisterBanking(pb);
4599 /* Phase 2 - Flow Analysis
4601 * In this phase, the pCode is partition into pCodeFlow
4602 * blocks. The flow blocks mark the points where a continuous
4603 * stream of instructions changes flow (e.g. because of
4604 * a call or goto or whatever).
4607 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4611 /* Phase 2 - Flow Analysis - linking flow blocks
4613 * In this phase, the individual flow blocks are examined
4614 * to determine their order of excution.
4617 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4620 /* Phase 3 - Flow Analysis - Flow Tree
4622 * In this phase, the individual flow blocks are examined
4623 * to determine their order of excution.
4626 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4630 /* Phase x - Flow Analysis - Used Banks
4632 * In this phase, the individual flow blocks are examined
4633 * to determine the Register Banks they use
4636 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4640 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4641 pCodeRegMapLiveRanges(pb);
4643 RemoveUnusedRegisters();
4645 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
4646 pCodeRegOptimizeRegUsage(level);
4651 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4656 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4658 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4659 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4660 pcflow = pcflow->next) {
4662 FillFlow(PCFL(pcflow));
4667 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4669 for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4670 (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4671 pcflow = pcflow->next) {
4673 FlowStats(PCFL(pcflow));
4679 /*-----------------------------------------------------------------*/
4680 /* AnalyzeBanking - Called after the memory addresses have been */
4681 /* assigned to the registers. */
4683 /*-----------------------------------------------------------------*/
4685 void AnalyzeBanking(void)
4689 if(!picIsInitialized()) {
4690 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
4694 if (!the_pFile) return;
4696 /* Phase x - Flow Analysis - Used Banks
4698 * In this phase, the individual flow blocks are examined
4699 * to determine the Register Banks they use
4705 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4706 FixRegisterBanking(pb);
4713 /*-----------------------------------------------------------------*/
4714 /*-----------------------------------------------------------------*/
4715 static DEFSETFUNC (resetrIdx)
4717 regs *r = (regs *)item;
4725 /*-----------------------------------------------------------------*/
4726 /* InitRegReuse - Initialises variables for code analyzer */
4727 /*-----------------------------------------------------------------*/
4728 static void InitReuseReg(void)
4730 /* Find end of statically allocated variables for start idx */
4731 /* Start from begining of GPR. Note may not be 0x20 on some PICs */
4732 /* XXX: Avoid clashes with fixed registers, start late. */
4733 unsigned maxIdx = 0x1000;
4735 for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
4736 if (r->type != REG_SFR) {
4737 maxIdx += r->size; /* Increment for all statically allocated variables */
4741 applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
4744 /*-----------------------------------------------------------------*/
4745 /*-----------------------------------------------------------------*/
4747 register_reassign(pBlock *pb, unsigned startIdx, unsigned level)
4751 unsigned idx = startIdx;
4753 /* check recursion */
4754 pc = setFirstItem(pb->function_entries);
4761 /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
4763 // Find the highest rIdx used by this function for return.
4764 regset = pb->tregisters;
4768 temp = ((regs *)regset->item)->rIdx;
4771 regset = regset->next;
4774 "%*s(%u) function \"%s\" already visited: max idx = %04x\n",
4775 4 * level, "", level,PCF(pc)->fname, idx));
4780 * We now traverse the call tree depth first, assigning indices > startIdx
4781 * to the registers of all called functions before assigning indices to
4782 * the registers of the calling function, starting with one greater than
4783 * the max. index used by any child function.
4784 * This approach guarantees that, if f calls g, all registers of f have
4785 * greater indices than those of g (also holds transitively).
4787 * XXX: If a function f calls a function g in a different module,
4788 * we should handle the case that g could call a function h
4790 * The consequence of this is that even though f and h might
4791 * share registers (they do not call each other locally) when
4792 * looking only at f's module, they actually must not do so!
4794 * For a non-static function f, let ES(f) be the set of functions
4795 * (including f) that can only be reached via f in the module-local
4796 * call graph (ES(f) will hence be a subgraph).
4797 * Let further REG(ES(f)) be the set of registers assigned to
4798 * functions in ES(f).
4799 * Then we should make sure that REG(ES(f)) and REG(ES(g)) are
4800 * disjoint for all non-static functions f and g.
4802 * Unfortunately, determining the sets ES(f) is non-trivial,
4803 * so we ignore this problem and declare all modules non-reentrant.
4809 "%*s(%u) reassigning registers for functions called by \"%s\":base idx = %04x\n",
4810 4 * level, "", level, PCF(pc)->fname, startIdx));
4812 for (pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls))
4814 if (pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
4816 char *dest = get_op_from_instruction(PCI(pc));
4817 pCode *pcn = findFunction(dest);
4822 * Reassign the registers of all called functions and record
4823 * the max. index I used by any child function --> I+1 will be
4824 * the first index available to this function.
4825 * (Problem shown with regression test src/regression/sub2.c)
4827 unsigned childsMaxIdx;
4828 childsMaxIdx = register_reassign(pcn->pb,startIdx,level+1);
4829 if (childsMaxIdx > idx)
4835 pc = setFirstItem(pb->function_entries);
4837 "%*s(%u) reassigning registers for function \"%s\":idx = %04x\n",
4838 4 * level, "", level, PCF(pc)->fname, idx));
4843 for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters))
4845 if ((r->type == REG_GPR) && (!r->isFixed) && (r->rIdx < (int)idx))
4850 * Make sure, idx is not yet used in this routine ...
4851 * XXX: This should no longer be required, as all functions
4852 * are reassigned at most once ...
4856 regset = pb->tregisters;
4857 // do not touch s->curr ==> outer loop!
4858 while (regset && ((regs *)regset->item)->rIdx != idx)
4859 regset = regset->next;
4867 sprintf(s,"r0x%02X", r->rIdx);
4869 "%*s(%u) reassigning register %p \"%s\" to \"%s\"\n",
4870 4 * level, "", level, r, r->name, s));
4872 r->name = Safe_strdup(s);
4877 /* return lowest index available for caller's registers */
4881 /*------------------------------------------------------------------*/
4882 /* ReuseReg were call tree permits */
4884 /* Re-allocate the GPR for optimum reuse for a given pblock */
4885 /* eg if a function m() calls function f1() and f2(), where f1 */
4886 /* allocates a local variable vf1 and f2 allocates a local */
4887 /* variable vf2. Then providing f1 and f2 do not call each other */
4888 /* they may share the same general purpose registers for vf1 and */
4890 /* This is done by first setting the the regs rIdx to start after */
4891 /* all the global variables, then walking through the call tree */
4892 /* renaming the registers to match their new idx and incrementng */
4893 /* it as it goes. If a function has already been called it will */
4894 /* only rename the registers if it has already used up those */
4895 /* registers ie rIdx of the function's registers is lower than the */
4896 /* current rIdx. That way the register will not be reused while */
4897 /* still being used by an eariler function call. */
4899 /* Note for this to work the functions need to be declared static. */
4901 /*------------------------------------------------------------------*/
4907 if (options.noOverlay || !the_pFile)
4912 for(pb = the_pFile->pbHead; pb; pb = pb->next)
4914 /* Non static functions can be called from other modules,
4915 * so their registers must reassign */
4916 if (pb->function_entries
4917 && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
4919 register_reassign(pb,peakIdx,0);
4924 /*-----------------------------------------------------------------*/
4925 /* buildCallTree - look at the flow and extract all of the calls */
4927 /*-----------------------------------------------------------------*/
4929 static void buildCallTree(void)
4938 /* Now build the call tree.
4939 First we examine all of the pCodes for functions.
4940 Keep in mind that the function boundaries coincide
4941 with pBlock boundaries.
4943 The algorithm goes something like this:
4944 We have two nested loops. The outer loop iterates
4945 through all of the pBlocks/functions. The inner
4946 loop iterates through all of the pCodes for
4947 a given pBlock. When we begin iterating through
4948 a pBlock, the variable pc_fstart, pCode of the start
4949 of a function, is cleared. We then search for pCodes
4950 of type PC_FUNCTION. When one is encountered, we
4951 initialize pc_fstart to this and at the same time
4952 associate a new pBranch object that signifies a
4953 branch entry. If a return is found, then this signifies
4954 a function exit point. We'll link the pCodes of these
4955 returns to the matching pc_fstart.
4957 When we're done, a doubly linked list of pBranches
4958 will exist. The head of this list is stored in
4959 `the_pFile', which is the meta structure for all
4960 of the pCode. Look at the printCallTree function
4961 on how the pBranches are linked together.
4964 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4965 pCode *pc_fstart=NULL;
4966 for(pc = pb->pcHead; pc; pc = pc->next) {
4968 pCodeFunction *pcf = PCF(pc);
4971 if(STRCASECMP(pcf->fname, "_main") == 0) {
4972 //fprintf(stderr," found main \n");
4973 pb->cmemmap = NULL; /* FIXME do we need to free ? */
4977 pbr = Safe_calloc(1,sizeof(pBranch));
4978 pbr->pc = pc_fstart = pc;
4981 the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4983 // Here's a better way of doing the same:
4984 addSet(&pb->function_entries, pc);
4987 // Found an exit point in a function, e.g. return
4988 // (Note, there may be more than one return per function)
4990 pBranchLink(PCF(pc_fstart), pcf);
4992 addSet(&pb->function_exits, pc);
4994 } else if(isCALL(pc)) {
4995 addSet(&pb->function_calls,pc);
5001 /*-----------------------------------------------------------------*/
5002 /* AnalyzepCode - parse the pCode that has been generated and form */
5003 /* all of the logical connections. */
5005 /* Essentially what's done here is that the pCode flow is */
5007 /*-----------------------------------------------------------------*/
5009 void AnalyzepCode(char dbName)
5020 /* Phase 1 - Register allocation and peep hole optimization
5022 * The first part of the analysis is to determine the registers
5023 * that are used in the pCode. Once that is done, the peep rules
5024 * are applied to the code. We continue to loop until no more
5025 * peep rule optimizations are found (or until we exceed the
5026 * MAX_PASSES threshold).
5028 * When done, the required registers will be determined.
5034 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5036 /* First, merge the labels with the instructions */
5037 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5038 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5040 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5041 pBlockMergeLabels(pb);
5044 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5048 changes = OptimizepCode(dbName);
5050 } while(changes && (i++ < MAX_PASSES));
5055 /*-----------------------------------------------------------------*/
5056 /* findFunction - Search for a function by name (given the name) */
5057 /* in the set of all functions that are in a pBlock */
5058 /* (note - I expect this to change because I'm planning to limit */
5059 /* pBlock's to just one function declaration */
5060 /*-----------------------------------------------------------------*/
5061 static pCode *findFunction(char *fname)
5068 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5070 pc = setFirstItem(pb->function_entries);
5073 if((pc->type == PC_FUNCTION) &&
5075 (strcmp(fname, PCF(pc)->fname)==0))
5078 pc = setNextItem(pb->function_entries);
5086 static void pBlockStats(FILE *of, pBlock *pb)
5092 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5094 // for now just print the first element of each set
5095 pc = setFirstItem(pb->function_entries);
5097 fprintf(of,";entry: ");
5100 pc = setFirstItem(pb->function_exits);
5102 fprintf(of,";has an exit\n");
5106 pc = setFirstItem(pb->function_calls);
5108 fprintf(of,";functions called:\n");
5111 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5112 fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
5114 pc = setNextItem(pb->function_calls);
5118 r = setFirstItem(pb->tregisters);
5120 int n = elementsInSet(pb->tregisters);
5122 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5125 fprintf(of,"; %s\n",r->name);
5126 r = setNextItem(pb->tregisters);
5132 /*-----------------------------------------------------------------*/
5133 /* printCallTree - writes the call tree to a file */
5135 /*-----------------------------------------------------------------*/
5136 static void pct2(FILE *of,pBlock *pb,int indent)
5140 // set *registersInCallPath = NULL;
5146 return; //recursion ?
5148 pc = setFirstItem(pb->function_entries);
5155 for(i=0;i<indent;i++) // Indentation
5158 if(pc->type == PC_FUNCTION)
5159 fprintf(of,"%s\n",PCF(pc)->fname);
5164 pc = setFirstItem(pb->function_calls);
5165 for( ; pc; pc = setNextItem(pb->function_calls)) {
5167 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5168 char *dest = get_op_from_instruction(PCI(pc));
5170 pcn = findFunction(dest);
5172 pct2(of,pcn->pb,indent+1);
5174 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5183 /*-----------------------------------------------------------------*/
5184 /* ispCodeFunction - returns true if *pc is the pCode of a */
5186 /*-----------------------------------------------------------------*/
5187 static bool ispCodeFunction(pCode *pc)
5190 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5196 /*-----------------------------------------------------------------*/
5197 /* printCallTree - writes the call tree to a file */
5199 /*-----------------------------------------------------------------*/
5201 static void printCallTree(FILE *of)
5213 fprintf(of, "\npBlock statistics\n");
5214 for(pb = the_pFile->pbHead; pb; pb = pb->next )
5219 fprintf(of,"Call Tree\n");
5220 pbr = the_pFile->functions;
5224 if(!ispCodeFunction(pc))
5225 fprintf(of,"bug in call tree");
5228 fprintf(of,"Function: %s\n", PCF(pc)->fname);
5230 while(pc->next && !ispCodeFunction(pc->next)) {
5232 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5233 fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5241 fprintf(of,"\n**************\n\na better call tree\n");
5242 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5247 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5248 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5254 /*-----------------------------------------------------------------*/
5256 /*-----------------------------------------------------------------*/
5258 static void InlineFunction(pBlock *pb)
5266 pc = setFirstItem(pb->function_calls);
5268 for( ; pc; pc = setNextItem(pb->function_calls)) {
5271 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5272 pCode *pcp = pc->prev;
5278 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 */
5280 InlineFunction(pcn->pb);
5283 At this point, *pc points to a CALL mnemonic, and
5284 *pcn points to the function that is being called.
5286 To in-line this call, we need to remove the CALL
5287 and RETURN(s), and link the function pCode in with
5294 /* Check if previous instruction was a bit skip */
5295 if (isPCI_BITSKIP(pcp)) {
5297 /* Invert skip instruction and add a goto */
5298 PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5300 if(isPCL(pc_call->next)) { // Label pcode
5301 pcl = PCL(pc_call->next);
5302 } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5303 pcl = PCL(PCI(pc_call->next)->label->pc);
5305 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5306 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5308 pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5311 /* remove callee pBlock from the pBlock linked list */
5312 removepBlock(pcn->pb);
5320 /* Remove the Function pCode */
5321 pct = findNextInstruction(pcn->next);
5323 /* Link the function with the callee */
5324 if (pcp) pcp->next = pcn->next;
5325 pcn->next->prev = pcp;
5327 /* Convert the function name into a label */
5329 pbr = Safe_calloc(1,sizeof(pBranch));
5330 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5332 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5333 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5335 /* turn all of the return's except the last into goto's */
5336 /* check case for 2 instruction pBlocks */
5337 pce = findNextInstruction(pcn->next);
5339 pCode *pce_next = findNextInstruction(pce->next);
5341 if(pce_next == NULL) {
5342 /* found the last return */
5343 pCode *pc_call_next = findNextInstruction(pc_call->next);
5345 //fprintf(stderr,"found last return\n");
5346 //pce->print(stderr,pce);
5347 pce->prev->next = pc_call->next;
5348 pc_call->next->prev = pce->prev;
5349 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5358 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5364 /*-----------------------------------------------------------------*/
5366 /*-----------------------------------------------------------------*/
5368 void InlinepCode(void)
5377 if(!functionInlining)
5380 /* Loop through all of the function definitions and count the
5381 * number of times each one is called */
5382 //fprintf(stderr,"inlining %d\n",__LINE__);
5384 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5386 pc = setFirstItem(pb->function_calls);
5388 for( ; pc; pc = setNextItem(pb->function_calls)) {
5391 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5392 if(pcn && isPCF(pcn)) {
5393 PCF(pcn)->ncalled++;
5396 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5401 //fprintf(stderr,"inlining %d\n",__LINE__);
5403 /* Now, Loop through the function definitions again, but this
5404 * time inline those functions that have only been called once. */
5406 InlineFunction(the_pFile->pbHead);
5407 //fprintf(stderr,"inlining %d\n",__LINE__);
5409 for(pb = the_pFile->pbHead; pb; pb = pb->next)