1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
63 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
65 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
66 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
67 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
68 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
69 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
70 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
72 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
73 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
74 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
75 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
79 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
81 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
85 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
87 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
93 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
94 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
97 static int mnemonics_initialized = 0;
100 static hTab *pic16MnemonicsHash = NULL;
101 static hTab *pic16pCodePeepCommandsHash = NULL;
103 static pFile *the_pFile = NULL;
104 static pBlock *pb_dead_pcodes = NULL;
106 /* Hardcoded flags to change the behavior of the PIC port */
107 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
108 static int functionInlining = 1; /* inline functions if nonzero */
109 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
111 int pic16_pcode_verbose = 0;
113 //static int GpCodeSequenceNumber = 1;
114 static int GpcFlowSeq = 1;
116 extern void pic16_RemoveUnusedRegisters(void);
117 extern void pic16_RegsUnMapLiveRanges(void);
118 extern void pic16_BuildFlowTree(pBlock *pb);
119 extern void pic16_pCodeRegOptimizeRegUsage(int level);
120 extern int pic16_picIsInitialized(void);
121 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
122 extern int mnem2key(char const *mnem);
124 /****************************************************************/
125 /* Forward declarations */
126 /****************************************************************/
128 void pic16_unlinkpCode(pCode *pc);
130 static void genericAnalyze(pCode *pc);
131 static void AnalyzeGOTO(pCode *pc);
132 static void AnalyzeSKIP(pCode *pc);
133 static void AnalyzeRETURN(pCode *pc);
136 static void genericDestruct(pCode *pc);
137 static void genericPrint(FILE *of,pCode *pc);
139 static void pCodePrintLabel(FILE *of, pCode *pc);
140 static void pCodePrintFunction(FILE *of, pCode *pc);
141 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
142 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
143 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
144 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
145 int pic16_pCodePeepMatchRule(pCode *pc);
146 static void pBlockStats(FILE *of, pBlock *pb);
147 static pBlock *newpBlock(void);
148 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
149 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
150 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
151 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
153 char *dumpPicOptype(PIC_OPTYPE type);
155 /****************************************************************/
156 /* PIC Instructions */
157 /****************************************************************/
159 pCodeInstruction pic16_pciADDWF = {
160 {PC_OPCODE, NULL, NULL, 0, NULL,
173 1,0, // dest, bit instruction
175 0, // literal operand
177 0, // fast call/return mode select bit
178 0, // second memory operand
179 0, // second literal operand
181 (PCC_W | PCC_REGISTER), // inCond
182 (PCC_REGISTER | PCC_Z), // outCond
186 pCodeInstruction pic16_pciADDFW = {
187 {PC_OPCODE, NULL, NULL, 0, NULL,
200 0,0, // dest, bit instruction
202 0, // literal operand
204 0, // fast call/return mode select bit
205 0, // second memory operand
206 0, // second literal operand
208 (PCC_W | PCC_REGISTER), // inCond
209 (PCC_W | PCC_Z), // outCond
213 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
214 {PC_OPCODE, NULL, NULL, 0, NULL,
227 1,0, // dest, bit instruction
229 0, // literal operand
231 0, // fast call/return mode select bit
232 0, // second memory operand
233 0, // second literal operand
235 (PCC_W | PCC_REGISTER | PCC_C), // inCond
236 (PCC_REGISTER | PCC_Z), // outCond
240 pCodeInstruction pic16_pciADDFWC = {
241 {PC_OPCODE, NULL, NULL, 0, NULL,
254 0,0, // dest, bit instruction
256 0, // literal operand
258 0, // fast call/return mode select bit
259 0, // second memory operand
260 0, // second literal operand
262 (PCC_W | PCC_REGISTER | PCC_C), // inCond
263 (PCC_W | PCC_Z), // outCond
267 pCodeInstruction pic16_pciADDLW = {
268 {PC_OPCODE, NULL, NULL, 0, NULL,
281 0,0, // dest, bit instruction
283 1, // literal operand
285 0, // fast call/return mode select bit
286 0, // second memory operand
287 0, // second literal operand
289 (PCC_W | PCC_LITERAL), // inCond
290 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
294 pCodeInstruction pic16_pciANDLW = {
295 {PC_OPCODE, NULL, NULL, 0, NULL,
308 0,0, // dest, bit instruction
310 1, // literal operand
312 0, // fast call/return mode select bit
313 0, // second memory operand
314 0, // second literal operand
316 (PCC_W | PCC_LITERAL), // inCond
317 (PCC_W | PCC_Z | PCC_N), // outCond
321 pCodeInstruction pic16_pciANDWF = {
322 {PC_OPCODE, NULL, NULL, 0, NULL,
335 1,0, // dest, bit instruction
337 0, // literal operand
339 0, // fast call/return mode select bit
340 0, // second memory operand
341 0, // second literal operand
343 (PCC_W | PCC_REGISTER), // inCond
344 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
348 pCodeInstruction pic16_pciANDFW = {
349 {PC_OPCODE, NULL, NULL, 0, NULL,
362 0,0, // dest, bit instruction
364 0, // literal operand
366 0, // fast call/return mode select bit
367 0, // second memory operand
368 0, // second literal operand
370 (PCC_W | PCC_REGISTER), // inCond
371 (PCC_W | PCC_Z) // outCond
374 pCodeInstruction pic16_pciBC = { // mdubuc - New
375 {PC_OPCODE, NULL, NULL, 0, NULL,
388 0,0, // dest, bit instruction
390 0, // literal operand
392 0, // fast call/return mode select bit
393 0, // second memory operand
394 0, // second literal operand
396 (PCC_REL_ADDR | PCC_C), // inCond
401 pCodeInstruction pic16_pciBCF = {
402 {PC_OPCODE, NULL, NULL, 0, NULL,
415 1,1, // dest, bit instruction
417 0, // literal operand
419 0, // fast call/return mode select bit
420 0, // second memory operand
421 0, // second literal operand
423 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
424 PCC_REGISTER, // outCond
428 pCodeInstruction pic16_pciBN = { // mdubuc - New
429 {PC_OPCODE, NULL, NULL, 0, NULL,
442 0,0, // dest, bit instruction
444 0, // literal operand
446 0, // fast call/return mode select bit
447 0, // second memory operand
448 0, // second literal operand
450 (PCC_REL_ADDR | PCC_N), // inCond
451 PCC_NONE , // outCond
455 pCodeInstruction pic16_pciBNC = { // mdubuc - New
456 {PC_OPCODE, NULL, NULL, 0, NULL,
469 0,0, // dest, bit instruction
471 0, // literal operand
473 0, // fast call/return mode select bit
474 0, // second memory operand
475 0, // second literal operand
477 (PCC_REL_ADDR | PCC_C), // inCond
478 PCC_NONE , // outCond
482 pCodeInstruction pic16_pciBNN = { // mdubuc - New
483 {PC_OPCODE, NULL, NULL, 0, NULL,
496 0,0, // dest, bit instruction
498 0, // literal operand
500 0, // fast call/return mode select bit
501 0, // second memory operand
502 0, // second literal operand
504 (PCC_REL_ADDR | PCC_N), // inCond
505 PCC_NONE , // outCond
509 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
510 {PC_OPCODE, NULL, NULL, 0, NULL,
523 0,0, // dest, bit instruction
525 0, // literal operand
527 0, // fast call/return mode select bit
528 0, // second memory operand
529 0, // second literal operand
531 (PCC_REL_ADDR | PCC_OV), // inCond
532 PCC_NONE , // outCond
536 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
537 {PC_OPCODE, NULL, NULL, 0, NULL,
550 0,0, // dest, bit instruction
552 0, // literal operand
554 0, // fast call/return mode select bit
555 0, // second memory operand
556 0, // second literal operand
558 (PCC_REL_ADDR | PCC_Z), // inCond
559 PCC_NONE , // outCond
563 pCodeInstruction pic16_pciBOV = { // mdubuc - New
564 {PC_OPCODE, NULL, NULL, 0, NULL,
577 0,0, // dest, bit instruction
579 0, // literal operand
581 0, // fast call/return mode select bit
582 0, // second memory operand
583 0, // second literal operand
585 (PCC_REL_ADDR | PCC_OV), // inCond
586 PCC_NONE , // outCond
590 pCodeInstruction pic16_pciBRA = { // mdubuc - New
591 {PC_OPCODE, NULL, NULL, 0, NULL,
604 0,0, // dest, bit instruction
606 0, // literal operand
608 0, // fast call/return mode select bit
609 0, // second memory operand
610 0, // second literal operand
612 PCC_REL_ADDR, // inCond
613 PCC_NONE , // outCond
617 pCodeInstruction pic16_pciBSF = {
618 {PC_OPCODE, NULL, NULL, 0, NULL,
631 1,1, // dest, bit instruction
633 0, // literal operand
635 0, // fast call/return mode select bit
636 0, // second memory operand
637 0, // second literal operand
639 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
640 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
644 pCodeInstruction pic16_pciBTFSC = {
645 {PC_OPCODE, NULL, NULL, 0, NULL,
658 0,1, // dest, bit instruction
660 0, // literal operand
662 0, // fast call/return mode select bit
663 0, // second memory operand
664 0, // second literal operand
666 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
667 PCC_EXAMINE_PCOP, // outCond
671 pCodeInstruction pic16_pciBTFSS = {
672 {PC_OPCODE, NULL, NULL, 0, NULL,
685 0,1, // dest, bit instruction
687 0, // literal operand
689 0, // fast call/return mode select bit
690 0, // second memory operand
691 0, // second literal operand
693 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
694 PCC_EXAMINE_PCOP, // outCond
698 pCodeInstruction pic16_pciBTG = { // mdubuc - New
699 {PC_OPCODE, NULL, NULL, 0, NULL,
712 0,1, // dest, bit instruction
714 0, // literal operand
716 0, // fast call/return mode select bit
717 0, // second memory operand
718 0, // second literal operand
720 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
721 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
725 pCodeInstruction pic16_pciBZ = { // mdubuc - New
726 {PC_OPCODE, NULL, NULL, 0, NULL,
739 0,0, // dest, bit instruction
741 0, // literal operand
743 0, // fast call/return mode select bit
744 0, // second memory operand
745 0, // second literal operand
752 pCodeInstruction pic16_pciCALL = {
753 {PC_OPCODE, NULL, NULL, 0, NULL,
766 0,0, // dest, bit instruction
768 0, // literal operand
770 1, // fast call/return mode select bit
771 0, // second memory operand
772 0, // second literal operand
775 PCC_NONE , // outCond
779 pCodeInstruction pic16_pciCOMF = {
780 {PC_OPCODE, NULL, NULL, 0, NULL,
793 1,0, // dest, bit instruction
795 0, // literal operand
797 0, // fast call/return mode select bit
798 0, // second memory operand
799 0, // second literal operand
801 PCC_REGISTER, // inCond
802 PCC_REGISTER , // outCond
806 pCodeInstruction pic16_pciCOMFW = {
807 {PC_OPCODE, NULL, NULL, 0, NULL,
820 0,0, // dest, bit instruction
822 0, // literal operand
824 0, // fast call/return mode select bit
825 0, // second memory operand
826 0, // second literal operand
828 PCC_REGISTER, // inCond
833 pCodeInstruction pic16_pciCLRF = {
834 {PC_OPCODE, NULL, NULL, 0, NULL,
847 0,0, // dest, bit instruction
849 0, // literal operand
851 0, // fast call/return mode select bit
852 0, // second memory operand
853 0, // second literal operand
855 PCC_REGISTER, // inCond
856 PCC_REGISTER , // outCond
860 pCodeInstruction pic16_pciCLRWDT = {
861 {PC_OPCODE, NULL, NULL, 0, NULL,
874 0,0, // dest, bit instruction
876 0, // literal operand
878 0, // fast call/return mode select bit
879 0, // second memory operand
880 0, // second literal operand
883 PCC_NONE , // outCond
887 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
888 {PC_OPCODE, NULL, NULL, 0, NULL,
901 0,0, // dest, bit instruction
903 0, // literal operand
905 0, // fast call/return mode select bit
906 0, // second memory operand
907 0, // second literal operand
909 (PCC_W | PCC_REGISTER), // inCond
910 PCC_NONE , // outCond
914 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
915 {PC_OPCODE, NULL, NULL, 0, NULL,
928 0,0, // dest, bit instruction
930 0, // literal operand
932 0, // fast call/return mode select bit
933 0, // second memory operand
934 0, // second literal operand
936 (PCC_W | PCC_REGISTER), // inCond
937 PCC_NONE , // outCond
941 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
942 {PC_OPCODE, NULL, NULL, 0, NULL,
955 1,0, // dest, bit instruction
957 0, // literal operand
959 0, // fast call/return mode select bit
960 0, // second memory operand
961 0, // second literal operand
963 (PCC_W | PCC_REGISTER), // inCond
964 PCC_NONE , // outCond
968 pCodeInstruction pic16_pciDAW = {
969 {PC_OPCODE, NULL, NULL, 0, NULL,
982 0,0, // dest, bit instruction
984 0, // literal operand
986 0, // fast call/return mode select bit
987 0, // second memory operand
988 0, // second literal operand
991 (PCC_W | PCC_C), // outCond
995 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
996 {PC_OPCODE, NULL, NULL, 0, NULL,
1002 NULL, // from branch
1009 1,0, // dest, bit instruction
1010 1,1, // branch, skip
1011 0, // literal operand
1012 1, // RAM access bit
1013 0, // fast call/return mode select bit
1014 0, // second memory operand
1015 0, // second literal operand
1017 PCC_REGISTER, // inCond
1018 PCC_REGISTER , // outCond
1022 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1023 {PC_OPCODE, NULL, NULL, 0, NULL,
1029 NULL, // from branch
1036 0,0, // dest, bit instruction
1037 1,1, // branch, skip
1038 0, // literal operand
1039 1, // RAM access bit
1040 0, // fast call/return mode select bit
1041 0, // second memory operand
1042 0, // second literal operand
1044 PCC_REGISTER, // inCond
1049 pCodeInstruction pic16_pciDECF = {
1050 {PC_OPCODE, NULL, NULL, 0, NULL,
1056 NULL, // from branch
1063 1,0, // dest, bit instruction
1064 0,0, // branch, skip
1065 0, // literal operand
1066 1, // RAM access bit
1067 0, // fast call/return mode select bit
1068 0, // second memory operand
1069 0, // second literal operand
1071 PCC_REGISTER, // inCond
1072 PCC_REGISTER , // outCond
1076 pCodeInstruction pic16_pciDECFW = {
1077 {PC_OPCODE, NULL, NULL, 0, NULL,
1083 NULL, // from branch
1090 0,0, // dest, bit instruction
1091 0,0, // branch, skip
1092 0, // literal operand
1093 1, // RAM access bit
1094 0, // fast call/return mode select bit
1095 0, // second memory operand
1096 0, // second literal operand
1098 PCC_REGISTER, // inCond
1103 pCodeInstruction pic16_pciDECFSZ = {
1104 {PC_OPCODE, NULL, NULL, 0, NULL,
1110 NULL, // from branch
1117 1,0, // dest, bit instruction
1118 1,1, // branch, skip
1119 0, // literal operand
1120 1, // RAM access bit
1121 0, // fast call/return mode select bit
1122 0, // second memory operand
1123 0, // second literal operand
1125 PCC_REGISTER, // inCond
1126 PCC_REGISTER , // outCond
1130 pCodeInstruction pic16_pciDECFSZW = {
1131 {PC_OPCODE, NULL, NULL, 0, NULL,
1137 NULL, // from branch
1144 0,0, // dest, bit instruction
1145 1,1, // branch, skip
1146 0, // literal operand
1147 1, // RAM access bit
1148 0, // fast call/return mode select bit
1149 0, // second memory operand
1150 0, // second literal operand
1152 PCC_REGISTER, // inCond
1157 pCodeInstruction pic16_pciGOTO = {
1158 {PC_OPCODE, NULL, NULL, 0, NULL,
1164 NULL, // from branch
1171 0,0, // dest, bit instruction
1172 1,0, // branch, skip
1173 0, // literal operand
1174 0, // RAM access bit
1175 0, // fast call/return mode select bit
1176 0, // second memory operand
1177 0, // second literal operand
1179 PCC_REL_ADDR, // inCond
1180 PCC_NONE , // outCond
1184 pCodeInstruction pic16_pciINCF = {
1185 {PC_OPCODE, NULL, NULL, 0, NULL,
1191 NULL, // from branch
1198 1,0, // dest, bit instruction
1199 0,0, // branch, skip
1200 0, // literal operand
1201 1, // RAM access bit
1202 0, // fast call/return mode select bit
1203 0, // second memory operand
1204 0, // second literal operand
1206 PCC_REGISTER, // inCond
1207 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1211 pCodeInstruction pic16_pciINCFW = {
1212 {PC_OPCODE, NULL, NULL, 0, NULL,
1218 NULL, // from branch
1225 0,0, // dest, bit instruction
1226 0,0, // branch, skip
1227 0, // literal operand
1228 1, // RAM access bit
1229 0, // fast call/return mode select bit
1230 0, // second memory operand
1231 0, // second literal operand
1233 PCC_REGISTER, // inCond
1238 pCodeInstruction pic16_pciINCFSZ = {
1239 {PC_OPCODE, NULL, NULL, 0, NULL,
1245 NULL, // from branch
1252 1,0, // dest, bit instruction
1253 1,1, // branch, skip
1254 0, // literal operand
1255 1, // RAM access bit
1256 0, // fast call/return mode select bit
1257 0, // second memory operand
1258 0, // second literal operand
1260 PCC_REGISTER, // inCond
1261 PCC_REGISTER , // outCond
1265 pCodeInstruction pic16_pciINCFSZW = {
1266 {PC_OPCODE, NULL, NULL, 0, NULL,
1272 NULL, // from branch
1279 0,0, // dest, bit instruction
1280 1,1, // branch, skip
1281 0, // literal operand
1282 1, // RAM access bit
1283 0, // fast call/return mode select bit
1284 0, // second memory operand
1285 0, // second literal operand
1287 PCC_REGISTER, // inCond
1292 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1293 {PC_OPCODE, NULL, NULL, 0, NULL,
1299 NULL, // from branch
1306 1,0, // dest, bit instruction
1307 1,1, // branch, skip
1308 0, // literal operand
1309 1, // RAM access bit
1310 0, // fast call/return mode select bit
1311 0, // second memory operand
1312 0, // second literal operand
1314 PCC_REGISTER, // inCond
1315 PCC_REGISTER , // outCond
1319 pCodeInstruction pic16_pciIORWF = {
1320 {PC_OPCODE, NULL, NULL, 0, NULL,
1326 NULL, // from branch
1333 1,0, // dest, bit instruction
1334 0,0, // branch, skip
1335 0, // literal operand
1336 1, // RAM access bit
1337 0, // fast call/return mode select bit
1338 0, // second memory operand
1339 0, // second literal operand
1341 (PCC_W | PCC_REGISTER), // inCond
1342 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1346 pCodeInstruction pic16_pciIORFW = {
1347 {PC_OPCODE, NULL, NULL, 0, NULL,
1353 NULL, // from branch
1360 0,0, // dest, bit instruction
1361 0,0, // branch, skip
1362 0, // literal operand
1363 1, // RAM access bit
1364 0, // fast call/return mode select bit
1365 0, // second memory operand
1366 0, // second literal operand
1368 (PCC_W | PCC_REGISTER), // inCond
1369 (PCC_W | PCC_Z | PCC_N), // outCond
1373 pCodeInstruction pic16_pciIORLW = {
1374 {PC_OPCODE, NULL, NULL, 0, NULL,
1380 NULL, // from branch
1387 0,0, // dest, bit instruction
1388 0,0, // branch, skip
1389 1, // literal operand
1390 0, // RAM access bit
1391 0, // fast call/return mode select bit
1392 0, // second memory operand
1393 0, // second literal operand
1395 (PCC_W | PCC_LITERAL), // inCond
1396 (PCC_W | PCC_Z | PCC_N), // outCond
1400 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1401 {PC_OPCODE, NULL, NULL, 0, NULL,
1407 NULL, // from branch
1414 0,0, // dest, bit instruction
1415 0,0, // branch, skip
1416 1, // literal operand
1417 0, // RAM access bit
1418 0, // fast call/return mode select bit
1419 0, // second memory operand
1420 1, // second literal operand
1422 (PCC_REGISTER | PCC_LITERAL),
1423 PCC_REGISTER, // outCond
1427 pCodeInstruction pic16_pciMOVF = {
1428 {PC_OPCODE, NULL, NULL, 0, NULL,
1434 NULL, // from branch
1441 1,0, // dest, bit instruction
1442 0,0, // branch, skip
1443 0, // literal operand
1444 1, // RAM access bit
1445 0, // fast call/return mode select bit
1446 0, // second memory operand
1447 0, // second literal operand
1449 PCC_REGISTER, // inCond
1450 (PCC_Z | PCC_N), // outCond
1454 pCodeInstruction pic16_pciMOVFW = {
1455 {PC_OPCODE, NULL, NULL, 0, NULL,
1461 NULL, // from branch
1468 0,0, // dest, bit instruction
1469 0,0, // branch, skip
1470 0, // literal operand
1471 1, // RAM access bit
1472 0, // fast call/return mode select bit
1473 0, // second memory operand
1474 0, // second literal operand
1476 PCC_REGISTER, // inCond
1477 (PCC_W | PCC_Z), // outCond
1481 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1482 {PC_OPCODE, NULL, NULL, 0, NULL,
1488 NULL, // from branch
1495 0,0, // dest, bit instruction
1496 0,0, // branch, skip
1497 0, // literal operand
1498 0, // RAM access bit
1499 0, // fast call/return mode select bit
1500 1, // second memory operand
1501 0, // second literal operand
1503 PCC_REGISTER, // inCond
1504 PCC_REGISTER2, // outCond
1508 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1509 {PC_OPCODE, NULL, NULL, 0, NULL,
1514 NULL, // from branch
1521 0,0, // dest, bit instruction
1522 0,0, // branch, skip
1523 1, // literal operand
1524 0, // RAM access bit
1525 0, // fast call/return mode select bit
1526 0, // second memory operand
1527 0, // second literal operand
1529 (PCC_NONE | PCC_LITERAL), // inCond
1530 PCC_REGISTER, // outCond - BSR
1534 pCodeInstruction pic16_pciMOVLW = {
1535 {PC_OPCODE, NULL, NULL, 0, NULL,
1540 NULL, // from branch
1547 0,0, // dest, bit instruction
1548 0,0, // branch, skip
1549 1, // literal operand
1550 0, // RAM access bit
1551 0, // fast call/return mode select bit
1552 0, // second memory operand
1553 0, // second literal operand
1555 (PCC_NONE | PCC_LITERAL), // inCond
1560 pCodeInstruction pic16_pciMOVWF = {
1561 {PC_OPCODE, NULL, NULL, 0, NULL,
1567 NULL, // from branch
1574 0,0, // dest, bit instruction
1575 0,0, // branch, skip
1576 0, // literal operand
1577 1, // RAM access bit
1578 0, // fast call/return mode select bit
1579 0, // second memory operand
1580 0, // second literal operand
1582 PCC_REGISTER, // inCond
1587 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1588 {PC_OPCODE, NULL, NULL, 0, NULL,
1593 NULL, // from branch
1600 0,0, // dest, bit instruction
1601 0,0, // branch, skip
1602 1, // literal operand
1603 0, // RAM access bit
1604 0, // fast call/return mode select bit
1605 0, // second memory operand
1606 0, // second literal operand
1608 (PCC_W | PCC_LITERAL), // inCond
1609 PCC_REGISTER, // outCond - PROD
1613 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1614 {PC_OPCODE, NULL, NULL, 0, NULL,
1619 NULL, // from branch
1626 0,0, // dest, bit instruction
1627 0,0, // branch, skip
1628 0, // literal operand
1629 1, // RAM access bit
1630 0, // fast call/return mode select bit
1631 0, // second memory operand
1632 0, // second literal operand
1634 (PCC_W | PCC_REGISTER), // inCond
1635 PCC_REGISTER, // outCond - PROD
1639 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1640 {PC_OPCODE, NULL, NULL, 0, NULL,
1645 NULL, // from branch
1652 0,0, // dest, bit instruction
1653 0,0, // branch, skip
1654 0, // literal operand
1655 1, // RAM access bit
1656 0, // fast call/return mode select bit
1657 0, // second memory operand
1658 0, // second literal operand
1660 PCC_REGISTER, // inCond
1661 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1665 pCodeInstruction pic16_pciNOP = {
1666 {PC_OPCODE, NULL, NULL, 0, NULL,
1671 NULL, // from branch
1678 0,0, // dest, bit instruction
1679 0,0, // branch, skip
1680 0, // literal operand
1681 0, // RAM access bit
1682 0, // fast call/return mode select bit
1683 0, // second memory operand
1684 0, // second literal operand
1687 PCC_NONE, // outCond
1691 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1692 {PC_OPCODE, NULL, NULL, 0, NULL,
1697 NULL, // from branch
1704 0,0, // dest, bit instruction
1705 0,0, // branch, skip
1706 0, // literal operand
1707 0, // RAM access bit
1708 0, // fast call/return mode select bit
1709 0, // second memory operand
1710 0, // second literal operand
1713 PCC_NONE , // outCond
1717 pCodeInstruction pic16_pciPUSH = {
1718 {PC_OPCODE, NULL, NULL, 0, NULL,
1723 NULL, // from branch
1730 0,0, // dest, bit instruction
1731 0,0, // branch, skip
1732 0, // literal operand
1733 0, // RAM access bit
1734 0, // fast call/return mode select bit
1735 0, // second memory operand
1736 0, // second literal operand
1739 PCC_NONE , // outCond
1743 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1744 {PC_OPCODE, NULL, NULL, 0, NULL,
1749 NULL, // from branch
1756 0,0, // dest, bit instruction
1757 0,0, // branch, skip
1758 0, // literal operand
1759 0, // RAM access bit
1760 0, // fast call/return mode select bit
1761 0, // second memory operand
1762 0, // second literal operand
1764 PCC_REL_ADDR, // inCond
1765 PCC_NONE , // outCond
1769 pCodeInstruction pic16_pciRETFIE = {
1770 {PC_OPCODE, NULL, NULL, 0, NULL,
1776 NULL, // from branch
1783 0,0, // dest, bit instruction
1784 1,0, // branch, skip
1785 0, // literal operand
1786 0, // RAM access bit
1787 1, // fast call/return mode select bit
1788 0, // second memory operand
1789 0, // second literal operand
1792 PCC_NONE, // outCond (not true... affects the GIE bit too)
1796 pCodeInstruction pic16_pciRETLW = {
1797 {PC_OPCODE, NULL, NULL, 0, NULL,
1803 NULL, // from branch
1810 0,0, // dest, bit instruction
1811 1,0, // branch, skip
1812 1, // literal operand
1813 0, // RAM access bit
1814 0, // fast call/return mode select bit
1815 0, // second memory operand
1816 0, // second literal operand
1818 PCC_LITERAL, // inCond
1823 pCodeInstruction pic16_pciRETURN = {
1824 {PC_OPCODE, NULL, NULL, 0, NULL,
1830 NULL, // from branch
1837 0,0, // dest, bit instruction
1838 1,0, // branch, skip
1839 0, // literal operand
1840 0, // RAM access bit
1841 1, // fast call/return mode select bit
1842 0, // second memory operand
1843 0, // second literal operand
1846 PCC_NONE, // outCond
1849 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1850 {PC_OPCODE, NULL, NULL, 0, NULL,
1856 NULL, // from branch
1863 1,0, // dest, bit instruction
1864 0,0, // branch, skip
1865 0, // literal operand
1866 1, // RAM access bit
1867 0, // fast call/return mode select bit
1868 0, // second memory operand
1869 0, // second literal operand
1871 (PCC_C | PCC_REGISTER), // inCond
1872 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1876 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1877 {PC_OPCODE, NULL, NULL, 0, NULL,
1883 NULL, // from branch
1890 0,0, // dest, bit instruction
1891 0,0, // branch, skip
1892 0, // literal operand
1893 1, // RAM access bit
1894 0, // fast call/return mode select bit
1895 0, // second memory operand
1896 0, // second literal operand
1898 (PCC_C | PCC_REGISTER), // inCond
1899 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1903 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1904 {PC_OPCODE, NULL, NULL, 0, NULL,
1910 NULL, // from branch
1917 1,0, // dest, bit instruction
1918 0,0, // branch, skip
1919 0, // literal operand
1920 1, // RAM access bit
1921 0, // fast call/return mode select bit
1922 0, // second memory operand
1923 0, // second literal operand
1925 PCC_REGISTER, // inCond
1926 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1929 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1930 {PC_OPCODE, NULL, NULL, 0, NULL,
1936 NULL, // from branch
1943 0,0, // dest, bit instruction
1944 0,0, // branch, skip
1945 0, // literal operand
1946 1, // RAM access bit
1947 0, // fast call/return mode select bit
1948 0, // second memory operand
1949 0, // second literal operand
1951 PCC_REGISTER, // inCond
1952 (PCC_W | PCC_Z | PCC_N), // outCond
1955 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1956 {PC_OPCODE, NULL, NULL, 0, NULL,
1962 NULL, // from branch
1969 1,0, // dest, bit instruction
1970 0,0, // branch, skip
1971 0, // literal operand
1972 1, // RAM access bit
1973 0, // fast call/return mode select bit
1974 0, // second memory operand
1975 0, // second literal operand
1977 (PCC_C | PCC_REGISTER), // inCond
1978 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1981 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1982 {PC_OPCODE, NULL, NULL, 0, NULL,
1988 NULL, // from branch
1995 0,0, // dest, bit instruction
1996 0,0, // branch, skip
1997 0, // literal operand
1998 1, // RAM access bit
1999 0, // fast call/return mode select bit
2000 0, // second memory operand
2001 0, // second literal operand
2003 (PCC_C | PCC_REGISTER), // inCond
2004 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2007 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2008 {PC_OPCODE, NULL, NULL, 0, NULL,
2014 NULL, // from branch
2021 1,0, // dest, bit instruction
2022 0,0, // branch, skip
2023 0, // literal operand
2024 1, // RAM access bit
2025 0, // fast call/return mode select bit
2026 0, // second memory operand
2027 0, // second literal operand
2029 PCC_REGISTER, // inCond
2030 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2034 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2035 {PC_OPCODE, NULL, NULL, 0, NULL,
2041 NULL, // from branch
2048 0,0, // dest, bit instruction
2049 0,0, // branch, skip
2050 0, // literal operand
2051 1, // RAM access bit
2052 0, // fast call/return mode select bit
2053 0, // second memory operand
2054 0, // second literal operand
2056 PCC_REGISTER, // inCond
2057 (PCC_W | PCC_Z | PCC_N), // outCond
2061 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2062 {PC_OPCODE, NULL, NULL, 0, NULL,
2068 NULL, // from branch
2075 0,0, // dest, bit instruction
2076 0,0, // branch, skip
2077 0, // literal operand
2078 1, // RAM access bit
2079 0, // fast call/return mode select bit
2080 0, // second memory operand
2081 0, // second literal operand
2083 PCC_REGISTER, // inCond
2084 PCC_REGISTER , // outCond
2088 pCodeInstruction pic16_pciSUBLW = {
2089 {PC_OPCODE, NULL, NULL, 0, NULL,
2095 NULL, // from branch
2102 0,0, // dest, bit instruction
2103 0,0, // branch, skip
2104 1, // literal operand
2105 0, // RAM access bit
2106 0, // fast call/return mode select bit
2107 0, // second memory operand
2108 0, // second literal operand
2110 (PCC_W | PCC_LITERAL), // inCond
2111 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2115 pCodeInstruction pic16_pciSUBFWB = {
2116 {PC_OPCODE, NULL, NULL, 0, NULL,
2122 NULL, // from branch
2129 1,0, // dest, bit instruction
2130 0,0, // branch, skip
2131 0, // literal operand
2132 1, // RAM access bit
2133 0, // fast call/return mode select bit
2134 0, // second memory operand
2135 0, // second literal operand
2137 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2138 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2142 pCodeInstruction pic16_pciSUBWF = {
2143 {PC_OPCODE, NULL, NULL, 0, NULL,
2149 NULL, // from branch
2156 1,0, // dest, bit instruction
2157 0,0, // branch, skip
2158 0, // literal operand
2159 1, // RAM access bit
2160 0, // fast call/return mode select bit
2161 0, // second memory operand
2162 0, // second literal operand
2164 (PCC_W | PCC_REGISTER), // inCond
2165 (PCC_REGISTER | PCC_Z), // outCond
2169 pCodeInstruction pic16_pciSUBFW = {
2170 {PC_OPCODE, NULL, NULL, 0, NULL,
2176 NULL, // from branch
2183 0,0, // dest, bit instruction
2184 0,0, // branch, skip
2185 0, // literal operand
2186 1, // RAM access bit
2187 0, // fast call/return mode select bit
2188 0, // second memory operand
2189 0, // second literal operand
2191 (PCC_W | PCC_REGISTER), // inCond
2192 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2196 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2197 {PC_OPCODE, NULL, NULL, 0, NULL,
2203 NULL, // from branch
2210 1,0, // dest, bit instruction
2211 0,0, // branch, skip
2212 0, // literal operand
2213 1, // RAM access bit
2214 0, // fast call/return mode select bit
2215 0, // second memory operand
2216 0, // second literal operand
2218 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2219 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2223 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2224 {PC_OPCODE, NULL, NULL, 0, NULL,
2230 NULL, // from branch
2237 0,0, // dest, bit instruction
2238 0,0, // branch, skip
2239 0, // literal operand
2240 1, // RAM access bit
2241 0, // fast call/return mode select bit
2242 0, // second memory operand
2243 0, // second literal operand
2245 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2246 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2250 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2251 {PC_OPCODE, NULL, NULL, 0, NULL,
2257 NULL, // from branch
2264 1,0, // dest, bit instruction
2265 0,0, // branch, skip
2266 0, // literal operand
2267 1, // RAM access bit
2268 0, // fast call/return mode select bit
2269 0, // second memory operand
2270 0, // second literal operand
2272 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2273 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2277 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2278 {PC_OPCODE, NULL, NULL, 0, NULL,
2284 NULL, // from branch
2291 0,0, // dest, bit instruction
2292 0,0, // branch, skip
2293 0, // literal operand
2294 1, // RAM access bit
2295 0, // fast call/return mode select bit
2296 0, // second memory operand
2297 0, // second literal operand
2299 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2300 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2304 pCodeInstruction pic16_pciSWAPF = {
2305 {PC_OPCODE, NULL, NULL, 0, NULL,
2311 NULL, // from branch
2318 1,0, // dest, bit instruction
2319 0,0, // branch, skip
2320 0, // literal operand
2321 1, // RAM access bit
2322 0, // fast call/return mode select bit
2323 0, // second memory operand
2324 0, // second literal operand
2326 (PCC_REGISTER), // inCond
2327 (PCC_REGISTER), // outCond
2331 pCodeInstruction pic16_pciSWAPFW = {
2332 {PC_OPCODE, NULL, NULL, 0, NULL,
2338 NULL, // from branch
2345 0,0, // dest, bit instruction
2346 0,0, // branch, skip
2347 0, // literal operand
2348 1, // RAM access bit
2349 0, // fast call/return mode select bit
2350 0, // second memory operand
2351 0, // second literal operand
2353 (PCC_REGISTER), // inCond
2358 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2359 {PC_OPCODE, NULL, NULL, 0, NULL,
2365 NULL, // from branch
2372 0,0, // dest, bit instruction
2373 1,1, // branch, skip
2374 0, // literal operand
2375 1, // RAM access bit
2376 0, // fast call/return mode select bit
2377 0, // second memory operand
2378 0, // second literal operand
2380 PCC_REGISTER, // inCond
2381 PCC_NONE, // outCond
2385 pCodeInstruction pic16_pciXORWF = {
2386 {PC_OPCODE, NULL, NULL, 0, NULL,
2392 NULL, // from branch
2399 1,0, // dest, bit instruction
2400 0,0, // branch, skip
2401 0, // literal operand
2402 1, // RAM access bit
2403 0, // fast call/return mode select bit
2404 0, // second memory operand
2405 0, // second literal operand
2407 (PCC_W | PCC_REGISTER), // inCond
2408 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2412 pCodeInstruction pic16_pciXORFW = {
2413 {PC_OPCODE, NULL, NULL, 0, NULL,
2419 NULL, // from branch
2426 0,0, // dest, bit instruction
2427 0,0, // branch, skip
2428 0, // literal operand
2429 1, // RAM access bit
2430 0, // fast call/return mode select bit
2431 0, // second memory operand
2432 0, // second literal operand
2434 (PCC_W | PCC_REGISTER), // inCond
2435 (PCC_W | PCC_Z | PCC_N), // outCond
2439 pCodeInstruction pic16_pciXORLW = {
2440 {PC_OPCODE, NULL, NULL, 0, NULL,
2446 NULL, // from branch
2453 0,0, // dest, bit instruction
2454 0,0, // branch, skip
2455 1, // literal operand
2456 1, // RAM access bit
2457 0, // fast call/return mode select bit
2458 0, // second memory operand
2459 0, // second literal operand
2461 (PCC_W | PCC_LITERAL), // inCond
2462 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2467 #define MAX_PIC16MNEMONICS 100
2468 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2470 //#define USE_VSNPRINTF
2473 #ifdef USE_VSNPRINTF
2474 // Alas, vsnprintf is not ANSI standard, and does not exist
2475 // on Solaris (and probably other non-Gnu flavored Unixes).
2477 /*-----------------------------------------------------------------*/
2478 /* SAFE_snprintf - like snprintf except the string pointer is */
2479 /* after the string has been printed to. This is */
2480 /* useful for printing to string as though if it */
2481 /* were a stream. */
2482 /*-----------------------------------------------------------------*/
2483 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2491 va_start(val, format);
2493 vsnprintf(*str, *size, format, val);
2499 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2500 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2509 // This version is *not* safe, despite the name.
2511 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2515 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2520 va_start(val, format);
2522 vsprintf(buffer, format, val);
2525 len = strlen(buffer);
2527 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2528 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2531 strcpy(*str, buffer);
2537 #endif // USE_VSNPRINTF
2540 extern void pic16_initStack(int base_address, int size);
2541 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2542 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2543 extern void pic16_init_pic(char *);
2545 void pic16_pCodeInitRegisters(void)
2547 static int initialized=0;
2554 pic16_initStack(0xfff, 8);
2555 pic16_init_pic(port->processor);
2557 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2558 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2559 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2560 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2561 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2563 // pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80); // deprecated !
2565 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2566 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2567 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2568 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2569 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2570 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2572 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2573 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2574 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2575 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2576 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2578 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2579 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2580 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2581 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2582 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2584 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2585 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2586 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2587 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2588 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2590 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2591 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2593 pic16_pc_status.rIdx = IDX_STATUS;
2594 pic16_pc_intcon.rIdx = IDX_INTCON;
2595 pic16_pc_pcl.rIdx = IDX_PCL;
2596 pic16_pc_pclath.rIdx = IDX_PCLATH;
2597 pic16_pc_wreg.rIdx = IDX_WREG;
2598 // pic16_pc_fsr0.rIdx = IDX_FSR0;
2599 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2600 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2601 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2602 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2603 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2604 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2605 pic16_pc_indf0.rIdx = IDX_INDF0;
2606 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2607 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2608 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2609 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2610 pic16_pc_indf1.rIdx = IDX_INDF1;
2611 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2612 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2613 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2614 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2615 pic16_pc_indf2.rIdx = IDX_INDF2;
2616 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2617 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2618 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2619 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2620 pic16_pc_prodl.rIdx = IDX_PRODL;
2621 pic16_pc_prodh.rIdx = IDX_PRODH;
2623 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2624 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2625 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2627 pic16_pc_kzero.rIdx = IDX_KZ;
2628 pic16_pc_wsave.rIdx = IDX_WSAVE;
2629 pic16_pc_ssave.rIdx = IDX_SSAVE;
2631 /* probably should put this in a separate initialization routine */
2632 pb_dead_pcodes = newpBlock();
2637 /*-----------------------------------------------------------------*/
2638 /* mnem2key - convert a pic mnemonic into a hash key */
2639 /* (BTW - this spreads the mnemonics quite well) */
2641 /*-----------------------------------------------------------------*/
2643 int mnem2key(char const *mnem)
2652 key += toupper(*mnem++) +1;
2656 return (key & 0x1f);
2661 void pic16initMnemonics(void)
2666 pCodeInstruction *pci;
2668 if(mnemonics_initialized)
2671 // NULL out the array before making the assignments
2672 // since we check the array contents below this initialization.
2674 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2675 pic16Mnemonics[i] = NULL;
2678 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2679 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2680 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2681 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2682 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2683 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2684 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2685 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2686 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2687 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2688 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2689 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2690 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2691 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2692 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2693 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2694 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2695 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2696 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2697 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2698 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2699 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2700 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2701 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2702 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2703 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2704 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2705 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2706 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2707 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2708 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2709 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2710 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2711 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2712 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2713 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2714 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2715 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2716 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2717 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2718 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2719 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2720 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2721 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2722 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2723 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2724 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2725 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2726 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2727 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2728 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2729 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2730 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2731 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2732 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2733 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2734 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2735 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2736 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2737 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2738 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2739 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2740 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2741 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2742 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF; // was [POC_RLCF] !!!
2743 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2744 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2745 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2746 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2747 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2748 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2749 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2750 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2751 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2752 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2753 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2754 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2755 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2756 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2757 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2758 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2759 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2760 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2761 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2763 for(i=0; i<MAX_PIC16MNEMONICS; i++)
2764 if(pic16Mnemonics[i])
2765 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2766 pci = hTabFirstItem(pic16MnemonicsHash, &key);
2769 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2770 pci = hTabNextItem(pic16MnemonicsHash, &key);
2773 mnemonics_initialized = 1;
2776 int pic16_getpCodePeepCommand(char *cmd);
2778 int pic16_getpCode(char *mnem,unsigned dest)
2781 pCodeInstruction *pci;
2782 int key = mnem2key(mnem);
2784 if(!mnemonics_initialized)
2785 pic16initMnemonics();
2787 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2791 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2792 if((pci->num_ops <= 1)
2793 || (pci->isModReg == dest)
2795 || (pci->num_ops <= 2 && pci->isAccess)
2796 || (pci->num_ops <= 2 && pci->isFastCall)
2797 || (pci->num_ops <= 2 && pci->is2MemOp)
2798 || (pci->num_ops <= 2 && pci->is2LitOp) )
2802 pci = hTabNextItemWK (pic16MnemonicsHash);
2809 /*-----------------------------------------------------------------*
2810 * pic16initpCodePeepCommands
2812 *-----------------------------------------------------------------*/
2813 void pic16initpCodePeepCommands(void)
2821 hTabAddItem(&pic16pCodePeepCommandsHash,
2822 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2824 } while (peepCommands[i].cmd);
2826 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2829 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
2830 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2835 /*-----------------------------------------------------------------
2838 *-----------------------------------------------------------------*/
2840 int pic16_getpCodePeepCommand(char *cmd)
2844 int key = mnem2key(cmd);
2847 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2850 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2851 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2855 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2862 static char getpBlock_dbName(pBlock *pb)
2868 return pb->cmemmap->dbName;
2872 void pic16_pBlockConvert2ISR(pBlock *pb)
2883 void pic16_pBlockConvert2Absolute(pBlock *pb)
2886 if(pb->cmemmap)pb->cmemmap = NULL;
2891 /*-----------------------------------------------------------------*/
2892 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
2893 /* instances to the front of the doubly linked */
2894 /* list of pBlocks */
2895 /*-----------------------------------------------------------------*/
2897 void pic16_movepBlock2Head(char dbName)
2902 /* this can happen in sources without code,
2903 * only variable definitions */
2904 if(!the_pFile)return;
2906 pb = the_pFile->pbHead;
2910 if(getpBlock_dbName(pb) == dbName) {
2911 pBlock *pbn = pb->next;
2912 pb->next = the_pFile->pbHead;
2913 the_pFile->pbHead->prev = pb;
2914 the_pFile->pbHead = pb;
2917 pb->prev->next = pbn;
2919 // If the pBlock that we just moved was the last
2920 // one in the link of all of the pBlocks, then we
2921 // need to point the tail to the block just before
2922 // the one we moved.
2923 // Note: if pb->next is NULL, then pb must have
2924 // been the last pBlock in the chain.
2927 pbn->prev = pb->prev;
2929 the_pFile->pbTail = pb->prev;
2940 void pic16_copypCode(FILE *of, char dbName)
2944 if(!of || !the_pFile)
2947 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2948 if(getpBlock_dbName(pb) == dbName) {
2949 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
2951 pic16_printpBlock(of,pb);
2956 void pic16_pcode_test(void)
2959 DFPRINTF((stderr,"pcode is alive!\n"));
2969 /* create the file name */
2970 strcpy(buffer,dstFileName);
2971 strcat(buffer,".p");
2973 if( !(pFile = fopen(buffer, "w" ))) {
2974 werror(E_FILE_OPEN_ERR,buffer);
2978 fprintf(pFile,"pcode dump\n\n");
2980 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2981 fprintf(pFile,"\n\tNew pBlock\n\n");
2983 fprintf(pFile,"%s",pb->cmemmap->sname);
2985 fprintf(pFile,"internal pblock");
2987 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2988 pic16_printpBlock(pFile,pb);
2992 /*-----------------------------------------------------------------*/
2993 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
2994 /* ister, RegCond will return the bit being referenced. */
2996 /* fixme - why not just OR in the pcop bit field */
2997 /*-----------------------------------------------------------------*/
2999 static int RegCond(pCodeOp *pcop)
3005 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3006 switch(PCORB(pcop)->bit) {
3020 /*-----------------------------------------------------------------*/
3021 /* pic16_newpCode - create and return a newly initialized pCode */
3023 /* fixme - rename this */
3025 /* The purpose of this routine is to create a new Instruction */
3026 /* pCode. This is called by gen.c while the assembly code is being */
3030 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3031 /* (note that the op is analogous to but not the */
3032 /* same thing as the opcode of the instruction.) */
3033 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3036 /* a pointer to the new malloc'd pCode is returned. */
3040 /*-----------------------------------------------------------------*/
3041 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3043 pCodeInstruction *pci ;
3045 if(!mnemonics_initialized)
3046 pic16initMnemonics();
3048 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3050 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3051 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3054 if(pci->inCond & PCC_EXAMINE_PCOP)
3055 pci->inCond |= RegCond(pcop);
3057 if(pci->outCond & PCC_EXAMINE_PCOP)
3058 pci->outCond |= RegCond(pcop);
3060 pci->pc.prev = pci->pc.next = NULL;
3061 return (pCode *)pci;
3064 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3070 /*-----------------------------------------------------------------*/
3071 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3073 /* Wild pcodes are used during the peep hole optimizer to serve */
3074 /* as place holders for any instruction. When a snippet of code is */
3075 /* compared to a peep hole rule, the wild card opcode will match */
3076 /* any instruction. However, the optional operand and label are */
3077 /* additional qualifiers that must also be matched before the */
3078 /* line (of assembly code) is declared matched. Note that the */
3079 /* operand may be wild too. */
3081 /* Note, a wild instruction is specified just like a wild var: */
3082 /* %4 ; A wild instruction, */
3083 /* See the peeph.def file for additional examples */
3085 /*-----------------------------------------------------------------*/
3087 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3092 pcw = Safe_calloc(1,sizeof(pCodeWild));
3094 pcw->pci.pc.type = PC_WILD;
3095 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3096 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3097 pcw->pci.pc.pb = NULL;
3099 // pcw->pci.pc.analyze = genericAnalyze;
3100 pcw->pci.pc.destruct = genericDestruct;
3101 pcw->pci.pc.print = genericPrint;
3103 pcw->id = pCodeID; // this is the 'n' in %n
3104 pcw->operand = optional_operand;
3105 pcw->label = optional_label;
3107 pcw->mustBeBitSkipInst = 0;
3108 pcw->mustNotBeBitSkipInst = 0;
3109 pcw->invertBitSkipInst = 0;
3111 return ( (pCode *)pcw);
3115 /*-----------------------------------------------------------------*/
3116 /* newPcodeInlineP - create a new pCode from a char string */
3117 /*-----------------------------------------------------------------*/
3120 pCode *pic16_newpCodeInlineP(char *cP)
3125 pcc = Safe_calloc(1,sizeof(pCodeComment));
3127 pcc->pc.type = PC_INLINE;
3128 pcc->pc.prev = pcc->pc.next = NULL;
3129 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3132 // pcc->pc.analyze = genericAnalyze;
3133 pcc->pc.destruct = genericDestruct;
3134 pcc->pc.print = genericPrint;
3137 pcc->comment = Safe_strdup(cP);
3139 pcc->comment = NULL;
3141 return ( (pCode *)pcc);
3145 /*-----------------------------------------------------------------*/
3146 /* newPcodeCharP - create a new pCode from a char string */
3147 /*-----------------------------------------------------------------*/
3149 pCode *pic16_newpCodeCharP(char *cP)
3154 pcc = Safe_calloc(1,sizeof(pCodeComment));
3156 pcc->pc.type = PC_COMMENT;
3157 pcc->pc.prev = pcc->pc.next = NULL;
3158 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3161 // pcc->pc.analyze = genericAnalyze;
3162 pcc->pc.destruct = genericDestruct;
3163 pcc->pc.print = genericPrint;
3166 pcc->comment = Safe_strdup(cP);
3168 pcc->comment = NULL;
3170 return ( (pCode *)pcc);
3174 /*-----------------------------------------------------------------*/
3175 /* pic16_newpCodeFunction - */
3176 /*-----------------------------------------------------------------*/
3179 pCode *pic16_newpCodeFunction(char *mod,char *f)
3183 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3185 pcf->pc.type = PC_FUNCTION;
3186 pcf->pc.prev = pcf->pc.next = NULL;
3187 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3190 // pcf->pc.analyze = genericAnalyze;
3191 pcf->pc.destruct = genericDestruct;
3192 pcf->pc.print = pCodePrintFunction;
3197 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3198 strcpy(pcf->modname,mod);
3200 pcf->modname = NULL;
3203 pcf->fname = Safe_calloc(1,strlen(f)+1);
3204 strcpy(pcf->fname,f);
3208 return ( (pCode *)pcf);
3212 /*-----------------------------------------------------------------*/
3213 /* pic16_newpCodeFlow */
3214 /*-----------------------------------------------------------------*/
3215 static void destructpCodeFlow(pCode *pc)
3217 if(!pc || !isPCFL(pc))
3224 pic16_unlinkpCode(pc);
3226 deleteSet(&PCFL(pc)->registers);
3227 deleteSet(&PCFL(pc)->from);
3228 deleteSet(&PCFL(pc)->to);
3233 pCode *pic16_newpCodeFlow(void )
3237 //_ALLOC(pcflow,sizeof(pCodeFlow));
3238 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3240 pcflow->pc.type = PC_FLOW;
3241 pcflow->pc.prev = pcflow->pc.next = NULL;
3242 pcflow->pc.pb = NULL;
3244 // pcflow->pc.analyze = genericAnalyze;
3245 pcflow->pc.destruct = destructpCodeFlow;
3246 pcflow->pc.print = genericPrint;
3248 pcflow->pc.seq = GpcFlowSeq++;
3250 pcflow->from = pcflow->to = NULL;
3252 pcflow->inCond = PCC_NONE;
3253 pcflow->outCond = PCC_NONE;
3255 pcflow->firstBank = -1;
3256 pcflow->lastBank = -1;
3258 pcflow->FromConflicts = 0;
3259 pcflow->ToConflicts = 0;
3263 pcflow->registers = newSet();
3265 return ( (pCode *)pcflow);
3269 /*-----------------------------------------------------------------*/
3270 /*-----------------------------------------------------------------*/
3271 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3273 pCodeFlowLink *pcflowLink;
3275 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3277 pcflowLink->pcflow = pcflow;
3278 pcflowLink->bank_conflict = 0;
3283 /*-----------------------------------------------------------------*/
3284 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3285 /*-----------------------------------------------------------------*/
3287 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3292 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3294 pccs->pc.type = PC_CSOURCE;
3295 pccs->pc.prev = pccs->pc.next = NULL;
3298 pccs->pc.destruct = genericDestruct;
3299 pccs->pc.print = genericPrint;
3301 pccs->line_number = ln;
3303 pccs->line = Safe_strdup(l);
3308 pccs->file_name = Safe_strdup(f);
3310 pccs->file_name = NULL;
3312 return ( (pCode *)pccs);
3317 /*******************************************************************/
3318 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3319 /* added by VR 6-Jun-2003 */
3320 /*******************************************************************/
3322 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3329 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3330 pcad->pc.type = PC_ASMDIR;
3331 pcad->pc.prev = pcad->pc.next = NULL;
3334 pcad->pc.destruct = genericDestruct;
3335 pcad->pc.print = genericPrint;
3337 if(asdir && *asdir) {
3339 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3341 pcad->directive = Safe_strdup( asdir );
3344 va_start(ap, argfmt);
3346 memset(buffer, 0, sizeof(buffer));
3347 if(argfmt && *argfmt)
3348 vsprintf(buffer, argfmt, ap);
3352 while(isspace(*lbp))lbp++;
3355 pcad->arg = Safe_strdup( lbp );
3357 return ((pCode *)pcad);
3360 /*-----------------------------------------------------------------*/
3361 /* pCodeLabelDestruct - free memory used by a label. */
3362 /*-----------------------------------------------------------------*/
3363 static void pCodeLabelDestruct(pCode *pc)
3369 if((pc->type == PC_LABEL) && PCL(pc)->label)
3370 free(PCL(pc)->label);
3376 pCode *pic16_newpCodeLabel(char *name, int key)
3382 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3384 pcl->pc.type = PC_LABEL;
3385 pcl->pc.prev = pcl->pc.next = NULL;
3386 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3389 // pcl->pc.analyze = genericAnalyze;
3390 pcl->pc.destruct = pCodeLabelDestruct;
3391 pcl->pc.print = pCodePrintLabel;
3397 sprintf(s,"_%05d_DS_",key);
3402 pcl->label = Safe_strdup(s);
3404 return ( (pCode *)pcl);
3409 /*-----------------------------------------------------------------*/
3410 /* newpBlock - create and return a pointer to a new pBlock */
3411 /*-----------------------------------------------------------------*/
3412 static pBlock *newpBlock(void)
3417 PpB = Safe_calloc(1,sizeof(pBlock) );
3418 PpB->next = PpB->prev = NULL;
3420 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3421 PpB->tregisters = NULL;
3423 PpB->FlowTree = NULL;
3429 /*-----------------------------------------------------------------*/
3430 /* pic16_newpCodeChain - create a new chain of pCodes */
3431 /*-----------------------------------------------------------------*
3433 * This function will create a new pBlock and the pointer to the
3434 * pCode that is passed in will be the first pCode in the block.
3435 *-----------------------------------------------------------------*/
3438 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3441 pBlock *pB = newpBlock();
3443 pB->pcHead = pB->pcTail = pc;
3450 /*-----------------------------------------------------------------*/
3451 /* pic16_newpCodeOpLabel - Create a new label given the key */
3452 /* Note, a negative key means that the label is part of wild card */
3453 /* (and hence a wild card label) used in the pCodePeep */
3454 /* optimizations). */
3455 /*-----------------------------------------------------------------*/
3457 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3460 static int label_key=-1;
3464 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3465 pcop->type = PO_LABEL;
3470 sprintf(s=buffer,"_%05d_DS_",key);
3472 s = name, key = label_key--;
3475 pcop->name = Safe_strdup(s);
3477 ((pCodeOpLabel *)pcop)->key = key;
3479 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3483 /*-----------------------------------------------------------------*/
3484 /*-----------------------------------------------------------------*/
3485 pCodeOp *pic16_newpCodeOpLit(int lit)
3491 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3492 pcop->type = PO_LITERAL;
3496 sprintf(s,"0x%02x",lit);
3498 pcop->name = Safe_strdup(s);
3501 ((pCodeOpLit *)pcop)->lit = lit;
3506 /*-----------------------------------------------------------------*/
3507 /*-----------------------------------------------------------------*/
3508 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3510 char *s = buffer, tbuf[256], *tb=tbuf;
3514 tb = pic16_get_op(arg2, NULL, 0);
3515 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3516 pcop->type = PO_LITERAL;
3520 sprintf(s,"0x%02x, %s",lit, tb);
3522 pcop->name = Safe_strdup(s);
3525 ((pCodeOpLit2 *)pcop)->lit = lit;
3526 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3531 /*-----------------------------------------------------------------*/
3532 /*-----------------------------------------------------------------*/
3533 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3537 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3538 pcop->type = PO_IMMEDIATE;
3540 regs *r = pic16_dirregWithName(name);
3541 pcop->name = Safe_strdup(name);
3545 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3546 PCOI(pcop)->rIdx = r->rIdx;
3548 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3549 // __FILE__, __LINE__, __FUNCTION__, name);
3550 PCOI(pcop)->rIdx = -1;
3552 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3557 PCOI(pcop)->index = index;
3558 PCOI(pcop)->offset = offset;
3559 PCOI(pcop)->_const = code_space;
3564 /*-----------------------------------------------------------------*/
3565 /*-----------------------------------------------------------------*/
3566 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3572 if(!pcwb || !subtype) {
3573 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3577 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3578 pcop->type = PO_WILD;
3579 sprintf(s,"%%%d",id);
3580 pcop->name = Safe_strdup(s);
3582 PCOW(pcop)->id = id;
3583 PCOW(pcop)->pcwb = pcwb;
3584 PCOW(pcop)->subtype = subtype;
3585 PCOW(pcop)->matched = NULL;
3590 /*-----------------------------------------------------------------*/
3591 /*-----------------------------------------------------------------*/
3592 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3596 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3597 pcop->type = PO_GPR_BIT;
3599 pcop->name = Safe_strdup(s);
3603 PCORB(pcop)->bit = bit;
3604 PCORB(pcop)->inBitSpace = inBitSpace;
3606 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3607 PCOR(pcop)->r = NULL;
3608 PCOR(pcop)->rIdx = 0;
3612 /*-----------------------------------------------------------------*
3613 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3615 * If rIdx >=0 then a specific register from the set of registers
3616 * will be selected. If rIdx <0, then a new register will be searched
3618 *-----------------------------------------------------------------*/
3620 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3624 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3629 PCOR(pcop)->rIdx = rIdx;
3630 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3632 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3635 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3637 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3638 __FUNCTION__, __LINE__);
3643 pcop->type = PCOR(pcop)->r->pc_type;
3648 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3653 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3654 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3655 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3656 pcop->type = PCOR(pcop)->r->pc_type;
3657 pcop->name = PCOR(pcop)->r->name;
3659 // if(pic16_pcode_verbose) {
3660 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3661 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3667 /*-----------------------------------------------------------------*/
3668 /*-----------------------------------------------------------------*/
3670 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3677 pcop = pic16_newpCodeOpBit(name, -1,0);
3681 pcop = pic16_newpCodeOpLit(-1);
3685 pcop = pic16_newpCodeOpLabel(NULL,-1);
3688 pcop = pic16_newpCodeOpReg(-1);
3691 case PO_GPR_REGISTER:
3693 pcop = pic16_newpCodeOpRegFromStr(name);
3695 pcop = pic16_newpCodeOpReg(-1);
3699 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3702 pcop->name = Safe_strdup(name);
3710 /*-----------------------------------------------------------------*/
3711 /*-----------------------------------------------------------------*/
3712 void pic16_pCodeConstString(char *name, char *value)
3716 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
3721 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3723 pic16_addpBlock(pb);
3725 sprintf(buffer,"; %s = %s",name,value);
3727 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3728 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3731 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3737 /*-----------------------------------------------------------------*/
3738 /*-----------------------------------------------------------------*/
3740 static void pCodeReadCodeTable(void)
3744 fprintf(stderr, " %s\n",__FUNCTION__);
3746 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3748 pic16_addpBlock(pb);
3750 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3751 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3752 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3753 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3755 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3756 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3757 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3758 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3763 /*-----------------------------------------------------------------*/
3764 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
3765 /*-----------------------------------------------------------------*/
3766 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3773 /* If this is the first pcode to be added to a block that
3774 * was initialized with a NULL pcode, then go ahead and
3775 * make this pcode the head and tail */
3776 pb->pcHead = pb->pcTail = pc;
3779 pb->pcTail->next = pc;
3781 pc->prev = pb->pcTail;
3788 /*-----------------------------------------------------------------*/
3789 /* pic16_addpBlock - place a pBlock into the pFile */
3790 /*-----------------------------------------------------------------*/
3791 void pic16_addpBlock(pBlock *pb)
3793 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3796 /* First time called, we'll pass through here. */
3797 //_ALLOC(the_pFile,sizeof(pFile));
3798 the_pFile = Safe_calloc(1,sizeof(pFile));
3799 the_pFile->pbHead = the_pFile->pbTail = pb;
3800 the_pFile->functions = NULL;
3804 the_pFile->pbTail->next = pb;
3805 pb->prev = the_pFile->pbTail;
3807 the_pFile->pbTail = pb;
3810 /*-----------------------------------------------------------------*/
3811 /* removepBlock - remove a pBlock from the pFile */
3812 /*-----------------------------------------------------------------*/
3813 static void removepBlock(pBlock *pb)
3821 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3823 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3826 if(pbs == the_pFile->pbHead)
3827 the_pFile->pbHead = pbs->next;
3829 if (pbs == the_pFile->pbTail)
3830 the_pFile->pbTail = pbs->prev;
3833 pbs->next->prev = pbs->prev;
3836 pbs->prev->next = pbs->next;
3843 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3847 /*-----------------------------------------------------------------*/
3848 /* printpCode - write the contents of a pCode to a file */
3849 /*-----------------------------------------------------------------*/
3850 static void printpCode(FILE *of, pCode *pc)
3861 fprintf(of,"warning - unable to print pCode\n");
3864 /*-----------------------------------------------------------------*/
3865 /* pic16_printpBlock - write the contents of a pBlock to a file */
3866 /*-----------------------------------------------------------------*/
3867 void pic16_printpBlock(FILE *of, pBlock *pb)
3876 if(pb->dbName == 'A') {
3880 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3882 // fprintf(of, "%s\tcode\t%d"
3886 for(pc = pb->pcHead; pc; pc = pc->next) {
3887 if(isPCF(pc) && PCF(pc)->fname) {
3888 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3889 if(pb->dbName == 'A') {
3891 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3892 if(strcmp(ab->name, PCF(pc)->fname)) {
3893 fprintf(of, "\t0X%06X", ab->address);
3903 /*-----------------------------------------------------------------*/
3905 /* pCode processing */
3909 /*-----------------------------------------------------------------*/
3911 void pic16_unlinkpCode(pCode *pc)
3917 fprintf(stderr,"Unlinking: ");
3918 printpCode(stderr, pc);
3921 pc->prev->next = pc->next;
3923 pc->next->prev = pc->prev;
3925 pc->prev = pc->next = NULL;
3929 /*-----------------------------------------------------------------*/
3930 /*-----------------------------------------------------------------*/
3932 static void genericDestruct(pCode *pc)
3935 pic16_unlinkpCode(pc);
3938 /* For instructions, tell the register (if there's one used)
3939 * that it's no longer needed */
3940 regs *reg = pic16_getRegFromInstruction(pc);
3942 deleteSetItem (&(reg->reglives.usedpCodes),pc);
3944 if(PCI(pc)->is2MemOp) {
3945 reg = pic16_getRegFromInstruction2(pc);
3947 deleteSetItem(&(reg->reglives.usedpCodes), pc);
3951 /* Instead of deleting the memory used by this pCode, mark
3952 * the object as bad so that if there's a pointer to this pCode
3953 * dangling around somewhere then (hopefully) when the type is
3954 * checked we'll catch it.
3959 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3967 /*-----------------------------------------------------------------*/
3968 /*-----------------------------------------------------------------*/
3969 /* modifiers for constant immediate */
3970 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3972 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3977 int use_buffer = 1; // copy the string to the passed buffer pointer
3982 use_buffer = 0; // Don't bother copying the string to the buffer.
3986 switch(pcop->type) {
3992 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3995 return PCOR(pcop)->r->name;
3998 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4000 SAFE_snprintf(&buffer,&size,"%s",r->name);
4007 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4008 if(PCOI(pcop)->index) {
4009 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4010 immdmod[ PCOI(pcop)->offset ],
4014 SAFE_snprintf(&s,&size,"%s(%s)",
4015 immdmod[ PCOI(pcop)->offset ],
4019 if(PCOI(pcop)->index) {
4020 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4025 SAFE_snprintf(&s,&size, "%s(%s)",
4034 // size = sizeof(buffer);
4035 if( PCOR(pcop)->instance) {
4036 SAFE_snprintf(&s,&size,"(%s + %d)",
4038 PCOR(pcop)->instance );
4040 SAFE_snprintf(&s,&size,"%s",pcop->name);
4047 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4056 return "NO operand1";
4059 /*-----------------------------------------------------------------*/
4060 /* pic16_get_op2 - variant to support two memory operand commands */
4061 /*-----------------------------------------------------------------*/
4062 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4067 int use_buffer = 1; // copy the string to the passed buffer pointer
4072 use_buffer = 0; // Don't bother copying the string to the buffer.
4076 fprintf(stderr, "%s:%d second operand %s is %d\tPO_DIR(%d) PO_GPR_TEMP(%d) PO_IMMEDIATE(%d) PO_INDF0(%d) PO_FSR0(%d)\n",
4077 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4078 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4082 switch(PCOR2(pcop)->pcop2->type) {
4088 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4091 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4094 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4097 SAFE_snprintf(&buffer,&size,"%s",r->name);
4108 if(PCOI(pcop)->_const) {
4109 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4110 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4113 8 * PCOI(pcop)->offset );
4115 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4117 if( PCOI(pcop)->index) {
4118 SAFE_snprintf(&s,&size,"(%s + %d)",
4120 PCOI(pcop)->index );
4122 if(PCOI(pcop)->offset)
4123 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4125 SAFE_snprintf(&s,&size,"%s",pcop->name);
4132 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4133 SAFE_snprintf(&s,&size,"(%s + %d)",
4134 PCOR(PCOR2(pcop)->pcop2)->r->name,
4135 PCOR(PCOR2(pcop)->pcop2)->instance );
4137 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4142 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4144 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4147 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4152 return "NO operand2";
4155 /*-----------------------------------------------------------------*/
4156 /*-----------------------------------------------------------------*/
4157 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4161 return pic16_get_op(pcc->pcop,NULL,0);
4163 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4164 * return ("ERROR Null: "__FUNCTION__);
4166 return ("ERROR Null: pic16_get_op_from_instruction");
4170 /*-----------------------------------------------------------------*/
4171 /*-----------------------------------------------------------------*/
4172 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4175 fprintf(of,"pcodeopprint- not implemented\n");
4178 /*-----------------------------------------------------------------*/
4179 /* pic16_pCode2str - convert a pCode instruction to string */
4180 /*-----------------------------------------------------------------*/
4181 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4187 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4188 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4189 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4197 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4199 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4201 if(PCI(pc)->is2MemOp) {
4202 SAFE_snprintf(&s,&size, "%s, %s",
4203 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4204 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4208 if(PCI(pc)->is2LitOp) {
4209 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4213 if(PCI(pc)->isBitInst) {
4214 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4215 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4216 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4217 PCI(pc)->pcop->name ,
4218 PCI(pc)->pcop->name );
4220 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4221 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4222 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4223 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4225 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4226 //PCI(pc)->pcop->t.bit );
4229 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4230 if( PCI(pc)->num_ops == 3)
4231 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4233 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4236 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4238 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4239 if(PCI(pc)->num_ops == 3)
4240 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4242 r = pic16_getRegFromInstruction(pc);
4243 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4244 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4246 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4255 /* assuming that comment ends with a \n */
4256 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4260 /* assuming that inline code ends with a \n */
4261 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4265 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4268 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4271 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4274 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4277 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4280 SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4284 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4291 /*-----------------------------------------------------------------*/
4292 /* genericPrint - the contents of a pCode to a file */
4293 /*-----------------------------------------------------------------*/
4294 static void genericPrint(FILE *of, pCode *pc)
4302 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4306 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4310 // If the opcode has a label, print that first
4312 pBranch *pbl = PCI(pc)->label;
4313 while(pbl && pbl->pc) {
4314 if(pbl->pc->type == PC_LABEL)
4315 pCodePrintLabel(of, pbl->pc);
4321 genericPrint(of,PCODE(PCI(pc)->cline));
4326 pic16_pCode2str(str, 256, pc);
4328 fprintf(of,"%s",str);
4330 if(pic16_debug_verbose) {
4331 fprintf(of, "\t;key=%03x",pc->seq);
4333 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4340 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4341 if(PCW(pc)->pci.label)
4342 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4344 if(PCW(pc)->operand) {
4345 fprintf(of,";\toperand ");
4346 pCodeOpPrint(of,PCW(pc)->operand );
4351 if(pic16_debug_verbose) {
4352 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4353 if(PCFL(pc)->ancestor)
4354 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4361 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4365 pBranch *pbl = PCAD(pc)->label;
4366 while(pbl && pbl->pc) {
4367 if(pbl->pc->type == PC_LABEL)
4368 pCodePrintLabel(of, pbl->pc);
4372 fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4377 fprintf(of,"unknown pCode type %d\n",pc->type);
4382 /*-----------------------------------------------------------------*/
4383 /* pCodePrintFunction - prints function begin/end */
4384 /*-----------------------------------------------------------------*/
4386 static void pCodePrintFunction(FILE *of, pCode *pc)
4393 if( ((pCodeFunction *)pc)->modname)
4394 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4397 if(PCF(pc)->fname) {
4398 pBranch *exits = PCF(pc)->to;
4400 fprintf(of,"%s", PCF(pc)->fname);
4402 // if(pic16_pcode_verbose)
4403 fprintf(of, "\t;Function start");
4409 exits = exits->next;
4413 if(pic16_pcode_verbose)
4414 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4417 if((PCF(pc)->from &&
4418 PCF(pc)->from->pc->type == PC_FUNCTION &&
4419 PCF(PCF(pc)->from->pc)->fname) ) {
4421 if(pic16_pcode_verbose)
4422 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4424 if(pic16_pcode_verbose)
4425 fprintf(of,"; exit point [can't find entry point]\n");
4430 /*-----------------------------------------------------------------*/
4431 /* pCodePrintLabel - prints label */
4432 /*-----------------------------------------------------------------*/
4434 static void pCodePrintLabel(FILE *of, pCode *pc)
4441 fprintf(of,"%s:\n",PCL(pc)->label);
4442 else if (PCL(pc)->key >=0)
4443 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4445 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4448 /*-----------------------------------------------------------------*/
4449 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4450 /* remove it if it is found. */
4451 /*-----------------------------------------------------------------*/
4452 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4459 if(pcl->type == PC_OPCODE)
4460 b = PCI(pcl)->label;
4462 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4467 //fprintf (stderr, "%s \n",__FUNCTION__);
4468 //pcl->print(stderr,pcl);
4469 //pc->print(stderr,pc);
4472 //fprintf (stderr, "found label\n");
4476 bprev->next = b->next; /* Not first pCode in chain */
4480 PCI(pcl)->label = b->next; /* First pCode in chain */
4483 return; /* A label can't occur more than once */
4491 /*-----------------------------------------------------------------*/
4492 /*-----------------------------------------------------------------*/
4493 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4512 /*-----------------------------------------------------------------*/
4513 /* pBranchLink - given two pcodes, this function will link them */
4514 /* together through their pBranches */
4515 /*-----------------------------------------------------------------*/
4516 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4520 // Declare a new branch object for the 'from' pCode.
4522 //_ALLOC(b,sizeof(pBranch));
4523 b = Safe_calloc(1,sizeof(pBranch));
4524 b->pc = PCODE(t); // The link to the 'to' pCode.
4527 f->to = pic16_pBranchAppend(f->to,b);
4529 // Now do the same for the 'to' pCode.
4531 //_ALLOC(b,sizeof(pBranch));
4532 b = Safe_calloc(1,sizeof(pBranch));
4536 t->from = pic16_pBranchAppend(t->from,b);
4541 /*-----------------------------------------------------------------*/
4542 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4544 /*-----------------------------------------------------------------*/
4545 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4558 /*-----------------------------------------------------------------*/
4559 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4560 /*-----------------------------------------------------------------*/
4561 static void pCodeUnlink(pCode *pc)
4566 if(!pc->prev || !pc->next) {
4567 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4571 /* first remove the pCode from the chain */
4572 pc->prev->next = pc->next;
4573 pc->next->prev = pc->prev;
4575 /* Now for the hard part... */
4577 /* Remove the branches */
4581 pc1 = pb1->pc; /* Get the pCode that branches to the
4582 * one we're unlinking */
4584 /* search for the link back to this pCode (the one we're
4586 if(pb2 = pBranchFind(pc1->to,pc)) {
4587 pb2->pc = pc->to->pc; // make the replacement
4589 /* if the pCode we're unlinking contains multiple 'to'
4590 * branches (e.g. this a skip instruction) then we need
4591 * to copy these extra branches to the chain. */
4593 pic16_pBranchAppend(pb2, pc->to->next);
4602 /*-----------------------------------------------------------------*/
4603 /*-----------------------------------------------------------------*/
4605 static void genericAnalyze(pCode *pc)
4615 // Go through the pCodes that are in pCode chain and link
4616 // them together through the pBranches. Note, the pCodes
4617 // are linked together as a contiguous stream like the
4618 // assembly source code lines. The linking here mimics this
4619 // except that comments are not linked in.
4621 pCode *npc = pc->next;
4623 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4624 pBranchLink(pc,npc);
4629 /* reached the end of the pcode chain without finding
4630 * an instruction we could link to. */
4634 fprintf(stderr,"analyze PC_FLOW\n");
4638 fprintf(stderr,,";A bad pCode is being used\n");
4644 /*-----------------------------------------------------------------*/
4645 /*-----------------------------------------------------------------*/
4646 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4650 if(pc->type == PC_LABEL) {
4651 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4654 if(pc->type == PC_OPCODE) {
4655 pbr = PCI(pc)->label;
4657 if(pbr->pc->type == PC_LABEL) {
4658 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4668 /*-----------------------------------------------------------------*/
4669 /*-----------------------------------------------------------------*/
4670 static int checkLabel(pCode *pc)
4674 if(pc && isPCI(pc)) {
4675 pbr = PCI(pc)->label;
4677 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4687 /*-----------------------------------------------------------------*/
4688 /* findLabelinpBlock - Search the pCode for a particular label */
4689 /*-----------------------------------------------------------------*/
4690 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4697 for(pc = pb->pcHead; pc; pc = pc->next)
4698 if(compareLabel(pc,pcop_label))
4704 /*-----------------------------------------------------------------*/
4705 /* findLabel - Search the pCode for a particular label */
4706 /*-----------------------------------------------------------------*/
4707 static pCode * findLabel(pCodeOpLabel *pcop_label)
4715 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4716 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4720 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4724 /*-----------------------------------------------------------------*/
4725 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
4726 /* in the linked list */
4727 /*-----------------------------------------------------------------*/
4728 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4741 /*-----------------------------------------------------------------*/
4742 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
4743 /* in the linked list */
4744 /*-----------------------------------------------------------------*/
4745 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4757 /*-----------------------------------------------------------------*/
4758 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4759 /* in the linked list */
4760 /*-----------------------------------------------------------------*/
4761 pCode * pic16_findNextInstruction(pCode *pci)
4766 if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4770 fprintf(stderr,"pic16_findNextInstruction: ");
4771 printpCode(stderr, pc);
4776 //fprintf(stderr,"Couldn't find instruction\n");
4780 /*-----------------------------------------------------------------*/
4781 /* pic16_findNextInstruction - given a pCode, find the next instruction */
4782 /* in the linked list */
4783 /*-----------------------------------------------------------------*/
4784 pCode * pic16_findPrevInstruction(pCode *pci)
4786 return findPrevpCode(pci, PC_OPCODE);
4789 /*-----------------------------------------------------------------*/
4790 /* findFunctionEnd - given a pCode find the end of the function */
4791 /* that contains it */
4792 /*-----------------------------------------------------------------*/
4793 static pCode * findFunctionEnd(pCode *pc)
4797 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
4803 fprintf(stderr,"Couldn't find function end\n");
4808 /*-----------------------------------------------------------------*/
4809 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
4810 /* instruction with which it is associated. */
4811 /*-----------------------------------------------------------------*/
4812 static void AnalyzeLabel(pCode *pc)
4821 static void AnalyzeGOTO(pCode *pc)
4824 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4828 static void AnalyzeSKIP(pCode *pc)
4831 pBranchLink(pc,pic16_findNextInstruction(pc->next));
4832 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4836 static void AnalyzeRETURN(pCode *pc)
4839 // branch_link(pc,findFunctionEnd(pc->next));
4845 /*-----------------------------------------------------------------*/
4846 /*-----------------------------------------------------------------*/
4847 regs * pic16_getRegFromInstruction(pCode *pc)
4853 PCI(pc)->num_ops == 0 ||
4854 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4858 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
4859 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
4862 switch(PCI(pc)->pcop->type) {
4868 return PCOR(PCI(pc)->pcop)->r;
4870 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4874 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4875 return PCOR(PCI(pc)->pcop)->r;
4878 if(PCOI(PCI(pc)->pcop)->r)
4879 return (PCOI(PCI(pc)->pcop)->r);
4881 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4882 return pic16_dirregWithName(PCI(pc)->pcop->name);
4883 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4886 return PCOR(PCI(pc)->pcop)->r;
4889 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4890 return PCOR(PCI(pc)->pcop)->r;
4892 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4896 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4897 // genericPrint(stderr, pc);
4905 /*-------------------------------------------------------------------------------*/
4906 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4907 /*-------------------------------------------------------------------------------*/
4908 regs * pic16_getRegFromInstruction2(pCode *pc)
4914 PCI(pc)->num_ops == 0 ||
4915 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
4920 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
4921 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
4925 * operands supported in MOVFF:
4932 switch(PCI(pc)->pcop->type) {
4938 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4940 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4944 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
4945 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4950 // if(PCOI(PCI(pc)->pcop)->r)
4951 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
4953 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
4954 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
4955 //return NULL; // PCOR(PCI(pc)->pcop)->r;
4960 // return PCOR2(PCI(pc)->pcop)->r;
4963 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
4964 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4968 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
4971 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
4972 //genericPrint(stderr, pc);
4980 /*-----------------------------------------------------------------*/
4981 /*-----------------------------------------------------------------*/
4983 static void AnalyzepBlock(pBlock *pb)
4990 /* Find all of the registers used in this pBlock
4991 * by looking at each instruction and examining it's
4994 for(pc = pb->pcHead; pc; pc = pc->next) {
4996 /* Is this an instruction with operands? */
4997 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4999 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5001 /* Loop through all of the registers declared so far in
5002 this block and see if we find this one there */
5004 regs *r = setFirstItem(pb->tregisters);
5007 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5008 PCOR(PCI(pc)->pcop)->r = r;
5011 r = setNextItem(pb->tregisters);
5015 /* register wasn't found */
5016 //r = Safe_calloc(1, sizeof(regs));
5017 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5018 //addSet(&pb->tregisters, r);
5019 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5020 //PCOR(PCI(pc)->pcop)->r = r;
5021 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5023 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5026 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5027 if(PCOR(PCI(pc)->pcop)->r) {
5028 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5029 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5031 if(PCI(pc)->pcop->name)
5032 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5034 fprintf(stderr,"ERROR: NULL register\n");
5043 /*-----------------------------------------------------------------*/
5045 /*-----------------------------------------------------------------*/
5046 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5048 static void InsertpFlow(pCode *pc, pCode **pflow)
5051 PCFL(*pflow)->end = pc;
5053 if(!pc || !pc->next)
5056 *pflow = pic16_newpCodeFlow();
5057 pic16_pCodeInsertAfter(pc, *pflow);
5060 /*-----------------------------------------------------------------*/
5061 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5062 /* the flow blocks. */
5064 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5065 * point the instruction flow changes.
5067 /*-----------------------------------------------------------------*/
5068 void pic16_BuildFlow(pBlock *pb)
5071 pCode *last_pci=NULL;
5078 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5079 /* Insert a pCodeFlow object at the beginning of a pBlock */
5081 InsertpFlow(pb->pcHead, &pflow);
5083 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5084 //pflow->next = pb->pcHead; /* Make the current head the next object */
5085 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5086 //pb->pcHead = pflow; /* Make the Flow object the head */
5089 for( pc = pic16_findNextInstruction(pb->pcHead);
5091 pc=pic16_findNextInstruction(pc)) {
5094 PCI(pc)->pcflow = PCFL(pflow);
5096 //fprintf(stderr," build: ");
5097 //pflow->print(stderr,pflow);
5099 if( PCI(pc)->isSkip) {
5101 /* The two instructions immediately following this one
5102 * mark the beginning of a new flow segment */
5104 while(pc && PCI(pc)->isSkip) {
5106 PCI(pc)->pcflow = PCFL(pflow);
5110 InsertpFlow(pc, &pflow);
5111 pc=pic16_findNextInstruction(pc->next);
5119 PCI(pc)->pcflow = PCFL(pflow);
5121 InsertpFlow(pc, &pflow);
5123 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5125 InsertpFlow(pc, &pflow);
5128 } else if (checkLabel(pc)) {
5130 /* This instruction marks the beginning of a
5131 * new flow segment */
5136 /* If the previous pCode is not a flow object, then
5137 * insert a new flow object. (This check prevents
5138 * two consecutive flow objects from being insert in
5139 * the case where a skip instruction preceeds an
5140 * instruction containing a label.) */
5142 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5143 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5145 PCI(pc)->pcflow = PCFL(pflow);
5152 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5154 PCFL(pflow)->end = pb->pcTail;
5157 /*-------------------------------------------------------------------*/
5158 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5159 /* the flow blocks. */
5161 * unBuildFlow removes pCodeFlow objects from a pCode chain
5163 /*-----------------------------------------------------------------*/
5164 static void unBuildFlow(pBlock *pb)
5179 if(PCI(pc)->pcflow) {
5180 //free(PCI(pc)->pcflow);
5181 PCI(pc)->pcflow = NULL;
5184 } else if(isPCFL(pc) )
5193 /*-----------------------------------------------------------------*/
5194 /*-----------------------------------------------------------------*/
5195 static void dumpCond(int cond)
5198 static char *pcc_str[] = {
5213 int ncond = sizeof(pcc_str) / sizeof(char *);
5216 fprintf(stderr, "0x%04X\n",cond);
5218 for(i=0,j=1; i<ncond; i++, j<<=1)
5220 fprintf(stderr, " %s\n",pcc_str[i]);
5226 /*-----------------------------------------------------------------*/
5227 /*-----------------------------------------------------------------*/
5228 static void FlowStats(pCodeFlow *pcflow)
5236 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5238 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5241 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5246 fprintf(stderr, " FlowStats inCond: ");
5247 dumpCond(pcflow->inCond);
5248 fprintf(stderr, " FlowStats outCond: ");
5249 dumpCond(pcflow->outCond);
5253 /*-----------------------------------------------------------------*
5254 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5255 * if it affects the banking bits.
5257 * return: -1 == Banking bits are unaffected by this pCode.
5259 * return: > 0 == Banking bits are affected.
5261 * If the banking bits are affected, then the returned value describes
5262 * which bits are affected and how they're affected. The lower half
5263 * of the integer maps to the bits that are affected, the upper half
5264 * to whether they're set or cleared.
5266 *-----------------------------------------------------------------*/
5268 static int isBankInstruction(pCode *pc)
5276 if( PCI(pc)->op == POC_MOVLB ||
5277 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5278 bank = PCOL(pc)->lit;
5285 /*-----------------------------------------------------------------*/
5286 /*-----------------------------------------------------------------*/
5287 static void FillFlow(pCodeFlow *pcflow)
5296 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5298 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5301 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5308 isBankInstruction(pc);
5310 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5314 fprintf(stderr, " FillFlow - Bad end of flow\n");
5316 fprintf(stderr, " FillFlow - Ending flow with\n ");
5317 pc->print(stderr,pc);
5320 fprintf(stderr, " FillFlow inCond: ");
5321 dumpCond(pcflow->inCond);
5322 fprintf(stderr, " FillFlow outCond: ");
5323 dumpCond(pcflow->outCond);
5327 /*-----------------------------------------------------------------*/
5328 /*-----------------------------------------------------------------*/
5329 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5331 pCodeFlowLink *fromLink, *toLink;
5333 if(!from || !to || !to->pcflow || !from->pcflow)
5336 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5337 toLink = pic16_newpCodeFlowLink(to->pcflow);
5339 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5340 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5344 /*-----------------------------------------------------------------*
5345 * void LinkFlow(pBlock *pb)
5347 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5348 * non-branching segments. In LinkFlow, we determine the execution
5349 * order of these segments. For example, if one of the segments ends
5350 * with a skip, then we know that there are two possible flow segments
5351 * to which control may be passed.
5352 *-----------------------------------------------------------------*/
5353 static void LinkFlow(pBlock *pb)
5359 //fprintf(stderr,"linkflow \n");
5361 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5363 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5366 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5368 //fprintf(stderr," link: ");
5369 //pcflow->print(stderr,pcflow);
5371 //FillFlow(PCFL(pcflow));
5373 pc = PCFL(pcflow)->end;
5375 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5376 if(isPCI_SKIP(pc)) {
5377 //fprintf(stderr, "ends with skip\n");
5378 //pc->print(stderr,pc);
5379 pct=pic16_findNextInstruction(pc->next);
5380 LinkFlow_pCode(PCI(pc),PCI(pct));
5381 pct=pic16_findNextInstruction(pct->next);
5382 LinkFlow_pCode(PCI(pc),PCI(pct));
5386 if(isPCI_BRANCH(pc)) {
5387 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5389 //fprintf(stderr, "ends with branch\n ");
5390 //pc->print(stderr,pc);
5392 if(!(pcol && isPCOLAB(pcol))) {
5393 if((PCI(pc)->op != POC_RETLW)
5394 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5396 /* continue if label is '$' which assembler knows how to parse */
5397 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5399 pc->print(stderr,pc);
5400 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5405 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5406 LinkFlow_pCode(PCI(pc),PCI(pct));
5408 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5409 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5410 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5416 //fprintf(stderr, "ends with non-branching instruction:\n");
5417 //pc->print(stderr,pc);
5419 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5425 //fprintf(stderr, "ends with unknown\n");
5426 //pc->print(stderr,pc);
5430 //fprintf(stderr, "ends with nothing: ERROR\n");
5434 /*-----------------------------------------------------------------*/
5435 /*-----------------------------------------------------------------*/
5437 /*-----------------------------------------------------------------*/
5438 /*-----------------------------------------------------------------*/
5439 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5445 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5448 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5458 /*-----------------------------------------------------------------*/
5459 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5460 /*-----------------------------------------------------------------*/
5461 static void insertBankSwitch(int position, pCode *pc, int bsr)
5470 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5471 * insert a BANKSEL assembler directive for the symbol used by
5472 * the pCode. This will allow the linker to setup the correct
5473 * bank at linking time
5476 if(!pic16_options.gen_banksel || bsr != -1) {
5477 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5480 /* emit the BANKSEL [symbol] */
5483 /* IMPORTANT: The following code does not check if a symbol is
5484 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5486 reg = pic16_getRegFromInstruction(pc);
5488 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5490 position = 0; // position is always before (sanity check!)
5494 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5495 pc->print(stderr, pc);
5499 /* insert the bank switch after this pc instruction */
5500 pCode *pcnext = pic16_findNextInstruction(pc);
5501 pic16_pCodeInsertAfter(pc, new_pc);
5506 pic16_pCodeInsertAfter(pc->prev, new_pc);
5508 /* Move the label, if there is one */
5510 if(PCI(pc)->label) {
5511 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5512 // __FILE__, __LINE__, pc, new_pc);
5513 PCAD(new_pc)->label = PCI(pc)->label;
5514 PCI(pc)->label = NULL;
5517 // fprintf(stderr, "BankSwitch has been inserted\n");
5521 /*-----------------------------------------------------------------*/
5522 /*int compareBankFlow - compare the banking requirements between */
5524 /*-----------------------------------------------------------------*/
5525 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5528 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5531 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5534 if(pcflow->firstBank == -1)
5538 if(pcflowLink->pcflow->firstBank == -1) {
5539 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5540 pcflowLink->pcflow->to :
5541 pcflowLink->pcflow->from);
5542 return compareBankFlow(pcflow, pctl, toORfrom);
5546 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5549 pcflowLink->bank_conflict++;
5550 pcflowLink->pcflow->FromConflicts++;
5551 pcflow->ToConflicts++;
5554 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5557 pcflowLink->bank_conflict++;
5558 pcflowLink->pcflow->ToConflicts++;
5559 pcflow->FromConflicts++;
5563 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5564 pcflowLink->pcflow->pc.seq,
5565 pcflowLink->pcflow->FromConflicts,
5566 pcflowLink->pcflow->ToConflicts);
5573 /*-----------------------------------------------------------------*/
5574 /*-----------------------------------------------------------------*/
5575 static void DumpFlow(pBlock *pb)
5579 pCodeFlowLink *pcfl;
5582 fprintf(stderr,"Dump flow \n");
5583 pb->pcHead->print(stderr, pb->pcHead);
5585 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5586 pcflow->print(stderr,pcflow);
5588 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5590 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5592 if(!isPCFL(pcflow)) {
5593 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5596 fprintf(stderr,"dumping: ");
5597 pcflow->print(stderr,pcflow);
5598 FlowStats(PCFL(pcflow));
5600 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5602 pc = PCODE(pcfl->pcflow);
5604 fprintf(stderr, " from seq %d:\n",pc->seq);
5606 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5607 pc->print(stderr,pc);
5612 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5614 pc = PCODE(pcfl->pcflow);
5616 fprintf(stderr, " to seq %d:\n",pc->seq);
5618 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5619 pc->print(stderr,pc);
5628 /*-----------------------------------------------------------------*/
5629 /*-----------------------------------------------------------------*/
5630 static int OptimizepBlock(pBlock *pb)
5635 if(!pb || !peepOptimizing)
5638 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5640 for(pc = pb->pcHead; pc; pc = pc->next)
5641 matches += pic16_pCodePeepMatchRule(pc);
5644 pc = pic16_findNextInstruction(pb->pcHead);
5652 if(pic16_pCodePeepMatchRule(pc)) {
5657 pc = pic16_findNextInstruction(pcprev->next);
5659 pc = pic16_findNextInstruction(pb->pcHead);
5661 pc = pic16_findNextInstruction(pc->next);
5665 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5670 /*-----------------------------------------------------------------*/
5671 /*-----------------------------------------------------------------*/
5672 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5676 for(pc = pcs; pc; pc = pc->next) {
5678 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
5680 (PCI(pc)->pcop->type == PO_LABEL) &&
5681 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5689 /*-----------------------------------------------------------------*/
5690 /*-----------------------------------------------------------------*/
5691 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5698 (PCI(pc)->pcop->type == PO_LABEL)) {
5700 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5702 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5704 free(pcol->pcop.name);
5706 /* If the key is negative, then we (probably) have a label to
5707 * a function and the name is already defined */
5710 sprintf(s=buffer,"_%05d_DS_",pcl->key);
5714 //sprintf(buffer,"_%05d_DS_",pcl->key);
5716 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5718 pcol->pcop.name = Safe_strdup(s);
5719 pcol->key = pcl->key;
5720 //pc->print(stderr,pc);
5727 /*-----------------------------------------------------------------*/
5728 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
5729 /* pCode chain if they're not used. */
5730 /*-----------------------------------------------------------------*/
5731 static void pBlockRemoveUnusedLabels(pBlock *pb)
5733 pCode *pc; pCodeLabel *pcl;
5738 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5740 pBranch *pbr = PCI(pc)->label;
5741 if(pbr && pbr->next) {
5742 pCode *pcd = pb->pcHead;
5744 //fprintf(stderr, "multiple labels\n");
5745 //pc->print(stderr,pc);
5750 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5751 //fprintf(stderr,"Used by:\n");
5752 //pcd->print(stderr,pcd);
5754 exchangeLabels(PCL(pbr->pc),pcd);
5763 for(pc = pb->pcHead; pc; pc = pc->next) {
5765 if(isPCL(pc)) // pc->type == PC_LABEL)
5767 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5768 pcl = PCL(PCI(pc)->label->pc);
5771 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5773 /* This pCode is a label, so search the pBlock to see if anyone
5776 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5777 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5778 /* Couldn't find an instruction that refers to this label
5779 * So, unlink the pCode label from it's pCode chain
5780 * and destroy the label */
5781 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5783 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5784 if(pc->type == PC_LABEL) {
5785 pic16_unlinkpCode(pc);
5786 pCodeLabelDestruct(pc);
5788 unlinkpCodeFromBranch(pc, PCODE(pcl));
5789 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5800 /*-----------------------------------------------------------------*/
5801 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
5802 /* chain and put them into pBranches that are */
5803 /* associated with the appropriate pCode */
5805 /*-----------------------------------------------------------------*/
5806 void pic16_pBlockMergeLabels(pBlock *pb)
5809 pCode *pc, *pcnext=NULL;
5814 /* First, Try to remove any unused labels */
5815 //pBlockRemoveUnusedLabels(pb);
5817 /* Now loop through the pBlock and merge the labels with the opcodes */
5820 // for(pc = pb->pcHead; pc; pc = pc->next) {
5823 pCode *pcn = pc->next;
5825 if(pc->type == PC_LABEL) {
5827 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5828 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5830 if((pcnext = pic16_findNextInstruction(pc) )) {
5832 // Unlink the pCode label from it's pCode chain
5833 pic16_unlinkpCode(pc);
5835 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5836 // And link it into the instruction's pBranch labels. (Note, since
5837 // it's possible to have multiple labels associated with one instruction
5838 // we must provide a means to accomodate the additional labels. Thus
5839 // the labels are placed into the singly-linked list "label" as
5840 // opposed to being a single member of the pCodeInstruction.)
5842 //_ALLOC(pbr,sizeof(pBranch));
5844 pbr = Safe_calloc(1,sizeof(pBranch));
5848 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5851 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5853 } else if(pc->type == PC_CSOURCE) {
5855 /* merge the source line symbolic info into the next instruction */
5856 if((pcnext = pic16_findNextInstruction(pc) )) {
5858 // Unlink the pCode label from it's pCode chain
5859 pic16_unlinkpCode(pc);
5860 PCI(pcnext)->cline = PCCS(pc);
5861 //fprintf(stderr, "merging CSRC\n");
5862 //genericPrint(stderr,pcnext);
5868 pBlockRemoveUnusedLabels(pb);
5872 /*-----------------------------------------------------------------*/
5873 /*-----------------------------------------------------------------*/
5874 static int OptimizepCode(char dbName)
5876 #define MAX_PASSES 4
5885 DFPRINTF((stderr," Optimizing pCode\n"));
5889 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5890 if('*' == dbName || getpBlock_dbName(pb) == dbName)
5891 matches += OptimizepBlock(pb);
5894 while(matches && ++passes < MAX_PASSES);
5899 /*-----------------------------------------------------------------*/
5900 /* pic16_popCopyGPR2Bit - copy a pcode operator */
5901 /*-----------------------------------------------------------------*/
5903 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5907 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5909 if( !( (pcop->type == PO_LABEL) ||
5910 (pcop->type == PO_LITERAL) ||
5911 (pcop->type == PO_STR) ))
5912 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
5913 PCOR(pcop)->r->wasUsed = 1;
5919 /*----------------------------------------------------------------------*
5920 * pic16_areRegsSame - check to see if the names of two registers match *
5921 *----------------------------------------------------------------------*/
5922 int pic16_areRegsSame(regs *r1, regs *r2)
5924 if(!strcmp(r1->name, r2->name))return 1;
5930 /*-----------------------------------------------------------------*/
5931 /*-----------------------------------------------------------------*/
5932 static void pic16_FixRegisterBanking(pBlock *pb)
5936 regs *reg, *prevreg;
5941 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5945 /* loop through all of the flow blocks with in one pblock */
5947 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5951 /* at this point, pc should point to a PC_FLOW object */
5952 /* for each flow block, determine the register banking
5955 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5956 reg = pic16_getRegFromInstruction(pc);
5959 fprintf(stderr, "reg = %p\n", reg);
5961 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5962 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5963 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5964 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5968 /* we can be 99% that within a pBlock, between two consequtive
5969 * refernces to the same register, the extra banksel is needless */
5971 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
5973 && (PCI(pc)->op != POC_CALL)
5975 && ( ((pic16_options.opt_banksel>0)
5976 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
5977 || (!pic16_options.opt_banksel)
5981 /* Examine the instruction before this one to make sure it is
5982 * not a skip type instruction */
5983 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5985 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
5986 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
5987 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5989 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
6001 if(pcprev && cur_bank) {
6003 int pos = 1; /* Assume that the bank switch instruction(s)
6004 * are inserted after this instruction */
6006 if((PCI(pcprev)->op == POC_RETLW) ||
6007 (PCI(pcprev)->op == POC_RETURN) ||
6008 (PCI(pcprev)->op == POC_RETFIE)) {
6010 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6016 /* Brute force - make sure that we point to bank 0 at the
6017 * end of each flow block */
6019 // insertBankSwitch(pos, pcprev, 0);
6021 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6022 pic16_pCodeInsertAfter(pcprev, new_pc);
6025 //fprintf(stderr, "Brute force switch\n");
6032 static void pBlockDestruct(pBlock *pb)
6043 /*-----------------------------------------------------------------*/
6044 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6045 /* name dbName and combine them */
6046 /* into one block */
6047 /*-----------------------------------------------------------------*/
6048 static void mergepBlocks(char dbName)
6051 pBlock *pb, *pbmerged = NULL,*pbn;
6053 pb = the_pFile->pbHead;
6055 //fprintf(stderr," merging blocks named %c\n",dbName);
6059 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6060 if( getpBlock_dbName(pb) == dbName) {
6062 //fprintf(stderr," merged block %c\n",dbName);
6067 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6068 /* pic16_addpCode2pBlock doesn't handle the tail: */
6069 pbmerged->pcTail = pb->pcTail;
6071 pb->prev->next = pbn;
6073 pbn->prev = pb->prev;
6078 //pic16_printpBlock(stderr, pbmerged);
6085 /*-----------------------------------------------------------------*/
6086 /* AnalyzeFlow - Examine the flow of the code and optimize */
6088 /* level 0 == minimal optimization */
6089 /* optimize registers that are used only by two instructions */
6090 /* level 1 == maximal optimization */
6091 /* optimize by looking at pairs of instructions that use the */
6093 /*-----------------------------------------------------------------*/
6095 static void AnalyzeFlow(int level)
6097 static int times_called=0;
6102 /* remove unused allocated registers before exiting */
6103 pic16_RemoveUnusedRegisters();
6109 /* if this is not the first time this function has been called,
6110 then clean up old flow information */
6111 if(times_called++) {
6112 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6115 pic16_RegsUnMapLiveRanges();
6120 /* Phase 2 - Flow Analysis - Register Banking
6122 * In this phase, the individual flow blocks are examined
6123 * and register banking is fixed.
6127 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6128 pic16_FixRegisterBanking(pb);
6131 /* Phase 2 - Flow Analysis
6133 * In this phase, the pCode is partition into pCodeFlow
6134 * blocks. The flow blocks mark the points where a continuous
6135 * stream of instructions changes flow (e.g. because of
6136 * a call or goto or whatever).
6139 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6140 pic16_BuildFlow(pb);
6143 /* Phase 2 - Flow Analysis - linking flow blocks
6145 * In this phase, the individual flow blocks are examined
6146 * to determine their order of excution.
6149 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6152 /* Phase 3 - Flow Analysis - Flow Tree
6154 * In this phase, the individual flow blocks are examined
6155 * to determine their order of execution.
6158 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6159 pic16_BuildFlowTree(pb);
6162 /* Phase x - Flow Analysis - Used Banks
6164 * In this phase, the individual flow blocks are examined
6165 * to determine the Register Banks they use
6169 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6174 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6175 pic16_pCodeRegMapLiveRanges(pb);
6177 pic16_RemoveUnusedRegisters();
6179 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6180 pic16_pCodeRegOptimizeRegUsage(level);
6188 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6193 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6195 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6196 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6197 pcflow = pcflow->next) {
6199 FillFlow(PCFL(pcflow));
6204 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6207 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6208 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6209 pcflow = pcflow->next) {
6211 FlowStats(PCFL(pcflow));
6217 /* VR -- no need to analyze banking in flow, but left here :
6218 * 1. because it may be used in the future for other purposes
6219 * 2. because if omitted we'll miss some optimization done here
6221 * Perhaps I should rename it to something else
6224 /*-----------------------------------------------------------------*/
6225 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6226 /* assigned to the registers. */
6228 /*-----------------------------------------------------------------*/
6230 void pic16_AnalyzeBanking(void)
6234 if(!pic16_picIsInitialized()) {
6235 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6236 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6237 fprintf(stderr,"support/scripts/inc2h.pl\n");
6238 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6240 /* I think it took a long long time to fix this bug! ;-) -- VR */
6246 /* Phase x - Flow Analysis - Used Banks
6248 * In this phase, the individual flow blocks are examined
6249 * to determine the Register Banks they use
6255 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6256 // BanksUsedFlow(pb);
6258 if(!the_pFile)return;
6260 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6261 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6262 pic16_FixRegisterBanking(pb);
6267 /*-----------------------------------------------------------------*/
6268 /* buildCallTree - Look at the flow and extract all of the calls. */
6269 /*-----------------------------------------------------------------*/
6270 static set *register_usage(pBlock *pb);
6272 static void buildCallTree(void )
6283 /* Now build the call tree.
6284 First we examine all of the pCodes for functions.
6285 Keep in mind that the function boundaries coincide
6286 with pBlock boundaries.
6288 The algorithm goes something like this:
6289 We have two nested loops. The outer loop iterates
6290 through all of the pBlocks/functions. The inner
6291 loop iterates through all of the pCodes for
6292 a given pBlock. When we begin iterating through
6293 a pBlock, the variable pc_fstart, pCode of the start
6294 of a function, is cleared. We then search for pCodes
6295 of type PC_FUNCTION. When one is encountered, we
6296 initialize pc_fstart to this and at the same time
6297 associate a new pBranch object that signifies a
6298 branch entry. If a return is found, then this signifies
6299 a function exit point. We'll link the pCodes of these
6300 returns to the matching pc_fstart.
6302 When we're done, a doubly linked list of pBranches
6303 will exist. The head of this list is stored in
6304 `the_pFile', which is the meta structure for all
6305 of the pCode. Look at the pic16_printCallTree function
6306 on how the pBranches are linked together.
6309 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6310 pCode *pc_fstart=NULL;
6311 for(pc = pb->pcHead; pc; pc = pc->next) {
6313 if (PCF(pc)->fname) {
6315 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6316 //fprintf(stderr," found main \n");
6317 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6321 pbr = Safe_calloc(1,sizeof(pBranch));
6322 pbr->pc = pc_fstart = pc;
6325 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6327 // Here's a better way of doing the same:
6328 addSet(&pb->function_entries, pc);
6331 // Found an exit point in a function, e.g. return
6332 // (Note, there may be more than one return per function)
6334 pBranchLink(PCF(pc_fstart), PCF(pc));
6336 addSet(&pb->function_exits, pc);
6338 } else if(isCALL(pc)) {
6339 addSet(&pb->function_calls,pc);
6344 /* Re-allocate the registers so that there are no collisions
6345 * between local variables when one function call another */
6348 // pic16_deallocateAllRegs();
6350 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6357 /*-----------------------------------------------------------------*/
6358 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6359 /* all of the logical connections. */
6361 /* Essentially what's done here is that the pCode flow is */
6363 /*-----------------------------------------------------------------*/
6365 void pic16_AnalyzepCode(char dbName)
6376 /* Phase 1 - Register allocation and peep hole optimization
6378 * The first part of the analysis is to determine the registers
6379 * that are used in the pCode. Once that is done, the peep rules
6380 * are applied to the code. We continue to loop until no more
6381 * peep rule optimizations are found (or until we exceed the
6382 * MAX_PASSES threshold).
6384 * When done, the required registers will be determined.
6390 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6391 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6393 /* First, merge the labels with the instructions */
6394 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6395 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6397 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6398 //fprintf(stderr," analyze and merging block %c\n",dbName);
6399 pic16_pBlockMergeLabels(pb);
6402 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6407 changes = OptimizepCode(dbName);
6410 } while(changes && (i++ < MAX_PASSES));
6415 /*-----------------------------------------------------------------*/
6416 /* ispCodeFunction - returns true if *pc is the pCode of a */
6418 /*-----------------------------------------------------------------*/
6419 static bool ispCodeFunction(pCode *pc)
6422 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6428 /*-----------------------------------------------------------------*/
6429 /* findFunction - Search for a function by name (given the name) */
6430 /* in the set of all functions that are in a pBlock */
6431 /* (note - I expect this to change because I'm planning to limit */
6432 /* pBlock's to just one function declaration */
6433 /*-----------------------------------------------------------------*/
6434 static pCode *findFunction(char *fname)
6441 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6443 pc = setFirstItem(pb->function_entries);
6446 if((pc->type == PC_FUNCTION) &&
6448 (strcmp(fname, PCF(pc)->fname)==0))
6451 pc = setNextItem(pb->function_entries);
6459 static void MarkUsedRegisters(set *regset)
6464 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6465 // fprintf(stderr, "marking register = %s\t", r1->name);
6466 r2 = pic16_regWithIdx(r1->rIdx);
6467 // fprintf(stderr, "to register = %s\n", r2->name);
6473 static void pBlockStats(FILE *of, pBlock *pb)
6479 if(!pic16_pcode_verbose)return;
6481 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6483 // for now just print the first element of each set
6484 pc = setFirstItem(pb->function_entries);
6486 fprintf(of,";entry: ");
6489 pc = setFirstItem(pb->function_exits);
6491 fprintf(of,";has an exit\n");
6495 pc = setFirstItem(pb->function_calls);
6497 fprintf(of,";functions called:\n");
6500 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6501 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6503 pc = setNextItem(pb->function_calls);
6507 r = setFirstItem(pb->tregisters);
6509 int n = elementsInSet(pb->tregisters);
6511 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6514 fprintf(of,"; %s\n",r->name);
6515 r = setNextItem(pb->tregisters);
6520 /*-----------------------------------------------------------------*/
6521 /*-----------------------------------------------------------------*/
6523 static void sequencepCode(void)
6529 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6531 pb->seq = GpCodeSequenceNumber+1;
6533 for( pc = pb->pcHead; pc; pc = pc->next)
6534 pc->seq = ++GpCodeSequenceNumber;
6540 /*-----------------------------------------------------------------*/
6541 /*-----------------------------------------------------------------*/
6542 static set *register_usage(pBlock *pb)
6545 set *registers=NULL;
6546 set *registersInCallPath = NULL;
6548 /* check recursion */
6550 pc = setFirstItem(pb->function_entries);
6557 if(pc->type != PC_FUNCTION)
6558 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6560 pc = setFirstItem(pb->function_calls);
6561 for( ; pc; pc = setNextItem(pb->function_calls)) {
6563 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6564 char *dest = pic16_get_op_from_instruction(PCI(pc));
6566 pcn = findFunction(dest);
6568 registersInCallPath = register_usage(pcn->pb);
6570 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6575 pBlockStats(stderr,pb); // debug
6578 // Mark the registers in this block as used.
6580 MarkUsedRegisters(pb->tregisters);
6581 if(registersInCallPath) {
6582 /* registers were used in the functions this pBlock has called */
6583 /* so now, we need to see if these collide with the ones we are */
6586 regs *r1,*r2, *newreg;
6588 DFPRINTF((stderr,"comparing registers\n"));
6590 r1 = setFirstItem(registersInCallPath);
6593 r2 = setFirstItem(pb->tregisters);
6595 while(r2 && (r1->type != REG_STK)) {
6597 if(r2->rIdx == r1->rIdx) {
6598 newreg = pic16_findFreeReg(REG_GPR);
6602 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6606 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6607 r1->rIdx, newreg->rIdx));
6608 r2->rIdx = newreg->rIdx;
6609 //if(r2->name) free(r2->name);
6611 r2->name = Safe_strdup(newreg->name);
6615 newreg->wasUsed = 1;
6617 r2 = setNextItem(pb->tregisters);
6620 r1 = setNextItem(registersInCallPath);
6623 /* Collisions have been resolved. Now free the registers in the call path */
6624 r1 = setFirstItem(registersInCallPath);
6626 if(r1->type != REG_STK) {
6627 newreg = pic16_regWithIdx(r1->rIdx);
6630 r1 = setNextItem(registersInCallPath);
6634 // MarkUsedRegisters(pb->registers);
6636 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6639 DFPRINTF((stderr,"returning regs\n"));
6641 DFPRINTF((stderr,"not returning regs\n"));
6643 DFPRINTF((stderr,"pBlock after register optim.\n"));
6644 pBlockStats(stderr,pb); // debug
6650 /*-----------------------------------------------------------------*/
6651 /* pct2 - writes the call tree to a file */
6653 /*-----------------------------------------------------------------*/
6654 static void pct2(FILE *of,pBlock *pb,int indent)
6658 // set *registersInCallPath = NULL;
6664 return; //recursion ?
6666 pc = setFirstItem(pb->function_entries);
6673 for(i=0;i<indent;i++) // Indentation
6676 if(pc->type == PC_FUNCTION)
6677 fprintf(of,"%s\n",PCF(pc)->fname);
6682 pc = setFirstItem(pb->function_calls);
6683 for( ; pc; pc = setNextItem(pb->function_calls)) {
6685 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6686 char *dest = pic16_get_op_from_instruction(PCI(pc));
6688 pcn = findFunction(dest);
6690 pct2(of,pcn->pb,indent+1);
6692 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6700 /*-----------------------------------------------------------------*/
6701 /* pic16_printCallTree - writes the call tree to a file */
6703 /*-----------------------------------------------------------------*/
6705 void pic16_printCallTree(FILE *of)
6717 fprintf(of, "\npBlock statistics\n");
6718 for(pb = the_pFile->pbHead; pb; pb = pb->next )
6723 fprintf(of,"Call Tree\n");
6724 pbr = the_pFile->functions;
6728 if(!ispCodeFunction(pc))
6729 fprintf(of,"bug in call tree");
6732 fprintf(of,"Function: %s\n", PCF(pc)->fname);
6734 while(pc->next && !ispCodeFunction(pc->next)) {
6736 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6737 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6745 fprintf(of,"\n**************\n\na better call tree\n");
6746 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6751 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6752 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6758 /*-----------------------------------------------------------------*/
6760 /*-----------------------------------------------------------------*/
6762 static void InlineFunction(pBlock *pb)
6770 pc = setFirstItem(pb->function_calls);
6772 for( ; pc; pc = setNextItem(pb->function_calls)) {
6775 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6781 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
6783 //fprintf(stderr,"Cool can inline:\n");
6784 //pcn->print(stderr,pcn);
6786 //fprintf(stderr,"recursive call Inline\n");
6787 InlineFunction(pcn->pb);
6788 //fprintf(stderr,"return from recursive call Inline\n");
6791 At this point, *pc points to a CALL mnemonic, and
6792 *pcn points to the function that is being called.
6794 To in-line this call, we need to remove the CALL
6795 and RETURN(s), and link the function pCode in with
6801 /* Remove the CALL */
6805 /* remove callee pBlock from the pBlock linked list */
6806 removepBlock(pcn->pb);
6814 /* Remove the Function pCode */
6815 pct = pic16_findNextInstruction(pcn->next);
6817 /* Link the function with the callee */
6818 pc->next = pcn->next;
6819 pcn->next->prev = pc;
6821 /* Convert the function name into a label */
6823 pbr = Safe_calloc(1,sizeof(pBranch));
6824 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6826 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6827 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6829 /* turn all of the return's except the last into goto's */
6830 /* check case for 2 instruction pBlocks */
6831 pce = pic16_findNextInstruction(pcn->next);
6833 pCode *pce_next = pic16_findNextInstruction(pce->next);
6835 if(pce_next == NULL) {
6836 /* found the last return */
6837 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
6839 //fprintf(stderr,"found last return\n");
6840 //pce->print(stderr,pce);
6841 pce->prev->next = pc_call->next;
6842 pc_call->next->prev = pce->prev;
6843 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6853 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6859 /*-----------------------------------------------------------------*/
6861 /*-----------------------------------------------------------------*/
6863 void pic16_InlinepCode(void)
6872 if(!functionInlining)
6875 /* Loop through all of the function definitions and count the
6876 * number of times each one is called */
6877 //fprintf(stderr,"inlining %d\n",__LINE__);
6879 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6881 pc = setFirstItem(pb->function_calls);
6883 for( ; pc; pc = setNextItem(pb->function_calls)) {
6886 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6887 if(pcn && isPCF(pcn)) {
6888 PCF(pcn)->ncalled++;
6891 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6896 //fprintf(stderr,"inlining %d\n",__LINE__);
6898 /* Now, Loop through the function definitions again, but this
6899 * time inline those functions that have only been called once. */
6901 InlineFunction(the_pFile->pbHead);
6902 //fprintf(stderr,"inlining %d\n",__LINE__);
6904 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6909 char *pic_optype_names[]={
6910 "PO_NONE", // No operand e.g. NOP
6911 "PO_W", // The working register (as a destination)
6912 "PO_WREG", // The working register (as a file register)
6913 "PO_STATUS", // The 'STATUS' register
6914 "PO_BSR", // The 'BSR' register
6915 "PO_FSR0", // The "file select register" (in PIC18 family it's one
6917 "PO_INDF0", // The Indirect register
6918 "PO_INTCON", // Interrupt Control register
6919 "PO_GPR_REGISTER", // A general purpose register
6920 "PO_GPR_BIT", // A bit of a general purpose register
6921 "PO_GPR_TEMP", // A general purpose temporary register
6922 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
6923 "PO_PCL", // Program counter Low register
6924 "PO_PCLATH", // Program counter Latch high register
6925 "PO_PCLATU", // Program counter Latch upper register
6926 "PO_PRODL", // Product Register Low
6927 "PO_PRODH", // Product Register High
6928 "PO_LITERAL", // A constant
6929 "PO_REL_ADDR", // A relative address
6930 "PO_IMMEDIATE", // (8051 legacy)
6931 "PO_DIR", // Direct memory (8051 legacy)
6932 "PO_CRY", // bit memory (8051 legacy)
6933 "PO_BIT", // bit operand.
6934 "PO_STR", // (8051 legacy)
6936 "PO_WILD" // Wild card operand in peep optimizer
6940 char *dumpPicOptype(PIC_OPTYPE type)
6942 return (pic_optype_names[ type ]);