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_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
116 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
118 char *OPT_TYPE_STR[] = { "begin", "end" };
119 char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
122 static int mnemonics_initialized = 0;
125 static hTab *pic16MnemonicsHash = NULL;
126 static hTab *pic16pCodePeepCommandsHash = NULL;
128 static pFile *the_pFile = NULL;
129 static pBlock *pb_dead_pcodes = NULL;
131 /* Hardcoded flags to change the behavior of the PIC port */
132 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
133 static int functionInlining = 1; /* inline functions if nonzero */
134 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
136 int pic16_pcode_verbose = 0;
138 //static int GpCodeSequenceNumber = 1;
139 static int GpcFlowSeq = 1;
141 extern void pic16_RemoveUnusedRegisters(void);
142 extern void pic16_RegsUnMapLiveRanges(void);
143 extern void pic16_BuildFlowTree(pBlock *pb);
144 extern void pic16_pCodeRegOptimizeRegUsage(int level);
145 extern int pic16_picIsInitialized(void);
146 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
147 extern int mnem2key(char const *mnem);
149 /****************************************************************/
150 /* Forward declarations */
151 /****************************************************************/
153 void pic16_unlinkpCode(pCode *pc);
155 static void genericAnalyze(pCode *pc);
156 static void AnalyzeGOTO(pCode *pc);
157 static void AnalyzeSKIP(pCode *pc);
158 static void AnalyzeRETURN(pCode *pc);
161 static void genericDestruct(pCode *pc);
162 static void genericPrint(FILE *of,pCode *pc);
164 static void pCodePrintLabel(FILE *of, pCode *pc);
165 static void pCodePrintFunction(FILE *of, pCode *pc);
166 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
167 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
168 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
169 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
170 int pic16_pCodePeepMatchRule(pCode *pc);
171 static void pBlockStats(FILE *of, pBlock *pb);
172 static pBlock *newpBlock(void);
173 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
174 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
175 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
176 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
177 void OptimizeLocalRegs(void);
178 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
180 char *dumpPicOptype(PIC_OPTYPE type);
182 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
183 pCodeOp *pic16_popGetLit(int);
184 pCodeOp *pic16_popGetWithString(char *);
185 extern int inWparamList(char *s);
188 /****************************************************************/
189 /* PIC Instructions */
190 /****************************************************************/
192 pCodeInstruction pic16_pciADDWF = {
193 {PC_OPCODE, NULL, NULL, 0, NULL,
207 1,0, // dest, bit instruction
209 0, // literal operand
211 0, // fast call/return mode select bit
212 0, // second memory operand
213 0, // second literal operand
215 (PCC_W | PCC_REGISTER), // inCond
216 (PCC_REGISTER | PCC_Z), // outCond
220 pCodeInstruction pic16_pciADDFW = {
221 {PC_OPCODE, NULL, NULL, 0, NULL,
235 0,0, // dest, bit instruction
237 0, // literal operand
239 0, // fast call/return mode select bit
240 0, // second memory operand
241 0, // second literal operand
243 (PCC_W | PCC_REGISTER), // inCond
244 (PCC_W | PCC_Z), // outCond
248 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
249 {PC_OPCODE, NULL, NULL, 0, NULL,
263 1,0, // dest, bit instruction
265 0, // literal operand
267 0, // fast call/return mode select bit
268 0, // second memory operand
269 0, // second literal operand
271 (PCC_W | PCC_REGISTER | PCC_C), // inCond
272 (PCC_REGISTER | PCC_Z), // outCond
276 pCodeInstruction pic16_pciADDFWC = {
277 {PC_OPCODE, NULL, NULL, 0, NULL,
291 0,0, // dest, bit instruction
293 0, // literal operand
295 0, // fast call/return mode select bit
296 0, // second memory operand
297 0, // second literal operand
299 (PCC_W | PCC_REGISTER | PCC_C), // inCond
300 (PCC_W | PCC_Z), // outCond
304 pCodeInstruction pic16_pciADDLW = {
305 {PC_OPCODE, NULL, NULL, 0, NULL,
319 0,0, // dest, bit instruction
321 1, // literal operand
323 0, // fast call/return mode select bit
324 0, // second memory operand
325 0, // second literal operand
327 (PCC_W | PCC_LITERAL), // inCond
328 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
332 pCodeInstruction pic16_pciANDLW = {
333 {PC_OPCODE, NULL, NULL, 0, NULL,
347 0,0, // dest, bit instruction
349 1, // literal operand
351 0, // fast call/return mode select bit
352 0, // second memory operand
353 0, // second literal operand
355 (PCC_W | PCC_LITERAL), // inCond
356 (PCC_W | PCC_Z | PCC_N), // outCond
360 pCodeInstruction pic16_pciANDWF = {
361 {PC_OPCODE, NULL, NULL, 0, NULL,
375 1,0, // dest, bit instruction
377 0, // literal operand
379 0, // fast call/return mode select bit
380 0, // second memory operand
381 0, // second literal operand
383 (PCC_W | PCC_REGISTER), // inCond
384 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
388 pCodeInstruction pic16_pciANDFW = {
389 {PC_OPCODE, NULL, NULL, 0, NULL,
403 0,0, // dest, bit instruction
405 0, // literal operand
407 0, // fast call/return mode select bit
408 0, // second memory operand
409 0, // second literal operand
411 (PCC_W | PCC_REGISTER), // inCond
412 (PCC_W | PCC_Z) // outCond
415 pCodeInstruction pic16_pciBC = { // mdubuc - New
416 {PC_OPCODE, NULL, NULL, 0, NULL,
430 0,0, // dest, bit instruction
432 0, // literal operand
434 0, // fast call/return mode select bit
435 0, // second memory operand
436 0, // second literal operand
438 (PCC_REL_ADDR | PCC_C), // inCond
443 pCodeInstruction pic16_pciBCF = {
444 {PC_OPCODE, NULL, NULL, 0, NULL,
458 1,1, // dest, bit instruction
460 0, // literal operand
462 0, // fast call/return mode select bit
463 0, // second memory operand
464 0, // second literal operand
466 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
467 PCC_REGISTER, // outCond
471 pCodeInstruction pic16_pciBN = { // mdubuc - New
472 {PC_OPCODE, NULL, NULL, 0, NULL,
486 0,0, // dest, bit instruction
488 0, // literal operand
490 0, // fast call/return mode select bit
491 0, // second memory operand
492 0, // second literal operand
494 (PCC_REL_ADDR | PCC_N), // inCond
495 PCC_NONE , // outCond
499 pCodeInstruction pic16_pciBNC = { // mdubuc - New
500 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 0, // fast call/return mode select bit
519 0, // second memory operand
520 0, // second literal operand
522 (PCC_REL_ADDR | PCC_C), // inCond
523 PCC_NONE , // outCond
527 pCodeInstruction pic16_pciBNN = { // mdubuc - New
528 {PC_OPCODE, NULL, NULL, 0, NULL,
542 0,0, // dest, bit instruction
544 0, // literal operand
546 0, // fast call/return mode select bit
547 0, // second memory operand
548 0, // second literal operand
550 (PCC_REL_ADDR | PCC_N), // inCond
551 PCC_NONE , // outCond
555 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
556 {PC_OPCODE, NULL, NULL, 0, NULL,
570 0,0, // dest, bit instruction
572 0, // literal operand
574 0, // fast call/return mode select bit
575 0, // second memory operand
576 0, // second literal operand
578 (PCC_REL_ADDR | PCC_OV), // inCond
579 PCC_NONE , // outCond
583 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
584 {PC_OPCODE, NULL, NULL, 0, NULL,
598 0,0, // dest, bit instruction
600 0, // literal operand
602 0, // fast call/return mode select bit
603 0, // second memory operand
604 0, // second literal operand
606 (PCC_REL_ADDR | PCC_Z), // inCond
607 PCC_NONE , // outCond
611 pCodeInstruction pic16_pciBOV = { // mdubuc - New
612 {PC_OPCODE, NULL, NULL, 0, NULL,
626 0,0, // dest, bit instruction
628 0, // literal operand
630 0, // fast call/return mode select bit
631 0, // second memory operand
632 0, // second literal operand
634 (PCC_REL_ADDR | PCC_OV), // inCond
635 PCC_NONE , // outCond
639 pCodeInstruction pic16_pciBRA = { // mdubuc - New
640 {PC_OPCODE, NULL, NULL, 0, NULL,
654 0,0, // dest, bit instruction
656 0, // literal operand
658 0, // fast call/return mode select bit
659 0, // second memory operand
660 0, // second literal operand
662 PCC_REL_ADDR, // inCond
663 PCC_NONE , // outCond
667 pCodeInstruction pic16_pciBSF = {
668 {PC_OPCODE, NULL, NULL, 0, NULL,
682 1,1, // dest, bit instruction
684 0, // literal operand
686 0, // fast call/return mode select bit
687 0, // second memory operand
688 0, // second literal operand
690 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
691 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
695 pCodeInstruction pic16_pciBTFSC = {
696 {PC_OPCODE, NULL, NULL, 0, NULL,
710 0,1, // dest, bit instruction
712 0, // literal operand
714 0, // fast call/return mode select bit
715 0, // second memory operand
716 0, // second literal operand
718 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
719 PCC_EXAMINE_PCOP, // outCond
723 pCodeInstruction pic16_pciBTFSS = {
724 {PC_OPCODE, NULL, NULL, 0, NULL,
738 0,1, // dest, bit instruction
740 0, // literal operand
742 0, // fast call/return mode select bit
743 0, // second memory operand
744 0, // second literal operand
746 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
747 PCC_EXAMINE_PCOP, // outCond
751 pCodeInstruction pic16_pciBTG = { // mdubuc - New
752 {PC_OPCODE, NULL, NULL, 0, NULL,
766 0,1, // dest, bit instruction
768 0, // literal operand
770 0, // fast call/return mode select bit
771 0, // second memory operand
772 0, // second literal operand
774 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
775 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
779 pCodeInstruction pic16_pciBZ = { // mdubuc - New
780 {PC_OPCODE, NULL, NULL, 0, NULL,
794 0,0, // dest, bit instruction
796 0, // literal operand
798 0, // fast call/return mode select bit
799 0, // second memory operand
800 0, // second literal operand
807 pCodeInstruction pic16_pciCALL = {
808 {PC_OPCODE, NULL, NULL, 0, NULL,
822 0,0, // dest, bit instruction
824 0, // literal operand
826 1, // fast call/return mode select bit
827 0, // second memory operand
828 0, // second literal operand
835 pCodeInstruction pic16_pciCOMF = {
836 {PC_OPCODE, NULL, NULL, 0, NULL,
850 1,0, // dest, bit instruction
852 0, // literal operand
854 0, // fast call/return mode select bit
855 0, // second memory operand
856 0, // second literal operand
858 PCC_REGISTER, // inCond
859 PCC_REGISTER , // outCond
863 pCodeInstruction pic16_pciCOMFW = {
864 {PC_OPCODE, NULL, NULL, 0, NULL,
878 0,0, // dest, bit instruction
880 0, // literal operand
882 0, // fast call/return mode select bit
883 0, // second memory operand
884 0, // second literal operand
886 PCC_REGISTER, // inCond
891 pCodeInstruction pic16_pciCLRF = {
892 {PC_OPCODE, NULL, NULL, 0, NULL,
906 0,0, // dest, bit instruction
908 0, // literal operand
910 0, // fast call/return mode select bit
911 0, // second memory operand
912 0, // second literal operand
914 PCC_REGISTER, // inCond
915 PCC_REGISTER , // outCond
919 pCodeInstruction pic16_pciCLRWDT = {
920 {PC_OPCODE, NULL, NULL, 0, NULL,
934 0,0, // dest, bit instruction
936 0, // literal operand
938 0, // fast call/return mode select bit
939 0, // second memory operand
940 0, // second literal operand
943 PCC_NONE , // outCond
947 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
948 {PC_OPCODE, NULL, NULL, 0, NULL,
962 0,0, // dest, bit instruction
964 0, // literal operand
966 0, // fast call/return mode select bit
967 0, // second memory operand
968 0, // second literal operand
970 (PCC_W | PCC_REGISTER), // inCond
971 PCC_NONE , // outCond
975 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
976 {PC_OPCODE, NULL, NULL, 0, NULL,
990 0,0, // dest, bit instruction
992 0, // literal operand
994 0, // fast call/return mode select bit
995 0, // second memory operand
996 0, // second literal operand
998 (PCC_W | PCC_REGISTER), // inCond
999 PCC_NONE , // outCond
1003 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
1004 {PC_OPCODE, NULL, NULL, 0, NULL,
1011 NULL, // from branch
1018 1,0, // dest, bit instruction
1019 1,1, // branch, skip
1020 0, // literal operand
1021 1, // RAM access bit
1022 0, // fast call/return mode select bit
1023 0, // second memory operand
1024 0, // second literal operand
1026 (PCC_W | PCC_REGISTER), // inCond
1027 PCC_NONE , // outCond
1031 pCodeInstruction pic16_pciDAW = {
1032 {PC_OPCODE, NULL, NULL, 0, NULL,
1039 NULL, // from branch
1046 0,0, // dest, bit instruction
1047 0,0, // branch, skip
1048 0, // literal operand
1049 0, // RAM access bit
1050 0, // fast call/return mode select bit
1051 0, // second memory operand
1052 0, // second literal operand
1055 (PCC_W | PCC_C), // outCond
1059 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1060 {PC_OPCODE, NULL, NULL, 0, NULL,
1067 NULL, // from branch
1074 1,0, // dest, bit instruction
1075 1,1, // branch, skip
1076 0, // literal operand
1077 1, // RAM access bit
1078 0, // fast call/return mode select bit
1079 0, // second memory operand
1080 0, // second literal operand
1082 PCC_REGISTER, // inCond
1083 PCC_REGISTER , // outCond
1087 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1088 {PC_OPCODE, NULL, NULL, 0, NULL,
1095 NULL, // from branch
1102 0,0, // dest, bit instruction
1103 1,1, // branch, skip
1104 0, // literal operand
1105 1, // RAM access bit
1106 0, // fast call/return mode select bit
1107 0, // second memory operand
1108 0, // second literal operand
1110 PCC_REGISTER, // inCond
1115 pCodeInstruction pic16_pciDECF = {
1116 {PC_OPCODE, NULL, NULL, 0, NULL,
1123 NULL, // from branch
1130 1,0, // dest, bit instruction
1131 0,0, // branch, skip
1132 0, // literal operand
1133 1, // RAM access bit
1134 0, // fast call/return mode select bit
1135 0, // second memory operand
1136 0, // second literal operand
1138 PCC_REGISTER, // inCond
1139 PCC_REGISTER , // outCond
1143 pCodeInstruction pic16_pciDECFW = {
1144 {PC_OPCODE, NULL, NULL, 0, NULL,
1151 NULL, // from branch
1158 0,0, // dest, bit instruction
1159 0,0, // branch, skip
1160 0, // literal operand
1161 1, // RAM access bit
1162 0, // fast call/return mode select bit
1163 0, // second memory operand
1164 0, // second literal operand
1166 PCC_REGISTER, // inCond
1171 pCodeInstruction pic16_pciDECFSZ = {
1172 {PC_OPCODE, NULL, NULL, 0, NULL,
1179 NULL, // from branch
1186 1,0, // dest, bit instruction
1187 1,1, // branch, skip
1188 0, // literal operand
1189 1, // RAM access bit
1190 0, // fast call/return mode select bit
1191 0, // second memory operand
1192 0, // second literal operand
1194 PCC_REGISTER, // inCond
1195 PCC_REGISTER , // outCond
1199 pCodeInstruction pic16_pciDECFSZW = {
1200 {PC_OPCODE, NULL, NULL, 0, NULL,
1207 NULL, // from branch
1214 0,0, // dest, bit instruction
1215 1,1, // branch, skip
1216 0, // literal operand
1217 1, // RAM access bit
1218 0, // fast call/return mode select bit
1219 0, // second memory operand
1220 0, // second literal operand
1222 PCC_REGISTER, // inCond
1227 pCodeInstruction pic16_pciGOTO = {
1228 {PC_OPCODE, NULL, NULL, 0, NULL,
1235 NULL, // from branch
1242 0,0, // dest, bit instruction
1243 1,0, // branch, skip
1244 0, // literal operand
1245 0, // RAM access bit
1246 0, // fast call/return mode select bit
1247 0, // second memory operand
1248 0, // second literal operand
1250 PCC_REL_ADDR, // inCond
1251 PCC_NONE , // outCond
1255 pCodeInstruction pic16_pciINCF = {
1256 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 1,0, // dest, bit instruction
1271 0,0, // branch, skip
1272 0, // literal operand
1273 1, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1276 0, // second literal operand
1278 PCC_REGISTER, // inCond
1279 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1283 pCodeInstruction pic16_pciINCFW = {
1284 {PC_OPCODE, NULL, NULL, 0, NULL,
1291 NULL, // from branch
1298 0,0, // dest, bit instruction
1299 0,0, // branch, skip
1300 0, // literal operand
1301 1, // RAM access bit
1302 0, // fast call/return mode select bit
1303 0, // second memory operand
1304 0, // second literal operand
1306 PCC_REGISTER, // inCond
1311 pCodeInstruction pic16_pciINCFSZ = {
1312 {PC_OPCODE, NULL, NULL, 0, NULL,
1319 NULL, // from branch
1326 1,0, // dest, bit instruction
1327 1,1, // branch, skip
1328 0, // literal operand
1329 1, // RAM access bit
1330 0, // fast call/return mode select bit
1331 0, // second memory operand
1332 0, // second literal operand
1334 PCC_REGISTER, // inCond
1335 PCC_REGISTER , // outCond
1339 pCodeInstruction pic16_pciINCFSZW = {
1340 {PC_OPCODE, NULL, NULL, 0, NULL,
1347 NULL, // from branch
1354 0,0, // dest, bit instruction
1355 1,1, // branch, skip
1356 0, // literal operand
1357 1, // RAM access bit
1358 0, // fast call/return mode select bit
1359 0, // second memory operand
1360 0, // second literal operand
1362 PCC_REGISTER, // inCond
1367 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1368 {PC_OPCODE, NULL, NULL, 0, NULL,
1375 NULL, // from branch
1382 1,0, // dest, bit instruction
1383 1,1, // branch, skip
1384 0, // literal operand
1385 1, // RAM access bit
1386 0, // fast call/return mode select bit
1387 0, // second memory operand
1388 0, // second literal operand
1390 PCC_REGISTER, // inCond
1391 PCC_REGISTER , // outCond
1395 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1396 {PC_OPCODE, NULL, NULL, 0, NULL,
1403 NULL, // from branch
1410 0,0, // dest, bit instruction
1411 1,1, // branch, skip
1412 0, // literal operand
1413 1, // RAM access bit
1414 0, // fast call/return mode select bit
1415 0, // second memory operand
1416 0, // second literal operand
1418 PCC_REGISTER, // inCond
1423 pCodeInstruction pic16_pciIORWF = {
1424 {PC_OPCODE, NULL, NULL, 0, NULL,
1431 NULL, // from branch
1438 1,0, // dest, bit instruction
1439 0,0, // branch, skip
1440 0, // literal operand
1441 1, // RAM access bit
1442 0, // fast call/return mode select bit
1443 0, // second memory operand
1444 0, // second literal operand
1446 (PCC_W | PCC_REGISTER), // inCond
1447 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1451 pCodeInstruction pic16_pciIORFW = {
1452 {PC_OPCODE, NULL, NULL, 0, NULL,
1459 NULL, // from branch
1466 0,0, // dest, bit instruction
1467 0,0, // branch, skip
1468 0, // literal operand
1469 1, // RAM access bit
1470 0, // fast call/return mode select bit
1471 0, // second memory operand
1472 0, // second literal operand
1474 (PCC_W | PCC_REGISTER), // inCond
1475 (PCC_W | PCC_Z | PCC_N), // outCond
1479 pCodeInstruction pic16_pciIORLW = {
1480 {PC_OPCODE, NULL, NULL, 0, NULL,
1487 NULL, // from branch
1494 0,0, // dest, bit instruction
1495 0,0, // branch, skip
1496 1, // literal operand
1497 0, // RAM access bit
1498 0, // fast call/return mode select bit
1499 0, // second memory operand
1500 0, // second literal operand
1502 (PCC_W | PCC_LITERAL), // inCond
1503 (PCC_W | PCC_Z | PCC_N), // outCond
1507 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1508 {PC_OPCODE, NULL, NULL, 0, NULL,
1515 NULL, // from branch
1522 0,0, // dest, bit instruction
1523 0,0, // branch, skip
1524 1, // literal operand
1525 0, // RAM access bit
1526 0, // fast call/return mode select bit
1527 0, // second memory operand
1528 1, // second literal operand
1530 (PCC_REGISTER | PCC_LITERAL),
1531 PCC_REGISTER, // outCond
1535 pCodeInstruction pic16_pciMOVF = {
1536 {PC_OPCODE, NULL, NULL, 0, NULL,
1543 NULL, // from branch
1550 1,0, // dest, bit instruction
1551 0,0, // branch, skip
1552 0, // literal operand
1553 1, // RAM access bit
1554 0, // fast call/return mode select bit
1555 0, // second memory operand
1556 0, // second literal operand
1558 PCC_REGISTER, // inCond
1559 (PCC_Z | PCC_N), // outCond
1563 pCodeInstruction pic16_pciMOVFW = {
1564 {PC_OPCODE, NULL, NULL, 0, NULL,
1571 NULL, // from branch
1578 0,0, // dest, bit instruction
1579 0,0, // branch, skip
1580 0, // literal operand
1581 1, // RAM access bit
1582 0, // fast call/return mode select bit
1583 0, // second memory operand
1584 0, // second literal operand
1586 PCC_REGISTER, // inCond
1587 (PCC_W | PCC_Z), // outCond
1591 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1592 {PC_OPCODE, NULL, NULL, 0, NULL,
1599 NULL, // from branch
1606 0,0, // dest, bit instruction
1607 0,0, // branch, skip
1608 0, // literal operand
1609 0, // RAM access bit
1610 0, // fast call/return mode select bit
1611 1, // second memory operand
1612 0, // second literal operand
1614 PCC_REGISTER, // inCond
1615 PCC_REGISTER, // outCond
1619 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1620 {PC_OPCODE, NULL, NULL, 0, NULL,
1626 NULL, // from branch
1633 0,0, // dest, bit instruction
1634 0,0, // branch, skip
1635 1, // literal operand
1636 0, // RAM access bit
1637 0, // fast call/return mode select bit
1638 0, // second memory operand
1639 0, // second literal operand
1641 (PCC_NONE | PCC_LITERAL), // inCond
1642 PCC_REGISTER, // outCond - BSR
1646 pCodeInstruction pic16_pciMOVLW = {
1647 {PC_OPCODE, NULL, NULL, 0, NULL,
1653 NULL, // from branch
1660 0,0, // dest, bit instruction
1661 0,0, // branch, skip
1662 1, // literal operand
1663 0, // RAM access bit
1664 0, // fast call/return mode select bit
1665 0, // second memory operand
1666 0, // second literal operand
1668 (PCC_NONE | PCC_LITERAL), // inCond
1673 pCodeInstruction pic16_pciMOVWF = {
1674 {PC_OPCODE, NULL, NULL, 0, NULL,
1681 NULL, // from branch
1688 0,0, // dest, bit instruction
1689 0,0, // branch, skip
1690 0, // literal operand
1691 1, // RAM access bit
1692 0, // fast call/return mode select bit
1693 0, // second memory operand
1694 0, // second literal operand
1696 PCC_REGISTER, // inCond
1701 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1702 {PC_OPCODE, NULL, NULL, 0, NULL,
1708 NULL, // from branch
1715 0,0, // dest, bit instruction
1716 0,0, // branch, skip
1717 1, // literal operand
1718 0, // RAM access bit
1719 0, // fast call/return mode select bit
1720 0, // second memory operand
1721 0, // second literal operand
1723 (PCC_W | PCC_LITERAL), // inCond
1724 PCC_REGISTER, // outCond - PROD
1728 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1729 {PC_OPCODE, NULL, NULL, 0, NULL,
1735 NULL, // from branch
1742 0,0, // dest, bit instruction
1743 0,0, // branch, skip
1744 0, // literal operand
1745 1, // RAM access bit
1746 0, // fast call/return mode select bit
1747 0, // second memory operand
1748 0, // second literal operand
1750 (PCC_W | PCC_REGISTER), // inCond
1751 PCC_REGISTER, // outCond - PROD
1755 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1756 {PC_OPCODE, NULL, NULL, 0, NULL,
1762 NULL, // from branch
1769 0,0, // dest, bit instruction
1770 0,0, // branch, skip
1771 0, // literal operand
1772 1, // RAM access bit
1773 0, // fast call/return mode select bit
1774 0, // second memory operand
1775 0, // second literal operand
1777 PCC_REGISTER, // inCond
1778 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1782 pCodeInstruction pic16_pciNOP = {
1783 {PC_OPCODE, NULL, NULL, 0, NULL,
1789 NULL, // from branch
1796 0,0, // dest, bit instruction
1797 0,0, // branch, skip
1798 0, // literal operand
1799 0, // RAM access bit
1800 0, // fast call/return mode select bit
1801 0, // second memory operand
1802 0, // second literal operand
1805 PCC_NONE, // outCond
1809 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1810 {PC_OPCODE, NULL, NULL, 0, NULL,
1816 NULL, // from branch
1823 0,0, // dest, bit instruction
1824 0,0, // branch, skip
1825 0, // literal operand
1826 0, // RAM access bit
1827 0, // fast call/return mode select bit
1828 0, // second memory operand
1829 0, // second literal operand
1832 PCC_NONE , // outCond
1836 pCodeInstruction pic16_pciPUSH = {
1837 {PC_OPCODE, NULL, NULL, 0, NULL,
1843 NULL, // from branch
1850 0,0, // dest, bit instruction
1851 0,0, // branch, skip
1852 0, // literal operand
1853 0, // RAM access bit
1854 0, // fast call/return mode select bit
1855 0, // second memory operand
1856 0, // second literal operand
1859 PCC_NONE , // outCond
1863 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1864 {PC_OPCODE, NULL, NULL, 0, NULL,
1870 NULL, // from branch
1877 0,0, // dest, bit instruction
1878 0,0, // branch, skip
1879 0, // literal operand
1880 0, // RAM access bit
1881 0, // fast call/return mode select bit
1882 0, // second memory operand
1883 0, // second literal operand
1885 PCC_REL_ADDR, // inCond
1886 PCC_NONE , // outCond
1890 pCodeInstruction pic16_pciRETFIE = {
1891 {PC_OPCODE, NULL, NULL, 0, NULL,
1898 NULL, // from branch
1905 0,0, // dest, bit instruction
1906 1,0, // branch, skip
1907 0, // literal operand
1908 0, // RAM access bit
1909 1, // fast call/return mode select bit
1910 0, // second memory operand
1911 0, // second literal operand
1914 PCC_NONE, // outCond (not true... affects the GIE bit too)
1918 pCodeInstruction pic16_pciRETLW = {
1919 {PC_OPCODE, NULL, NULL, 0, NULL,
1926 NULL, // from branch
1933 0,0, // dest, bit instruction
1934 1,0, // branch, skip
1935 1, // literal operand
1936 0, // RAM access bit
1937 0, // fast call/return mode select bit
1938 0, // second memory operand
1939 0, // second literal operand
1941 PCC_LITERAL, // inCond
1946 pCodeInstruction pic16_pciRETURN = {
1947 {PC_OPCODE, NULL, NULL, 0, NULL,
1954 NULL, // from branch
1961 0,0, // dest, bit instruction
1962 1,0, // branch, skip
1963 0, // literal operand
1964 0, // RAM access bit
1965 1, // fast call/return mode select bit
1966 0, // second memory operand
1967 0, // second literal operand
1970 PCC_NONE, // outCond
1973 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1974 {PC_OPCODE, NULL, NULL, 0, NULL,
1981 NULL, // from branch
1988 1,0, // dest, bit instruction
1989 0,0, // branch, skip
1990 0, // literal operand
1991 1, // RAM access bit
1992 0, // fast call/return mode select bit
1993 0, // second memory operand
1994 0, // second literal operand
1996 (PCC_C | PCC_REGISTER), // inCond
1997 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2001 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
2002 {PC_OPCODE, NULL, NULL, 0, NULL,
2009 NULL, // from branch
2016 0,0, // dest, bit instruction
2017 0,0, // branch, skip
2018 0, // literal operand
2019 1, // RAM access bit
2020 0, // fast call/return mode select bit
2021 0, // second memory operand
2022 0, // second literal operand
2024 (PCC_C | PCC_REGISTER), // inCond
2025 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2029 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
2030 {PC_OPCODE, NULL, NULL, 0, NULL,
2037 NULL, // from branch
2044 1,0, // dest, bit instruction
2045 0,0, // branch, skip
2046 0, // literal operand
2047 1, // RAM access bit
2048 0, // fast call/return mode select bit
2049 0, // second memory operand
2050 0, // second literal operand
2052 PCC_REGISTER, // inCond
2053 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2056 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
2057 {PC_OPCODE, NULL, NULL, 0, NULL,
2064 NULL, // from branch
2071 0,0, // dest, bit instruction
2072 0,0, // branch, skip
2073 0, // literal operand
2074 1, // RAM access bit
2075 0, // fast call/return mode select bit
2076 0, // second memory operand
2077 0, // second literal operand
2079 PCC_REGISTER, // inCond
2080 (PCC_W | PCC_Z | PCC_N), // outCond
2083 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2084 {PC_OPCODE, NULL, NULL, 0, NULL,
2091 NULL, // from branch
2098 1,0, // dest, bit instruction
2099 0,0, // branch, skip
2100 0, // literal operand
2101 1, // RAM access bit
2102 0, // fast call/return mode select bit
2103 0, // second memory operand
2104 0, // second literal operand
2106 (PCC_C | PCC_REGISTER), // inCond
2107 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2110 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2111 {PC_OPCODE, NULL, NULL, 0, NULL,
2118 NULL, // from branch
2125 0,0, // dest, bit instruction
2126 0,0, // branch, skip
2127 0, // literal operand
2128 1, // RAM access bit
2129 0, // fast call/return mode select bit
2130 0, // second memory operand
2131 0, // second literal operand
2133 (PCC_C | PCC_REGISTER), // inCond
2134 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2137 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2138 {PC_OPCODE, NULL, NULL, 0, NULL,
2145 NULL, // from branch
2152 1,0, // dest, bit instruction
2153 0,0, // branch, skip
2154 0, // literal operand
2155 1, // RAM access bit
2156 0, // fast call/return mode select bit
2157 0, // second memory operand
2158 0, // second literal operand
2160 PCC_REGISTER, // inCond
2161 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2165 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2166 {PC_OPCODE, NULL, NULL, 0, NULL,
2173 NULL, // from branch
2180 0,0, // dest, bit instruction
2181 0,0, // branch, skip
2182 0, // literal operand
2183 1, // RAM access bit
2184 0, // fast call/return mode select bit
2185 0, // second memory operand
2186 0, // second literal operand
2188 PCC_REGISTER, // inCond
2189 (PCC_W | PCC_Z | PCC_N), // outCond
2193 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2194 {PC_OPCODE, NULL, NULL, 0, NULL,
2201 NULL, // from branch
2208 0,0, // dest, bit instruction
2209 0,0, // branch, skip
2210 0, // literal operand
2211 1, // RAM access bit
2212 0, // fast call/return mode select bit
2213 0, // second memory operand
2214 0, // second literal operand
2216 PCC_REGISTER, // inCond
2217 PCC_REGISTER , // outCond
2221 pCodeInstruction pic16_pciSUBLW = {
2222 {PC_OPCODE, NULL, NULL, 0, NULL,
2229 NULL, // from branch
2236 0,0, // dest, bit instruction
2237 0,0, // branch, skip
2238 1, // literal operand
2239 0, // RAM access bit
2240 0, // fast call/return mode select bit
2241 0, // second memory operand
2242 0, // second literal operand
2244 (PCC_W | PCC_LITERAL), // inCond
2245 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2249 pCodeInstruction pic16_pciSUBFWB = {
2250 {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_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2277 pCodeInstruction pic16_pciSUBWF = {
2278 {PC_OPCODE, NULL, NULL, 0, NULL,
2285 NULL, // from branch
2292 1,0, // dest, bit instruction
2293 0,0, // branch, skip
2294 0, // literal operand
2295 1, // RAM access bit
2296 0, // fast call/return mode select bit
2297 0, // second memory operand
2298 0, // second literal operand
2300 (PCC_W | PCC_REGISTER), // inCond
2301 (PCC_REGISTER | PCC_Z), // outCond
2305 pCodeInstruction pic16_pciSUBFW = {
2306 {PC_OPCODE, NULL, NULL, 0, NULL,
2313 NULL, // from branch
2320 0,0, // dest, bit instruction
2321 0,0, // branch, skip
2322 0, // literal operand
2323 1, // RAM access bit
2324 0, // fast call/return mode select bit
2325 0, // second memory operand
2326 0, // second literal operand
2328 (PCC_W | PCC_REGISTER), // inCond
2329 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2333 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2334 {PC_OPCODE, NULL, NULL, 0, NULL,
2341 NULL, // from branch
2348 1,0, // dest, bit instruction
2349 0,0, // branch, skip
2350 0, // literal operand
2351 1, // RAM access bit
2352 0, // fast call/return mode select bit
2353 0, // second memory operand
2354 0, // second literal operand
2356 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2357 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2361 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2362 {PC_OPCODE, NULL, NULL, 0, NULL,
2369 NULL, // from branch
2376 0,0, // dest, bit instruction
2377 0,0, // branch, skip
2378 0, // literal operand
2379 1, // RAM access bit
2380 0, // fast call/return mode select bit
2381 0, // second memory operand
2382 0, // second literal operand
2384 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2385 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2389 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2390 {PC_OPCODE, NULL, NULL, 0, NULL,
2397 NULL, // from branch
2404 1,0, // dest, bit instruction
2405 0,0, // branch, skip
2406 0, // literal operand
2407 1, // RAM access bit
2408 0, // fast call/return mode select bit
2409 0, // second memory operand
2410 0, // second literal operand
2412 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2413 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2417 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2418 {PC_OPCODE, NULL, NULL, 0, NULL,
2425 NULL, // from branch
2432 0,0, // dest, bit instruction
2433 0,0, // branch, skip
2434 0, // literal operand
2435 1, // RAM access bit
2436 0, // fast call/return mode select bit
2437 0, // second memory operand
2438 0, // second literal operand
2440 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2441 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2445 pCodeInstruction pic16_pciSWAPF = {
2446 {PC_OPCODE, NULL, NULL, 0, NULL,
2453 NULL, // from branch
2460 1,0, // dest, bit instruction
2461 0,0, // branch, skip
2462 0, // literal operand
2463 1, // RAM access bit
2464 0, // fast call/return mode select bit
2465 0, // second memory operand
2466 0, // second literal operand
2468 (PCC_REGISTER), // inCond
2469 (PCC_REGISTER), // outCond
2473 pCodeInstruction pic16_pciSWAPFW = {
2474 {PC_OPCODE, NULL, NULL, 0, NULL,
2481 NULL, // from branch
2488 0,0, // dest, bit instruction
2489 0,0, // branch, skip
2490 0, // literal operand
2491 1, // RAM access bit
2492 0, // fast call/return mode select bit
2493 0, // second memory operand
2494 0, // second literal operand
2496 (PCC_REGISTER), // inCond
2501 pCodeInstruction pic16_pciTBLRD = { // patch 15
2502 {PC_OPCODE, NULL, NULL, 0, NULL,
2508 NULL, // from branch
2515 0,0, // dest, bit instruction
2516 0,0, // branch, skip
2517 0, // literal operand
2518 0, // RAM access bit
2519 0, // fast call/return mode select bit
2520 0, // second memory operand
2521 0, // second literal operand
2524 PCC_NONE , // outCond
2528 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2529 {PC_OPCODE, NULL, NULL, 0, NULL,
2535 NULL, // from branch
2542 0,0, // dest, bit instruction
2543 0,0, // branch, skip
2544 0, // literal operand
2545 0, // RAM access bit
2546 0, // fast call/return mode select bit
2547 0, // second memory operand
2548 0, // second literal operand
2551 PCC_NONE , // outCond
2555 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2556 {PC_OPCODE, NULL, NULL, 0, NULL,
2562 NULL, // from branch
2569 0,0, // dest, bit instruction
2570 0,0, // branch, skip
2571 0, // literal operand
2572 0, // RAM access bit
2573 0, // fast call/return mode select bit
2574 0, // second memory operand
2575 0, // second literal operand
2578 PCC_NONE , // outCond
2582 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2583 {PC_OPCODE, NULL, NULL, 0, NULL,
2589 NULL, // from branch
2596 0,0, // dest, bit instruction
2597 0,0, // branch, skip
2598 0, // literal operand
2599 0, // RAM access bit
2600 0, // fast call/return mode select bit
2601 0, // second memory operand
2602 0, // second literal operand
2605 PCC_NONE , // outCond
2609 pCodeInstruction pic16_pciTBLWT = { // patch 15
2610 {PC_OPCODE, NULL, NULL, 0, NULL,
2616 NULL, // from branch
2623 0,0, // dest, bit instruction
2624 0,0, // branch, skip
2625 0, // literal operand
2626 0, // RAM access bit
2627 0, // fast call/return mode select bit
2628 0, // second memory operand
2629 0, // second literal operand
2632 PCC_NONE , // outCond
2636 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2637 {PC_OPCODE, NULL, NULL, 0, NULL,
2643 NULL, // from branch
2650 0,0, // dest, bit instruction
2651 0,0, // branch, skip
2652 0, // literal operand
2653 0, // RAM access bit
2654 0, // fast call/return mode select bit
2655 0, // second memory operand
2656 0, // second literal operand
2659 PCC_NONE , // outCond
2663 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2664 {PC_OPCODE, NULL, NULL, 0, NULL,
2670 NULL, // from branch
2677 0,0, // dest, bit instruction
2678 0,0, // branch, skip
2679 0, // literal operand
2680 0, // RAM access bit
2681 0, // fast call/return mode select bit
2682 0, // second memory operand
2683 0, // second literal operand
2686 PCC_NONE , // outCond
2690 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2691 {PC_OPCODE, NULL, NULL, 0, NULL,
2697 NULL, // from branch
2704 0,0, // dest, bit instruction
2705 0,0, // branch, skip
2706 0, // literal operand
2707 0, // RAM access bit
2708 0, // fast call/return mode select bit
2709 0, // second memory operand
2710 0, // second literal operand
2713 PCC_NONE , // outCond
2717 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2718 {PC_OPCODE, NULL, NULL, 0, NULL,
2725 NULL, // from branch
2732 0,0, // dest, bit instruction
2733 1,1, // branch, skip
2734 0, // literal operand
2735 1, // RAM access bit
2736 0, // fast call/return mode select bit
2737 0, // second memory operand
2738 0, // second literal operand
2740 PCC_REGISTER, // inCond
2741 PCC_NONE, // outCond
2745 pCodeInstruction pic16_pciXORWF = {
2746 {PC_OPCODE, NULL, NULL, 0, NULL,
2753 NULL, // from branch
2760 1,0, // dest, bit instruction
2761 0,0, // branch, skip
2762 0, // literal operand
2763 1, // RAM access bit
2764 0, // fast call/return mode select bit
2765 0, // second memory operand
2766 0, // second literal operand
2768 (PCC_W | PCC_REGISTER), // inCond
2769 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2773 pCodeInstruction pic16_pciXORFW = {
2774 {PC_OPCODE, NULL, NULL, 0, NULL,
2781 NULL, // from branch
2788 0,0, // dest, bit instruction
2789 0,0, // branch, skip
2790 0, // literal operand
2791 1, // RAM access bit
2792 0, // fast call/return mode select bit
2793 0, // second memory operand
2794 0, // second literal operand
2796 (PCC_W | PCC_REGISTER), // inCond
2797 (PCC_W | PCC_Z | PCC_N), // outCond
2801 pCodeInstruction pic16_pciXORLW = {
2802 {PC_OPCODE, NULL, NULL, 0, NULL,
2809 NULL, // from branch
2816 0,0, // dest, bit instruction
2817 0,0, // branch, skip
2818 1, // literal operand
2819 1, // RAM access bit
2820 0, // fast call/return mode select bit
2821 0, // second memory operand
2822 0, // second literal operand
2824 (PCC_W | PCC_LITERAL), // inCond
2825 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2830 pCodeInstruction pic16_pciBANKSEL = {
2831 {PC_OPCODE, NULL, NULL, 0, NULL,
2837 NULL, // from branch
2844 0,0, // dest, bit instruction
2845 0,0, // branch, skip
2846 0, // literal operand
2847 0, // RAM access bit
2848 0, // fast call/return mode select bit
2849 0, // second memory operand
2850 0, // second literal operand
2853 PCC_NONE, // outCond
2858 #define MAX_PIC16MNEMONICS 100
2859 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2861 //#define USE_VSNPRINTF
2864 #ifdef USE_VSNPRINTF
2865 // Alas, vsnprintf is not ANSI standard, and does not exist
2866 // on Solaris (and probably other non-Gnu flavored Unixes).
2868 /*-----------------------------------------------------------------*/
2869 /* SAFE_snprintf - like snprintf except the string pointer is */
2870 /* after the string has been printed to. This is */
2871 /* useful for printing to string as though if it */
2872 /* were a stream. */
2873 /*-----------------------------------------------------------------*/
2874 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2882 va_start(val, format);
2884 vsnprintf(*str, *size, format, val);
2890 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2891 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2900 // This version is *not* safe, despite the name.
2902 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2906 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2911 va_start(val, format);
2913 vsprintf(buffer, format, val);
2916 len = strlen(buffer);
2918 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2919 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2922 strcpy(*str, buffer);
2928 #endif // USE_VSNPRINTF
2931 extern set *externs;
2932 extern void pic16_initStack(int base_address, int size);
2933 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2934 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2935 extern void pic16_init_pic(char *);
2937 void pic16_pCodeInitRegisters(void)
2939 static int initialized=0;
2946 // pic16_initStack(0xfff, 8);
2947 pic16_init_pic(port->processor);
2949 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2950 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2951 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2952 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2953 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2954 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2955 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2957 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2958 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2959 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2961 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2962 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2963 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2964 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2966 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2967 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2968 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2969 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2970 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2971 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2973 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2974 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2975 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2976 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2977 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2979 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2980 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2981 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2982 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2983 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2985 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2986 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2987 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2988 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2989 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2991 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2992 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2995 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2996 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2997 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2998 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
3001 pic16_pc_status.rIdx = IDX_STATUS;
3002 pic16_pc_intcon.rIdx = IDX_INTCON;
3003 pic16_pc_pcl.rIdx = IDX_PCL;
3004 pic16_pc_pclath.rIdx = IDX_PCLATH;
3005 pic16_pc_pclatu.rIdx = IDX_PCLATU;
3006 pic16_pc_wreg.rIdx = IDX_WREG;
3007 pic16_pc_bsr.rIdx = IDX_BSR;
3009 pic16_pc_tosl.rIdx = IDX_TOSL;
3010 pic16_pc_tosh.rIdx = IDX_TOSH;
3011 pic16_pc_tosu.rIdx = IDX_TOSU;
3013 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
3014 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
3015 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
3016 pic16_pc_tablat.rIdx = IDX_TABLAT;
3018 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
3019 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
3020 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
3021 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
3022 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
3023 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
3024 pic16_pc_indf0.rIdx = IDX_INDF0;
3025 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
3026 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
3027 pic16_pc_preinc0.rIdx = IDX_PREINC0;
3028 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
3029 pic16_pc_indf1.rIdx = IDX_INDF1;
3030 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
3031 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
3032 pic16_pc_preinc1.rIdx = IDX_PREINC1;
3033 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
3034 pic16_pc_indf2.rIdx = IDX_INDF2;
3035 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
3036 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
3037 pic16_pc_preinc2.rIdx = IDX_PREINC2;
3038 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
3039 pic16_pc_prodl.rIdx = IDX_PRODL;
3040 pic16_pc_prodh.rIdx = IDX_PRODH;
3042 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
3043 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
3044 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
3046 pic16_pc_kzero.rIdx = IDX_KZ;
3047 pic16_pc_wsave.rIdx = IDX_WSAVE;
3048 pic16_pc_ssave.rIdx = IDX_SSAVE;
3050 pic16_pc_eecon1.rIdx = IDX_EECON1;
3051 pic16_pc_eecon2.rIdx = IDX_EECON2;
3052 pic16_pc_eedata.rIdx = IDX_EEDATA;
3053 pic16_pc_eeadr.rIdx = IDX_EEADR;
3056 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
3057 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
3059 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
3060 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
3062 /* probably should put this in a separate initialization routine */
3063 pb_dead_pcodes = newpBlock();
3068 /*-----------------------------------------------------------------*/
3069 /* mnem2key - convert a pic mnemonic into a hash key */
3070 /* (BTW - this spreads the mnemonics quite well) */
3072 /*-----------------------------------------------------------------*/
3074 int mnem2key(char const *mnem)
3083 key += toupper(*mnem++) +1;
3087 return (key & 0x1f);
3092 void pic16initMnemonics(void)
3097 pCodeInstruction *pci;
3099 if(mnemonics_initialized)
3102 // NULL out the array before making the assignments
3103 // since we check the array contents below this initialization.
3105 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3106 pic16Mnemonics[i] = NULL;
3109 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3110 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3111 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3112 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3113 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3114 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3115 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3116 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3117 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3118 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3119 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3120 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3121 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3122 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3123 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3124 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3125 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3126 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3127 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3128 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3129 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3130 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3131 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3132 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3133 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3134 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3135 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3136 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3137 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3138 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3139 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3140 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3141 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3142 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3143 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3144 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3145 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3146 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3147 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3148 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3149 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3150 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3151 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3152 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3153 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3154 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3155 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3156 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3157 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3158 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3159 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3160 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3161 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3162 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3163 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3164 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3165 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3166 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3167 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3168 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3169 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3170 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3171 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3172 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3173 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3174 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3175 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3176 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3177 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3178 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3179 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3180 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3181 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3182 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3183 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3184 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3185 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3186 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3187 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3188 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3189 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3190 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3191 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3192 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3193 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3194 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3195 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3196 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3197 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3198 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3199 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3200 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3201 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3202 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3204 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3205 if(pic16Mnemonics[i])
3206 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3207 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3210 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3211 pci = hTabNextItem(pic16MnemonicsHash, &key);
3214 mnemonics_initialized = 1;
3217 int pic16_getpCodePeepCommand(char *cmd);
3219 int pic16_getpCode(char *mnem,unsigned dest)
3222 pCodeInstruction *pci;
3223 int key = mnem2key(mnem);
3225 if(!mnemonics_initialized)
3226 pic16initMnemonics();
3228 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3232 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3233 if((pci->num_ops <= 1)
3234 || (pci->isModReg == dest)
3236 || (pci->num_ops <= 2 && pci->isAccess)
3237 || (pci->num_ops <= 2 && pci->isFastCall)
3238 || (pci->num_ops <= 2 && pci->is2MemOp)
3239 || (pci->num_ops <= 2 && pci->is2LitOp) )
3243 pci = hTabNextItemWK (pic16MnemonicsHash);
3250 /*-----------------------------------------------------------------*
3251 * pic16initpCodePeepCommands
3253 *-----------------------------------------------------------------*/
3254 void pic16initpCodePeepCommands(void)
3262 hTabAddItem(&pic16pCodePeepCommandsHash,
3263 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3265 } while (peepCommands[i].cmd);
3267 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3270 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3271 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3276 /*-----------------------------------------------------------------
3279 *-----------------------------------------------------------------*/
3281 int pic16_getpCodePeepCommand(char *cmd)
3285 int key = mnem2key(cmd);
3288 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3291 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3292 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3296 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3303 static char getpBlock_dbName(pBlock *pb)
3309 return pb->cmemmap->dbName;
3313 void pic16_pBlockConvert2ISR(pBlock *pb)
3317 if(pb->cmemmap)pb->cmemmap = NULL;
3321 if(pic16_pcode_verbose)
3322 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3325 void pic16_pBlockConvert2Absolute(pBlock *pb)
3328 if(pb->cmemmap)pb->cmemmap = NULL;
3332 if(pic16_pcode_verbose)
3333 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3336 /*-----------------------------------------------------------------*/
3337 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3338 /* instances to the front of the doubly linked */
3339 /* list of pBlocks */
3340 /*-----------------------------------------------------------------*/
3342 void pic16_movepBlock2Head(char dbName)
3347 /* this can happen in sources without code,
3348 * only variable definitions */
3349 if(!the_pFile)return;
3351 pb = the_pFile->pbHead;
3355 if(getpBlock_dbName(pb) == dbName) {
3356 pBlock *pbn = pb->next;
3357 pb->next = the_pFile->pbHead;
3358 the_pFile->pbHead->prev = pb;
3359 the_pFile->pbHead = pb;
3362 pb->prev->next = pbn;
3364 // If the pBlock that we just moved was the last
3365 // one in the link of all of the pBlocks, then we
3366 // need to point the tail to the block just before
3367 // the one we moved.
3368 // Note: if pb->next is NULL, then pb must have
3369 // been the last pBlock in the chain.
3372 pbn->prev = pb->prev;
3374 the_pFile->pbTail = pb->prev;
3385 void pic16_copypCode(FILE *of, char dbName)
3389 if(!of || !the_pFile)
3392 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3393 if(getpBlock_dbName(pb) == dbName) {
3394 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3396 pic16_printpBlock(of,pb);
3401 void pic16_pcode_test(void)
3404 DFPRINTF((stderr,"pcode is alive!\n"));
3414 /* create the file name */
3415 strcpy(buffer,dstFileName);
3416 strcat(buffer,".p");
3418 if( !(pFile = fopen(buffer, "w" ))) {
3419 werror(E_FILE_OPEN_ERR,buffer);
3423 fprintf(pFile,"pcode dump\n\n");
3425 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3426 fprintf(pFile,"\n\tNew pBlock\n\n");
3428 fprintf(pFile,"%s",pb->cmemmap->sname);
3430 fprintf(pFile,"internal pblock");
3432 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3433 pic16_printpBlock(pFile,pb);
3439 unsigned long pic16_countInstructions(void)
3443 unsigned long isize=0;
3445 if(!the_pFile)return -1;
3447 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3448 for(pc = pb->pcHead; pc; pc = pc->next) {
3449 if(isPCI(pc) || isPCAD(pc))isize += PCI(pc)->isize;
3456 /*-----------------------------------------------------------------*/
3457 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3458 /* ister, RegCond will return the bit being referenced. */
3460 /* fixme - why not just OR in the pcop bit field */
3461 /*-----------------------------------------------------------------*/
3463 static int RegCond(pCodeOp *pcop)
3469 if(!pcop->name)return 0;
3471 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3472 switch(PCORB(pcop)->bit) {
3486 /*-----------------------------------------------------------------*/
3487 /* pic16_newpCode - create and return a newly initialized pCode */
3489 /* fixme - rename this */
3491 /* The purpose of this routine is to create a new Instruction */
3492 /* pCode. This is called by gen.c while the assembly code is being */
3496 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3497 /* (note that the op is analogous to but not the */
3498 /* same thing as the opcode of the instruction.) */
3499 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3502 /* a pointer to the new malloc'd pCode is returned. */
3506 /*-----------------------------------------------------------------*/
3507 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3509 pCodeInstruction *pci ;
3511 if(!mnemonics_initialized)
3512 pic16initMnemonics();
3514 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3516 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3517 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3520 if(pci->inCond & PCC_EXAMINE_PCOP)
3521 pci->inCond |= RegCond(pcop);
3523 if(pci->outCond & PCC_EXAMINE_PCOP)
3524 pci->outCond |= RegCond(pcop);
3526 pci->pc.prev = pci->pc.next = NULL;
3527 return (pCode *)pci;
3530 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3536 /*-----------------------------------------------------------------*/
3537 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3539 /* Wild pcodes are used during the peep hole optimizer to serve */
3540 /* as place holders for any instruction. When a snippet of code is */
3541 /* compared to a peep hole rule, the wild card opcode will match */
3542 /* any instruction. However, the optional operand and label are */
3543 /* additional qualifiers that must also be matched before the */
3544 /* line (of assembly code) is declared matched. Note that the */
3545 /* operand may be wild too. */
3547 /* Note, a wild instruction is specified just like a wild var: */
3548 /* %4 ; A wild instruction, */
3549 /* See the peeph.def file for additional examples */
3551 /*-----------------------------------------------------------------*/
3553 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3558 pcw = Safe_calloc(1,sizeof(pCodeWild));
3560 pcw->pci.pc.type = PC_WILD;
3561 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3562 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3563 pcw->pci.pc.pb = NULL;
3565 // pcw->pci.pc.analyze = genericAnalyze;
3566 pcw->pci.pc.destruct = genericDestruct;
3567 pcw->pci.pc.print = genericPrint;
3569 pcw->id = pCodeID; // this is the 'n' in %n
3570 pcw->operand = optional_operand;
3571 pcw->label = optional_label;
3573 pcw->mustBeBitSkipInst = 0;
3574 pcw->mustNotBeBitSkipInst = 0;
3575 pcw->invertBitSkipInst = 0;
3577 return ( (pCode *)pcw);
3581 /*-----------------------------------------------------------------*/
3582 /* newPcodeInlineP - create a new pCode from a char string */
3583 /*-----------------------------------------------------------------*/
3586 pCode *pic16_newpCodeInlineP(char *cP)
3591 pcc = Safe_calloc(1,sizeof(pCodeComment));
3593 pcc->pc.type = PC_INLINE;
3594 pcc->pc.prev = pcc->pc.next = NULL;
3595 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3598 // pcc->pc.analyze = genericAnalyze;
3599 pcc->pc.destruct = genericDestruct;
3600 pcc->pc.print = genericPrint;
3603 pcc->comment = Safe_strdup(cP);
3605 pcc->comment = NULL;
3607 return ( (pCode *)pcc);
3611 /*-----------------------------------------------------------------*/
3612 /* newPcodeCharP - create a new pCode from a char string */
3613 /*-----------------------------------------------------------------*/
3615 pCode *pic16_newpCodeCharP(char *cP)
3620 pcc = Safe_calloc(1,sizeof(pCodeComment));
3622 pcc->pc.type = PC_COMMENT;
3623 pcc->pc.prev = pcc->pc.next = NULL;
3624 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3627 // pcc->pc.analyze = genericAnalyze;
3628 pcc->pc.destruct = genericDestruct;
3629 pcc->pc.print = genericPrint;
3632 pcc->comment = Safe_strdup(cP);
3634 pcc->comment = NULL;
3636 return ( (pCode *)pcc);
3640 /*-----------------------------------------------------------------*/
3641 /* pic16_newpCodeFunction - */
3642 /*-----------------------------------------------------------------*/
3645 pCode *pic16_newpCodeFunction(char *mod,char *f)
3649 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3651 pcf->pc.type = PC_FUNCTION;
3652 pcf->pc.prev = pcf->pc.next = NULL;
3653 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3656 // pcf->pc.analyze = genericAnalyze;
3657 pcf->pc.destruct = genericDestruct;
3658 pcf->pc.print = pCodePrintFunction;
3664 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3665 strcpy(pcf->modname,mod);
3667 pcf->modname = NULL;
3670 pcf->fname = Safe_calloc(1,strlen(f)+1);
3671 strcpy(pcf->fname,f);
3675 pcf->stackusage = 0;
3677 return ( (pCode *)pcf);
3680 /*-----------------------------------------------------------------*/
3681 /* pic16_newpCodeFlow */
3682 /*-----------------------------------------------------------------*/
3683 static void destructpCodeFlow(pCode *pc)
3685 if(!pc || !isPCFL(pc))
3692 pic16_unlinkpCode(pc);
3694 deleteSet(&PCFL(pc)->registers);
3695 deleteSet(&PCFL(pc)->from);
3696 deleteSet(&PCFL(pc)->to);
3698 /* Instead of deleting the memory used by this pCode, mark
3699 * the object as bad so that if there's a pointer to this pCode
3700 * dangling around somewhere then (hopefully) when the type is
3701 * checked we'll catch it.
3705 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3711 pCode *pic16_newpCodeFlow(void )
3715 //_ALLOC(pcflow,sizeof(pCodeFlow));
3716 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3718 pcflow->pc.type = PC_FLOW;
3719 pcflow->pc.prev = pcflow->pc.next = NULL;
3720 pcflow->pc.pb = NULL;
3722 // pcflow->pc.analyze = genericAnalyze;
3723 pcflow->pc.destruct = destructpCodeFlow;
3724 pcflow->pc.print = genericPrint;
3726 pcflow->pc.seq = GpcFlowSeq++;
3728 pcflow->from = pcflow->to = NULL;
3730 pcflow->inCond = PCC_NONE;
3731 pcflow->outCond = PCC_NONE;
3733 pcflow->firstBank = -1;
3734 pcflow->lastBank = -1;
3736 pcflow->FromConflicts = 0;
3737 pcflow->ToConflicts = 0;
3741 pcflow->registers = newSet();
3743 return ( (pCode *)pcflow);
3747 /*-----------------------------------------------------------------*/
3748 /*-----------------------------------------------------------------*/
3749 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3751 pCodeFlowLink *pcflowLink;
3753 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3755 pcflowLink->pcflow = pcflow;
3756 pcflowLink->bank_conflict = 0;
3761 /*-----------------------------------------------------------------*/
3762 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3763 /*-----------------------------------------------------------------*/
3765 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3770 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3772 pccs->pc.type = PC_CSOURCE;
3773 pccs->pc.prev = pccs->pc.next = NULL;
3776 pccs->pc.destruct = genericDestruct;
3777 pccs->pc.print = genericPrint;
3779 pccs->line_number = ln;
3781 pccs->line = Safe_strdup(l);
3786 pccs->file_name = Safe_strdup(f);
3788 pccs->file_name = NULL;
3790 return ( (pCode *)pccs);
3795 /*******************************************************************/
3796 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3797 /* added by VR 6-Jun-2003 */
3798 /*******************************************************************/
3800 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3807 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3808 pcad->pci.pc.type = PC_ASMDIR;
3809 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3810 pcad->pci.pc.pb = NULL;
3811 pcad->pci.isize = 2;
3812 pcad->pci.pc.destruct = genericDestruct;
3813 pcad->pci.pc.print = genericPrint;
3815 if(asdir && *asdir) {
3817 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3819 pcad->directive = Safe_strdup( asdir );
3822 va_start(ap, argfmt);
3824 memset(buffer, 0, sizeof(buffer));
3825 if(argfmt && *argfmt)
3826 vsprintf(buffer, argfmt, ap);
3830 while(isspace(*lbp))lbp++;
3833 pcad->arg = Safe_strdup( lbp );
3835 return ((pCode *)pcad);
3838 /*-----------------------------------------------------------------*/
3839 /* pCodeLabelDestruct - free memory used by a label. */
3840 /*-----------------------------------------------------------------*/
3841 static void pCodeLabelDestruct(pCode *pc)
3847 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3848 // free(PCL(pc)->label);
3850 /* Instead of deleting the memory used by this pCode, mark
3851 * the object as bad so that if there's a pointer to this pCode
3852 * dangling around somewhere then (hopefully) when the type is
3853 * checked we'll catch it.
3857 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3863 pCode *pic16_newpCodeLabel(char *name, int key)
3869 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3871 pcl->pc.type = PC_LABEL;
3872 pcl->pc.prev = pcl->pc.next = NULL;
3873 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3876 // pcl->pc.analyze = genericAnalyze;
3877 pcl->pc.destruct = pCodeLabelDestruct;
3878 pcl->pc.print = pCodePrintLabel;
3885 sprintf(s,"_%05d_DS_",key);
3890 pcl->label = Safe_strdup(s);
3892 // if(pic16_pcode_verbose)
3893 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3896 return ( (pCode *)pcl);
3900 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3902 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3906 return ( (pCode *)pcl );
3909 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3913 pci = Safe_calloc(1, sizeof(pCodeInfo));
3914 pci->pci.pc.type = PC_INFO;
3915 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3916 pci->pci.pc.pb = NULL;
3917 pci->pci.label = NULL;
3919 pci->pci.pc.destruct = genericDestruct;
3920 pci->pci.pc.print = genericPrint;
3925 return ((pCode *)pci);
3929 /*-----------------------------------------------------------------*/
3930 /* newpBlock - create and return a pointer to a new pBlock */
3931 /*-----------------------------------------------------------------*/
3932 static pBlock *newpBlock(void)
3937 PpB = Safe_calloc(1,sizeof(pBlock) );
3938 PpB->next = PpB->prev = NULL;
3940 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3941 PpB->tregisters = NULL;
3943 PpB->FlowTree = NULL;
3949 /*-----------------------------------------------------------------*/
3950 /* pic16_newpCodeChain - create a new chain of pCodes */
3951 /*-----------------------------------------------------------------*
3953 * This function will create a new pBlock and the pointer to the
3954 * pCode that is passed in will be the first pCode in the block.
3955 *-----------------------------------------------------------------*/
3958 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3961 pBlock *pB = newpBlock();
3963 pB->pcHead = pB->pcTail = pc;
3972 /*-----------------------------------------------------------------*/
3973 /* pic16_newpCodeOpLabel - Create a new label given the key */
3974 /* Note, a negative key means that the label is part of wild card */
3975 /* (and hence a wild card label) used in the pCodePeep */
3976 /* optimizations). */
3977 /*-----------------------------------------------------------------*/
3979 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3982 static int label_key=-1;
3986 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3987 pcop->type = PO_LABEL;
3992 sprintf(s=buffer,"_%05d_DS_",key);
3994 s = name, key = label_key--;
3997 pcop->name = Safe_strdup(s);
3999 ((pCodeOpLabel *)pcop)->key = key;
4001 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4005 /*-----------------------------------------------------------------*/
4006 /*-----------------------------------------------------------------*/
4007 pCodeOp *pic16_newpCodeOpLit(int lit)
4013 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4014 pcop->type = PO_LITERAL;
4018 sprintf(s,"0x%02hhx",(char)(lit));
4020 // sprintf(s, "%i", lit);
4023 pcop->name = Safe_strdup(s);
4025 ((pCodeOpLit *)pcop)->lit = lit;
4030 /*-----------------------------------------------------------------*/
4031 /*-----------------------------------------------------------------*/
4032 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4034 char *s = buffer, tbuf[256], *tb=tbuf;
4038 tb = pic16_get_op(arg2, NULL, 0);
4039 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4040 pcop->type = PO_LITERAL;
4044 sprintf(s,"0x%02x, %s",lit, tb);
4046 pcop->name = Safe_strdup(s);
4049 ((pCodeOpLit2 *)pcop)->lit = lit;
4050 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4055 /*-----------------------------------------------------------------*/
4056 /*-----------------------------------------------------------------*/
4057 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4061 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4062 pcop->type = PO_IMMEDIATE;
4064 regs *r = pic16_dirregWithName(name);
4065 pcop->name = Safe_strdup(name);
4069 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4070 PCOI(pcop)->rIdx = r->rIdx;
4072 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4073 PCOI(pcop)->rIdx = -1;
4075 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4080 PCOI(pcop)->index = index;
4081 PCOI(pcop)->offset = offset;
4082 PCOI(pcop)->_const = code_space;
4087 /*-----------------------------------------------------------------*/
4088 /*-----------------------------------------------------------------*/
4089 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4095 if(!pcwb || !subtype) {
4096 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4100 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4101 pcop->type = PO_WILD;
4102 sprintf(s,"%%%d",id);
4103 pcop->name = Safe_strdup(s);
4105 PCOW(pcop)->id = id;
4106 PCOW(pcop)->pcwb = pcwb;
4107 PCOW(pcop)->subtype = subtype;
4108 PCOW(pcop)->matched = NULL;
4110 PCOW(pcop)->pcop2 = NULL;
4115 /*-----------------------------------------------------------------*/
4116 /*-----------------------------------------------------------------*/
4117 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4123 if(!pcwb || !subtype || !subtype2) {
4124 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4128 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4129 pcop->type = PO_WILD;
4130 sprintf(s,"%%%d",id);
4131 pcop->name = Safe_strdup(s);
4133 PCOW(pcop)->id = id;
4134 PCOW(pcop)->pcwb = pcwb;
4135 PCOW(pcop)->subtype = subtype;
4136 PCOW(pcop)->matched = NULL;
4138 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4140 if(!subtype2->name) {
4141 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4142 PCOW2(pcop)->pcop.type = PO_WILD;
4143 sprintf(s, "%%%d", id2);
4144 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4145 PCOW2(pcop)->id = id2;
4146 PCOW2(pcop)->subtype = subtype2;
4148 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4149 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4151 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4153 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4154 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4163 /*-----------------------------------------------------------------*/
4164 /*-----------------------------------------------------------------*/
4165 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4169 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4170 pcop->type = PO_GPR_BIT;
4172 pcop->name = Safe_strdup(s);
4176 PCORB(pcop)->bit = bit;
4177 PCORB(pcop)->inBitSpace = inBitSpace;
4178 PCORB(pcop)->subtype = subt;
4180 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4181 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4182 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4183 // PCOR(pcop)->rIdx = 0;
4188 /*-----------------------------------------------------------------*
4189 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4191 * If rIdx >=0 then a specific register from the set of registers
4192 * will be selected. If rIdx <0, then a new register will be searched
4194 *-----------------------------------------------------------------*/
4196 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4200 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4205 PCOR(pcop)->rIdx = rIdx;
4206 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4208 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4211 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4213 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4214 __FUNCTION__, __LINE__);
4219 pcop->type = PCOR(pcop)->r->pc_type;
4224 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4229 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4230 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4231 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4232 pcop->type = PCOR(pcop)->r->pc_type;
4233 pcop->name = PCOR(pcop)->r->name;
4235 // if(pic16_pcode_verbose) {
4236 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4237 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4243 /*-----------------------------------------------------------------*/
4244 /*-----------------------------------------------------------------*/
4245 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4249 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4252 pcop->key = Safe_strdup( key );
4254 return (PCOP(pcop));
4257 /*-----------------------------------------------------------------*/
4258 /*-----------------------------------------------------------------*/
4259 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4261 pCodeOpLocalReg *pcop;
4263 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4267 return (PCOP(pcop));
4271 /*-----------------------------------------------------------------*/
4272 /*-----------------------------------------------------------------*/
4274 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4281 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4285 pcop = pic16_newpCodeOpLit(-1);
4289 pcop = pic16_newpCodeOpLabel(NULL,-1);
4292 pcop = pic16_newpCodeOpReg(-1);
4295 case PO_GPR_REGISTER:
4297 pcop = pic16_newpCodeOpRegFromStr(name);
4299 pcop = pic16_newpCodeOpReg(-1);
4303 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4306 pcop->name = Safe_strdup(name);
4314 #define DB_ITEMS_PER_LINE 8
4316 typedef struct DBdata
4323 static int DBd_init = -1;
4325 /*-----------------------------------------------------------------*/
4326 /* Initialiase "DB" data buffer */
4327 /*-----------------------------------------------------------------*/
4328 void pic16_initDB(void)
4334 /*-----------------------------------------------------------------*/
4335 /* Flush pending "DB" data to a pBlock */
4337 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4338 /*-----------------------------------------------------------------*/
4339 void pic16_flushDB(char ptype, void *p)
4343 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4346 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4349 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4353 DBd.buffer[0] = '\0';
4358 /*-----------------------------------------------------------------*/
4359 /* Add "DB" directives to a pBlock */
4360 /*-----------------------------------------------------------------*/
4361 void pic16_emitDB(char c, char ptype, void *p)
4366 // we need to initialize
4369 DBd.buffer[0] = '\0';
4372 l = strlen(DBd.buffer);
4373 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4375 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4378 if (DBd.count>= DB_ITEMS_PER_LINE)
4379 pic16_flushDB(ptype, p);
4382 void pic16_emitDS(char *s, char ptype, void *p)
4387 // we need to initialize
4390 DBd.buffer[0] = '\0';
4393 l = strlen(DBd.buffer);
4394 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4396 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4398 DBd.count++; //=strlen(s);
4400 pic16_flushDB(ptype, p);
4404 /*-----------------------------------------------------------------*/
4405 /*-----------------------------------------------------------------*/
4406 void pic16_pCodeConstString(char *name, char *value)
4410 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4415 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4417 pic16_addpBlock(pb);
4419 // sprintf(buffer,"; %s = ", name);
4420 // strcat(buffer, value);
4421 // fputs(buffer, stderr);
4423 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4424 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4427 pic16_emitDB(*value, 'p', (void *)pb);
4429 pic16_flushDB('p', (void *)pb);
4432 /*-----------------------------------------------------------------*/
4433 /*-----------------------------------------------------------------*/
4435 static void pCodeReadCodeTable(void)
4439 fprintf(stderr, " %s\n",__FUNCTION__);
4441 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4443 pic16_addpBlock(pb);
4445 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4446 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4447 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4448 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4450 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4451 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4452 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4453 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4458 /*-----------------------------------------------------------------*/
4459 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4460 /*-----------------------------------------------------------------*/
4461 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4468 /* If this is the first pcode to be added to a block that
4469 * was initialized with a NULL pcode, then go ahead and
4470 * make this pcode the head and tail */
4471 pb->pcHead = pb->pcTail = pc;
4474 pb->pcTail->next = pc;
4476 pc->prev = pb->pcTail;
4483 /*-----------------------------------------------------------------*/
4484 /* pic16_addpBlock - place a pBlock into the pFile */
4485 /*-----------------------------------------------------------------*/
4486 void pic16_addpBlock(pBlock *pb)
4488 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4491 /* First time called, we'll pass through here. */
4492 //_ALLOC(the_pFile,sizeof(pFile));
4493 the_pFile = Safe_calloc(1,sizeof(pFile));
4494 the_pFile->pbHead = the_pFile->pbTail = pb;
4495 the_pFile->functions = NULL;
4499 the_pFile->pbTail->next = pb;
4500 pb->prev = the_pFile->pbTail;
4502 the_pFile->pbTail = pb;
4505 /*-----------------------------------------------------------------*/
4506 /* removepBlock - remove a pBlock from the pFile */
4507 /*-----------------------------------------------------------------*/
4508 static void removepBlock(pBlock *pb)
4516 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4518 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4521 if(pbs == the_pFile->pbHead)
4522 the_pFile->pbHead = pbs->next;
4524 if (pbs == the_pFile->pbTail)
4525 the_pFile->pbTail = pbs->prev;
4528 pbs->next->prev = pbs->prev;
4531 pbs->prev->next = pbs->next;
4538 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4542 /*-----------------------------------------------------------------*/
4543 /* printpCode - write the contents of a pCode to a file */
4544 /*-----------------------------------------------------------------*/
4545 static void printpCode(FILE *of, pCode *pc)
4556 fprintf(of,"warning - unable to print pCode\n");
4559 /*-----------------------------------------------------------------*/
4560 /* pic16_printpBlock - write the contents of a pBlock to a file */
4561 /*-----------------------------------------------------------------*/
4562 void pic16_printpBlock(FILE *of, pBlock *pb)
4570 for(pc = pb->pcHead; pc; pc = pc->next) {
4571 if(isPCF(pc) && PCF(pc)->fname) {
4572 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4573 if(pb->dbName == 'A') {
4575 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4576 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4577 if(!strcmp(ab->name, PCF(pc)->fname)) {
4578 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4579 fprintf(of, "\t0X%06X", ab->address);
4590 /*-----------------------------------------------------------------*/
4592 /* pCode processing */
4596 /*-----------------------------------------------------------------*/
4598 void pic16_unlinkpCode(pCode *pc)
4604 fprintf(stderr,"Unlinking: ");
4605 printpCode(stderr, pc);
4608 pc->prev->next = pc->next;
4610 pc->next->prev = pc->prev;
4612 pc->prev = pc->next = NULL;
4616 /*-----------------------------------------------------------------*/
4617 /*-----------------------------------------------------------------*/
4619 static void genericDestruct(pCode *pc)
4622 pic16_unlinkpCode(pc);
4625 /* For instructions, tell the register (if there's one used)
4626 * that it's no longer needed */
4627 regs *reg = pic16_getRegFromInstruction(pc);
4629 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4631 if(PCI(pc)->is2MemOp) {
4632 reg = pic16_getRegFromInstruction2(pc);
4634 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4638 /* Instead of deleting the memory used by this pCode, mark
4639 * the object as bad so that if there's a pointer to this pCode
4640 * dangling around somewhere then (hopefully) when the type is
4641 * checked we'll catch it.
4645 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4651 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4652 /*-----------------------------------------------------------------*/
4653 /*-----------------------------------------------------------------*/
4654 /* modifiers for constant immediate */
4655 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4657 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4662 int use_buffer = 1; // copy the string to the passed buffer pointer
4667 use_buffer = 0; // Don't bother copying the string to the buffer.
4671 switch(pcop->type) {
4679 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4682 return PCOR(pcop)->r->name;
4685 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4687 SAFE_snprintf(&buffer,&size,"%s",r->name);
4694 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4695 if(PCOI(pcop)->index) {
4696 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4697 immdmod[ PCOI(pcop)->offset ],
4701 SAFE_snprintf(&s,&size,"%s(%s)",
4702 immdmod[ PCOI(pcop)->offset ],
4706 if(PCOI(pcop)->index) {
4707 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4712 SAFE_snprintf(&s,&size, "%s(%s)",
4719 case PO_GPR_REGISTER:
4722 // size = sizeof(buffer);
4723 if( PCOR(pcop)->instance) {
4724 SAFE_snprintf(&s,&size,"(%s + %d)",
4726 PCOR(pcop)->instance );
4728 SAFE_snprintf(&s,&size,"%s",pcop->name);
4733 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4734 SAFE_snprintf(&s, &size, "%s", pcop->name);
4736 if(PCORB(pcop)->pcor.instance)
4737 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4739 SAFE_snprintf(&s, &size, "%s", pcop->name);
4746 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4755 return "NO operand1";
4758 /*-----------------------------------------------------------------*/
4759 /* pic16_get_op2 - variant to support two memory operand commands */
4760 /*-----------------------------------------------------------------*/
4761 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4766 int use_buffer = 1; // copy the string to the passed buffer pointer
4771 use_buffer = 0; // Don't bother copying the string to the buffer.
4775 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",
4776 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4777 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4781 switch(PCOR2(pcop)->pcop2->type) {
4789 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4792 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4795 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4798 SAFE_snprintf(&buffer,&size,"%s",r->name);
4809 if(PCOI(pcop)->_const) {
4810 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4811 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4814 8 * PCOI(pcop)->offset );
4816 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4818 if( PCOI(pcop)->index) {
4819 SAFE_snprintf(&s,&size,"(%s + %d)",
4821 PCOI(pcop)->index );
4823 if(PCOI(pcop)->offset)
4824 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4826 SAFE_snprintf(&s,&size,"%s",pcop->name);
4833 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4834 SAFE_snprintf(&s,&size,"(%s + %d)",
4835 PCOR(PCOR2(pcop)->pcop2)->r->name,
4836 PCOR(PCOR2(pcop)->pcop2)->instance );
4838 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4843 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4845 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4848 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4853 return "NO operand2";
4856 /*-----------------------------------------------------------------*/
4857 /*-----------------------------------------------------------------*/
4858 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4862 return pic16_get_op(pcc->pcop,NULL,0);
4864 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4865 * return ("ERROR Null: "__FUNCTION__);
4867 return ("ERROR Null: pic16_get_op_from_instruction");
4871 /*-----------------------------------------------------------------*/
4872 /*-----------------------------------------------------------------*/
4873 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4876 fprintf(of,"pcodeopprint- not implemented\n");
4879 /*-----------------------------------------------------------------*/
4880 /* pic16_pCode2str - convert a pCode instruction to string */
4881 /*-----------------------------------------------------------------*/
4882 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4888 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4889 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4890 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4898 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4900 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4902 if(PCI(pc)->is2MemOp) {
4903 SAFE_snprintf(&s,&size, "%s, %s",
4904 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4905 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4909 if(PCI(pc)->is2LitOp) {
4910 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4914 if(PCI(pc)->isBitInst) {
4915 if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4916 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4917 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4918 PCI(pc)->pcop->name ,
4919 PCI(pc)->pcop->name );
4921 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4922 // (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4923 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4925 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4926 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4928 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4929 //PCI(pc)->pcop->t.bit );
4932 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4933 if( PCI(pc)->num_ops == 3)
4934 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4936 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4939 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4941 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4942 if(PCI(pc)->num_ops == 3)
4943 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4945 r = pic16_getRegFromInstruction(pc);
4946 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4947 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4949 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4958 /* assuming that comment ends with a \n */
4959 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4963 SAFE_snprintf(&s,&size,"; info ==>");
4964 switch(((pCodeInfo *)pc)->type) {
4965 case INF_OPTIMIZATION:
4966 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4969 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
4974 /* assuming that inline code ends with a \n */
4975 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4979 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4982 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4985 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4988 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4991 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4992 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4993 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4996 if(PCAD(pc)->directive) {
4997 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5000 /* special case to handle inline labels without a tab */
5001 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5006 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5014 /*-----------------------------------------------------------------*/
5015 /* genericPrint - the contents of a pCode to a file */
5016 /*-----------------------------------------------------------------*/
5017 static void genericPrint(FILE *of, pCode *pc)
5025 // fputs(((pCodeComment *)pc)->comment, of);
5026 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5031 pBranch *pbl = PCI(pc)->label;
5032 while(pbl && pbl->pc) {
5033 if(pbl->pc->type == PC_LABEL)
5034 pCodePrintLabel(of, pbl->pc);
5039 if(pic16_pcode_verbose) {
5040 fprintf(of, "; info ==>");
5041 switch(((pCodeInfo *)pc)->type) {
5042 case INF_OPTIMIZATION:
5043 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5046 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5054 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5058 // If the opcode has a label, print that first
5060 pBranch *pbl = PCI(pc)->label;
5061 while(pbl && pbl->pc) {
5062 if(pbl->pc->type == PC_LABEL)
5063 pCodePrintLabel(of, pbl->pc);
5069 genericPrint(of,PCODE(PCI(pc)->cline));
5074 pic16_pCode2str(str, 256, pc);
5076 fprintf(of,"%s",str);
5078 if(pic16_debug_verbose) {
5079 fprintf(of, "\t;key=%03x",pc->seq);
5081 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5088 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5089 if(PCW(pc)->pci.label)
5090 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5092 if(PCW(pc)->operand) {
5093 fprintf(of,";\toperand ");
5094 pCodeOpPrint(of,PCW(pc)->operand );
5099 if(pic16_debug_verbose) {
5100 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5101 if(PCFL(pc)->ancestor)
5102 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5109 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5110 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5111 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5117 pBranch *pbl = PCAD(pc)->pci.label;
5118 while(pbl && pbl->pc) {
5119 if(pbl->pc->type == PC_LABEL)
5120 pCodePrintLabel(of, pbl->pc);
5124 if(PCAD(pc)->directive) {
5125 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5128 /* special case to handle inline labels without tab */
5129 fprintf(of, "%s\n", PCAD(pc)->arg);
5135 fprintf(of,"unknown pCode type %d\n",pc->type);
5140 /*-----------------------------------------------------------------*/
5141 /* pCodePrintFunction - prints function begin/end */
5142 /*-----------------------------------------------------------------*/
5144 static void pCodePrintFunction(FILE *of, pCode *pc)
5151 if( ((pCodeFunction *)pc)->modname)
5152 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5155 if(!PCF(pc)->absblock) {
5156 if(PCF(pc)->fname) {
5157 pBranch *exits = PCF(pc)->to;
5160 fprintf(of,"%s:", PCF(pc)->fname);
5162 if(pic16_pcode_verbose)
5163 fprintf(of, "\t;Function start");
5169 exits = exits->next;
5173 if(pic16_pcode_verbose)
5174 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5177 if((PCF(pc)->from &&
5178 PCF(pc)->from->pc->type == PC_FUNCTION &&
5179 PCF(PCF(pc)->from->pc)->fname) ) {
5181 if(pic16_pcode_verbose)
5182 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5184 if(pic16_pcode_verbose)
5185 fprintf(of,"; exit point [can't find entry point]\n");
5191 /*-----------------------------------------------------------------*/
5192 /* pCodePrintLabel - prints label */
5193 /*-----------------------------------------------------------------*/
5195 static void pCodePrintLabel(FILE *of, pCode *pc)
5202 fprintf(of,"%s:\n",PCL(pc)->label);
5203 else if (PCL(pc)->key >=0)
5204 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5206 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5209 /*-----------------------------------------------------------------*/
5210 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5211 /* remove it if it is found. */
5212 /*-----------------------------------------------------------------*/
5213 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5220 if(pcl->type == PC_OPCODE)
5221 b = PCI(pcl)->label;
5223 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5228 //fprintf (stderr, "%s \n",__FUNCTION__);
5229 //pcl->print(stderr,pcl);
5230 //pc->print(stderr,pc);
5233 //fprintf (stderr, "found label\n");
5234 //pc->print(stderr, pc);
5238 bprev->next = b->next; /* Not first pCode in chain */
5242 PCI(pcl)->label = b->next; /* First pCode in chain */
5245 return; /* A label can't occur more than once */
5253 /*-----------------------------------------------------------------*/
5254 /*-----------------------------------------------------------------*/
5255 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5274 /*-----------------------------------------------------------------*/
5275 /* pBranchLink - given two pcodes, this function will link them */
5276 /* together through their pBranches */
5277 /*-----------------------------------------------------------------*/
5278 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5282 // Declare a new branch object for the 'from' pCode.
5284 //_ALLOC(b,sizeof(pBranch));
5285 b = Safe_calloc(1,sizeof(pBranch));
5286 b->pc = PCODE(t); // The link to the 'to' pCode.
5289 f->to = pic16_pBranchAppend(f->to,b);
5291 // Now do the same for the 'to' pCode.
5293 //_ALLOC(b,sizeof(pBranch));
5294 b = Safe_calloc(1,sizeof(pBranch));
5298 t->from = pic16_pBranchAppend(t->from,b);
5303 /*-----------------------------------------------------------------*/
5304 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5306 /*-----------------------------------------------------------------*/
5307 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5320 /*-----------------------------------------------------------------*/
5321 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5322 /*-----------------------------------------------------------------*/
5323 void pic16_pCodeUnlink(pCode *pc)
5328 if(!pc->prev || !pc->next) {
5329 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5333 /* first remove the pCode from the chain */
5334 pc->prev->next = pc->next;
5335 pc->next->prev = pc->prev;
5337 /* Now for the hard part... */
5339 /* Remove the branches */
5341 pb1 = PCI(pc)->from;
5343 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5344 * one we're unlinking */
5346 /* search for the link back to this pCode (the one we're
5348 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5349 pb2->pc = PCI(pc)->to->pc; // make the replacement
5351 /* if the pCode we're unlinking contains multiple 'to'
5352 * branches (e.g. this a skip instruction) then we need
5353 * to copy these extra branches to the chain. */
5354 if(PCI(pc)->to->next)
5355 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5364 /*-----------------------------------------------------------------*/
5365 /*-----------------------------------------------------------------*/
5367 static void genericAnalyze(pCode *pc)
5377 // Go through the pCodes that are in pCode chain and link
5378 // them together through the pBranches. Note, the pCodes
5379 // are linked together as a contiguous stream like the
5380 // assembly source code lines. The linking here mimics this
5381 // except that comments are not linked in.
5383 pCode *npc = pc->next;
5385 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5386 pBranchLink(pc,npc);
5391 /* reached the end of the pcode chain without finding
5392 * an instruction we could link to. */
5396 fprintf(stderr,"analyze PC_FLOW\n");
5400 fprintf(stderr,,";A bad pCode is being used\n");
5406 /*-----------------------------------------------------------------*/
5407 /*-----------------------------------------------------------------*/
5408 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5412 if(pc->type == PC_LABEL) {
5413 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5416 if((pc->type == PC_OPCODE)
5417 || (pc->type == PC_ASMDIR)
5419 pbr = PCI(pc)->label;
5421 if(pbr->pc->type == PC_LABEL) {
5422 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5432 /*-----------------------------------------------------------------*/
5433 /*-----------------------------------------------------------------*/
5434 static int checkLabel(pCode *pc)
5438 if(pc && isPCI(pc)) {
5439 pbr = PCI(pc)->label;
5441 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5451 /*-----------------------------------------------------------------*/
5452 /* findLabelinpBlock - Search the pCode for a particular label */
5453 /*-----------------------------------------------------------------*/
5454 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5461 for(pc = pb->pcHead; pc; pc = pc->next)
5462 if(compareLabel(pc,pcop_label))
5468 /*-----------------------------------------------------------------*/
5469 /* findLabel - Search the pCode for a particular label */
5470 /*-----------------------------------------------------------------*/
5471 static pCode * findLabel(pCodeOpLabel *pcop_label)
5479 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5480 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5484 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5488 /*-----------------------------------------------------------------*/
5489 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5490 /* in the linked list */
5491 /*-----------------------------------------------------------------*/
5492 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5505 /*-----------------------------------------------------------------*/
5506 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5507 /* in the linked list */
5508 /*-----------------------------------------------------------------*/
5509 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5523 //#define PCODE_DEBUG
5524 /*-----------------------------------------------------------------*/
5525 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5526 /* in the linked list */
5527 /*-----------------------------------------------------------------*/
5528 pCode * pic16_findNextInstruction(pCode *pci)
5533 if((pc->type == PC_OPCODE)
5534 || (pc->type == PC_WILD)
5535 || (pc->type == PC_ASMDIR)
5540 fprintf(stderr,"pic16_findNextInstruction: ");
5541 printpCode(stderr, pc);
5546 //fprintf(stderr,"Couldn't find instruction\n");
5550 /*-----------------------------------------------------------------*/
5551 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5552 /* in the linked list */
5553 /*-----------------------------------------------------------------*/
5554 pCode * pic16_findPrevInstruction(pCode *pci)
5560 if((pc->type == PC_OPCODE)
5561 || (pc->type == PC_WILD)
5562 || (pc->type == PC_ASMDIR)
5568 fprintf(stderr,"pic16_findPrevInstruction: ");
5569 printpCode(stderr, pc);
5574 //fprintf(stderr,"Couldn't find instruction\n");
5581 /*-----------------------------------------------------------------*/
5582 /* findFunctionEnd - given a pCode find the end of the function */
5583 /* that contains it */
5584 /*-----------------------------------------------------------------*/
5585 static pCode * findFunctionEnd(pCode *pc)
5589 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5595 fprintf(stderr,"Couldn't find function end\n");
5600 /*-----------------------------------------------------------------*/
5601 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5602 /* instruction with which it is associated. */
5603 /*-----------------------------------------------------------------*/
5604 static void AnalyzeLabel(pCode *pc)
5607 pic16_pCodeUnlink(pc);
5613 static void AnalyzeGOTO(pCode *pc)
5616 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5620 static void AnalyzeSKIP(pCode *pc)
5623 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5624 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5628 static void AnalyzeRETURN(pCode *pc)
5631 // branch_link(pc,findFunctionEnd(pc->next));
5637 /*-----------------------------------------------------------------*/
5638 /*-----------------------------------------------------------------*/
5639 regs * pic16_getRegFromInstruction(pCode *pc)
5645 PCI(pc)->num_ops == 0 ||
5646 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5650 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5651 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5654 switch(PCI(pc)->pcop->type) {
5660 return PCOR(PCI(pc)->pcop)->r;
5664 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5665 return PCOR(PCI(pc)->pcop)->r;
5668 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5670 if(PCOI(PCI(pc)->pcop)->r)
5671 return (PCOI(PCI(pc)->pcop)->r);
5676 return PCOR(PCI(pc)->pcop)->r;
5678 case PO_GPR_REGISTER:
5680 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5681 return PCOR(PCI(pc)->pcop)->r;
5684 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5688 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5689 // genericPrint(stderr, pc);
5697 /*-------------------------------------------------------------------------------*/
5698 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5699 /*-------------------------------------------------------------------------------*/
5700 regs * pic16_getRegFromInstruction2(pCode *pc)
5706 PCI(pc)->num_ops == 0 ||
5707 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5712 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5713 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5717 * operands supported in MOVFF:
5724 switch(PCI(pc)->pcop->type) {
5730 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5732 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5736 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5737 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5741 // if(PCOI(PCI(pc)->pcop)->r)
5742 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5744 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5745 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5748 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5749 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5756 // return PCOR2(PCI(pc)->pcop)->r;
5758 case PO_GPR_REGISTER:
5760 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5761 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5765 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5768 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5769 //genericPrint(stderr, pc);
5777 /*-----------------------------------------------------------------*/
5778 /*-----------------------------------------------------------------*/
5780 static void AnalyzepBlock(pBlock *pb)
5787 /* Find all of the registers used in this pBlock
5788 * by looking at each instruction and examining it's
5791 for(pc = pb->pcHead; pc; pc = pc->next) {
5793 /* Is this an instruction with operands? */
5794 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5796 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5798 /* Loop through all of the registers declared so far in
5799 this block and see if we find this one there */
5801 regs *r = setFirstItem(pb->tregisters);
5804 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5805 PCOR(PCI(pc)->pcop)->r = r;
5808 r = setNextItem(pb->tregisters);
5812 /* register wasn't found */
5813 //r = Safe_calloc(1, sizeof(regs));
5814 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5815 //addSet(&pb->tregisters, r);
5816 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5817 //PCOR(PCI(pc)->pcop)->r = r;
5818 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5820 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5823 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5824 if(PCOR(PCI(pc)->pcop)->r) {
5825 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5826 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5828 if(PCI(pc)->pcop->name)
5829 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5831 fprintf(stderr,"ERROR: NULL register\n");
5840 /*-----------------------------------------------------------------*/
5842 /*-----------------------------------------------------------------*/
5843 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5845 static void InsertpFlow(pCode *pc, pCode **pflow)
5848 PCFL(*pflow)->end = pc;
5850 if(!pc || !pc->next)
5853 *pflow = pic16_newpCodeFlow();
5854 pic16_pCodeInsertAfter(pc, *pflow);
5857 /*-----------------------------------------------------------------*/
5858 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5859 /* the flow blocks. */
5861 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5862 * point the instruction flow changes.
5864 /*-----------------------------------------------------------------*/
5865 void pic16_BuildFlow(pBlock *pb)
5868 pCode *last_pci=NULL;
5875 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5876 /* Insert a pCodeFlow object at the beginning of a pBlock */
5878 InsertpFlow(pb->pcHead, &pflow);
5880 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5881 //pflow->next = pb->pcHead; /* Make the current head the next object */
5882 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5883 //pb->pcHead = pflow; /* Make the Flow object the head */
5886 for( pc = pic16_findNextInstruction(pb->pcHead);
5888 pc=pic16_findNextInstruction(pc)) {
5891 PCI(pc)->pcflow = PCFL(pflow);
5893 //fprintf(stderr," build: ");
5894 //pflow->print(stderr,pflow);
5896 if( PCI(pc)->isSkip) {
5898 /* The two instructions immediately following this one
5899 * mark the beginning of a new flow segment */
5901 while(pc && PCI(pc)->isSkip) {
5903 PCI(pc)->pcflow = PCFL(pflow);
5907 InsertpFlow(pc, &pflow);
5908 pc=pic16_findNextInstruction(pc->next);
5916 PCI(pc)->pcflow = PCFL(pflow);
5918 InsertpFlow(pc, &pflow);
5920 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5922 InsertpFlow(pc, &pflow);
5925 } else if (checkLabel(pc)) {
5927 /* This instruction marks the beginning of a
5928 * new flow segment */
5933 /* If the previous pCode is not a flow object, then
5934 * insert a new flow object. (This check prevents
5935 * two consecutive flow objects from being insert in
5936 * the case where a skip instruction preceeds an
5937 * instruction containing a label.) */
5939 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5940 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5942 PCI(pc)->pcflow = PCFL(pflow);
5949 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5951 PCFL(pflow)->end = pb->pcTail;
5954 /*-------------------------------------------------------------------*/
5955 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5956 /* the flow blocks. */
5958 * unBuildFlow removes pCodeFlow objects from a pCode chain
5960 /*-----------------------------------------------------------------*/
5961 static void unBuildFlow(pBlock *pb)
5976 if(PCI(pc)->pcflow) {
5977 //free(PCI(pc)->pcflow);
5978 PCI(pc)->pcflow = NULL;
5981 } else if(isPCFL(pc) )
5990 /*-----------------------------------------------------------------*/
5991 /*-----------------------------------------------------------------*/
5992 static void dumpCond(int cond)
5995 static char *pcc_str[] = {
6009 int ncond = sizeof(pcc_str) / sizeof(char *);
6012 fprintf(stderr, "0x%04X\n",cond);
6014 for(i=0,j=1; i<ncond; i++, j<<=1)
6016 fprintf(stderr, " %s\n",pcc_str[i]);
6022 /*-----------------------------------------------------------------*/
6023 /*-----------------------------------------------------------------*/
6024 static void FlowStats(pCodeFlow *pcflow)
6032 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6034 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6037 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6042 fprintf(stderr, " FlowStats inCond: ");
6043 dumpCond(pcflow->inCond);
6044 fprintf(stderr, " FlowStats outCond: ");
6045 dumpCond(pcflow->outCond);
6049 /*-----------------------------------------------------------------*
6050 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6051 * if it affects the banking bits.
6053 * return: -1 == Banking bits are unaffected by this pCode.
6055 * return: > 0 == Banking bits are affected.
6057 * If the banking bits are affected, then the returned value describes
6058 * which bits are affected and how they're affected. The lower half
6059 * of the integer maps to the bits that are affected, the upper half
6060 * to whether they're set or cleared.
6062 *-----------------------------------------------------------------*/
6064 static int isBankInstruction(pCode *pc)
6072 if( PCI(pc)->op == POC_MOVLB ||
6073 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6074 bank = PCOL(pc)->lit;
6081 /*-----------------------------------------------------------------*/
6082 /*-----------------------------------------------------------------*/
6083 static void FillFlow(pCodeFlow *pcflow)
6092 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6094 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6097 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6104 isBankInstruction(pc);
6106 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6110 fprintf(stderr, " FillFlow - Bad end of flow\n");
6112 fprintf(stderr, " FillFlow - Ending flow with\n ");
6113 pc->print(stderr,pc);
6116 fprintf(stderr, " FillFlow inCond: ");
6117 dumpCond(pcflow->inCond);
6118 fprintf(stderr, " FillFlow outCond: ");
6119 dumpCond(pcflow->outCond);
6123 /*-----------------------------------------------------------------*/
6124 /*-----------------------------------------------------------------*/
6125 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6127 pCodeFlowLink *fromLink, *toLink;
6129 if(!from || !to || !to->pcflow || !from->pcflow)
6132 fromLink = pic16_newpCodeFlowLink(from->pcflow);
6133 toLink = pic16_newpCodeFlowLink(to->pcflow);
6135 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6136 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6140 /*-----------------------------------------------------------------*
6141 * void LinkFlow(pBlock *pb)
6143 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6144 * non-branching segments. In LinkFlow, we determine the execution
6145 * order of these segments. For example, if one of the segments ends
6146 * with a skip, then we know that there are two possible flow segments
6147 * to which control may be passed.
6148 *-----------------------------------------------------------------*/
6149 static void LinkFlow(pBlock *pb)
6155 //fprintf(stderr,"linkflow \n");
6157 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6159 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6162 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6164 //fprintf(stderr," link: ");
6165 //pcflow->print(stderr,pcflow);
6167 //FillFlow(PCFL(pcflow));
6169 pc = PCFL(pcflow)->end;
6171 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6172 if(isPCI_SKIP(pc)) {
6173 //fprintf(stderr, "ends with skip\n");
6174 //pc->print(stderr,pc);
6175 pct=pic16_findNextInstruction(pc->next);
6176 LinkFlow_pCode(PCI(pc),PCI(pct));
6177 pct=pic16_findNextInstruction(pct->next);
6178 LinkFlow_pCode(PCI(pc),PCI(pct));
6182 if(isPCI_BRANCH(pc)) {
6183 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6185 //fprintf(stderr, "ends with branch\n ");
6186 //pc->print(stderr,pc);
6188 if(!(pcol && isPCOLAB(pcol))) {
6189 if((PCI(pc)->op != POC_RETLW)
6190 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6192 /* continue if label is '$' which assembler knows how to parse */
6193 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6195 if(pic16_pcode_verbose) {
6196 pc->print(stderr,pc);
6197 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6203 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6204 LinkFlow_pCode(PCI(pc),PCI(pct));
6206 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6207 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6209 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6215 //fprintf(stderr, "ends with non-branching instruction:\n");
6216 //pc->print(stderr,pc);
6218 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6224 //fprintf(stderr, "ends with unknown\n");
6225 //pc->print(stderr,pc);
6229 //fprintf(stderr, "ends with nothing: ERROR\n");
6233 /*-----------------------------------------------------------------*/
6234 /*-----------------------------------------------------------------*/
6236 /*-----------------------------------------------------------------*/
6237 /*-----------------------------------------------------------------*/
6238 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6244 if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6247 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6257 /*-----------------------------------------------------------------*/
6258 /* insertBankSwitch - inserts a bank switch statement in the */
6259 /* assembly listing */
6261 /* position == 0: insert before */
6262 /* position == 1: insert after pc */
6263 /* position == 2: like 0 but previous was a skip instruction */
6264 /*-----------------------------------------------------------------*/
6265 pCodeOp *pic16_popGetLabel(unsigned int key);
6266 extern int pic16_labelOffset;
6268 static void insertBankSwitch(unsigned char position, pCode *pc)
6275 /* emit BANKSEL [symbol] */
6278 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6280 // position = 0; // position is always before (sanity check!)
6283 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6284 pc->print(stderr, pc);
6289 /* insert the bank switch after this pc instruction */
6290 pCode *pcnext = pic16_findNextInstruction(pc);
6292 pic16_pCodeInsertAfter(pc, new_pc);
6293 if(pcnext)pc = pcnext;
6297 /* insert the bank switch BEFORE this pc instruction */
6298 pic16_pCodeInsertAfter(pc->prev, new_pc);
6303 pCode *pcnext, *pcprev, *npci, *ppc;
6305 int ofs1=0, ofs2=0, len=0;
6307 /* just like 0, but previous was a skip instruction,
6308 * so some care should be taken */
6310 pic16_labelOffset += 10000;
6311 tlbl = newiTempLabel(NULL);
6313 /* invert skip instruction */
6314 pcprev = pic16_findPrevInstruction(pc->prev);
6315 ipci = PCI(pcprev)->inverted_op;
6316 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6318 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6320 /* copy info from old pCode */
6321 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6322 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6323 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6324 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6325 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6326 PCI(npci)->op = PCI(pcprev)->inverted_op;
6328 /* unlink old pCode */
6330 ppc->next = pcprev->next;
6331 pcprev->next->prev = ppc;
6332 pic16_pCodeInsertAfter(ppc, npci);
6334 /* extra instructions to handle invertion */
6335 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6336 pic16_pCodeInsertAfter(npci, pcnext);
6337 pic16_pCodeInsertAfter(pc->prev, new_pc);
6339 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6340 pic16_pCodeInsertAfter(pc, pcnext);
6345 /* Move the label, if there is one */
6346 if(PCI(pc)->label) {
6347 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6348 // __FILE__, __LINE__, pc, new_pc);
6349 PCAD(new_pc)->pci.label = PCI(pc)->label;
6350 PCI(pc)->label = NULL;
6355 /*-----------------------------------------------------------------*/
6356 /*int compareBankFlow - compare the banking requirements between */
6358 /*-----------------------------------------------------------------*/
6359 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6362 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6365 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6368 if(pcflow->firstBank == -1)
6372 if(pcflowLink->pcflow->firstBank == -1) {
6373 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6374 pcflowLink->pcflow->to :
6375 pcflowLink->pcflow->from);
6376 return compareBankFlow(pcflow, pctl, toORfrom);
6380 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6383 pcflowLink->bank_conflict++;
6384 pcflowLink->pcflow->FromConflicts++;
6385 pcflow->ToConflicts++;
6388 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6391 pcflowLink->bank_conflict++;
6392 pcflowLink->pcflow->ToConflicts++;
6393 pcflow->FromConflicts++;
6397 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6398 pcflowLink->pcflow->pc.seq,
6399 pcflowLink->pcflow->FromConflicts,
6400 pcflowLink->pcflow->ToConflicts);
6407 /*-----------------------------------------------------------------*/
6408 /*-----------------------------------------------------------------*/
6409 static void DumpFlow(pBlock *pb)
6413 pCodeFlowLink *pcfl;
6416 fprintf(stderr,"Dump flow \n");
6417 pb->pcHead->print(stderr, pb->pcHead);
6419 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6420 pcflow->print(stderr,pcflow);
6422 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6424 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6426 if(!isPCFL(pcflow)) {
6427 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6430 fprintf(stderr,"dumping: ");
6431 pcflow->print(stderr,pcflow);
6432 FlowStats(PCFL(pcflow));
6434 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6436 pc = PCODE(pcfl->pcflow);
6438 fprintf(stderr, " from seq %d:\n",pc->seq);
6440 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6441 pc->print(stderr,pc);
6446 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6448 pc = PCODE(pcfl->pcflow);
6450 fprintf(stderr, " to seq %d:\n",pc->seq);
6452 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6453 pc->print(stderr,pc);
6462 /*-----------------------------------------------------------------*/
6463 /*-----------------------------------------------------------------*/
6464 static int OptimizepBlock(pBlock *pb)
6469 if(!pb || !peepOptimizing)
6472 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6474 for(pc = pb->pcHead; pc; pc = pc->next)
6475 matches += pic16_pCodePeepMatchRule(pc);
6478 pc = pic16_findNextInstruction(pb->pcHead);
6486 if(pic16_pCodePeepMatchRule(pc)) {
6491 pc = pic16_findNextInstruction(pcprev->next);
6493 pc = pic16_findNextInstruction(pb->pcHead);
6495 pc = pic16_findNextInstruction(pc->next);
6499 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6504 /*-----------------------------------------------------------------*/
6505 /*-----------------------------------------------------------------*/
6506 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6510 for(pc = pcs; pc; pc = pc->next) {
6512 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6514 (PCI(pc)->pcop->type == PO_LABEL) &&
6515 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6523 /*-----------------------------------------------------------------*/
6524 /*-----------------------------------------------------------------*/
6525 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6532 (PCI(pc)->pcop->type == PO_LABEL)) {
6534 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6536 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6537 // if(pcol->pcop.name)
6538 // free(pcol->pcop.name);
6540 /* If the key is negative, then we (probably) have a label to
6541 * a function and the name is already defined */
6544 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6548 //sprintf(buffer,"_%05d_DS_",pcl->key);
6550 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6552 pcol->pcop.name = Safe_strdup(s);
6553 pcol->key = pcl->key;
6554 //pc->print(stderr,pc);
6561 /*-----------------------------------------------------------------*/
6562 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6563 /* pCode chain if they're not used. */
6564 /*-----------------------------------------------------------------*/
6565 static void pBlockRemoveUnusedLabels(pBlock *pb)
6567 pCode *pc; pCodeLabel *pcl;
6572 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6574 pBranch *pbr = PCI(pc)->label;
6575 if(pbr && pbr->next) {
6576 pCode *pcd = pb->pcHead;
6578 // fprintf(stderr, "multiple labels\n");
6579 // pc->print(stderr,pc);
6584 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6585 //fprintf(stderr,"Used by:\n");
6586 //pcd->print(stderr,pcd);
6588 exchangeLabels(PCL(pbr->pc),pcd);
6597 for(pc = pb->pcHead; pc; pc = pc->next) {
6599 if(isPCL(pc)) // pc->type == PC_LABEL)
6601 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6602 pcl = PCL(PCI(pc)->label->pc);
6605 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6607 /* This pCode is a label, so search the pBlock to see if anyone
6610 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6612 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6613 /* Couldn't find an instruction that refers to this label
6614 * So, unlink the pCode label from it's pCode chain
6615 * and destroy the label */
6616 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6618 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6619 if(pc->type == PC_LABEL) {
6620 pic16_unlinkpCode(pc);
6621 pCodeLabelDestruct(pc);
6623 unlinkpCodeFromBranch(pc, PCODE(pcl));
6624 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6635 /*-----------------------------------------------------------------*/
6636 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6637 /* chain and put them into pBranches that are */
6638 /* associated with the appropriate pCode */
6640 /*-----------------------------------------------------------------*/
6641 void pic16_pBlockMergeLabels(pBlock *pb)
6644 pCode *pc, *pcnext=NULL;
6649 /* First, Try to remove any unused labels */
6650 //pBlockRemoveUnusedLabels(pb);
6652 /* Now loop through the pBlock and merge the labels with the opcodes */
6655 // for(pc = pb->pcHead; pc; pc = pc->next) {
6658 pCode *pcn = pc->next;
6660 if(pc->type == PC_LABEL) {
6662 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6663 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6665 if((pcnext = pic16_findNextInstruction(pc) )) {
6667 // pcnext->print(stderr, pcnext);
6669 // Unlink the pCode label from it's pCode chain
6670 pic16_unlinkpCode(pc);
6672 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6673 // And link it into the instruction's pBranch labels. (Note, since
6674 // it's possible to have multiple labels associated with one instruction
6675 // we must provide a means to accomodate the additional labels. Thus
6676 // the labels are placed into the singly-linked list "label" as
6677 // opposed to being a single member of the pCodeInstruction.)
6679 //_ALLOC(pbr,sizeof(pBranch));
6681 pbr = Safe_calloc(1,sizeof(pBranch));
6685 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6688 if(pic16_pcode_verbose)
6689 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6691 } else if(pc->type == PC_CSOURCE) {
6693 /* merge the source line symbolic info into the next instruction */
6694 if((pcnext = pic16_findNextInstruction(pc) )) {
6696 // Unlink the pCode label from it's pCode chain
6697 pic16_unlinkpCode(pc);
6698 PCI(pcnext)->cline = PCCS(pc);
6699 //fprintf(stderr, "merging CSRC\n");
6700 //genericPrint(stderr,pcnext);
6706 pBlockRemoveUnusedLabels(pb);
6710 /*-----------------------------------------------------------------*/
6711 /*-----------------------------------------------------------------*/
6712 static int OptimizepCode(char dbName)
6714 #define MAX_PASSES 4
6723 DFPRINTF((stderr," Optimizing pCode\n"));
6727 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6728 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6729 matches += OptimizepBlock(pb);
6732 while(matches && ++passes < MAX_PASSES);
6739 const char *pic16_pCodeOpType(pCodeOp *pcop);
6740 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6743 /*-----------------------------------------------------------------*/
6744 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6745 /*-----------------------------------------------------------------*/
6747 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6751 // fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6754 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6756 if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6759 assert(pcop != NULL);
6761 if( !( (pcop->type == PO_LABEL) ||
6762 (pcop->type == PO_LITERAL) ||
6763 (pcop->type == PO_STR) ))
6764 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6765 PCOR(pcop)->r->wasUsed = 1;
6766 PCOR(pcop)->instance = PCOR(pc)->instance;
6772 /*----------------------------------------------------------------------*
6773 * pic16_areRegsSame - check to see if the names of two registers match *
6774 *----------------------------------------------------------------------*/
6775 int pic16_areRegsSame(regs *r1, regs *r2)
6777 if(!strcmp(r1->name, r2->name))return 1;
6783 /*-----------------------------------------------------------------*/
6784 /*-----------------------------------------------------------------*/
6785 static void pic16_FixRegisterBanking(pBlock *pb)
6789 regs *reg, *prevreg;
6790 unsigned char flag=0;
6795 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6798 /* loop through all of the flow blocks with in one pblock */
6800 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6804 /* at this point, pc should point to a PC_FLOW object */
6805 /* for each flow block, determine the register banking
6809 /* if label, then might come from other point, force banksel */
6810 if(isPCL(pc))prevreg = NULL;
6812 if(!isPCI(pc))goto loop;
6814 if(PCI(pc)->label)prevreg = NULL;
6816 if(PCI(pc)->is2MemOp)goto loop;
6818 /* if goto, then force banksel */
6819 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6821 reg = pic16_getRegFromInstruction(pc);
6824 pc->print(stderr, pc);
6825 fprintf(stderr, "reg = %p\n", reg);
6828 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6829 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6830 reg->address,reg->isBitField, reg->isFixed);
6834 /* now make some tests to make sure that instruction needs bank switch */
6836 /* if no register exists, and if not a bit opcode goto loop */
6838 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6841 if(isPCI_SKIP(pc)) {
6842 // fprintf(stderr, "instruction is SKIP instruction\n");
6845 if(reg && isACCESS_BANK(reg))goto loop;
6847 if(!isBankInstruction(pc))goto loop;
6849 if(isPCI_LIT(pc))goto loop;
6851 if(PCI(pc)->op == POC_CALL)goto loop;
6853 /* Examine the instruction before this one to make sure it is
6854 * not a skip type instruction */
6855 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6857 flag = 0; /* add before this instruction */
6859 /* if previous instruction is a skip one, then set flag
6860 * to 2 and call insertBankSwitch */
6861 if(pcprev && isPCI_SKIP(pcprev)) {
6866 if(pic16_options.opt_banksel>0) {
6867 char op1[128], op2[128];
6870 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6871 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6872 if(!strcmp(op1, op2))goto loop;
6876 insertBankSwitch(flag, pc);
6878 // fprintf(stderr, "BANK SWITCH inserted\n");
6888 static void pBlockDestruct(pBlock *pb)
6899 /*-----------------------------------------------------------------*/
6900 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6901 /* name dbName and combine them */
6902 /* into one block */
6903 /*-----------------------------------------------------------------*/
6904 static void mergepBlocks(char dbName)
6907 pBlock *pb, *pbmerged = NULL,*pbn;
6909 pb = the_pFile->pbHead;
6911 //fprintf(stderr," merging blocks named %c\n",dbName);
6915 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6916 if( getpBlock_dbName(pb) == dbName) {
6918 //fprintf(stderr," merged block %c\n",dbName);
6923 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6924 /* pic16_addpCode2pBlock doesn't handle the tail: */
6925 pbmerged->pcTail = pb->pcTail;
6927 pb->prev->next = pbn;
6929 pbn->prev = pb->prev;
6934 //pic16_printpBlock(stderr, pbmerged);
6941 /*-----------------------------------------------------------------*/
6942 /* AnalyzeFlow - Examine the flow of the code and optimize */
6944 /* level 0 == minimal optimization */
6945 /* optimize registers that are used only by two instructions */
6946 /* level 1 == maximal optimization */
6947 /* optimize by looking at pairs of instructions that use the */
6949 /*-----------------------------------------------------------------*/
6951 static void AnalyzeFlow(int level)
6953 static int times_called=0;
6958 /* remove unused allocated registers before exiting */
6959 pic16_RemoveUnusedRegisters();
6965 /* if this is not the first time this function has been called,
6966 then clean up old flow information */
6967 if(times_called++) {
6968 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6971 pic16_RegsUnMapLiveRanges();
6976 /* Phase 2 - Flow Analysis - Register Banking
6978 * In this phase, the individual flow blocks are examined
6979 * and register banking is fixed.
6983 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6984 pic16_FixRegisterBanking(pb);
6987 /* Phase 2 - Flow Analysis
6989 * In this phase, the pCode is partition into pCodeFlow
6990 * blocks. The flow blocks mark the points where a continuous
6991 * stream of instructions changes flow (e.g. because of
6992 * a call or goto or whatever).
6995 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6996 pic16_BuildFlow(pb);
6999 /* Phase 2 - Flow Analysis - linking flow blocks
7001 * In this phase, the individual flow blocks are examined
7002 * to determine their order of excution.
7005 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7008 /* Phase 3 - Flow Analysis - Flow Tree
7010 * In this phase, the individual flow blocks are examined
7011 * to determine their order of execution.
7014 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7015 pic16_BuildFlowTree(pb);
7018 /* Phase x - Flow Analysis - Used Banks
7020 * In this phase, the individual flow blocks are examined
7021 * to determine the Register Banks they use
7025 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7030 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7031 pic16_pCodeRegMapLiveRanges(pb);
7033 pic16_RemoveUnusedRegisters();
7035 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7036 pic16_pCodeRegOptimizeRegUsage(level);
7044 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7049 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7051 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7052 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7053 pcflow = pcflow->next) {
7055 FillFlow(PCFL(pcflow));
7060 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7063 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7064 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7065 pcflow = pcflow->next) {
7067 FlowStats(PCFL(pcflow));
7073 /* VR -- no need to analyze banking in flow, but left here :
7074 * 1. because it may be used in the future for other purposes
7075 * 2. because if omitted we'll miss some optimization done here
7077 * Perhaps I should rename it to something else
7080 /*-----------------------------------------------------------------*/
7081 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7082 /* assigned to the registers. */
7084 /*-----------------------------------------------------------------*/
7086 void pic16_AnalyzeBanking(void)
7091 /* Phase x - Flow Analysis - Used Banks
7093 * In this phase, the individual flow blocks are examined
7094 * to determine the Register Banks they use
7100 if(!the_pFile)return;
7102 if(!pic16_options.no_banksel) {
7103 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7104 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7105 pic16_FixRegisterBanking(pb);
7111 /*-----------------------------------------------------------------*/
7112 /* buildCallTree - Look at the flow and extract all of the calls. */
7113 /*-----------------------------------------------------------------*/
7114 static set *register_usage(pBlock *pb);
7116 static void buildCallTree(void )
7128 /* Now build the call tree.
7129 First we examine all of the pCodes for functions.
7130 Keep in mind that the function boundaries coincide
7131 with pBlock boundaries.
7133 The algorithm goes something like this:
7134 We have two nested loops. The outer loop iterates
7135 through all of the pBlocks/functions. The inner
7136 loop iterates through all of the pCodes for
7137 a given pBlock. When we begin iterating through
7138 a pBlock, the variable pc_fstart, pCode of the start
7139 of a function, is cleared. We then search for pCodes
7140 of type PC_FUNCTION. When one is encountered, we
7141 initialize pc_fstart to this and at the same time
7142 associate a new pBranch object that signifies a
7143 branch entry. If a return is found, then this signifies
7144 a function exit point. We'll link the pCodes of these
7145 returns to the matching pc_fstart.
7147 When we're done, a doubly linked list of pBranches
7148 will exist. The head of this list is stored in
7149 `the_pFile', which is the meta structure for all
7150 of the pCode. Look at the pic16_printCallTree function
7151 on how the pBranches are linked together.
7154 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7155 pCode *pc_fstart=NULL;
7156 for(pc = pb->pcHead; pc; pc = pc->next) {
7158 if(isPCI(pc) && pc_fstart) {
7159 if(PCI(pc)->is2MemOp) {
7160 r = pic16_getRegFromInstruction2(pc);
7161 if(r && !strcmp(r->name, "POSTDEC1"))
7162 PCF(pc_fstart)->stackusage++;
7164 r = pic16_getRegFromInstruction(pc);
7165 if(r && !strcmp(r->name, "PREINC1"))
7166 PCF(pc_fstart)->stackusage--;
7171 if (PCF(pc)->fname) {
7173 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7174 //fprintf(stderr," found main \n");
7175 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7179 pbr = Safe_calloc(1,sizeof(pBranch));
7180 pbr->pc = pc_fstart = pc;
7183 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7185 // Here's a better way of doing the same:
7186 addSet(&pb->function_entries, pc);
7189 // Found an exit point in a function, e.g. return
7190 // (Note, there may be more than one return per function)
7192 pBranchLink(PCF(pc_fstart), PCF(pc));
7194 addSet(&pb->function_exits, pc);
7196 } else if(isCALL(pc)) {
7197 addSet(&pb->function_calls,pc);
7204 /* This is not needed because currently all register used
7205 * by a function are stored in stack -- VR */
7207 /* Re-allocate the registers so that there are no collisions
7208 * between local variables when one function call another */
7211 // pic16_deallocateAllRegs();
7213 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7221 /*-----------------------------------------------------------------*/
7222 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7223 /* all of the logical connections. */
7225 /* Essentially what's done here is that the pCode flow is */
7227 /*-----------------------------------------------------------------*/
7229 void pic16_AnalyzepCode(char dbName)
7240 /* Phase 1 - Register allocation and peep hole optimization
7242 * The first part of the analysis is to determine the registers
7243 * that are used in the pCode. Once that is done, the peep rules
7244 * are applied to the code. We continue to loop until no more
7245 * peep rule optimizations are found (or until we exceed the
7246 * MAX_PASSES threshold).
7248 * When done, the required registers will be determined.
7254 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7255 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7257 /* First, merge the labels with the instructions */
7258 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7259 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7261 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7262 //fprintf(stderr," analyze and merging block %c\n",dbName);
7263 pic16_pBlockMergeLabels(pb);
7266 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7271 changes = OptimizepCode(dbName);
7274 } while(changes && (i++ < MAX_PASSES));
7281 /* convert a series of movff's of local regs to stack, with a single call to
7282 * a support functions which does the same thing via loop */
7283 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7287 char *fname[]={"__lr_store", "__lr_restore"};
7289 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7291 pct = pic16_findNextInstruction(pcstart->next);
7294 pct = pc->next; //pic16_findNextInstruction(pc->next);
7295 // pc->print(stderr, pc);
7296 if(isPCI(pc) && PCI(pc)->label) {
7297 pbr = PCI(pc)->label;
7298 while(pbr && pbr->pc) {
7299 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7303 // pc->print(stderr, pc);
7305 pc->prev->next = pct;
7306 pct->prev = pc->prev;
7310 } while ((pc) && (pc != pcend));
7312 /* unlink movff instructions */
7313 pcstart->next = pcend;
7314 pcend->prev = pcstart;
7318 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7319 // pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(&pic16_pc_fsr2l)))); pc = pct;
7322 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7323 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7324 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7327 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7328 // pic16_popCopyReg(&pic16_pc_fsr2l), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7335 sym = newSymbol( fname[ entry?0:1 ], 0 );
7336 strcpy(sym->rname, fname[ entry?0:1 ]);
7337 checkAddSym(&externs, sym);
7339 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7344 /*-----------------------------------------------------------------*/
7345 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7346 /* local registers to a support function call */
7347 /*-----------------------------------------------------------------*/
7348 void pic16_OptimizeLocalRegs(void)
7353 pCodeOpLocalReg *pclr;
7356 regs *r, *lastr=NULL, *firstr=NULL;
7357 pCode *pcstart=NULL, *pcend=NULL;
7362 * local_regs begin mark
7363 * MOVFF r0x01, POSTDEC1
7364 * MOVFF r0x02, POSTDEC1
7367 * MOVFF r0x0n, POSTDEC1
7368 * local_regs end mark
7370 * convert the above to the below:
7371 * MOVLW starting_register_index
7373 * MOVLW register_count
7374 * call __save_registers_in_stack
7380 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7381 inRegCount = regCount = 0;
7382 firstr = lastr = NULL;
7383 for(pc = pb->pcHead; pc; pc = pc->next) {
7385 /* hold current function name */
7386 if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7388 if(pc && (pc->type == PC_INFO)) {
7391 if(pci->type == INF_LOCALREGS) {
7392 pclr = PCOLR(pci->oper1);
7394 if((pclr->type == LR_ENTRY_BEGIN)
7395 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7398 switch(pclr->type) {
7399 case LR_ENTRY_BEGIN:
7401 inRegCount = 1; regCount = 0;
7402 pcstart = pc; //pic16_findNextInstruction(pc->next);
7403 firstr = lastr = NULL;
7409 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7412 if(curFunc && inWparamList(curFunc+1)) {
7413 fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7417 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7422 firstr = lastr = NULL;
7426 if(inRegCount == -1) {
7427 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7433 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7435 r = pic16_getRegFromInstruction(pc);
7437 r = pic16_getRegFromInstruction2(pc);
7438 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7439 if(!firstr)firstr = r;
7441 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
7453 /*-----------------------------------------------------------------*/
7454 /* ispCodeFunction - returns true if *pc is the pCode of a */
7456 /*-----------------------------------------------------------------*/
7457 static bool ispCodeFunction(pCode *pc)
7460 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7466 /*-----------------------------------------------------------------*/
7467 /* findFunction - Search for a function by name (given the name) */
7468 /* in the set of all functions that are in a pBlock */
7469 /* (note - I expect this to change because I'm planning to limit */
7470 /* pBlock's to just one function declaration */
7471 /*-----------------------------------------------------------------*/
7472 static pCode *findFunction(char *fname)
7479 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7481 pc = setFirstItem(pb->function_entries);
7484 if((pc->type == PC_FUNCTION) &&
7486 (strcmp(fname, PCF(pc)->fname)==0))
7489 pc = setNextItem(pb->function_entries);
7497 static void MarkUsedRegisters(set *regset)
7502 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7503 // fprintf(stderr, "marking register = %s\t", r1->name);
7504 r2 = pic16_regWithIdx(r1->rIdx);
7505 // fprintf(stderr, "to register = %s\n", r2->name);
7511 static void pBlockStats(FILE *of, pBlock *pb)
7517 if(!pic16_pcode_verbose)return;
7519 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7521 // for now just print the first element of each set
7522 pc = setFirstItem(pb->function_entries);
7524 fprintf(of,";entry: ");
7527 pc = setFirstItem(pb->function_exits);
7529 fprintf(of,";has an exit\n");
7533 pc = setFirstItem(pb->function_calls);
7535 fprintf(of,";functions called:\n");
7538 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7539 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7541 pc = setNextItem(pb->function_calls);
7545 r = setFirstItem(pb->tregisters);
7547 int n = elementsInSet(pb->tregisters);
7549 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7552 fprintf(of,"; %s\n",r->name);
7553 r = setNextItem(pb->tregisters);
7557 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7560 /*-----------------------------------------------------------------*/
7561 /*-----------------------------------------------------------------*/
7563 static void sequencepCode(void)
7569 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7571 pb->seq = GpCodeSequenceNumber+1;
7573 for( pc = pb->pcHead; pc; pc = pc->next)
7574 pc->seq = ++GpCodeSequenceNumber;
7580 /*-----------------------------------------------------------------*/
7581 /*-----------------------------------------------------------------*/
7582 static set *register_usage(pBlock *pb)
7585 set *registers=NULL;
7586 set *registersInCallPath = NULL;
7588 /* check recursion */
7590 pc = setFirstItem(pb->function_entries);
7597 if(pc->type != PC_FUNCTION)
7598 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7600 pc = setFirstItem(pb->function_calls);
7601 for( ; pc; pc = setNextItem(pb->function_calls)) {
7603 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7604 char *dest = pic16_get_op_from_instruction(PCI(pc));
7606 pcn = findFunction(dest);
7608 registersInCallPath = register_usage(pcn->pb);
7610 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7615 pBlockStats(stderr,pb); // debug
7618 // Mark the registers in this block as used.
7620 MarkUsedRegisters(pb->tregisters);
7621 if(registersInCallPath) {
7622 /* registers were used in the functions this pBlock has called */
7623 /* so now, we need to see if these collide with the ones we are */
7626 regs *r1,*r2, *newreg;
7628 DFPRINTF((stderr,"comparing registers\n"));
7630 r1 = setFirstItem(registersInCallPath);
7633 r2 = setFirstItem(pb->tregisters);
7635 while(r2 && (r1->type != REG_STK)) {
7637 if(r2->rIdx == r1->rIdx) {
7638 newreg = pic16_findFreeReg(REG_GPR);
7642 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7646 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7647 r1->rIdx, newreg->rIdx));
7648 r2->rIdx = newreg->rIdx;
7649 //if(r2->name) free(r2->name);
7651 r2->name = Safe_strdup(newreg->name);
7655 newreg->wasUsed = 1;
7657 r2 = setNextItem(pb->tregisters);
7660 r1 = setNextItem(registersInCallPath);
7663 /* Collisions have been resolved. Now free the registers in the call path */
7664 r1 = setFirstItem(registersInCallPath);
7666 if(r1->type != REG_STK) {
7667 newreg = pic16_regWithIdx(r1->rIdx);
7670 r1 = setNextItem(registersInCallPath);
7674 // MarkUsedRegisters(pb->registers);
7676 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7679 DFPRINTF((stderr,"returning regs\n"));
7681 DFPRINTF((stderr,"not returning regs\n"));
7683 DFPRINTF((stderr,"pBlock after register optim.\n"));
7684 pBlockStats(stderr,pb); // debug
7690 /*-----------------------------------------------------------------*/
7691 /* pct2 - writes the call tree to a file */
7693 /*-----------------------------------------------------------------*/
7694 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7698 // set *registersInCallPath = NULL;
7704 fprintf(of, "recursive function\n");
7705 return; //recursion ?
7708 pc = setFirstItem(pb->function_entries);
7715 for(i=0;i<indent;i++) // Indentation
7719 if(pc->type == PC_FUNCTION) {
7720 usedstack += PCF(pc)->stackusage;
7721 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7722 } else return; // ???
7725 pc = setFirstItem(pb->function_calls);
7726 for( ; pc; pc = setNextItem(pb->function_calls)) {
7728 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7729 char *dest = pic16_get_op_from_instruction(PCI(pc));
7731 pcn = findFunction(dest);
7733 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7735 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7743 /*-----------------------------------------------------------------*/
7744 /* pic16_printCallTree - writes the call tree to a file */
7746 /*-----------------------------------------------------------------*/
7748 void pic16_printCallTree(FILE *of)
7760 fprintf(of, "\npBlock statistics\n");
7761 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7765 fprintf(of,"Call Tree\n");
7766 pbr = the_pFile->functions;
7770 if(!ispCodeFunction(pc))
7771 fprintf(of,"bug in call tree");
7774 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7776 while(pc->next && !ispCodeFunction(pc->next)) {
7778 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7779 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7787 fprintf(of,"\n**************\n\na better call tree\n");
7788 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7793 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7794 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7800 /*-----------------------------------------------------------------*/
7802 /*-----------------------------------------------------------------*/
7804 static void InlineFunction(pBlock *pb)
7812 pc = setFirstItem(pb->function_calls);
7814 for( ; pc; pc = setNextItem(pb->function_calls)) {
7817 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7823 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7825 //fprintf(stderr,"Cool can inline:\n");
7826 //pcn->print(stderr,pcn);
7828 //fprintf(stderr,"recursive call Inline\n");
7829 InlineFunction(pcn->pb);
7830 //fprintf(stderr,"return from recursive call Inline\n");
7833 At this point, *pc points to a CALL mnemonic, and
7834 *pcn points to the function that is being called.
7836 To in-line this call, we need to remove the CALL
7837 and RETURN(s), and link the function pCode in with
7843 /* Remove the CALL */
7847 /* remove callee pBlock from the pBlock linked list */
7848 removepBlock(pcn->pb);
7856 /* Remove the Function pCode */
7857 pct = pic16_findNextInstruction(pcn->next);
7859 /* Link the function with the callee */
7860 pc->next = pcn->next;
7861 pcn->next->prev = pc;
7863 /* Convert the function name into a label */
7865 pbr = Safe_calloc(1,sizeof(pBranch));
7866 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7868 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7869 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7871 /* turn all of the return's except the last into goto's */
7872 /* check case for 2 instruction pBlocks */
7873 pce = pic16_findNextInstruction(pcn->next);
7875 pCode *pce_next = pic16_findNextInstruction(pce->next);
7877 if(pce_next == NULL) {
7878 /* found the last return */
7879 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7881 //fprintf(stderr,"found last return\n");
7882 //pce->print(stderr,pce);
7883 pce->prev->next = pc_call->next;
7884 pc_call->next->prev = pce->prev;
7885 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7895 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7901 /*-----------------------------------------------------------------*/
7903 /*-----------------------------------------------------------------*/
7905 void pic16_InlinepCode(void)
7914 if(!functionInlining)
7917 /* Loop through all of the function definitions and count the
7918 * number of times each one is called */
7919 //fprintf(stderr,"inlining %d\n",__LINE__);
7921 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7923 pc = setFirstItem(pb->function_calls);
7925 for( ; pc; pc = setNextItem(pb->function_calls)) {
7928 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7929 if(pcn && isPCF(pcn)) {
7930 PCF(pcn)->ncalled++;
7933 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7938 //fprintf(stderr,"inlining %d\n",__LINE__);
7940 /* Now, Loop through the function definitions again, but this
7941 * time inline those functions that have only been called once. */
7943 InlineFunction(the_pFile->pbHead);
7944 //fprintf(stderr,"inlining %d\n",__LINE__);
7946 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7951 char *pic_optype_names[]={
7952 "PO_NONE", // No operand e.g. NOP
7953 "PO_W", // The working register (as a destination)
7954 "PO_WREG", // The working register (as a file register)
7955 "PO_STATUS", // The 'STATUS' register
7956 "PO_BSR", // The 'BSR' register
7957 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7959 "PO_INDF0", // The Indirect register
7960 "PO_INTCON", // Interrupt Control register
7961 "PO_GPR_REGISTER", // A general purpose register
7962 "PO_GPR_BIT", // A bit of a general purpose register
7963 "PO_GPR_TEMP", // A general purpose temporary register
7964 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7965 "PO_PCL", // Program counter Low register
7966 "PO_PCLATH", // Program counter Latch high register
7967 "PO_PCLATU", // Program counter Latch upper register
7968 "PO_PRODL", // Product Register Low
7969 "PO_PRODH", // Product Register High
7970 "PO_LITERAL", // A constant
7971 "PO_REL_ADDR", // A relative address
7972 "PO_IMMEDIATE", // (8051 legacy)
7973 "PO_DIR", // Direct memory (8051 legacy)
7974 "PO_CRY", // bit memory (8051 legacy)
7975 "PO_BIT", // bit operand.
7976 "PO_STR", // (8051 legacy)
7978 "PO_WILD" // Wild card operand in peep optimizer
7982 char *dumpPicOptype(PIC_OPTYPE type)
7984 return (pic_optype_names[ type ]);