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);
179 char *dumpPicOptype(PIC_OPTYPE type);
181 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
182 pCodeOp *pic16_popGetLit(int);
183 pCodeOp *pic16_popGetWithString(char *);
186 /****************************************************************/
187 /* PIC Instructions */
188 /****************************************************************/
190 pCodeInstruction pic16_pciADDWF = {
191 {PC_OPCODE, NULL, NULL, 0, NULL,
205 1,0, // dest, bit instruction
207 0, // literal operand
209 0, // fast call/return mode select bit
210 0, // second memory operand
211 0, // second literal operand
213 (PCC_W | PCC_REGISTER), // inCond
214 (PCC_REGISTER | PCC_Z), // outCond
218 pCodeInstruction pic16_pciADDFW = {
219 {PC_OPCODE, NULL, NULL, 0, NULL,
233 0,0, // dest, bit instruction
235 0, // literal operand
237 0, // fast call/return mode select bit
238 0, // second memory operand
239 0, // second literal operand
241 (PCC_W | PCC_REGISTER), // inCond
242 (PCC_W | PCC_Z), // outCond
246 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
247 {PC_OPCODE, NULL, NULL, 0, NULL,
261 1,0, // dest, bit instruction
263 0, // literal operand
265 0, // fast call/return mode select bit
266 0, // second memory operand
267 0, // second literal operand
269 (PCC_W | PCC_REGISTER | PCC_C), // inCond
270 (PCC_REGISTER | PCC_Z), // outCond
274 pCodeInstruction pic16_pciADDFWC = {
275 {PC_OPCODE, NULL, NULL, 0, NULL,
289 0,0, // dest, bit instruction
291 0, // literal operand
293 0, // fast call/return mode select bit
294 0, // second memory operand
295 0, // second literal operand
297 (PCC_W | PCC_REGISTER | PCC_C), // inCond
298 (PCC_W | PCC_Z), // outCond
302 pCodeInstruction pic16_pciADDLW = {
303 {PC_OPCODE, NULL, NULL, 0, NULL,
317 0,0, // dest, bit instruction
319 1, // literal operand
321 0, // fast call/return mode select bit
322 0, // second memory operand
323 0, // second literal operand
325 (PCC_W | PCC_LITERAL), // inCond
326 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
330 pCodeInstruction pic16_pciANDLW = {
331 {PC_OPCODE, NULL, NULL, 0, NULL,
345 0,0, // dest, bit instruction
347 1, // literal operand
349 0, // fast call/return mode select bit
350 0, // second memory operand
351 0, // second literal operand
353 (PCC_W | PCC_LITERAL), // inCond
354 (PCC_W | PCC_Z | PCC_N), // outCond
358 pCodeInstruction pic16_pciANDWF = {
359 {PC_OPCODE, NULL, NULL, 0, NULL,
373 1,0, // dest, bit instruction
375 0, // literal operand
377 0, // fast call/return mode select bit
378 0, // second memory operand
379 0, // second literal operand
381 (PCC_W | PCC_REGISTER), // inCond
382 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
386 pCodeInstruction pic16_pciANDFW = {
387 {PC_OPCODE, NULL, NULL, 0, NULL,
401 0,0, // dest, bit instruction
403 0, // literal operand
405 0, // fast call/return mode select bit
406 0, // second memory operand
407 0, // second literal operand
409 (PCC_W | PCC_REGISTER), // inCond
410 (PCC_W | PCC_Z) // outCond
413 pCodeInstruction pic16_pciBC = { // mdubuc - New
414 {PC_OPCODE, NULL, NULL, 0, NULL,
428 0,0, // dest, bit instruction
430 0, // literal operand
432 0, // fast call/return mode select bit
433 0, // second memory operand
434 0, // second literal operand
436 (PCC_REL_ADDR | PCC_C), // inCond
441 pCodeInstruction pic16_pciBCF = {
442 {PC_OPCODE, NULL, NULL, 0, NULL,
456 1,1, // dest, bit instruction
458 0, // literal operand
460 0, // fast call/return mode select bit
461 0, // second memory operand
462 0, // second literal operand
464 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
465 PCC_REGISTER, // outCond
469 pCodeInstruction pic16_pciBN = { // mdubuc - New
470 {PC_OPCODE, NULL, NULL, 0, NULL,
484 0,0, // dest, bit instruction
486 0, // literal operand
488 0, // fast call/return mode select bit
489 0, // second memory operand
490 0, // second literal operand
492 (PCC_REL_ADDR | PCC_N), // inCond
493 PCC_NONE , // outCond
497 pCodeInstruction pic16_pciBNC = { // mdubuc - New
498 {PC_OPCODE, NULL, NULL, 0, NULL,
512 0,0, // dest, bit instruction
514 0, // literal operand
516 0, // fast call/return mode select bit
517 0, // second memory operand
518 0, // second literal operand
520 (PCC_REL_ADDR | PCC_C), // inCond
521 PCC_NONE , // outCond
525 pCodeInstruction pic16_pciBNN = { // mdubuc - New
526 {PC_OPCODE, NULL, NULL, 0, NULL,
540 0,0, // dest, bit instruction
542 0, // literal operand
544 0, // fast call/return mode select bit
545 0, // second memory operand
546 0, // second literal operand
548 (PCC_REL_ADDR | PCC_N), // inCond
549 PCC_NONE , // outCond
553 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
554 {PC_OPCODE, NULL, NULL, 0, NULL,
568 0,0, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
574 0, // second literal operand
576 (PCC_REL_ADDR | PCC_OV), // inCond
577 PCC_NONE , // outCond
581 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
582 {PC_OPCODE, NULL, NULL, 0, NULL,
596 0,0, // dest, bit instruction
598 0, // literal operand
600 0, // fast call/return mode select bit
601 0, // second memory operand
602 0, // second literal operand
604 (PCC_REL_ADDR | PCC_Z), // inCond
605 PCC_NONE , // outCond
609 pCodeInstruction pic16_pciBOV = { // mdubuc - New
610 {PC_OPCODE, NULL, NULL, 0, NULL,
624 0,0, // dest, bit instruction
626 0, // literal operand
628 0, // fast call/return mode select bit
629 0, // second memory operand
630 0, // second literal operand
632 (PCC_REL_ADDR | PCC_OV), // inCond
633 PCC_NONE , // outCond
637 pCodeInstruction pic16_pciBRA = { // mdubuc - New
638 {PC_OPCODE, NULL, NULL, 0, NULL,
652 0,0, // dest, bit instruction
654 0, // literal operand
656 0, // fast call/return mode select bit
657 0, // second memory operand
658 0, // second literal operand
660 PCC_REL_ADDR, // inCond
661 PCC_NONE , // outCond
665 pCodeInstruction pic16_pciBSF = {
666 {PC_OPCODE, NULL, NULL, 0, NULL,
680 1,1, // dest, bit instruction
682 0, // literal operand
684 0, // fast call/return mode select bit
685 0, // second memory operand
686 0, // second literal operand
688 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
689 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
693 pCodeInstruction pic16_pciBTFSC = {
694 {PC_OPCODE, NULL, NULL, 0, NULL,
708 0,1, // dest, bit instruction
710 0, // literal operand
712 0, // fast call/return mode select bit
713 0, // second memory operand
714 0, // second literal operand
716 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
717 PCC_EXAMINE_PCOP, // outCond
721 pCodeInstruction pic16_pciBTFSS = {
722 {PC_OPCODE, NULL, NULL, 0, NULL,
736 0,1, // dest, bit instruction
738 0, // literal operand
740 0, // fast call/return mode select bit
741 0, // second memory operand
742 0, // second literal operand
744 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
745 PCC_EXAMINE_PCOP, // outCond
749 pCodeInstruction pic16_pciBTG = { // mdubuc - New
750 {PC_OPCODE, NULL, NULL, 0, NULL,
764 0,1, // dest, bit instruction
766 0, // literal operand
768 0, // fast call/return mode select bit
769 0, // second memory operand
770 0, // second literal operand
772 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
773 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
777 pCodeInstruction pic16_pciBZ = { // mdubuc - New
778 {PC_OPCODE, NULL, NULL, 0, NULL,
792 0,0, // dest, bit instruction
794 0, // literal operand
796 0, // fast call/return mode select bit
797 0, // second memory operand
798 0, // second literal operand
805 pCodeInstruction pic16_pciCALL = {
806 {PC_OPCODE, NULL, NULL, 0, NULL,
820 0,0, // dest, bit instruction
822 0, // literal operand
824 1, // fast call/return mode select bit
825 0, // second memory operand
826 0, // second literal operand
829 PCC_NONE , // outCond
833 pCodeInstruction pic16_pciCOMF = {
834 {PC_OPCODE, NULL, NULL, 0, NULL,
848 1,0, // dest, bit instruction
850 0, // literal operand
852 0, // fast call/return mode select bit
853 0, // second memory operand
854 0, // second literal operand
856 PCC_REGISTER, // inCond
857 PCC_REGISTER , // outCond
861 pCodeInstruction pic16_pciCOMFW = {
862 {PC_OPCODE, NULL, NULL, 0, NULL,
876 0,0, // dest, bit instruction
878 0, // literal operand
880 0, // fast call/return mode select bit
881 0, // second memory operand
882 0, // second literal operand
884 PCC_REGISTER, // inCond
889 pCodeInstruction pic16_pciCLRF = {
890 {PC_OPCODE, NULL, NULL, 0, NULL,
904 0,0, // dest, bit instruction
906 0, // literal operand
908 0, // fast call/return mode select bit
909 0, // second memory operand
910 0, // second literal operand
912 PCC_REGISTER, // inCond
913 PCC_REGISTER , // outCond
917 pCodeInstruction pic16_pciCLRWDT = {
918 {PC_OPCODE, NULL, NULL, 0, NULL,
932 0,0, // dest, bit instruction
934 0, // literal operand
936 0, // fast call/return mode select bit
937 0, // second memory operand
938 0, // second literal operand
941 PCC_NONE , // outCond
945 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
946 {PC_OPCODE, NULL, NULL, 0, NULL,
960 0,0, // dest, bit instruction
962 0, // literal operand
964 0, // fast call/return mode select bit
965 0, // second memory operand
966 0, // second literal operand
968 (PCC_W | PCC_REGISTER), // inCond
969 PCC_NONE , // outCond
973 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
974 {PC_OPCODE, NULL, NULL, 0, NULL,
988 0,0, // dest, bit instruction
990 0, // literal operand
992 0, // fast call/return mode select bit
993 0, // second memory operand
994 0, // second literal operand
996 (PCC_W | PCC_REGISTER), // inCond
997 PCC_NONE , // outCond
1001 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
1002 {PC_OPCODE, NULL, NULL, 0, NULL,
1009 NULL, // from branch
1016 1,0, // dest, bit instruction
1017 1,1, // branch, skip
1018 0, // literal operand
1019 1, // RAM access bit
1020 0, // fast call/return mode select bit
1021 0, // second memory operand
1022 0, // second literal operand
1024 (PCC_W | PCC_REGISTER), // inCond
1025 PCC_NONE , // outCond
1029 pCodeInstruction pic16_pciDAW = {
1030 {PC_OPCODE, NULL, NULL, 0, NULL,
1037 NULL, // from branch
1044 0,0, // dest, bit instruction
1045 0,0, // branch, skip
1046 0, // literal operand
1047 0, // RAM access bit
1048 0, // fast call/return mode select bit
1049 0, // second memory operand
1050 0, // second literal operand
1053 (PCC_W | PCC_C), // outCond
1057 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1058 {PC_OPCODE, NULL, NULL, 0, NULL,
1065 NULL, // from branch
1072 1,0, // dest, bit instruction
1073 1,1, // branch, skip
1074 0, // literal operand
1075 1, // RAM access bit
1076 0, // fast call/return mode select bit
1077 0, // second memory operand
1078 0, // second literal operand
1080 PCC_REGISTER, // inCond
1081 PCC_REGISTER , // outCond
1085 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1086 {PC_OPCODE, NULL, NULL, 0, NULL,
1093 NULL, // from branch
1100 0,0, // dest, bit instruction
1101 1,1, // branch, skip
1102 0, // literal operand
1103 1, // RAM access bit
1104 0, // fast call/return mode select bit
1105 0, // second memory operand
1106 0, // second literal operand
1108 PCC_REGISTER, // inCond
1113 pCodeInstruction pic16_pciDECF = {
1114 {PC_OPCODE, NULL, NULL, 0, NULL,
1121 NULL, // from branch
1128 1,0, // dest, bit instruction
1129 0,0, // branch, skip
1130 0, // literal operand
1131 1, // RAM access bit
1132 0, // fast call/return mode select bit
1133 0, // second memory operand
1134 0, // second literal operand
1136 PCC_REGISTER, // inCond
1137 PCC_REGISTER , // outCond
1141 pCodeInstruction pic16_pciDECFW = {
1142 {PC_OPCODE, NULL, NULL, 0, NULL,
1149 NULL, // from branch
1156 0,0, // dest, bit instruction
1157 0,0, // branch, skip
1158 0, // literal operand
1159 1, // RAM access bit
1160 0, // fast call/return mode select bit
1161 0, // second memory operand
1162 0, // second literal operand
1164 PCC_REGISTER, // inCond
1169 pCodeInstruction pic16_pciDECFSZ = {
1170 {PC_OPCODE, NULL, NULL, 0, NULL,
1177 NULL, // from branch
1184 1,0, // dest, bit instruction
1185 1,1, // branch, skip
1186 0, // literal operand
1187 1, // RAM access bit
1188 0, // fast call/return mode select bit
1189 0, // second memory operand
1190 0, // second literal operand
1192 PCC_REGISTER, // inCond
1193 PCC_REGISTER , // outCond
1197 pCodeInstruction pic16_pciDECFSZW = {
1198 {PC_OPCODE, NULL, NULL, 0, NULL,
1205 NULL, // from branch
1212 0,0, // dest, bit instruction
1213 1,1, // branch, skip
1214 0, // literal operand
1215 1, // RAM access bit
1216 0, // fast call/return mode select bit
1217 0, // second memory operand
1218 0, // second literal operand
1220 PCC_REGISTER, // inCond
1225 pCodeInstruction pic16_pciGOTO = {
1226 {PC_OPCODE, NULL, NULL, 0, NULL,
1233 NULL, // from branch
1240 0,0, // dest, bit instruction
1241 1,0, // branch, skip
1242 0, // literal operand
1243 0, // RAM access bit
1244 0, // fast call/return mode select bit
1245 0, // second memory operand
1246 0, // second literal operand
1248 PCC_REL_ADDR, // inCond
1249 PCC_NONE , // outCond
1253 pCodeInstruction pic16_pciINCF = {
1254 {PC_OPCODE, NULL, NULL, 0, NULL,
1261 NULL, // from branch
1268 1,0, // dest, bit instruction
1269 0,0, // branch, skip
1270 0, // literal operand
1271 1, // RAM access bit
1272 0, // fast call/return mode select bit
1273 0, // second memory operand
1274 0, // second literal operand
1276 PCC_REGISTER, // inCond
1277 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1281 pCodeInstruction pic16_pciINCFW = {
1282 {PC_OPCODE, NULL, NULL, 0, NULL,
1289 NULL, // from branch
1296 0,0, // dest, bit instruction
1297 0,0, // branch, skip
1298 0, // literal operand
1299 1, // RAM access bit
1300 0, // fast call/return mode select bit
1301 0, // second memory operand
1302 0, // second literal operand
1304 PCC_REGISTER, // inCond
1309 pCodeInstruction pic16_pciINCFSZ = {
1310 {PC_OPCODE, NULL, NULL, 0, NULL,
1317 NULL, // from branch
1324 1,0, // dest, bit instruction
1325 1,1, // branch, skip
1326 0, // literal operand
1327 1, // RAM access bit
1328 0, // fast call/return mode select bit
1329 0, // second memory operand
1330 0, // second literal operand
1332 PCC_REGISTER, // inCond
1333 PCC_REGISTER , // outCond
1337 pCodeInstruction pic16_pciINCFSZW = {
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1345 NULL, // from branch
1352 0,0, // dest, bit instruction
1353 1,1, // branch, skip
1354 0, // literal operand
1355 1, // RAM access bit
1356 0, // fast call/return mode select bit
1357 0, // second memory operand
1358 0, // second literal operand
1360 PCC_REGISTER, // inCond
1365 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1366 {PC_OPCODE, NULL, NULL, 0, NULL,
1373 NULL, // from branch
1380 1,0, // dest, bit instruction
1381 1,1, // branch, skip
1382 0, // literal operand
1383 1, // RAM access bit
1384 0, // fast call/return mode select bit
1385 0, // second memory operand
1386 0, // second literal operand
1388 PCC_REGISTER, // inCond
1389 PCC_REGISTER , // outCond
1393 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1394 {PC_OPCODE, NULL, NULL, 0, NULL,
1401 NULL, // from branch
1408 0,0, // dest, bit instruction
1409 1,1, // branch, skip
1410 0, // literal operand
1411 1, // RAM access bit
1412 0, // fast call/return mode select bit
1413 0, // second memory operand
1414 0, // second literal operand
1416 PCC_REGISTER, // inCond
1421 pCodeInstruction pic16_pciIORWF = {
1422 {PC_OPCODE, NULL, NULL, 0, NULL,
1429 NULL, // from branch
1436 1,0, // dest, bit instruction
1437 0,0, // branch, skip
1438 0, // literal operand
1439 1, // RAM access bit
1440 0, // fast call/return mode select bit
1441 0, // second memory operand
1442 0, // second literal operand
1444 (PCC_W | PCC_REGISTER), // inCond
1445 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1449 pCodeInstruction pic16_pciIORFW = {
1450 {PC_OPCODE, NULL, NULL, 0, NULL,
1457 NULL, // from branch
1464 0,0, // dest, bit instruction
1465 0,0, // branch, skip
1466 0, // literal operand
1467 1, // RAM access bit
1468 0, // fast call/return mode select bit
1469 0, // second memory operand
1470 0, // second literal operand
1472 (PCC_W | PCC_REGISTER), // inCond
1473 (PCC_W | PCC_Z | PCC_N), // outCond
1477 pCodeInstruction pic16_pciIORLW = {
1478 {PC_OPCODE, NULL, NULL, 0, NULL,
1485 NULL, // from branch
1492 0,0, // dest, bit instruction
1493 0,0, // branch, skip
1494 1, // literal operand
1495 0, // RAM access bit
1496 0, // fast call/return mode select bit
1497 0, // second memory operand
1498 0, // second literal operand
1500 (PCC_W | PCC_LITERAL), // inCond
1501 (PCC_W | PCC_Z | PCC_N), // outCond
1505 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1506 {PC_OPCODE, NULL, NULL, 0, NULL,
1513 NULL, // from branch
1520 0,0, // dest, bit instruction
1521 0,0, // branch, skip
1522 1, // literal operand
1523 0, // RAM access bit
1524 0, // fast call/return mode select bit
1525 0, // second memory operand
1526 1, // second literal operand
1528 (PCC_REGISTER | PCC_LITERAL),
1529 PCC_REGISTER, // outCond
1533 pCodeInstruction pic16_pciMOVF = {
1534 {PC_OPCODE, NULL, NULL, 0, NULL,
1541 NULL, // from branch
1548 1,0, // dest, bit instruction
1549 0,0, // branch, skip
1550 0, // literal operand
1551 1, // RAM access bit
1552 0, // fast call/return mode select bit
1553 0, // second memory operand
1554 0, // second literal operand
1556 PCC_REGISTER, // inCond
1557 (PCC_Z | PCC_N), // outCond
1561 pCodeInstruction pic16_pciMOVFW = {
1562 {PC_OPCODE, NULL, NULL, 0, NULL,
1569 NULL, // from branch
1576 0,0, // dest, bit instruction
1577 0,0, // branch, skip
1578 0, // literal operand
1579 1, // RAM access bit
1580 0, // fast call/return mode select bit
1581 0, // second memory operand
1582 0, // second literal operand
1584 PCC_REGISTER, // inCond
1585 (PCC_W | PCC_Z), // outCond
1589 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1590 {PC_OPCODE, NULL, NULL, 0, NULL,
1597 NULL, // from branch
1604 0,0, // dest, bit instruction
1605 0,0, // branch, skip
1606 0, // literal operand
1607 0, // RAM access bit
1608 0, // fast call/return mode select bit
1609 1, // second memory operand
1610 0, // second literal operand
1612 PCC_REGISTER, // inCond
1613 PCC_REGISTER, // outCond
1617 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1618 {PC_OPCODE, NULL, NULL, 0, NULL,
1624 NULL, // from branch
1631 0,0, // dest, bit instruction
1632 0,0, // branch, skip
1633 1, // literal operand
1634 0, // RAM access bit
1635 0, // fast call/return mode select bit
1636 0, // second memory operand
1637 0, // second literal operand
1639 (PCC_NONE | PCC_LITERAL), // inCond
1640 PCC_REGISTER, // outCond - BSR
1644 pCodeInstruction pic16_pciMOVLW = {
1645 {PC_OPCODE, NULL, NULL, 0, NULL,
1651 NULL, // from branch
1658 0,0, // dest, bit instruction
1659 0,0, // branch, skip
1660 1, // literal operand
1661 0, // RAM access bit
1662 0, // fast call/return mode select bit
1663 0, // second memory operand
1664 0, // second literal operand
1666 (PCC_NONE | PCC_LITERAL), // inCond
1671 pCodeInstruction pic16_pciMOVWF = {
1672 {PC_OPCODE, NULL, NULL, 0, NULL,
1679 NULL, // from branch
1686 0,0, // dest, bit instruction
1687 0,0, // branch, skip
1688 0, // literal operand
1689 1, // RAM access bit
1690 0, // fast call/return mode select bit
1691 0, // second memory operand
1692 0, // second literal operand
1694 PCC_REGISTER, // inCond
1699 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1700 {PC_OPCODE, NULL, NULL, 0, NULL,
1706 NULL, // from branch
1713 0,0, // dest, bit instruction
1714 0,0, // branch, skip
1715 1, // literal operand
1716 0, // RAM access bit
1717 0, // fast call/return mode select bit
1718 0, // second memory operand
1719 0, // second literal operand
1721 (PCC_W | PCC_LITERAL), // inCond
1722 PCC_REGISTER, // outCond - PROD
1726 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1727 {PC_OPCODE, NULL, NULL, 0, NULL,
1733 NULL, // from branch
1740 0,0, // dest, bit instruction
1741 0,0, // branch, skip
1742 0, // literal operand
1743 1, // RAM access bit
1744 0, // fast call/return mode select bit
1745 0, // second memory operand
1746 0, // second literal operand
1748 (PCC_W | PCC_REGISTER), // inCond
1749 PCC_REGISTER, // outCond - PROD
1753 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1754 {PC_OPCODE, NULL, NULL, 0, NULL,
1760 NULL, // from branch
1767 0,0, // dest, bit instruction
1768 0,0, // branch, skip
1769 0, // literal operand
1770 1, // RAM access bit
1771 0, // fast call/return mode select bit
1772 0, // second memory operand
1773 0, // second literal operand
1775 PCC_REGISTER, // inCond
1776 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1780 pCodeInstruction pic16_pciNOP = {
1781 {PC_OPCODE, NULL, NULL, 0, NULL,
1787 NULL, // from branch
1794 0,0, // dest, bit instruction
1795 0,0, // branch, skip
1796 0, // literal operand
1797 0, // RAM access bit
1798 0, // fast call/return mode select bit
1799 0, // second memory operand
1800 0, // second literal operand
1803 PCC_NONE, // outCond
1807 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1808 {PC_OPCODE, NULL, NULL, 0, NULL,
1814 NULL, // from branch
1821 0,0, // dest, bit instruction
1822 0,0, // branch, skip
1823 0, // literal operand
1824 0, // RAM access bit
1825 0, // fast call/return mode select bit
1826 0, // second memory operand
1827 0, // second literal operand
1830 PCC_NONE , // outCond
1834 pCodeInstruction pic16_pciPUSH = {
1835 {PC_OPCODE, NULL, NULL, 0, NULL,
1841 NULL, // from branch
1848 0,0, // dest, bit instruction
1849 0,0, // branch, skip
1850 0, // literal operand
1851 0, // RAM access bit
1852 0, // fast call/return mode select bit
1853 0, // second memory operand
1854 0, // second literal operand
1857 PCC_NONE , // outCond
1861 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1862 {PC_OPCODE, NULL, NULL, 0, NULL,
1868 NULL, // from branch
1875 0,0, // dest, bit instruction
1876 0,0, // branch, skip
1877 0, // literal operand
1878 0, // RAM access bit
1879 0, // fast call/return mode select bit
1880 0, // second memory operand
1881 0, // second literal operand
1883 PCC_REL_ADDR, // inCond
1884 PCC_NONE , // outCond
1888 pCodeInstruction pic16_pciRETFIE = {
1889 {PC_OPCODE, NULL, NULL, 0, NULL,
1896 NULL, // from branch
1903 0,0, // dest, bit instruction
1904 1,0, // branch, skip
1905 0, // literal operand
1906 0, // RAM access bit
1907 1, // fast call/return mode select bit
1908 0, // second memory operand
1909 0, // second literal operand
1912 PCC_NONE, // outCond (not true... affects the GIE bit too)
1916 pCodeInstruction pic16_pciRETLW = {
1917 {PC_OPCODE, NULL, NULL, 0, NULL,
1924 NULL, // from branch
1931 0,0, // dest, bit instruction
1932 1,0, // branch, skip
1933 1, // literal operand
1934 0, // RAM access bit
1935 0, // fast call/return mode select bit
1936 0, // second memory operand
1937 0, // second literal operand
1939 PCC_LITERAL, // inCond
1944 pCodeInstruction pic16_pciRETURN = {
1945 {PC_OPCODE, NULL, NULL, 0, NULL,
1952 NULL, // from branch
1959 0,0, // dest, bit instruction
1960 1,0, // branch, skip
1961 0, // literal operand
1962 0, // RAM access bit
1963 1, // fast call/return mode select bit
1964 0, // second memory operand
1965 0, // second literal operand
1968 PCC_NONE, // outCond
1971 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1972 {PC_OPCODE, NULL, NULL, 0, NULL,
1979 NULL, // from branch
1986 1,0, // dest, bit instruction
1987 0,0, // branch, skip
1988 0, // literal operand
1989 1, // RAM access bit
1990 0, // fast call/return mode select bit
1991 0, // second memory operand
1992 0, // second literal operand
1994 (PCC_C | PCC_REGISTER), // inCond
1995 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1999 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
2000 {PC_OPCODE, NULL, NULL, 0, NULL,
2007 NULL, // from branch
2014 0,0, // dest, bit instruction
2015 0,0, // branch, skip
2016 0, // literal operand
2017 1, // RAM access bit
2018 0, // fast call/return mode select bit
2019 0, // second memory operand
2020 0, // second literal operand
2022 (PCC_C | PCC_REGISTER), // inCond
2023 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2027 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
2028 {PC_OPCODE, NULL, NULL, 0, NULL,
2035 NULL, // from branch
2042 1,0, // dest, bit instruction
2043 0,0, // branch, skip
2044 0, // literal operand
2045 1, // RAM access bit
2046 0, // fast call/return mode select bit
2047 0, // second memory operand
2048 0, // second literal operand
2050 PCC_REGISTER, // inCond
2051 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2054 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
2055 {PC_OPCODE, NULL, NULL, 0, NULL,
2062 NULL, // from branch
2069 0,0, // dest, bit instruction
2070 0,0, // branch, skip
2071 0, // literal operand
2072 1, // RAM access bit
2073 0, // fast call/return mode select bit
2074 0, // second memory operand
2075 0, // second literal operand
2077 PCC_REGISTER, // inCond
2078 (PCC_W | PCC_Z | PCC_N), // outCond
2081 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2082 {PC_OPCODE, NULL, NULL, 0, NULL,
2089 NULL, // from branch
2096 1,0, // dest, bit instruction
2097 0,0, // branch, skip
2098 0, // literal operand
2099 1, // RAM access bit
2100 0, // fast call/return mode select bit
2101 0, // second memory operand
2102 0, // second literal operand
2104 (PCC_C | PCC_REGISTER), // inCond
2105 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2108 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2109 {PC_OPCODE, NULL, NULL, 0, NULL,
2116 NULL, // from branch
2123 0,0, // dest, bit instruction
2124 0,0, // branch, skip
2125 0, // literal operand
2126 1, // RAM access bit
2127 0, // fast call/return mode select bit
2128 0, // second memory operand
2129 0, // second literal operand
2131 (PCC_C | PCC_REGISTER), // inCond
2132 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2135 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2136 {PC_OPCODE, NULL, NULL, 0, NULL,
2143 NULL, // from branch
2150 1,0, // dest, bit instruction
2151 0,0, // branch, skip
2152 0, // literal operand
2153 1, // RAM access bit
2154 0, // fast call/return mode select bit
2155 0, // second memory operand
2156 0, // second literal operand
2158 PCC_REGISTER, // inCond
2159 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2163 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2164 {PC_OPCODE, NULL, NULL, 0, NULL,
2171 NULL, // from branch
2178 0,0, // dest, bit instruction
2179 0,0, // branch, skip
2180 0, // literal operand
2181 1, // RAM access bit
2182 0, // fast call/return mode select bit
2183 0, // second memory operand
2184 0, // second literal operand
2186 PCC_REGISTER, // inCond
2187 (PCC_W | PCC_Z | PCC_N), // outCond
2191 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2192 {PC_OPCODE, NULL, NULL, 0, NULL,
2199 NULL, // from branch
2206 0,0, // dest, bit instruction
2207 0,0, // branch, skip
2208 0, // literal operand
2209 1, // RAM access bit
2210 0, // fast call/return mode select bit
2211 0, // second memory operand
2212 0, // second literal operand
2214 PCC_REGISTER, // inCond
2215 PCC_REGISTER , // outCond
2219 pCodeInstruction pic16_pciSUBLW = {
2220 {PC_OPCODE, NULL, NULL, 0, NULL,
2227 NULL, // from branch
2234 0,0, // dest, bit instruction
2235 0,0, // branch, skip
2236 1, // literal operand
2237 0, // RAM access bit
2238 0, // fast call/return mode select bit
2239 0, // second memory operand
2240 0, // second literal operand
2242 (PCC_W | PCC_LITERAL), // inCond
2243 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2247 pCodeInstruction pic16_pciSUBFWB = {
2248 {PC_OPCODE, NULL, NULL, 0, NULL,
2255 NULL, // from branch
2262 1,0, // dest, bit instruction
2263 0,0, // branch, skip
2264 0, // literal operand
2265 1, // RAM access bit
2266 0, // fast call/return mode select bit
2267 0, // second memory operand
2268 0, // second literal operand
2270 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2271 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2275 pCodeInstruction pic16_pciSUBWF = {
2276 {PC_OPCODE, NULL, NULL, 0, NULL,
2283 NULL, // from branch
2290 1,0, // dest, bit instruction
2291 0,0, // branch, skip
2292 0, // literal operand
2293 1, // RAM access bit
2294 0, // fast call/return mode select bit
2295 0, // second memory operand
2296 0, // second literal operand
2298 (PCC_W | PCC_REGISTER), // inCond
2299 (PCC_REGISTER | PCC_Z), // outCond
2303 pCodeInstruction pic16_pciSUBFW = {
2304 {PC_OPCODE, NULL, NULL, 0, NULL,
2311 NULL, // from branch
2318 0,0, // dest, bit instruction
2319 0,0, // branch, skip
2320 0, // literal operand
2321 1, // RAM access bit
2322 0, // fast call/return mode select bit
2323 0, // second memory operand
2324 0, // second literal operand
2326 (PCC_W | PCC_REGISTER), // inCond
2327 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2331 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2332 {PC_OPCODE, NULL, NULL, 0, NULL,
2339 NULL, // from branch
2346 1,0, // dest, bit instruction
2347 0,0, // branch, skip
2348 0, // literal operand
2349 1, // RAM access bit
2350 0, // fast call/return mode select bit
2351 0, // second memory operand
2352 0, // second literal operand
2354 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2355 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2359 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2360 {PC_OPCODE, NULL, NULL, 0, NULL,
2367 NULL, // from branch
2374 0,0, // dest, bit instruction
2375 0,0, // branch, skip
2376 0, // literal operand
2377 1, // RAM access bit
2378 0, // fast call/return mode select bit
2379 0, // second memory operand
2380 0, // second literal operand
2382 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2383 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2387 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2388 {PC_OPCODE, NULL, NULL, 0, NULL,
2395 NULL, // from branch
2402 1,0, // dest, bit instruction
2403 0,0, // branch, skip
2404 0, // literal operand
2405 1, // RAM access bit
2406 0, // fast call/return mode select bit
2407 0, // second memory operand
2408 0, // second literal operand
2410 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2411 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2415 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2416 {PC_OPCODE, NULL, NULL, 0, NULL,
2423 NULL, // from branch
2430 0,0, // dest, bit instruction
2431 0,0, // branch, skip
2432 0, // literal operand
2433 1, // RAM access bit
2434 0, // fast call/return mode select bit
2435 0, // second memory operand
2436 0, // second literal operand
2438 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2439 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2443 pCodeInstruction pic16_pciSWAPF = {
2444 {PC_OPCODE, NULL, NULL, 0, NULL,
2451 NULL, // from branch
2458 1,0, // dest, bit instruction
2459 0,0, // branch, skip
2460 0, // literal operand
2461 1, // RAM access bit
2462 0, // fast call/return mode select bit
2463 0, // second memory operand
2464 0, // second literal operand
2466 (PCC_REGISTER), // inCond
2467 (PCC_REGISTER), // outCond
2471 pCodeInstruction pic16_pciSWAPFW = {
2472 {PC_OPCODE, NULL, NULL, 0, NULL,
2479 NULL, // from branch
2486 0,0, // dest, bit instruction
2487 0,0, // branch, skip
2488 0, // literal operand
2489 1, // RAM access bit
2490 0, // fast call/return mode select bit
2491 0, // second memory operand
2492 0, // second literal operand
2494 (PCC_REGISTER), // inCond
2499 pCodeInstruction pic16_pciTBLRD = { // patch 15
2500 {PC_OPCODE, NULL, NULL, 0, NULL,
2506 NULL, // from branch
2513 0,0, // dest, bit instruction
2514 0,0, // branch, skip
2515 0, // literal operand
2516 0, // RAM access bit
2517 0, // fast call/return mode select bit
2518 0, // second memory operand
2519 0, // second literal operand
2522 PCC_NONE , // outCond
2526 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2527 {PC_OPCODE, NULL, NULL, 0, NULL,
2533 NULL, // from branch
2540 0,0, // dest, bit instruction
2541 0,0, // branch, skip
2542 0, // literal operand
2543 0, // RAM access bit
2544 0, // fast call/return mode select bit
2545 0, // second memory operand
2546 0, // second literal operand
2549 PCC_NONE , // outCond
2553 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2554 {PC_OPCODE, NULL, NULL, 0, NULL,
2560 NULL, // from branch
2567 0,0, // dest, bit instruction
2568 0,0, // branch, skip
2569 0, // literal operand
2570 0, // RAM access bit
2571 0, // fast call/return mode select bit
2572 0, // second memory operand
2573 0, // second literal operand
2576 PCC_NONE , // outCond
2580 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2581 {PC_OPCODE, NULL, NULL, 0, NULL,
2587 NULL, // from branch
2594 0,0, // dest, bit instruction
2595 0,0, // branch, skip
2596 0, // literal operand
2597 0, // RAM access bit
2598 0, // fast call/return mode select bit
2599 0, // second memory operand
2600 0, // second literal operand
2603 PCC_NONE , // outCond
2607 pCodeInstruction pic16_pciTBLWT = { // patch 15
2608 {PC_OPCODE, NULL, NULL, 0, NULL,
2614 NULL, // from branch
2621 0,0, // dest, bit instruction
2622 0,0, // branch, skip
2623 0, // literal operand
2624 0, // RAM access bit
2625 0, // fast call/return mode select bit
2626 0, // second memory operand
2627 0, // second literal operand
2630 PCC_NONE , // outCond
2634 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2635 {PC_OPCODE, NULL, NULL, 0, NULL,
2641 NULL, // from branch
2648 0,0, // dest, bit instruction
2649 0,0, // branch, skip
2650 0, // literal operand
2651 0, // RAM access bit
2652 0, // fast call/return mode select bit
2653 0, // second memory operand
2654 0, // second literal operand
2657 PCC_NONE , // outCond
2661 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2662 {PC_OPCODE, NULL, NULL, 0, NULL,
2668 NULL, // from branch
2675 0,0, // dest, bit instruction
2676 0,0, // branch, skip
2677 0, // literal operand
2678 0, // RAM access bit
2679 0, // fast call/return mode select bit
2680 0, // second memory operand
2681 0, // second literal operand
2684 PCC_NONE , // outCond
2688 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2689 {PC_OPCODE, NULL, NULL, 0, NULL,
2695 NULL, // from branch
2702 0,0, // dest, bit instruction
2703 0,0, // branch, skip
2704 0, // literal operand
2705 0, // RAM access bit
2706 0, // fast call/return mode select bit
2707 0, // second memory operand
2708 0, // second literal operand
2711 PCC_NONE , // outCond
2715 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2716 {PC_OPCODE, NULL, NULL, 0, NULL,
2723 NULL, // from branch
2730 0,0, // dest, bit instruction
2731 1,1, // branch, skip
2732 0, // literal operand
2733 1, // RAM access bit
2734 0, // fast call/return mode select bit
2735 0, // second memory operand
2736 0, // second literal operand
2738 PCC_REGISTER, // inCond
2739 PCC_NONE, // outCond
2743 pCodeInstruction pic16_pciXORWF = {
2744 {PC_OPCODE, NULL, NULL, 0, NULL,
2751 NULL, // from branch
2758 1,0, // dest, bit instruction
2759 0,0, // branch, skip
2760 0, // literal operand
2761 1, // RAM access bit
2762 0, // fast call/return mode select bit
2763 0, // second memory operand
2764 0, // second literal operand
2766 (PCC_W | PCC_REGISTER), // inCond
2767 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2771 pCodeInstruction pic16_pciXORFW = {
2772 {PC_OPCODE, NULL, NULL, 0, NULL,
2779 NULL, // from branch
2786 0,0, // dest, bit instruction
2787 0,0, // branch, skip
2788 0, // literal operand
2789 1, // RAM access bit
2790 0, // fast call/return mode select bit
2791 0, // second memory operand
2792 0, // second literal operand
2794 (PCC_W | PCC_REGISTER), // inCond
2795 (PCC_W | PCC_Z | PCC_N), // outCond
2799 pCodeInstruction pic16_pciXORLW = {
2800 {PC_OPCODE, NULL, NULL, 0, NULL,
2807 NULL, // from branch
2814 0,0, // dest, bit instruction
2815 0,0, // branch, skip
2816 1, // literal operand
2817 1, // RAM access bit
2818 0, // fast call/return mode select bit
2819 0, // second memory operand
2820 0, // second literal operand
2822 (PCC_W | PCC_LITERAL), // inCond
2823 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2828 pCodeInstruction pic16_pciBANKSEL = {
2829 {PC_OPCODE, NULL, NULL, 0, NULL,
2835 NULL, // from branch
2842 0,0, // dest, bit instruction
2843 0,0, // branch, skip
2844 0, // literal operand
2845 0, // RAM access bit
2846 0, // fast call/return mode select bit
2847 0, // second memory operand
2848 0, // second literal operand
2851 PCC_NONE, // outCond
2856 #define MAX_PIC16MNEMONICS 100
2857 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2859 //#define USE_VSNPRINTF
2862 #ifdef USE_VSNPRINTF
2863 // Alas, vsnprintf is not ANSI standard, and does not exist
2864 // on Solaris (and probably other non-Gnu flavored Unixes).
2866 /*-----------------------------------------------------------------*/
2867 /* SAFE_snprintf - like snprintf except the string pointer is */
2868 /* after the string has been printed to. This is */
2869 /* useful for printing to string as though if it */
2870 /* were a stream. */
2871 /*-----------------------------------------------------------------*/
2872 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2880 va_start(val, format);
2882 vsnprintf(*str, *size, format, val);
2888 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2889 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2898 // This version is *not* safe, despite the name.
2900 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2904 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2909 va_start(val, format);
2911 vsprintf(buffer, format, val);
2914 len = strlen(buffer);
2916 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2917 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2920 strcpy(*str, buffer);
2926 #endif // USE_VSNPRINTF
2929 extern set *externs;
2930 extern void pic16_initStack(int base_address, int size);
2931 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2932 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2933 extern void pic16_init_pic(char *);
2935 void pic16_pCodeInitRegisters(void)
2937 static int initialized=0;
2944 // pic16_initStack(0xfff, 8);
2945 pic16_init_pic(port->processor);
2947 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2948 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2949 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2950 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2951 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2952 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2953 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2955 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2956 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2957 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2959 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2960 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2961 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2962 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2964 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2965 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2966 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2967 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2968 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2969 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2971 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2972 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2973 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2974 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2975 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2977 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2978 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2979 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2980 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2981 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2983 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2984 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2985 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2986 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2987 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2989 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2990 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2993 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2994 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2995 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2996 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2999 pic16_pc_status.rIdx = IDX_STATUS;
3000 pic16_pc_intcon.rIdx = IDX_INTCON;
3001 pic16_pc_pcl.rIdx = IDX_PCL;
3002 pic16_pc_pclath.rIdx = IDX_PCLATH;
3003 pic16_pc_pclatu.rIdx = IDX_PCLATU;
3004 pic16_pc_wreg.rIdx = IDX_WREG;
3005 pic16_pc_bsr.rIdx = IDX_BSR;
3007 pic16_pc_tosl.rIdx = IDX_TOSL;
3008 pic16_pc_tosh.rIdx = IDX_TOSH;
3009 pic16_pc_tosu.rIdx = IDX_TOSU;
3011 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
3012 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
3013 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
3014 pic16_pc_tablat.rIdx = IDX_TABLAT;
3016 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
3017 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
3018 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
3019 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
3020 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
3021 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
3022 pic16_pc_indf0.rIdx = IDX_INDF0;
3023 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
3024 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
3025 pic16_pc_preinc0.rIdx = IDX_PREINC0;
3026 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
3027 pic16_pc_indf1.rIdx = IDX_INDF1;
3028 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
3029 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
3030 pic16_pc_preinc1.rIdx = IDX_PREINC1;
3031 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
3032 pic16_pc_indf2.rIdx = IDX_INDF2;
3033 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
3034 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
3035 pic16_pc_preinc2.rIdx = IDX_PREINC2;
3036 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
3037 pic16_pc_prodl.rIdx = IDX_PRODL;
3038 pic16_pc_prodh.rIdx = IDX_PRODH;
3040 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
3041 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
3042 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
3044 pic16_pc_kzero.rIdx = IDX_KZ;
3045 pic16_pc_wsave.rIdx = IDX_WSAVE;
3046 pic16_pc_ssave.rIdx = IDX_SSAVE;
3048 pic16_pc_eecon1.rIdx = IDX_EECON1;
3049 pic16_pc_eecon2.rIdx = IDX_EECON2;
3050 pic16_pc_eedata.rIdx = IDX_EEDATA;
3051 pic16_pc_eeadr.rIdx = IDX_EEADR;
3054 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
3055 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
3057 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
3058 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
3060 /* probably should put this in a separate initialization routine */
3061 pb_dead_pcodes = newpBlock();
3066 /*-----------------------------------------------------------------*/
3067 /* mnem2key - convert a pic mnemonic into a hash key */
3068 /* (BTW - this spreads the mnemonics quite well) */
3070 /*-----------------------------------------------------------------*/
3072 int mnem2key(char const *mnem)
3081 key += toupper(*mnem++) +1;
3085 return (key & 0x1f);
3090 void pic16initMnemonics(void)
3095 pCodeInstruction *pci;
3097 if(mnemonics_initialized)
3100 // NULL out the array before making the assignments
3101 // since we check the array contents below this initialization.
3103 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3104 pic16Mnemonics[i] = NULL;
3107 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3108 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3109 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3110 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3111 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3112 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3113 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3114 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3115 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3116 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3117 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3118 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3119 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3120 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3121 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3122 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3123 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3124 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3125 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3126 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3127 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3128 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3129 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3130 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3131 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3132 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3133 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3134 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3135 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3136 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3137 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3138 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3139 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3140 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3141 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3142 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3143 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3144 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3145 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3146 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3147 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3148 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3149 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3150 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3151 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3152 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3153 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3154 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3155 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3156 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3157 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3158 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3159 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3160 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3161 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3162 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3163 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3164 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3165 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3166 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3167 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3168 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3169 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3170 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3171 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3172 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3173 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3174 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3175 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3176 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3177 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3178 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3179 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3180 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3181 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3182 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3183 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3184 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3185 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3186 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3187 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3188 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3189 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3190 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3191 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3192 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3193 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3194 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3195 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3196 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3197 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3198 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3199 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3200 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3202 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3203 if(pic16Mnemonics[i])
3204 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3205 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3208 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3209 pci = hTabNextItem(pic16MnemonicsHash, &key);
3212 mnemonics_initialized = 1;
3215 int pic16_getpCodePeepCommand(char *cmd);
3217 int pic16_getpCode(char *mnem,unsigned dest)
3220 pCodeInstruction *pci;
3221 int key = mnem2key(mnem);
3223 if(!mnemonics_initialized)
3224 pic16initMnemonics();
3226 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3230 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3231 if((pci->num_ops <= 1)
3232 || (pci->isModReg == dest)
3234 || (pci->num_ops <= 2 && pci->isAccess)
3235 || (pci->num_ops <= 2 && pci->isFastCall)
3236 || (pci->num_ops <= 2 && pci->is2MemOp)
3237 || (pci->num_ops <= 2 && pci->is2LitOp) )
3241 pci = hTabNextItemWK (pic16MnemonicsHash);
3248 /*-----------------------------------------------------------------*
3249 * pic16initpCodePeepCommands
3251 *-----------------------------------------------------------------*/
3252 void pic16initpCodePeepCommands(void)
3260 hTabAddItem(&pic16pCodePeepCommandsHash,
3261 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3263 } while (peepCommands[i].cmd);
3265 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3268 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3269 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3274 /*-----------------------------------------------------------------
3277 *-----------------------------------------------------------------*/
3279 int pic16_getpCodePeepCommand(char *cmd)
3283 int key = mnem2key(cmd);
3286 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3289 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3290 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3294 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3301 static char getpBlock_dbName(pBlock *pb)
3307 return pb->cmemmap->dbName;
3311 void pic16_pBlockConvert2ISR(pBlock *pb)
3315 if(pb->cmemmap)pb->cmemmap = NULL;
3319 if(pic16_pcode_verbose)
3320 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3323 void pic16_pBlockConvert2Absolute(pBlock *pb)
3326 if(pb->cmemmap)pb->cmemmap = NULL;
3330 if(pic16_pcode_verbose)
3331 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3334 /*-----------------------------------------------------------------*/
3335 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3336 /* instances to the front of the doubly linked */
3337 /* list of pBlocks */
3338 /*-----------------------------------------------------------------*/
3340 void pic16_movepBlock2Head(char dbName)
3345 /* this can happen in sources without code,
3346 * only variable definitions */
3347 if(!the_pFile)return;
3349 pb = the_pFile->pbHead;
3353 if(getpBlock_dbName(pb) == dbName) {
3354 pBlock *pbn = pb->next;
3355 pb->next = the_pFile->pbHead;
3356 the_pFile->pbHead->prev = pb;
3357 the_pFile->pbHead = pb;
3360 pb->prev->next = pbn;
3362 // If the pBlock that we just moved was the last
3363 // one in the link of all of the pBlocks, then we
3364 // need to point the tail to the block just before
3365 // the one we moved.
3366 // Note: if pb->next is NULL, then pb must have
3367 // been the last pBlock in the chain.
3370 pbn->prev = pb->prev;
3372 the_pFile->pbTail = pb->prev;
3383 void pic16_copypCode(FILE *of, char dbName)
3387 if(!of || !the_pFile)
3390 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3391 if(getpBlock_dbName(pb) == dbName) {
3392 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3394 pic16_printpBlock(of,pb);
3399 void pic16_pcode_test(void)
3402 DFPRINTF((stderr,"pcode is alive!\n"));
3412 /* create the file name */
3413 strcpy(buffer,dstFileName);
3414 strcat(buffer,".p");
3416 if( !(pFile = fopen(buffer, "w" ))) {
3417 werror(E_FILE_OPEN_ERR,buffer);
3421 fprintf(pFile,"pcode dump\n\n");
3423 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3424 fprintf(pFile,"\n\tNew pBlock\n\n");
3426 fprintf(pFile,"%s",pb->cmemmap->sname);
3428 fprintf(pFile,"internal pblock");
3430 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3431 pic16_printpBlock(pFile,pb);
3437 unsigned long pic16_countInstructions(void)
3441 unsigned long isize=0;
3443 if(!the_pFile)return -1;
3445 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3446 for(pc = pb->pcHead; pc; pc = pc->next) {
3447 if(isPCI(pc) || isASMDIR(pc))isize += PCI(pc)->isize;
3454 /*-----------------------------------------------------------------*/
3455 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3456 /* ister, RegCond will return the bit being referenced. */
3458 /* fixme - why not just OR in the pcop bit field */
3459 /*-----------------------------------------------------------------*/
3461 static int RegCond(pCodeOp *pcop)
3467 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3468 switch(PCORB(pcop)->bit) {
3482 /*-----------------------------------------------------------------*/
3483 /* pic16_newpCode - create and return a newly initialized pCode */
3485 /* fixme - rename this */
3487 /* The purpose of this routine is to create a new Instruction */
3488 /* pCode. This is called by gen.c while the assembly code is being */
3492 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3493 /* (note that the op is analogous to but not the */
3494 /* same thing as the opcode of the instruction.) */
3495 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3498 /* a pointer to the new malloc'd pCode is returned. */
3502 /*-----------------------------------------------------------------*/
3503 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3505 pCodeInstruction *pci ;
3507 if(!mnemonics_initialized)
3508 pic16initMnemonics();
3510 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3512 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3513 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3516 if(pci->inCond & PCC_EXAMINE_PCOP)
3517 pci->inCond |= RegCond(pcop);
3519 if(pci->outCond & PCC_EXAMINE_PCOP)
3520 pci->outCond |= RegCond(pcop);
3522 pci->pc.prev = pci->pc.next = NULL;
3523 return (pCode *)pci;
3526 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3532 /*-----------------------------------------------------------------*/
3533 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3535 /* Wild pcodes are used during the peep hole optimizer to serve */
3536 /* as place holders for any instruction. When a snippet of code is */
3537 /* compared to a peep hole rule, the wild card opcode will match */
3538 /* any instruction. However, the optional operand and label are */
3539 /* additional qualifiers that must also be matched before the */
3540 /* line (of assembly code) is declared matched. Note that the */
3541 /* operand may be wild too. */
3543 /* Note, a wild instruction is specified just like a wild var: */
3544 /* %4 ; A wild instruction, */
3545 /* See the peeph.def file for additional examples */
3547 /*-----------------------------------------------------------------*/
3549 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3554 pcw = Safe_calloc(1,sizeof(pCodeWild));
3556 pcw->pci.pc.type = PC_WILD;
3557 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3558 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3559 pcw->pci.pc.pb = NULL;
3561 // pcw->pci.pc.analyze = genericAnalyze;
3562 pcw->pci.pc.destruct = genericDestruct;
3563 pcw->pci.pc.print = genericPrint;
3565 pcw->id = pCodeID; // this is the 'n' in %n
3566 pcw->operand = optional_operand;
3567 pcw->label = optional_label;
3569 pcw->mustBeBitSkipInst = 0;
3570 pcw->mustNotBeBitSkipInst = 0;
3571 pcw->invertBitSkipInst = 0;
3573 return ( (pCode *)pcw);
3577 /*-----------------------------------------------------------------*/
3578 /* newPcodeInlineP - create a new pCode from a char string */
3579 /*-----------------------------------------------------------------*/
3582 pCode *pic16_newpCodeInlineP(char *cP)
3587 pcc = Safe_calloc(1,sizeof(pCodeComment));
3589 pcc->pc.type = PC_INLINE;
3590 pcc->pc.prev = pcc->pc.next = NULL;
3591 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3594 // pcc->pc.analyze = genericAnalyze;
3595 pcc->pc.destruct = genericDestruct;
3596 pcc->pc.print = genericPrint;
3599 pcc->comment = Safe_strdup(cP);
3601 pcc->comment = NULL;
3603 return ( (pCode *)pcc);
3607 /*-----------------------------------------------------------------*/
3608 /* newPcodeCharP - create a new pCode from a char string */
3609 /*-----------------------------------------------------------------*/
3611 pCode *pic16_newpCodeCharP(char *cP)
3616 pcc = Safe_calloc(1,sizeof(pCodeComment));
3618 pcc->pc.type = PC_COMMENT;
3619 pcc->pc.prev = pcc->pc.next = NULL;
3620 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3623 // pcc->pc.analyze = genericAnalyze;
3624 pcc->pc.destruct = genericDestruct;
3625 pcc->pc.print = genericPrint;
3628 pcc->comment = Safe_strdup(cP);
3630 pcc->comment = NULL;
3632 return ( (pCode *)pcc);
3636 /*-----------------------------------------------------------------*/
3637 /* pic16_newpCodeFunction - */
3638 /*-----------------------------------------------------------------*/
3641 pCode *pic16_newpCodeFunction(char *mod,char *f)
3645 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3647 pcf->pc.type = PC_FUNCTION;
3648 pcf->pc.prev = pcf->pc.next = NULL;
3649 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3652 // pcf->pc.analyze = genericAnalyze;
3653 pcf->pc.destruct = genericDestruct;
3654 pcf->pc.print = pCodePrintFunction;
3660 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3661 strcpy(pcf->modname,mod);
3663 pcf->modname = NULL;
3666 pcf->fname = Safe_calloc(1,strlen(f)+1);
3667 strcpy(pcf->fname,f);
3671 pcf->stackusage = 0;
3673 return ( (pCode *)pcf);
3676 /*-----------------------------------------------------------------*/
3677 /* pic16_newpCodeFlow */
3678 /*-----------------------------------------------------------------*/
3679 static void destructpCodeFlow(pCode *pc)
3681 if(!pc || !isPCFL(pc))
3688 pic16_unlinkpCode(pc);
3690 deleteSet(&PCFL(pc)->registers);
3691 deleteSet(&PCFL(pc)->from);
3692 deleteSet(&PCFL(pc)->to);
3694 /* Instead of deleting the memory used by this pCode, mark
3695 * the object as bad so that if there's a pointer to this pCode
3696 * dangling around somewhere then (hopefully) when the type is
3697 * checked we'll catch it.
3701 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3707 pCode *pic16_newpCodeFlow(void )
3711 //_ALLOC(pcflow,sizeof(pCodeFlow));
3712 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3714 pcflow->pc.type = PC_FLOW;
3715 pcflow->pc.prev = pcflow->pc.next = NULL;
3716 pcflow->pc.pb = NULL;
3718 // pcflow->pc.analyze = genericAnalyze;
3719 pcflow->pc.destruct = destructpCodeFlow;
3720 pcflow->pc.print = genericPrint;
3722 pcflow->pc.seq = GpcFlowSeq++;
3724 pcflow->from = pcflow->to = NULL;
3726 pcflow->inCond = PCC_NONE;
3727 pcflow->outCond = PCC_NONE;
3729 pcflow->firstBank = -1;
3730 pcflow->lastBank = -1;
3732 pcflow->FromConflicts = 0;
3733 pcflow->ToConflicts = 0;
3737 pcflow->registers = newSet();
3739 return ( (pCode *)pcflow);
3743 /*-----------------------------------------------------------------*/
3744 /*-----------------------------------------------------------------*/
3745 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3747 pCodeFlowLink *pcflowLink;
3749 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3751 pcflowLink->pcflow = pcflow;
3752 pcflowLink->bank_conflict = 0;
3757 /*-----------------------------------------------------------------*/
3758 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3759 /*-----------------------------------------------------------------*/
3761 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3766 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3768 pccs->pc.type = PC_CSOURCE;
3769 pccs->pc.prev = pccs->pc.next = NULL;
3772 pccs->pc.destruct = genericDestruct;
3773 pccs->pc.print = genericPrint;
3775 pccs->line_number = ln;
3777 pccs->line = Safe_strdup(l);
3782 pccs->file_name = Safe_strdup(f);
3784 pccs->file_name = NULL;
3786 return ( (pCode *)pccs);
3791 /*******************************************************************/
3792 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3793 /* added by VR 6-Jun-2003 */
3794 /*******************************************************************/
3796 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3803 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3804 pcad->pci.pc.type = PC_ASMDIR;
3805 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3806 pcad->pci.pc.pb = NULL;
3807 pcad->pci.isize = 2;
3808 pcad->pci.pc.destruct = genericDestruct;
3809 pcad->pci.pc.print = genericPrint;
3811 if(asdir && *asdir) {
3813 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3815 pcad->directive = Safe_strdup( asdir );
3818 va_start(ap, argfmt);
3820 memset(buffer, 0, sizeof(buffer));
3821 if(argfmt && *argfmt)
3822 vsprintf(buffer, argfmt, ap);
3826 while(isspace(*lbp))lbp++;
3829 pcad->arg = Safe_strdup( lbp );
3831 return ((pCode *)pcad);
3834 /*-----------------------------------------------------------------*/
3835 /* pCodeLabelDestruct - free memory used by a label. */
3836 /*-----------------------------------------------------------------*/
3837 static void pCodeLabelDestruct(pCode *pc)
3843 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3844 // free(PCL(pc)->label);
3846 /* Instead of deleting the memory used by this pCode, mark
3847 * the object as bad so that if there's a pointer to this pCode
3848 * dangling around somewhere then (hopefully) when the type is
3849 * checked we'll catch it.
3853 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3859 pCode *pic16_newpCodeLabel(char *name, int key)
3865 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3867 pcl->pc.type = PC_LABEL;
3868 pcl->pc.prev = pcl->pc.next = NULL;
3869 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3872 // pcl->pc.analyze = genericAnalyze;
3873 pcl->pc.destruct = pCodeLabelDestruct;
3874 pcl->pc.print = pCodePrintLabel;
3881 sprintf(s,"_%05d_DS_",key);
3886 pcl->label = Safe_strdup(s);
3888 // if(pic16_pcode_verbose)
3889 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3892 return ( (pCode *)pcl);
3896 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3898 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3902 return ( (pCode *)pcl );
3905 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3909 pci = Safe_calloc(1, sizeof(pCodeInfo));
3910 pci->pci.pc.type = PC_INFO;
3911 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3912 pci->pci.pc.pb = NULL;
3913 pci->pci.label = NULL;
3915 pci->pci.pc.destruct = genericDestruct;
3916 pci->pci.pc.print = genericPrint;
3921 return ((pCode *)pci);
3925 /*-----------------------------------------------------------------*/
3926 /* newpBlock - create and return a pointer to a new pBlock */
3927 /*-----------------------------------------------------------------*/
3928 static pBlock *newpBlock(void)
3933 PpB = Safe_calloc(1,sizeof(pBlock) );
3934 PpB->next = PpB->prev = NULL;
3936 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3937 PpB->tregisters = NULL;
3939 PpB->FlowTree = NULL;
3945 /*-----------------------------------------------------------------*/
3946 /* pic16_newpCodeChain - create a new chain of pCodes */
3947 /*-----------------------------------------------------------------*
3949 * This function will create a new pBlock and the pointer to the
3950 * pCode that is passed in will be the first pCode in the block.
3951 *-----------------------------------------------------------------*/
3954 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3957 pBlock *pB = newpBlock();
3959 pB->pcHead = pB->pcTail = pc;
3968 /*-----------------------------------------------------------------*/
3969 /* pic16_newpCodeOpLabel - Create a new label given the key */
3970 /* Note, a negative key means that the label is part of wild card */
3971 /* (and hence a wild card label) used in the pCodePeep */
3972 /* optimizations). */
3973 /*-----------------------------------------------------------------*/
3975 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3978 static int label_key=-1;
3982 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3983 pcop->type = PO_LABEL;
3988 sprintf(s=buffer,"_%05d_DS_",key);
3990 s = name, key = label_key--;
3993 pcop->name = Safe_strdup(s);
3995 ((pCodeOpLabel *)pcop)->key = key;
3997 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4001 /*-----------------------------------------------------------------*/
4002 /*-----------------------------------------------------------------*/
4003 pCodeOp *pic16_newpCodeOpLit(int lit)
4009 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4010 pcop->type = PO_LITERAL;
4014 sprintf(s,"0x%02hhx",(char)(lit));
4016 // sprintf(s, "%i", lit);
4019 pcop->name = Safe_strdup(s);
4021 ((pCodeOpLit *)pcop)->lit = lit;
4026 /*-----------------------------------------------------------------*/
4027 /*-----------------------------------------------------------------*/
4028 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4030 char *s = buffer, tbuf[256], *tb=tbuf;
4034 tb = pic16_get_op(arg2, NULL, 0);
4035 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4036 pcop->type = PO_LITERAL;
4040 sprintf(s,"0x%02x, %s",lit, tb);
4042 pcop->name = Safe_strdup(s);
4045 ((pCodeOpLit2 *)pcop)->lit = lit;
4046 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4051 /*-----------------------------------------------------------------*/
4052 /*-----------------------------------------------------------------*/
4053 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4057 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4058 pcop->type = PO_IMMEDIATE;
4060 regs *r = pic16_dirregWithName(name);
4061 pcop->name = Safe_strdup(name);
4065 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4066 PCOI(pcop)->rIdx = r->rIdx;
4068 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4069 PCOI(pcop)->rIdx = -1;
4071 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4076 PCOI(pcop)->index = index;
4077 PCOI(pcop)->offset = offset;
4078 PCOI(pcop)->_const = code_space;
4083 /*-----------------------------------------------------------------*/
4084 /*-----------------------------------------------------------------*/
4085 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4091 if(!pcwb || !subtype) {
4092 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4096 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4097 pcop->type = PO_WILD;
4098 sprintf(s,"%%%d",id);
4099 pcop->name = Safe_strdup(s);
4101 PCOW(pcop)->id = id;
4102 PCOW(pcop)->pcwb = pcwb;
4103 PCOW(pcop)->subtype = subtype;
4104 PCOW(pcop)->matched = NULL;
4106 PCOW(pcop)->pcop2 = NULL;
4111 /*-----------------------------------------------------------------*/
4112 /*-----------------------------------------------------------------*/
4113 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4119 if(!pcwb || !subtype || !subtype2) {
4120 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4124 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4125 pcop->type = PO_WILD;
4126 sprintf(s,"%%%d",id);
4127 pcop->name = Safe_strdup(s);
4129 PCOW(pcop)->id = id;
4130 PCOW(pcop)->pcwb = pcwb;
4131 PCOW(pcop)->subtype = subtype;
4132 PCOW(pcop)->matched = NULL;
4134 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4136 if(!subtype2->name) {
4137 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4138 PCOW2(pcop)->pcop.type = PO_WILD;
4139 sprintf(s, "%%%d", id2);
4140 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4141 PCOW2(pcop)->id = id2;
4142 PCOW2(pcop)->subtype = subtype2;
4144 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4145 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4147 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4149 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4150 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4159 /*-----------------------------------------------------------------*/
4160 /*-----------------------------------------------------------------*/
4161 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4165 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4166 pcop->type = PO_GPR_BIT;
4168 pcop->name = Safe_strdup(s);
4172 PCORB(pcop)->bit = bit;
4173 PCORB(pcop)->inBitSpace = inBitSpace;
4174 PCORB(pcop)->subtype = subt;
4176 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4177 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4178 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4179 // PCOR(pcop)->rIdx = 0;
4184 /*-----------------------------------------------------------------*
4185 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4187 * If rIdx >=0 then a specific register from the set of registers
4188 * will be selected. If rIdx <0, then a new register will be searched
4190 *-----------------------------------------------------------------*/
4192 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4196 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4201 PCOR(pcop)->rIdx = rIdx;
4202 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4204 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4207 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4209 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4210 __FUNCTION__, __LINE__);
4215 pcop->type = PCOR(pcop)->r->pc_type;
4220 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4225 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4226 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4227 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4228 pcop->type = PCOR(pcop)->r->pc_type;
4229 pcop->name = PCOR(pcop)->r->name;
4231 // if(pic16_pcode_verbose) {
4232 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4233 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4239 /*-----------------------------------------------------------------*/
4240 /*-----------------------------------------------------------------*/
4241 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4245 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4248 pcop->key = Safe_strdup( key );
4250 return (PCOP(pcop));
4253 /*-----------------------------------------------------------------*/
4254 /*-----------------------------------------------------------------*/
4255 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4257 pCodeOpLocalReg *pcop;
4259 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4263 return (PCOP(pcop));
4267 /*-----------------------------------------------------------------*/
4268 /*-----------------------------------------------------------------*/
4270 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4277 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4281 pcop = pic16_newpCodeOpLit(-1);
4285 pcop = pic16_newpCodeOpLabel(NULL,-1);
4288 pcop = pic16_newpCodeOpReg(-1);
4291 case PO_GPR_REGISTER:
4293 pcop = pic16_newpCodeOpRegFromStr(name);
4295 pcop = pic16_newpCodeOpReg(-1);
4299 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4302 pcop->name = Safe_strdup(name);
4310 #define DB_ITEMS_PER_LINE 8
4312 typedef struct DBdata
4319 static int DBd_init = -1;
4321 /*-----------------------------------------------------------------*/
4322 /* Initialiase "DB" data buffer */
4323 /*-----------------------------------------------------------------*/
4324 void pic16_initDB(void)
4330 /*-----------------------------------------------------------------*/
4331 /* Flush pending "DB" data to a pBlock */
4333 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4334 /*-----------------------------------------------------------------*/
4335 void pic16_flushDB(char ptype, void *p)
4339 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4342 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4345 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4349 DBd.buffer[0] = '\0';
4354 /*-----------------------------------------------------------------*/
4355 /* Add "DB" directives to a pBlock */
4356 /*-----------------------------------------------------------------*/
4357 void pic16_emitDB(char c, char ptype, void *p)
4362 // we need to initialize
4365 DBd.buffer[0] = '\0';
4368 l = strlen(DBd.buffer);
4369 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4371 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4374 if (DBd.count>= DB_ITEMS_PER_LINE)
4375 pic16_flushDB(ptype, p);
4378 void pic16_emitDS(char *s, char ptype, void *p)
4383 // we need to initialize
4386 DBd.buffer[0] = '\0';
4389 l = strlen(DBd.buffer);
4390 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4392 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4394 DBd.count++; //=strlen(s);
4396 pic16_flushDB(ptype, p);
4400 /*-----------------------------------------------------------------*/
4401 /*-----------------------------------------------------------------*/
4402 void pic16_pCodeConstString(char *name, char *value)
4406 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4411 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4413 pic16_addpBlock(pb);
4415 // sprintf(buffer,"; %s = ", name);
4416 // strcat(buffer, value);
4417 // fputs(buffer, stderr);
4419 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4420 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4423 pic16_emitDB(*value, 'p', (void *)pb);
4425 pic16_flushDB('p', (void *)pb);
4428 /*-----------------------------------------------------------------*/
4429 /*-----------------------------------------------------------------*/
4431 static void pCodeReadCodeTable(void)
4435 fprintf(stderr, " %s\n",__FUNCTION__);
4437 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4439 pic16_addpBlock(pb);
4441 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4442 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4443 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4444 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4446 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4447 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4448 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4449 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4454 /*-----------------------------------------------------------------*/
4455 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4456 /*-----------------------------------------------------------------*/
4457 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4464 /* If this is the first pcode to be added to a block that
4465 * was initialized with a NULL pcode, then go ahead and
4466 * make this pcode the head and tail */
4467 pb->pcHead = pb->pcTail = pc;
4470 pb->pcTail->next = pc;
4472 pc->prev = pb->pcTail;
4479 /*-----------------------------------------------------------------*/
4480 /* pic16_addpBlock - place a pBlock into the pFile */
4481 /*-----------------------------------------------------------------*/
4482 void pic16_addpBlock(pBlock *pb)
4484 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4487 /* First time called, we'll pass through here. */
4488 //_ALLOC(the_pFile,sizeof(pFile));
4489 the_pFile = Safe_calloc(1,sizeof(pFile));
4490 the_pFile->pbHead = the_pFile->pbTail = pb;
4491 the_pFile->functions = NULL;
4495 the_pFile->pbTail->next = pb;
4496 pb->prev = the_pFile->pbTail;
4498 the_pFile->pbTail = pb;
4501 /*-----------------------------------------------------------------*/
4502 /* removepBlock - remove a pBlock from the pFile */
4503 /*-----------------------------------------------------------------*/
4504 static void removepBlock(pBlock *pb)
4512 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4514 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4517 if(pbs == the_pFile->pbHead)
4518 the_pFile->pbHead = pbs->next;
4520 if (pbs == the_pFile->pbTail)
4521 the_pFile->pbTail = pbs->prev;
4524 pbs->next->prev = pbs->prev;
4527 pbs->prev->next = pbs->next;
4534 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4538 /*-----------------------------------------------------------------*/
4539 /* printpCode - write the contents of a pCode to a file */
4540 /*-----------------------------------------------------------------*/
4541 static void printpCode(FILE *of, pCode *pc)
4552 fprintf(of,"warning - unable to print pCode\n");
4555 /*-----------------------------------------------------------------*/
4556 /* pic16_printpBlock - write the contents of a pBlock to a file */
4557 /*-----------------------------------------------------------------*/
4558 void pic16_printpBlock(FILE *of, pBlock *pb)
4566 for(pc = pb->pcHead; pc; pc = pc->next) {
4567 if(isPCF(pc) && PCF(pc)->fname) {
4568 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4569 if(pb->dbName == 'A') {
4571 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4572 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4573 if(!strcmp(ab->name, PCF(pc)->fname)) {
4574 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4575 fprintf(of, "\t0X%06X", ab->address);
4586 /*-----------------------------------------------------------------*/
4588 /* pCode processing */
4592 /*-----------------------------------------------------------------*/
4594 void pic16_unlinkpCode(pCode *pc)
4600 fprintf(stderr,"Unlinking: ");
4601 printpCode(stderr, pc);
4604 pc->prev->next = pc->next;
4606 pc->next->prev = pc->prev;
4608 pc->prev = pc->next = NULL;
4612 /*-----------------------------------------------------------------*/
4613 /*-----------------------------------------------------------------*/
4615 static void genericDestruct(pCode *pc)
4618 pic16_unlinkpCode(pc);
4621 /* For instructions, tell the register (if there's one used)
4622 * that it's no longer needed */
4623 regs *reg = pic16_getRegFromInstruction(pc);
4625 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4627 if(PCI(pc)->is2MemOp) {
4628 reg = pic16_getRegFromInstruction2(pc);
4630 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4634 /* Instead of deleting the memory used by this pCode, mark
4635 * the object as bad so that if there's a pointer to this pCode
4636 * dangling around somewhere then (hopefully) when the type is
4637 * checked we'll catch it.
4641 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4647 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4648 /*-----------------------------------------------------------------*/
4649 /*-----------------------------------------------------------------*/
4650 /* modifiers for constant immediate */
4651 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4653 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4658 int use_buffer = 1; // copy the string to the passed buffer pointer
4663 use_buffer = 0; // Don't bother copying the string to the buffer.
4667 switch(pcop->type) {
4675 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4678 return PCOR(pcop)->r->name;
4681 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4683 SAFE_snprintf(&buffer,&size,"%s",r->name);
4690 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4691 if(PCOI(pcop)->index) {
4692 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4693 immdmod[ PCOI(pcop)->offset ],
4697 SAFE_snprintf(&s,&size,"%s(%s)",
4698 immdmod[ PCOI(pcop)->offset ],
4702 if(PCOI(pcop)->index) {
4703 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4708 SAFE_snprintf(&s,&size, "%s(%s)",
4715 case PO_GPR_REGISTER:
4718 // size = sizeof(buffer);
4719 if( PCOR(pcop)->instance) {
4720 SAFE_snprintf(&s,&size,"(%s + %d)",
4722 PCOR(pcop)->instance );
4724 SAFE_snprintf(&s,&size,"%s",pcop->name);
4731 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4740 return "NO operand1";
4743 /*-----------------------------------------------------------------*/
4744 /* pic16_get_op2 - variant to support two memory operand commands */
4745 /*-----------------------------------------------------------------*/
4746 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4751 int use_buffer = 1; // copy the string to the passed buffer pointer
4756 use_buffer = 0; // Don't bother copying the string to the buffer.
4760 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",
4761 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4762 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4766 switch(PCOR2(pcop)->pcop2->type) {
4774 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4777 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4780 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4783 SAFE_snprintf(&buffer,&size,"%s",r->name);
4794 if(PCOI(pcop)->_const) {
4795 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4796 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4799 8 * PCOI(pcop)->offset );
4801 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4803 if( PCOI(pcop)->index) {
4804 SAFE_snprintf(&s,&size,"(%s + %d)",
4806 PCOI(pcop)->index );
4808 if(PCOI(pcop)->offset)
4809 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4811 SAFE_snprintf(&s,&size,"%s",pcop->name);
4818 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4819 SAFE_snprintf(&s,&size,"(%s + %d)",
4820 PCOR(PCOR2(pcop)->pcop2)->r->name,
4821 PCOR(PCOR2(pcop)->pcop2)->instance );
4823 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4828 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4830 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4833 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4838 return "NO operand2";
4841 /*-----------------------------------------------------------------*/
4842 /*-----------------------------------------------------------------*/
4843 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4847 return pic16_get_op(pcc->pcop,NULL,0);
4849 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4850 * return ("ERROR Null: "__FUNCTION__);
4852 return ("ERROR Null: pic16_get_op_from_instruction");
4856 /*-----------------------------------------------------------------*/
4857 /*-----------------------------------------------------------------*/
4858 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4861 fprintf(of,"pcodeopprint- not implemented\n");
4864 /*-----------------------------------------------------------------*/
4865 /* pic16_pCode2str - convert a pCode instruction to string */
4866 /*-----------------------------------------------------------------*/
4867 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4873 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4874 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4875 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4883 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4885 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4887 if(PCI(pc)->is2MemOp) {
4888 SAFE_snprintf(&s,&size, "%s, %s",
4889 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4890 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4894 if(PCI(pc)->is2LitOp) {
4895 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4899 if(PCI(pc)->isBitInst) {
4900 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4901 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4902 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4903 PCI(pc)->pcop->name ,
4904 PCI(pc)->pcop->name );
4906 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4907 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4908 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4909 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4911 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4912 //PCI(pc)->pcop->t.bit );
4915 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4916 if( PCI(pc)->num_ops == 3)
4917 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4919 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4922 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4924 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4925 if(PCI(pc)->num_ops == 3)
4926 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4928 r = pic16_getRegFromInstruction(pc);
4929 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4930 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4932 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4941 /* assuming that comment ends with a \n */
4942 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4946 SAFE_snprintf(&s,&size,"; info ==>");
4947 switch(((pCodeInfo *)pc)->type) {
4948 case INF_OPTIMIZATION:
4949 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4952 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
4957 /* assuming that inline code ends with a \n */
4958 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4962 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4965 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4968 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4971 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4974 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4975 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4976 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4979 if(PCAD(pc)->directive) {
4980 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4983 /* special case to handle inline labels without a tab */
4984 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4989 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4997 /*-----------------------------------------------------------------*/
4998 /* genericPrint - the contents of a pCode to a file */
4999 /*-----------------------------------------------------------------*/
5000 static void genericPrint(FILE *of, pCode *pc)
5008 // fputs(((pCodeComment *)pc)->comment, of);
5009 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5014 pBranch *pbl = PCI(pc)->label;
5015 while(pbl && pbl->pc) {
5016 if(pbl->pc->type == PC_LABEL)
5017 pCodePrintLabel(of, pbl->pc);
5022 fprintf(of, "; info ==>");
5023 switch(((pCodeInfo *)pc)->type) {
5024 case INF_OPTIMIZATION:
5025 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5028 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5033 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5037 // If the opcode has a label, print that first
5039 pBranch *pbl = PCI(pc)->label;
5040 while(pbl && pbl->pc) {
5041 if(pbl->pc->type == PC_LABEL)
5042 pCodePrintLabel(of, pbl->pc);
5048 genericPrint(of,PCODE(PCI(pc)->cline));
5053 pic16_pCode2str(str, 256, pc);
5055 fprintf(of,"%s",str);
5057 if(pic16_debug_verbose) {
5058 fprintf(of, "\t;key=%03x",pc->seq);
5060 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5067 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5068 if(PCW(pc)->pci.label)
5069 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5071 if(PCW(pc)->operand) {
5072 fprintf(of,";\toperand ");
5073 pCodeOpPrint(of,PCW(pc)->operand );
5078 if(pic16_debug_verbose) {
5079 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5080 if(PCFL(pc)->ancestor)
5081 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5088 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5089 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5090 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5096 pBranch *pbl = PCAD(pc)->pci.label;
5097 while(pbl && pbl->pc) {
5098 if(pbl->pc->type == PC_LABEL)
5099 pCodePrintLabel(of, pbl->pc);
5103 if(PCAD(pc)->directive) {
5104 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5107 /* special case to handle inline labels without tab */
5108 fprintf(of, "%s\n", PCAD(pc)->arg);
5114 fprintf(of,"unknown pCode type %d\n",pc->type);
5119 /*-----------------------------------------------------------------*/
5120 /* pCodePrintFunction - prints function begin/end */
5121 /*-----------------------------------------------------------------*/
5123 static void pCodePrintFunction(FILE *of, pCode *pc)
5130 if( ((pCodeFunction *)pc)->modname)
5131 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5134 if(!PCF(pc)->absblock) {
5135 if(PCF(pc)->fname) {
5136 pBranch *exits = PCF(pc)->to;
5139 fprintf(of,"%s:", PCF(pc)->fname);
5141 if(pic16_pcode_verbose)
5142 fprintf(of, "\t;Function start");
5148 exits = exits->next;
5152 if(pic16_pcode_verbose)
5153 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5156 if((PCF(pc)->from &&
5157 PCF(pc)->from->pc->type == PC_FUNCTION &&
5158 PCF(PCF(pc)->from->pc)->fname) ) {
5160 if(pic16_pcode_verbose)
5161 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5163 if(pic16_pcode_verbose)
5164 fprintf(of,"; exit point [can't find entry point]\n");
5170 /*-----------------------------------------------------------------*/
5171 /* pCodePrintLabel - prints label */
5172 /*-----------------------------------------------------------------*/
5174 static void pCodePrintLabel(FILE *of, pCode *pc)
5181 fprintf(of,"%s:\n",PCL(pc)->label);
5182 else if (PCL(pc)->key >=0)
5183 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5185 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5188 /*-----------------------------------------------------------------*/
5189 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5190 /* remove it if it is found. */
5191 /*-----------------------------------------------------------------*/
5192 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5199 if(pcl->type == PC_OPCODE)
5200 b = PCI(pcl)->label;
5202 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5207 //fprintf (stderr, "%s \n",__FUNCTION__);
5208 //pcl->print(stderr,pcl);
5209 //pc->print(stderr,pc);
5212 //fprintf (stderr, "found label\n");
5213 //pc->print(stderr, pc);
5217 bprev->next = b->next; /* Not first pCode in chain */
5221 PCI(pcl)->label = b->next; /* First pCode in chain */
5224 return; /* A label can't occur more than once */
5232 /*-----------------------------------------------------------------*/
5233 /*-----------------------------------------------------------------*/
5234 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5253 /*-----------------------------------------------------------------*/
5254 /* pBranchLink - given two pcodes, this function will link them */
5255 /* together through their pBranches */
5256 /*-----------------------------------------------------------------*/
5257 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5261 // Declare a new branch object for the 'from' pCode.
5263 //_ALLOC(b,sizeof(pBranch));
5264 b = Safe_calloc(1,sizeof(pBranch));
5265 b->pc = PCODE(t); // The link to the 'to' pCode.
5268 f->to = pic16_pBranchAppend(f->to,b);
5270 // Now do the same for the 'to' pCode.
5272 //_ALLOC(b,sizeof(pBranch));
5273 b = Safe_calloc(1,sizeof(pBranch));
5277 t->from = pic16_pBranchAppend(t->from,b);
5282 /*-----------------------------------------------------------------*/
5283 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5285 /*-----------------------------------------------------------------*/
5286 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5299 /*-----------------------------------------------------------------*/
5300 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5301 /*-----------------------------------------------------------------*/
5302 void pic16_pCodeUnlink(pCode *pc)
5307 if(!pc->prev || !pc->next) {
5308 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5312 /* first remove the pCode from the chain */
5313 pc->prev->next = pc->next;
5314 pc->next->prev = pc->prev;
5316 /* Now for the hard part... */
5318 /* Remove the branches */
5320 pb1 = PCI(pc)->from;
5322 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5323 * one we're unlinking */
5325 /* search for the link back to this pCode (the one we're
5327 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5328 pb2->pc = PCI(pc)->to->pc; // make the replacement
5330 /* if the pCode we're unlinking contains multiple 'to'
5331 * branches (e.g. this a skip instruction) then we need
5332 * to copy these extra branches to the chain. */
5333 if(PCI(pc)->to->next)
5334 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5343 /*-----------------------------------------------------------------*/
5344 /*-----------------------------------------------------------------*/
5346 static void genericAnalyze(pCode *pc)
5356 // Go through the pCodes that are in pCode chain and link
5357 // them together through the pBranches. Note, the pCodes
5358 // are linked together as a contiguous stream like the
5359 // assembly source code lines. The linking here mimics this
5360 // except that comments are not linked in.
5362 pCode *npc = pc->next;
5364 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5365 pBranchLink(pc,npc);
5370 /* reached the end of the pcode chain without finding
5371 * an instruction we could link to. */
5375 fprintf(stderr,"analyze PC_FLOW\n");
5379 fprintf(stderr,,";A bad pCode is being used\n");
5385 /*-----------------------------------------------------------------*/
5386 /*-----------------------------------------------------------------*/
5387 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5391 if(pc->type == PC_LABEL) {
5392 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5395 if((pc->type == PC_OPCODE)
5396 || (pc->type == PC_ASMDIR)
5398 pbr = PCI(pc)->label;
5400 if(pbr->pc->type == PC_LABEL) {
5401 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5411 /*-----------------------------------------------------------------*/
5412 /*-----------------------------------------------------------------*/
5413 static int checkLabel(pCode *pc)
5417 if(pc && isPCI(pc)) {
5418 pbr = PCI(pc)->label;
5420 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5430 /*-----------------------------------------------------------------*/
5431 /* findLabelinpBlock - Search the pCode for a particular label */
5432 /*-----------------------------------------------------------------*/
5433 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5440 for(pc = pb->pcHead; pc; pc = pc->next)
5441 if(compareLabel(pc,pcop_label))
5447 /*-----------------------------------------------------------------*/
5448 /* findLabel - Search the pCode for a particular label */
5449 /*-----------------------------------------------------------------*/
5450 static pCode * findLabel(pCodeOpLabel *pcop_label)
5458 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5459 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5463 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5467 /*-----------------------------------------------------------------*/
5468 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5469 /* in the linked list */
5470 /*-----------------------------------------------------------------*/
5471 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5484 /*-----------------------------------------------------------------*/
5485 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5486 /* in the linked list */
5487 /*-----------------------------------------------------------------*/
5488 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5502 //#define PCODE_DEBUG
5503 /*-----------------------------------------------------------------*/
5504 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5505 /* in the linked list */
5506 /*-----------------------------------------------------------------*/
5507 pCode * pic16_findNextInstruction(pCode *pci)
5512 if((pc->type == PC_OPCODE)
5513 || (pc->type == PC_WILD)
5514 || (pc->type == PC_ASMDIR)
5519 fprintf(stderr,"pic16_findNextInstruction: ");
5520 printpCode(stderr, pc);
5525 //fprintf(stderr,"Couldn't find instruction\n");
5529 /*-----------------------------------------------------------------*/
5530 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5531 /* in the linked list */
5532 /*-----------------------------------------------------------------*/
5533 pCode * pic16_findPrevInstruction(pCode *pci)
5539 if((pc->type == PC_OPCODE)
5540 || (pc->type == PC_WILD)
5541 || (pc->type == PC_ASMDIR)
5547 fprintf(stderr,"pic16_findPrevInstruction: ");
5548 printpCode(stderr, pc);
5553 //fprintf(stderr,"Couldn't find instruction\n");
5560 /*-----------------------------------------------------------------*/
5561 /* findFunctionEnd - given a pCode find the end of the function */
5562 /* that contains it */
5563 /*-----------------------------------------------------------------*/
5564 static pCode * findFunctionEnd(pCode *pc)
5568 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5574 fprintf(stderr,"Couldn't find function end\n");
5579 /*-----------------------------------------------------------------*/
5580 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5581 /* instruction with which it is associated. */
5582 /*-----------------------------------------------------------------*/
5583 static void AnalyzeLabel(pCode *pc)
5586 pic16_pCodeUnlink(pc);
5592 static void AnalyzeGOTO(pCode *pc)
5595 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5599 static void AnalyzeSKIP(pCode *pc)
5602 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5603 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5607 static void AnalyzeRETURN(pCode *pc)
5610 // branch_link(pc,findFunctionEnd(pc->next));
5616 /*-----------------------------------------------------------------*/
5617 /*-----------------------------------------------------------------*/
5618 regs * pic16_getRegFromInstruction(pCode *pc)
5624 PCI(pc)->num_ops == 0 ||
5625 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5629 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5630 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5633 switch(PCI(pc)->pcop->type) {
5639 return PCOR(PCI(pc)->pcop)->r;
5643 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5644 return PCOR(PCI(pc)->pcop)->r;
5647 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5649 if(PCOI(PCI(pc)->pcop)->r)
5650 return (PCOI(PCI(pc)->pcop)->r);
5655 return PCOR(PCI(pc)->pcop)->r;
5657 case PO_GPR_REGISTER:
5659 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5660 return PCOR(PCI(pc)->pcop)->r;
5663 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5667 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5668 // genericPrint(stderr, pc);
5676 /*-------------------------------------------------------------------------------*/
5677 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5678 /*-------------------------------------------------------------------------------*/
5679 regs * pic16_getRegFromInstruction2(pCode *pc)
5685 PCI(pc)->num_ops == 0 ||
5686 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5691 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5692 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5696 * operands supported in MOVFF:
5703 switch(PCI(pc)->pcop->type) {
5709 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5711 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5715 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5716 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5720 // if(PCOI(PCI(pc)->pcop)->r)
5721 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5723 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5724 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5727 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5728 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5735 // return PCOR2(PCI(pc)->pcop)->r;
5737 case PO_GPR_REGISTER:
5739 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5740 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5744 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5747 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5748 //genericPrint(stderr, pc);
5756 /*-----------------------------------------------------------------*/
5757 /*-----------------------------------------------------------------*/
5759 static void AnalyzepBlock(pBlock *pb)
5766 /* Find all of the registers used in this pBlock
5767 * by looking at each instruction and examining it's
5770 for(pc = pb->pcHead; pc; pc = pc->next) {
5772 /* Is this an instruction with operands? */
5773 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5775 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5777 /* Loop through all of the registers declared so far in
5778 this block and see if we find this one there */
5780 regs *r = setFirstItem(pb->tregisters);
5783 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5784 PCOR(PCI(pc)->pcop)->r = r;
5787 r = setNextItem(pb->tregisters);
5791 /* register wasn't found */
5792 //r = Safe_calloc(1, sizeof(regs));
5793 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5794 //addSet(&pb->tregisters, r);
5795 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5796 //PCOR(PCI(pc)->pcop)->r = r;
5797 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5799 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5802 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5803 if(PCOR(PCI(pc)->pcop)->r) {
5804 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5805 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5807 if(PCI(pc)->pcop->name)
5808 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5810 fprintf(stderr,"ERROR: NULL register\n");
5819 /*-----------------------------------------------------------------*/
5821 /*-----------------------------------------------------------------*/
5822 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5824 static void InsertpFlow(pCode *pc, pCode **pflow)
5827 PCFL(*pflow)->end = pc;
5829 if(!pc || !pc->next)
5832 *pflow = pic16_newpCodeFlow();
5833 pic16_pCodeInsertAfter(pc, *pflow);
5836 /*-----------------------------------------------------------------*/
5837 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5838 /* the flow blocks. */
5840 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5841 * point the instruction flow changes.
5843 /*-----------------------------------------------------------------*/
5844 void pic16_BuildFlow(pBlock *pb)
5847 pCode *last_pci=NULL;
5854 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5855 /* Insert a pCodeFlow object at the beginning of a pBlock */
5857 InsertpFlow(pb->pcHead, &pflow);
5859 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5860 //pflow->next = pb->pcHead; /* Make the current head the next object */
5861 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5862 //pb->pcHead = pflow; /* Make the Flow object the head */
5865 for( pc = pic16_findNextInstruction(pb->pcHead);
5867 pc=pic16_findNextInstruction(pc)) {
5870 PCI(pc)->pcflow = PCFL(pflow);
5872 //fprintf(stderr," build: ");
5873 //pflow->print(stderr,pflow);
5875 if( PCI(pc)->isSkip) {
5877 /* The two instructions immediately following this one
5878 * mark the beginning of a new flow segment */
5880 while(pc && PCI(pc)->isSkip) {
5882 PCI(pc)->pcflow = PCFL(pflow);
5886 InsertpFlow(pc, &pflow);
5887 pc=pic16_findNextInstruction(pc->next);
5895 PCI(pc)->pcflow = PCFL(pflow);
5897 InsertpFlow(pc, &pflow);
5899 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5901 InsertpFlow(pc, &pflow);
5904 } else if (checkLabel(pc)) {
5906 /* This instruction marks the beginning of a
5907 * new flow segment */
5912 /* If the previous pCode is not a flow object, then
5913 * insert a new flow object. (This check prevents
5914 * two consecutive flow objects from being insert in
5915 * the case where a skip instruction preceeds an
5916 * instruction containing a label.) */
5918 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5919 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5921 PCI(pc)->pcflow = PCFL(pflow);
5928 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5930 PCFL(pflow)->end = pb->pcTail;
5933 /*-------------------------------------------------------------------*/
5934 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5935 /* the flow blocks. */
5937 * unBuildFlow removes pCodeFlow objects from a pCode chain
5939 /*-----------------------------------------------------------------*/
5940 static void unBuildFlow(pBlock *pb)
5955 if(PCI(pc)->pcflow) {
5956 //free(PCI(pc)->pcflow);
5957 PCI(pc)->pcflow = NULL;
5960 } else if(isPCFL(pc) )
5969 /*-----------------------------------------------------------------*/
5970 /*-----------------------------------------------------------------*/
5971 static void dumpCond(int cond)
5974 static char *pcc_str[] = {
5988 int ncond = sizeof(pcc_str) / sizeof(char *);
5991 fprintf(stderr, "0x%04X\n",cond);
5993 for(i=0,j=1; i<ncond; i++, j<<=1)
5995 fprintf(stderr, " %s\n",pcc_str[i]);
6001 /*-----------------------------------------------------------------*/
6002 /*-----------------------------------------------------------------*/
6003 static void FlowStats(pCodeFlow *pcflow)
6011 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6013 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6016 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6021 fprintf(stderr, " FlowStats inCond: ");
6022 dumpCond(pcflow->inCond);
6023 fprintf(stderr, " FlowStats outCond: ");
6024 dumpCond(pcflow->outCond);
6028 /*-----------------------------------------------------------------*
6029 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6030 * if it affects the banking bits.
6032 * return: -1 == Banking bits are unaffected by this pCode.
6034 * return: > 0 == Banking bits are affected.
6036 * If the banking bits are affected, then the returned value describes
6037 * which bits are affected and how they're affected. The lower half
6038 * of the integer maps to the bits that are affected, the upper half
6039 * to whether they're set or cleared.
6041 *-----------------------------------------------------------------*/
6043 static int isBankInstruction(pCode *pc)
6051 if( PCI(pc)->op == POC_MOVLB ||
6052 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6053 bank = PCOL(pc)->lit;
6060 /*-----------------------------------------------------------------*/
6061 /*-----------------------------------------------------------------*/
6062 static void FillFlow(pCodeFlow *pcflow)
6071 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6073 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6076 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6083 isBankInstruction(pc);
6085 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6089 fprintf(stderr, " FillFlow - Bad end of flow\n");
6091 fprintf(stderr, " FillFlow - Ending flow with\n ");
6092 pc->print(stderr,pc);
6095 fprintf(stderr, " FillFlow inCond: ");
6096 dumpCond(pcflow->inCond);
6097 fprintf(stderr, " FillFlow outCond: ");
6098 dumpCond(pcflow->outCond);
6102 /*-----------------------------------------------------------------*/
6103 /*-----------------------------------------------------------------*/
6104 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6106 pCodeFlowLink *fromLink, *toLink;
6108 if(!from || !to || !to->pcflow || !from->pcflow)
6111 fromLink = pic16_newpCodeFlowLink(from->pcflow);
6112 toLink = pic16_newpCodeFlowLink(to->pcflow);
6114 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6115 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6119 /*-----------------------------------------------------------------*
6120 * void LinkFlow(pBlock *pb)
6122 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6123 * non-branching segments. In LinkFlow, we determine the execution
6124 * order of these segments. For example, if one of the segments ends
6125 * with a skip, then we know that there are two possible flow segments
6126 * to which control may be passed.
6127 *-----------------------------------------------------------------*/
6128 static void LinkFlow(pBlock *pb)
6134 //fprintf(stderr,"linkflow \n");
6136 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6138 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6141 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6143 //fprintf(stderr," link: ");
6144 //pcflow->print(stderr,pcflow);
6146 //FillFlow(PCFL(pcflow));
6148 pc = PCFL(pcflow)->end;
6150 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6151 if(isPCI_SKIP(pc)) {
6152 //fprintf(stderr, "ends with skip\n");
6153 //pc->print(stderr,pc);
6154 pct=pic16_findNextInstruction(pc->next);
6155 LinkFlow_pCode(PCI(pc),PCI(pct));
6156 pct=pic16_findNextInstruction(pct->next);
6157 LinkFlow_pCode(PCI(pc),PCI(pct));
6161 if(isPCI_BRANCH(pc)) {
6162 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6164 //fprintf(stderr, "ends with branch\n ");
6165 //pc->print(stderr,pc);
6167 if(!(pcol && isPCOLAB(pcol))) {
6168 if((PCI(pc)->op != POC_RETLW)
6169 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6171 /* continue if label is '$' which assembler knows how to parse */
6172 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6174 if(pic16_pcode_verbose) {
6175 pc->print(stderr,pc);
6176 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6182 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6183 LinkFlow_pCode(PCI(pc),PCI(pct));
6185 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6186 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6188 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6194 //fprintf(stderr, "ends with non-branching instruction:\n");
6195 //pc->print(stderr,pc);
6197 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6203 //fprintf(stderr, "ends with unknown\n");
6204 //pc->print(stderr,pc);
6208 //fprintf(stderr, "ends with nothing: ERROR\n");
6212 /*-----------------------------------------------------------------*/
6213 /*-----------------------------------------------------------------*/
6215 /*-----------------------------------------------------------------*/
6216 /*-----------------------------------------------------------------*/
6217 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6223 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6226 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6236 /*-----------------------------------------------------------------*/
6237 /* insertBankSwitch - inserts a bank switch statement in the */
6238 /* assembly listing */
6240 /* position == 0: insert before */
6241 /* position == 1: insert after pc */
6242 /* position == 2: like 0 but previous was a skip instruction */
6243 /*-----------------------------------------------------------------*/
6244 pCodeOp *pic16_popGetLabel(unsigned int key);
6245 extern int pic16_labelOffset;
6247 static void insertBankSwitch(unsigned char position, pCode *pc)
6254 /* emit BANKSEL [symbol] */
6257 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6259 // position = 0; // position is always before (sanity check!)
6262 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6263 pc->print(stderr, pc);
6268 /* insert the bank switch after this pc instruction */
6269 pCode *pcnext = pic16_findNextInstruction(pc);
6271 pic16_pCodeInsertAfter(pc, new_pc);
6272 if(pcnext)pc = pcnext;
6276 /* insert the bank switch BEFORE this pc instruction */
6277 pic16_pCodeInsertAfter(pc->prev, new_pc);
6282 pCode *pcnext, *pcprev, *npci, *ppc;
6284 int ofs1=0, ofs2=0, len=0;
6286 /* just like 0, but previous was a skip instruction,
6287 * so some care should be taken */
6289 pic16_labelOffset += 10000;
6290 tlbl = newiTempLabel(NULL);
6292 /* invert skip instruction */
6293 pcprev = pic16_findPrevInstruction(pc->prev);
6294 ipci = PCI(pcprev)->inverted_op;
6295 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6297 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6299 /* copy info from old pCode */
6300 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6301 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6302 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6303 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6304 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6305 PCI(npci)->op = PCI(pcprev)->inverted_op;
6307 /* unlink old pCode */
6309 ppc->next = pcprev->next;
6310 pcprev->next->prev = ppc;
6311 pic16_pCodeInsertAfter(ppc, npci);
6313 /* extra instructions to handle invertion */
6314 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6315 pic16_pCodeInsertAfter(npci, pcnext);
6316 pic16_pCodeInsertAfter(pc->prev, new_pc);
6318 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6319 pic16_pCodeInsertAfter(pc, pcnext);
6324 /* Move the label, if there is one */
6325 if(PCI(pc)->label) {
6326 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6327 // __FILE__, __LINE__, pc, new_pc);
6328 PCAD(new_pc)->pci.label = PCI(pc)->label;
6329 PCI(pc)->label = NULL;
6334 /*-----------------------------------------------------------------*/
6335 /*int compareBankFlow - compare the banking requirements between */
6337 /*-----------------------------------------------------------------*/
6338 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6341 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6344 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6347 if(pcflow->firstBank == -1)
6351 if(pcflowLink->pcflow->firstBank == -1) {
6352 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6353 pcflowLink->pcflow->to :
6354 pcflowLink->pcflow->from);
6355 return compareBankFlow(pcflow, pctl, toORfrom);
6359 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6362 pcflowLink->bank_conflict++;
6363 pcflowLink->pcflow->FromConflicts++;
6364 pcflow->ToConflicts++;
6367 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6370 pcflowLink->bank_conflict++;
6371 pcflowLink->pcflow->ToConflicts++;
6372 pcflow->FromConflicts++;
6376 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6377 pcflowLink->pcflow->pc.seq,
6378 pcflowLink->pcflow->FromConflicts,
6379 pcflowLink->pcflow->ToConflicts);
6386 /*-----------------------------------------------------------------*/
6387 /*-----------------------------------------------------------------*/
6388 static void DumpFlow(pBlock *pb)
6392 pCodeFlowLink *pcfl;
6395 fprintf(stderr,"Dump flow \n");
6396 pb->pcHead->print(stderr, pb->pcHead);
6398 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6399 pcflow->print(stderr,pcflow);
6401 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6403 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6405 if(!isPCFL(pcflow)) {
6406 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6409 fprintf(stderr,"dumping: ");
6410 pcflow->print(stderr,pcflow);
6411 FlowStats(PCFL(pcflow));
6413 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6415 pc = PCODE(pcfl->pcflow);
6417 fprintf(stderr, " from seq %d:\n",pc->seq);
6419 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6420 pc->print(stderr,pc);
6425 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6427 pc = PCODE(pcfl->pcflow);
6429 fprintf(stderr, " to seq %d:\n",pc->seq);
6431 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6432 pc->print(stderr,pc);
6441 /*-----------------------------------------------------------------*/
6442 /*-----------------------------------------------------------------*/
6443 static int OptimizepBlock(pBlock *pb)
6448 if(!pb || !peepOptimizing)
6451 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6453 for(pc = pb->pcHead; pc; pc = pc->next)
6454 matches += pic16_pCodePeepMatchRule(pc);
6457 pc = pic16_findNextInstruction(pb->pcHead);
6465 if(pic16_pCodePeepMatchRule(pc)) {
6470 pc = pic16_findNextInstruction(pcprev->next);
6472 pc = pic16_findNextInstruction(pb->pcHead);
6474 pc = pic16_findNextInstruction(pc->next);
6478 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6483 /*-----------------------------------------------------------------*/
6484 /*-----------------------------------------------------------------*/
6485 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6489 for(pc = pcs; pc; pc = pc->next) {
6491 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6493 (PCI(pc)->pcop->type == PO_LABEL) &&
6494 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6502 /*-----------------------------------------------------------------*/
6503 /*-----------------------------------------------------------------*/
6504 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6511 (PCI(pc)->pcop->type == PO_LABEL)) {
6513 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6515 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6516 // if(pcol->pcop.name)
6517 // free(pcol->pcop.name);
6519 /* If the key is negative, then we (probably) have a label to
6520 * a function and the name is already defined */
6523 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6527 //sprintf(buffer,"_%05d_DS_",pcl->key);
6529 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6531 pcol->pcop.name = Safe_strdup(s);
6532 pcol->key = pcl->key;
6533 //pc->print(stderr,pc);
6540 /*-----------------------------------------------------------------*/
6541 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6542 /* pCode chain if they're not used. */
6543 /*-----------------------------------------------------------------*/
6544 static void pBlockRemoveUnusedLabels(pBlock *pb)
6546 pCode *pc; pCodeLabel *pcl;
6551 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6553 pBranch *pbr = PCI(pc)->label;
6554 if(pbr && pbr->next) {
6555 pCode *pcd = pb->pcHead;
6557 // fprintf(stderr, "multiple labels\n");
6558 // pc->print(stderr,pc);
6563 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6564 //fprintf(stderr,"Used by:\n");
6565 //pcd->print(stderr,pcd);
6567 exchangeLabels(PCL(pbr->pc),pcd);
6576 for(pc = pb->pcHead; pc; pc = pc->next) {
6578 if(isPCL(pc)) // pc->type == PC_LABEL)
6580 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6581 pcl = PCL(PCI(pc)->label->pc);
6584 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6586 /* This pCode is a label, so search the pBlock to see if anyone
6589 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6591 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6592 /* Couldn't find an instruction that refers to this label
6593 * So, unlink the pCode label from it's pCode chain
6594 * and destroy the label */
6595 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6597 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6598 if(pc->type == PC_LABEL) {
6599 pic16_unlinkpCode(pc);
6600 pCodeLabelDestruct(pc);
6602 unlinkpCodeFromBranch(pc, PCODE(pcl));
6603 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6614 /*-----------------------------------------------------------------*/
6615 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6616 /* chain and put them into pBranches that are */
6617 /* associated with the appropriate pCode */
6619 /*-----------------------------------------------------------------*/
6620 void pic16_pBlockMergeLabels(pBlock *pb)
6623 pCode *pc, *pcnext=NULL;
6628 /* First, Try to remove any unused labels */
6629 //pBlockRemoveUnusedLabels(pb);
6631 /* Now loop through the pBlock and merge the labels with the opcodes */
6634 // for(pc = pb->pcHead; pc; pc = pc->next) {
6637 pCode *pcn = pc->next;
6639 if(pc->type == PC_LABEL) {
6641 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6642 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6644 if((pcnext = pic16_findNextInstruction(pc) )) {
6646 // pcnext->print(stderr, pcnext);
6648 // Unlink the pCode label from it's pCode chain
6649 pic16_unlinkpCode(pc);
6651 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6652 // And link it into the instruction's pBranch labels. (Note, since
6653 // it's possible to have multiple labels associated with one instruction
6654 // we must provide a means to accomodate the additional labels. Thus
6655 // the labels are placed into the singly-linked list "label" as
6656 // opposed to being a single member of the pCodeInstruction.)
6658 //_ALLOC(pbr,sizeof(pBranch));
6660 pbr = Safe_calloc(1,sizeof(pBranch));
6664 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6667 if(pic16_pcode_verbose)
6668 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6670 } else if(pc->type == PC_CSOURCE) {
6672 /* merge the source line symbolic info into the next instruction */
6673 if((pcnext = pic16_findNextInstruction(pc) )) {
6675 // Unlink the pCode label from it's pCode chain
6676 pic16_unlinkpCode(pc);
6677 PCI(pcnext)->cline = PCCS(pc);
6678 //fprintf(stderr, "merging CSRC\n");
6679 //genericPrint(stderr,pcnext);
6685 pBlockRemoveUnusedLabels(pb);
6689 /*-----------------------------------------------------------------*/
6690 /*-----------------------------------------------------------------*/
6691 static int OptimizepCode(char dbName)
6693 #define MAX_PASSES 4
6702 DFPRINTF((stderr," Optimizing pCode\n"));
6706 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6707 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6708 matches += OptimizepBlock(pb);
6711 while(matches && ++passes < MAX_PASSES);
6718 const char *pic16_pCodeOpType(pCodeOp *pcop);
6719 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6722 /*-----------------------------------------------------------------*/
6723 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6724 /*-----------------------------------------------------------------*/
6726 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6730 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6731 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6733 if( !( (pcop->type == PO_LABEL) ||
6734 (pcop->type == PO_LITERAL) ||
6735 (pcop->type == PO_STR) ))
6736 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6737 PCOR(pcop)->r->wasUsed = 1;
6743 /*----------------------------------------------------------------------*
6744 * pic16_areRegsSame - check to see if the names of two registers match *
6745 *----------------------------------------------------------------------*/
6746 int pic16_areRegsSame(regs *r1, regs *r2)
6748 if(!strcmp(r1->name, r2->name))return 1;
6754 /*-----------------------------------------------------------------*/
6755 /*-----------------------------------------------------------------*/
6756 static void pic16_FixRegisterBanking(pBlock *pb)
6760 regs *reg, *prevreg;
6761 unsigned char flag=0;
6766 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6769 /* loop through all of the flow blocks with in one pblock */
6771 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6775 /* at this point, pc should point to a PC_FLOW object */
6776 /* for each flow block, determine the register banking
6780 /* if label, then might come from other point, force banksel */
6781 if(isPCL(pc))prevreg = NULL;
6783 if(!isPCI(pc))goto loop;
6785 if(PCI(pc)->label)prevreg = NULL;
6787 if(PCI(pc)->is2MemOp)goto loop;
6789 /* if goto, then force banksel */
6790 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6792 reg = pic16_getRegFromInstruction(pc);
6795 pc->print(stderr, pc);
6796 fprintf(stderr, "reg = %p\n", reg);
6799 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6800 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6801 reg->address,reg->isBitField, reg->isFixed);
6805 /* now make some tests to make sure that instruction needs bank switch */
6807 /* if no register exists, and if not a bit opcode goto loop */
6809 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6812 if(isPCI_SKIP(pc)) {
6813 // fprintf(stderr, "instruction is SKIP instruction\n");
6816 if(reg && isACCESS_BANK(reg))goto loop;
6818 if(!isBankInstruction(pc))goto loop;
6820 if(isPCI_LIT(pc))goto loop;
6822 if(PCI(pc)->op == POC_CALL)goto loop;
6824 /* Examine the instruction before this one to make sure it is
6825 * not a skip type instruction */
6826 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6828 flag = 0; /* add before this instruction */
6830 /* if previous instruction is a skip one, then set flag
6831 * to 2 and call insertBankSwitch */
6832 if(pcprev && isPCI_SKIP(pcprev)) {
6837 if(pic16_options.opt_banksel>0) {
6838 char op1[128], op2[128];
6841 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6842 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6843 if(!strcmp(op1, op2))goto loop;
6847 insertBankSwitch(flag, pc);
6849 // fprintf(stderr, "BANK SWITCH inserted\n");
6859 static void pBlockDestruct(pBlock *pb)
6870 /*-----------------------------------------------------------------*/
6871 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6872 /* name dbName and combine them */
6873 /* into one block */
6874 /*-----------------------------------------------------------------*/
6875 static void mergepBlocks(char dbName)
6878 pBlock *pb, *pbmerged = NULL,*pbn;
6880 pb = the_pFile->pbHead;
6882 //fprintf(stderr," merging blocks named %c\n",dbName);
6886 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6887 if( getpBlock_dbName(pb) == dbName) {
6889 //fprintf(stderr," merged block %c\n",dbName);
6894 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6895 /* pic16_addpCode2pBlock doesn't handle the tail: */
6896 pbmerged->pcTail = pb->pcTail;
6898 pb->prev->next = pbn;
6900 pbn->prev = pb->prev;
6905 //pic16_printpBlock(stderr, pbmerged);
6912 /*-----------------------------------------------------------------*/
6913 /* AnalyzeFlow - Examine the flow of the code and optimize */
6915 /* level 0 == minimal optimization */
6916 /* optimize registers that are used only by two instructions */
6917 /* level 1 == maximal optimization */
6918 /* optimize by looking at pairs of instructions that use the */
6920 /*-----------------------------------------------------------------*/
6922 static void AnalyzeFlow(int level)
6924 static int times_called=0;
6929 /* remove unused allocated registers before exiting */
6930 pic16_RemoveUnusedRegisters();
6936 /* if this is not the first time this function has been called,
6937 then clean up old flow information */
6938 if(times_called++) {
6939 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6942 pic16_RegsUnMapLiveRanges();
6947 /* Phase 2 - Flow Analysis - Register Banking
6949 * In this phase, the individual flow blocks are examined
6950 * and register banking is fixed.
6954 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6955 pic16_FixRegisterBanking(pb);
6958 /* Phase 2 - Flow Analysis
6960 * In this phase, the pCode is partition into pCodeFlow
6961 * blocks. The flow blocks mark the points where a continuous
6962 * stream of instructions changes flow (e.g. because of
6963 * a call or goto or whatever).
6966 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6967 pic16_BuildFlow(pb);
6970 /* Phase 2 - Flow Analysis - linking flow blocks
6972 * In this phase, the individual flow blocks are examined
6973 * to determine their order of excution.
6976 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6979 /* Phase 3 - Flow Analysis - Flow Tree
6981 * In this phase, the individual flow blocks are examined
6982 * to determine their order of execution.
6985 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6986 pic16_BuildFlowTree(pb);
6989 /* Phase x - Flow Analysis - Used Banks
6991 * In this phase, the individual flow blocks are examined
6992 * to determine the Register Banks they use
6996 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7001 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7002 pic16_pCodeRegMapLiveRanges(pb);
7004 pic16_RemoveUnusedRegisters();
7006 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7007 pic16_pCodeRegOptimizeRegUsage(level);
7015 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7020 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7022 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7023 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7024 pcflow = pcflow->next) {
7026 FillFlow(PCFL(pcflow));
7031 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7034 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7035 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7036 pcflow = pcflow->next) {
7038 FlowStats(PCFL(pcflow));
7044 /* VR -- no need to analyze banking in flow, but left here :
7045 * 1. because it may be used in the future for other purposes
7046 * 2. because if omitted we'll miss some optimization done here
7048 * Perhaps I should rename it to something else
7051 /*-----------------------------------------------------------------*/
7052 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7053 /* assigned to the registers. */
7055 /*-----------------------------------------------------------------*/
7057 void pic16_AnalyzeBanking(void)
7062 /* Phase x - Flow Analysis - Used Banks
7064 * In this phase, the individual flow blocks are examined
7065 * to determine the Register Banks they use
7071 if(!the_pFile)return;
7073 if(!pic16_options.no_banksel) {
7074 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7075 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7076 pic16_FixRegisterBanking(pb);
7082 /*-----------------------------------------------------------------*/
7083 /* buildCallTree - Look at the flow and extract all of the calls. */
7084 /*-----------------------------------------------------------------*/
7085 static set *register_usage(pBlock *pb);
7087 static void buildCallTree(void )
7099 /* Now build the call tree.
7100 First we examine all of the pCodes for functions.
7101 Keep in mind that the function boundaries coincide
7102 with pBlock boundaries.
7104 The algorithm goes something like this:
7105 We have two nested loops. The outer loop iterates
7106 through all of the pBlocks/functions. The inner
7107 loop iterates through all of the pCodes for
7108 a given pBlock. When we begin iterating through
7109 a pBlock, the variable pc_fstart, pCode of the start
7110 of a function, is cleared. We then search for pCodes
7111 of type PC_FUNCTION. When one is encountered, we
7112 initialize pc_fstart to this and at the same time
7113 associate a new pBranch object that signifies a
7114 branch entry. If a return is found, then this signifies
7115 a function exit point. We'll link the pCodes of these
7116 returns to the matching pc_fstart.
7118 When we're done, a doubly linked list of pBranches
7119 will exist. The head of this list is stored in
7120 `the_pFile', which is the meta structure for all
7121 of the pCode. Look at the pic16_printCallTree function
7122 on how the pBranches are linked together.
7125 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7126 pCode *pc_fstart=NULL;
7127 for(pc = pb->pcHead; pc; pc = pc->next) {
7129 if(isPCI(pc) && pc_fstart) {
7130 if(PCI(pc)->is2MemOp) {
7131 r = pic16_getRegFromInstruction2(pc);
7132 if(r && !strcmp(r->name, "POSTDEC1"))
7133 PCF(pc_fstart)->stackusage++;
7135 r = pic16_getRegFromInstruction(pc);
7136 if(r && !strcmp(r->name, "PREINC1"))
7137 PCF(pc_fstart)->stackusage--;
7142 if (PCF(pc)->fname) {
7144 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7145 //fprintf(stderr," found main \n");
7146 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7150 pbr = Safe_calloc(1,sizeof(pBranch));
7151 pbr->pc = pc_fstart = pc;
7154 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7156 // Here's a better way of doing the same:
7157 addSet(&pb->function_entries, pc);
7160 // Found an exit point in a function, e.g. return
7161 // (Note, there may be more than one return per function)
7163 pBranchLink(PCF(pc_fstart), PCF(pc));
7165 addSet(&pb->function_exits, pc);
7167 } else if(isCALL(pc)) {
7168 addSet(&pb->function_calls,pc);
7175 /* This is not needed because currently all register used
7176 * by a function are stored in stack -- VR */
7178 /* Re-allocate the registers so that there are no collisions
7179 * between local variables when one function call another */
7182 // pic16_deallocateAllRegs();
7184 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7192 /*-----------------------------------------------------------------*/
7193 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7194 /* all of the logical connections. */
7196 /* Essentially what's done here is that the pCode flow is */
7198 /*-----------------------------------------------------------------*/
7200 void pic16_AnalyzepCode(char dbName)
7211 /* Phase 1 - Register allocation and peep hole optimization
7213 * The first part of the analysis is to determine the registers
7214 * that are used in the pCode. Once that is done, the peep rules
7215 * are applied to the code. We continue to loop until no more
7216 * peep rule optimizations are found (or until we exceed the
7217 * MAX_PASSES threshold).
7219 * When done, the required registers will be determined.
7225 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7226 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7228 /* First, merge the labels with the instructions */
7229 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7230 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7232 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7233 //fprintf(stderr," analyze and merging block %c\n",dbName);
7234 pic16_pBlockMergeLabels(pb);
7237 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7242 changes = OptimizepCode(dbName);
7245 } while(changes && (i++ < MAX_PASSES));
7252 /* convert a series of movff's of local regs to stack, with a single call to
7253 * a support functions which does the same thing via loop */
7254 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7258 char *fname[]={"__lr_store", "__lr_restore"};
7260 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7262 pct = pic16_findNextInstruction(pcstart->next);
7265 pct = pc->next; //pic16_findNextInstruction(pc->next);
7266 // pc->print(stderr, pc);
7267 if(isPCI(pc) && PCI(pc)->label) {
7268 pbr = PCI(pc)->label;
7269 while(pbr && pbr->pc) {
7270 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7274 // pc->print(stderr, pc);
7276 pc->prev->next = pct;
7277 pct->prev = pc->prev;
7281 } while ((pc) && (pc != pcend));
7283 /* unlink movff instructions */
7284 pcstart->next = pcend;
7285 pcend->prev = pcstart;
7287 pic16_pCodeInsertAfter(pcstart, (pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name))))); pc = pct;
7288 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7289 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] )));
7294 sym = newSymbol( fname[ entry?0:1 ], 0 );
7295 strcpy(sym->rname, fname[ entry?0:1 ]);
7296 checkAddSym(&externs, sym);
7298 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7304 /*-----------------------------------------------------------------*/
7305 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7306 /* local registers to a support function call */
7307 /*-----------------------------------------------------------------*/
7308 void pic16_OptimizeLocalRegs(void)
7313 pCodeOpLocalReg *pclr;
7316 regs *r, *lastr=NULL, *firstr=NULL;
7317 pCode *pcstart=NULL, *pcend=NULL;
7321 * local_regs begin mark
7322 * MOVFF r0x01, POSTDEC1
7323 * MOVFF r0x02, POSTDEC1
7326 * MOVFF r0x0n, POSTDEC1
7327 * local_regs end mark
7329 * convert the above to the below:
7330 * MOVLW starting_register_index
7332 * MOVLW register_count
7333 * call __save_registers_in_stack
7339 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7340 inRegCount = regCount = 0;
7341 firstr = lastr = NULL;
7342 for(pc = pb->pcHead; pc; pc = pc->next) {
7343 if(pc && (pc->type == PC_INFO)) {
7346 if(pci->type == INF_LOCALREGS) {
7347 pclr = PCOLR(pci->oper1);
7349 if((pclr->type == LR_ENTRY_BEGIN)
7350 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7353 switch(pclr->type) {
7354 case LR_ENTRY_BEGIN:
7356 inRegCount = 1; regCount = 0;
7357 pcstart = pc; //pic16_findNextInstruction(pc->next);
7358 firstr = lastr = NULL;
7364 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7368 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7372 firstr = lastr = NULL;
7376 if(inRegCount == -1) {
7377 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7383 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7385 r = pic16_getRegFromInstruction(pc);
7387 r = pic16_getRegFromInstruction2(pc);
7388 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7389 if(!firstr)firstr = r;
7391 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
7403 /*-----------------------------------------------------------------*/
7404 /* ispCodeFunction - returns true if *pc is the pCode of a */
7406 /*-----------------------------------------------------------------*/
7407 static bool ispCodeFunction(pCode *pc)
7410 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7416 /*-----------------------------------------------------------------*/
7417 /* findFunction - Search for a function by name (given the name) */
7418 /* in the set of all functions that are in a pBlock */
7419 /* (note - I expect this to change because I'm planning to limit */
7420 /* pBlock's to just one function declaration */
7421 /*-----------------------------------------------------------------*/
7422 static pCode *findFunction(char *fname)
7429 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7431 pc = setFirstItem(pb->function_entries);
7434 if((pc->type == PC_FUNCTION) &&
7436 (strcmp(fname, PCF(pc)->fname)==0))
7439 pc = setNextItem(pb->function_entries);
7447 static void MarkUsedRegisters(set *regset)
7452 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7453 // fprintf(stderr, "marking register = %s\t", r1->name);
7454 r2 = pic16_regWithIdx(r1->rIdx);
7455 // fprintf(stderr, "to register = %s\n", r2->name);
7461 static void pBlockStats(FILE *of, pBlock *pb)
7467 if(!pic16_pcode_verbose)return;
7469 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7471 // for now just print the first element of each set
7472 pc = setFirstItem(pb->function_entries);
7474 fprintf(of,";entry: ");
7477 pc = setFirstItem(pb->function_exits);
7479 fprintf(of,";has an exit\n");
7483 pc = setFirstItem(pb->function_calls);
7485 fprintf(of,";functions called:\n");
7488 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7489 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7491 pc = setNextItem(pb->function_calls);
7495 r = setFirstItem(pb->tregisters);
7497 int n = elementsInSet(pb->tregisters);
7499 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7502 fprintf(of,"; %s\n",r->name);
7503 r = setNextItem(pb->tregisters);
7507 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7510 /*-----------------------------------------------------------------*/
7511 /*-----------------------------------------------------------------*/
7513 static void sequencepCode(void)
7519 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7521 pb->seq = GpCodeSequenceNumber+1;
7523 for( pc = pb->pcHead; pc; pc = pc->next)
7524 pc->seq = ++GpCodeSequenceNumber;
7530 /*-----------------------------------------------------------------*/
7531 /*-----------------------------------------------------------------*/
7532 static set *register_usage(pBlock *pb)
7535 set *registers=NULL;
7536 set *registersInCallPath = NULL;
7538 /* check recursion */
7540 pc = setFirstItem(pb->function_entries);
7547 if(pc->type != PC_FUNCTION)
7548 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7550 pc = setFirstItem(pb->function_calls);
7551 for( ; pc; pc = setNextItem(pb->function_calls)) {
7553 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7554 char *dest = pic16_get_op_from_instruction(PCI(pc));
7556 pcn = findFunction(dest);
7558 registersInCallPath = register_usage(pcn->pb);
7560 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7565 pBlockStats(stderr,pb); // debug
7568 // Mark the registers in this block as used.
7570 MarkUsedRegisters(pb->tregisters);
7571 if(registersInCallPath) {
7572 /* registers were used in the functions this pBlock has called */
7573 /* so now, we need to see if these collide with the ones we are */
7576 regs *r1,*r2, *newreg;
7578 DFPRINTF((stderr,"comparing registers\n"));
7580 r1 = setFirstItem(registersInCallPath);
7583 r2 = setFirstItem(pb->tregisters);
7585 while(r2 && (r1->type != REG_STK)) {
7587 if(r2->rIdx == r1->rIdx) {
7588 newreg = pic16_findFreeReg(REG_GPR);
7592 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7596 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7597 r1->rIdx, newreg->rIdx));
7598 r2->rIdx = newreg->rIdx;
7599 //if(r2->name) free(r2->name);
7601 r2->name = Safe_strdup(newreg->name);
7605 newreg->wasUsed = 1;
7607 r2 = setNextItem(pb->tregisters);
7610 r1 = setNextItem(registersInCallPath);
7613 /* Collisions have been resolved. Now free the registers in the call path */
7614 r1 = setFirstItem(registersInCallPath);
7616 if(r1->type != REG_STK) {
7617 newreg = pic16_regWithIdx(r1->rIdx);
7620 r1 = setNextItem(registersInCallPath);
7624 // MarkUsedRegisters(pb->registers);
7626 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7629 DFPRINTF((stderr,"returning regs\n"));
7631 DFPRINTF((stderr,"not returning regs\n"));
7633 DFPRINTF((stderr,"pBlock after register optim.\n"));
7634 pBlockStats(stderr,pb); // debug
7640 /*-----------------------------------------------------------------*/
7641 /* pct2 - writes the call tree to a file */
7643 /*-----------------------------------------------------------------*/
7644 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7648 // set *registersInCallPath = NULL;
7654 fprintf(of, "recursive function\n");
7655 return; //recursion ?
7658 pc = setFirstItem(pb->function_entries);
7665 for(i=0;i<indent;i++) // Indentation
7669 if(pc->type == PC_FUNCTION) {
7670 usedstack += PCF(pc)->stackusage;
7671 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7672 } else return; // ???
7675 pc = setFirstItem(pb->function_calls);
7676 for( ; pc; pc = setNextItem(pb->function_calls)) {
7678 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7679 char *dest = pic16_get_op_from_instruction(PCI(pc));
7681 pcn = findFunction(dest);
7683 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7685 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7693 /*-----------------------------------------------------------------*/
7694 /* pic16_printCallTree - writes the call tree to a file */
7696 /*-----------------------------------------------------------------*/
7698 void pic16_printCallTree(FILE *of)
7710 fprintf(of, "\npBlock statistics\n");
7711 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7715 fprintf(of,"Call Tree\n");
7716 pbr = the_pFile->functions;
7720 if(!ispCodeFunction(pc))
7721 fprintf(of,"bug in call tree");
7724 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7726 while(pc->next && !ispCodeFunction(pc->next)) {
7728 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7729 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7737 fprintf(of,"\n**************\n\na better call tree\n");
7738 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7743 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7744 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7750 /*-----------------------------------------------------------------*/
7752 /*-----------------------------------------------------------------*/
7754 static void InlineFunction(pBlock *pb)
7762 pc = setFirstItem(pb->function_calls);
7764 for( ; pc; pc = setNextItem(pb->function_calls)) {
7767 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7773 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7775 //fprintf(stderr,"Cool can inline:\n");
7776 //pcn->print(stderr,pcn);
7778 //fprintf(stderr,"recursive call Inline\n");
7779 InlineFunction(pcn->pb);
7780 //fprintf(stderr,"return from recursive call Inline\n");
7783 At this point, *pc points to a CALL mnemonic, and
7784 *pcn points to the function that is being called.
7786 To in-line this call, we need to remove the CALL
7787 and RETURN(s), and link the function pCode in with
7793 /* Remove the CALL */
7797 /* remove callee pBlock from the pBlock linked list */
7798 removepBlock(pcn->pb);
7806 /* Remove the Function pCode */
7807 pct = pic16_findNextInstruction(pcn->next);
7809 /* Link the function with the callee */
7810 pc->next = pcn->next;
7811 pcn->next->prev = pc;
7813 /* Convert the function name into a label */
7815 pbr = Safe_calloc(1,sizeof(pBranch));
7816 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7818 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7819 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7821 /* turn all of the return's except the last into goto's */
7822 /* check case for 2 instruction pBlocks */
7823 pce = pic16_findNextInstruction(pcn->next);
7825 pCode *pce_next = pic16_findNextInstruction(pce->next);
7827 if(pce_next == NULL) {
7828 /* found the last return */
7829 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7831 //fprintf(stderr,"found last return\n");
7832 //pce->print(stderr,pce);
7833 pce->prev->next = pc_call->next;
7834 pc_call->next->prev = pce->prev;
7835 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7845 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7851 /*-----------------------------------------------------------------*/
7853 /*-----------------------------------------------------------------*/
7855 void pic16_InlinepCode(void)
7864 if(!functionInlining)
7867 /* Loop through all of the function definitions and count the
7868 * number of times each one is called */
7869 //fprintf(stderr,"inlining %d\n",__LINE__);
7871 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7873 pc = setFirstItem(pb->function_calls);
7875 for( ; pc; pc = setNextItem(pb->function_calls)) {
7878 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7879 if(pcn && isPCF(pcn)) {
7880 PCF(pcn)->ncalled++;
7883 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7888 //fprintf(stderr,"inlining %d\n",__LINE__);
7890 /* Now, Loop through the function definitions again, but this
7891 * time inline those functions that have only been called once. */
7893 InlineFunction(the_pFile->pbHead);
7894 //fprintf(stderr,"inlining %d\n",__LINE__);
7896 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7901 char *pic_optype_names[]={
7902 "PO_NONE", // No operand e.g. NOP
7903 "PO_W", // The working register (as a destination)
7904 "PO_WREG", // The working register (as a file register)
7905 "PO_STATUS", // The 'STATUS' register
7906 "PO_BSR", // The 'BSR' register
7907 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7909 "PO_INDF0", // The Indirect register
7910 "PO_INTCON", // Interrupt Control register
7911 "PO_GPR_REGISTER", // A general purpose register
7912 "PO_GPR_BIT", // A bit of a general purpose register
7913 "PO_GPR_TEMP", // A general purpose temporary register
7914 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7915 "PO_PCL", // Program counter Low register
7916 "PO_PCLATH", // Program counter Latch high register
7917 "PO_PCLATU", // Program counter Latch upper register
7918 "PO_PRODL", // Product Register Low
7919 "PO_PRODH", // Product Register High
7920 "PO_LITERAL", // A constant
7921 "PO_REL_ADDR", // A relative address
7922 "PO_IMMEDIATE", // (8051 legacy)
7923 "PO_DIR", // Direct memory (8051 legacy)
7924 "PO_CRY", // bit memory (8051 legacy)
7925 "PO_BIT", // bit operand.
7926 "PO_STR", // (8051 legacy)
7928 "PO_WILD" // Wild card operand in peep optimizer
7932 char *dumpPicOptype(PIC_OPTYPE type)
7934 return (pic_optype_names[ type ]);