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 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
104 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
105 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
107 static int mnemonics_initialized = 0;
110 static hTab *pic16MnemonicsHash = NULL;
111 static hTab *pic16pCodePeepCommandsHash = NULL;
113 static pFile *the_pFile = NULL;
114 static pBlock *pb_dead_pcodes = NULL;
116 /* Hardcoded flags to change the behavior of the PIC port */
117 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
118 static int functionInlining = 1; /* inline functions if nonzero */
119 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
121 int pic16_pcode_verbose = 0;
123 //static int GpCodeSequenceNumber = 1;
124 static int GpcFlowSeq = 1;
126 extern void pic16_RemoveUnusedRegisters(void);
127 extern void pic16_RegsUnMapLiveRanges(void);
128 extern void pic16_BuildFlowTree(pBlock *pb);
129 extern void pic16_pCodeRegOptimizeRegUsage(int level);
130 extern int pic16_picIsInitialized(void);
131 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
132 extern int mnem2key(char const *mnem);
134 /****************************************************************/
135 /* Forward declarations */
136 /****************************************************************/
138 void pic16_unlinkpCode(pCode *pc);
140 static void genericAnalyze(pCode *pc);
141 static void AnalyzeGOTO(pCode *pc);
142 static void AnalyzeSKIP(pCode *pc);
143 static void AnalyzeRETURN(pCode *pc);
146 static void genericDestruct(pCode *pc);
147 static void genericPrint(FILE *of,pCode *pc);
149 static void pCodePrintLabel(FILE *of, pCode *pc);
150 static void pCodePrintFunction(FILE *of, pCode *pc);
151 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
152 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
153 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
154 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
155 int pic16_pCodePeepMatchRule(pCode *pc);
156 static void pBlockStats(FILE *of, pBlock *pb);
157 static pBlock *newpBlock(void);
158 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
159 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
160 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
161 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
163 char *dumpPicOptype(PIC_OPTYPE type);
165 /****************************************************************/
166 /* PIC Instructions */
167 /****************************************************************/
169 pCodeInstruction pic16_pciADDWF = {
170 {PC_OPCODE, NULL, NULL, 0, NULL,
183 1,0, // dest, bit instruction
185 0, // literal operand
187 0, // fast call/return mode select bit
188 0, // second memory operand
189 0, // second literal operand
191 (PCC_W | PCC_REGISTER), // inCond
192 (PCC_REGISTER | PCC_Z), // outCond
196 pCodeInstruction pic16_pciADDFW = {
197 {PC_OPCODE, NULL, NULL, 0, NULL,
210 0,0, // dest, bit instruction
212 0, // literal operand
214 0, // fast call/return mode select bit
215 0, // second memory operand
216 0, // second literal operand
218 (PCC_W | PCC_REGISTER), // inCond
219 (PCC_W | PCC_Z), // outCond
223 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
224 {PC_OPCODE, NULL, NULL, 0, NULL,
237 1,0, // dest, bit instruction
239 0, // literal operand
241 0, // fast call/return mode select bit
242 0, // second memory operand
243 0, // second literal operand
245 (PCC_W | PCC_REGISTER | PCC_C), // inCond
246 (PCC_REGISTER | PCC_Z), // outCond
250 pCodeInstruction pic16_pciADDFWC = {
251 {PC_OPCODE, NULL, NULL, 0, NULL,
264 0,0, // dest, bit instruction
266 0, // literal operand
268 0, // fast call/return mode select bit
269 0, // second memory operand
270 0, // second literal operand
272 (PCC_W | PCC_REGISTER | PCC_C), // inCond
273 (PCC_W | PCC_Z), // outCond
277 pCodeInstruction pic16_pciADDLW = {
278 {PC_OPCODE, NULL, NULL, 0, NULL,
291 0,0, // dest, bit instruction
293 1, // literal operand
295 0, // fast call/return mode select bit
296 0, // second memory operand
297 0, // second literal operand
299 (PCC_W | PCC_LITERAL), // inCond
300 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
304 pCodeInstruction pic16_pciANDLW = {
305 {PC_OPCODE, NULL, NULL, 0, NULL,
318 0,0, // dest, bit instruction
320 1, // literal operand
322 0, // fast call/return mode select bit
323 0, // second memory operand
324 0, // second literal operand
326 (PCC_W | PCC_LITERAL), // inCond
327 (PCC_W | PCC_Z | PCC_N), // outCond
331 pCodeInstruction pic16_pciANDWF = {
332 {PC_OPCODE, NULL, NULL, 0, NULL,
345 1,0, // dest, bit instruction
347 0, // literal operand
349 0, // fast call/return mode select bit
350 0, // second memory operand
351 0, // second literal operand
353 (PCC_W | PCC_REGISTER), // inCond
354 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
358 pCodeInstruction pic16_pciANDFW = {
359 {PC_OPCODE, NULL, NULL, 0, NULL,
372 0,0, // dest, bit instruction
374 0, // literal operand
376 0, // fast call/return mode select bit
377 0, // second memory operand
378 0, // second literal operand
380 (PCC_W | PCC_REGISTER), // inCond
381 (PCC_W | PCC_Z) // outCond
384 pCodeInstruction pic16_pciBC = { // mdubuc - New
385 {PC_OPCODE, NULL, NULL, 0, NULL,
398 0,0, // dest, bit instruction
400 0, // literal operand
402 0, // fast call/return mode select bit
403 0, // second memory operand
404 0, // second literal operand
406 (PCC_REL_ADDR | PCC_C), // inCond
411 pCodeInstruction pic16_pciBCF = {
412 {PC_OPCODE, NULL, NULL, 0, NULL,
425 1,1, // dest, bit instruction
427 0, // literal operand
429 0, // fast call/return mode select bit
430 0, // second memory operand
431 0, // second literal operand
433 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
434 PCC_REGISTER, // outCond
438 pCodeInstruction pic16_pciBN = { // mdubuc - New
439 {PC_OPCODE, NULL, NULL, 0, NULL,
452 0,0, // dest, bit instruction
454 0, // literal operand
456 0, // fast call/return mode select bit
457 0, // second memory operand
458 0, // second literal operand
460 (PCC_REL_ADDR | PCC_N), // inCond
461 PCC_NONE , // outCond
465 pCodeInstruction pic16_pciBNC = { // mdubuc - New
466 {PC_OPCODE, NULL, NULL, 0, NULL,
479 0,0, // dest, bit instruction
481 0, // literal operand
483 0, // fast call/return mode select bit
484 0, // second memory operand
485 0, // second literal operand
487 (PCC_REL_ADDR | PCC_C), // inCond
488 PCC_NONE , // outCond
492 pCodeInstruction pic16_pciBNN = { // mdubuc - New
493 {PC_OPCODE, NULL, NULL, 0, NULL,
506 0,0, // dest, bit instruction
508 0, // literal operand
510 0, // fast call/return mode select bit
511 0, // second memory operand
512 0, // second literal operand
514 (PCC_REL_ADDR | PCC_N), // inCond
515 PCC_NONE , // outCond
519 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
520 {PC_OPCODE, NULL, NULL, 0, NULL,
533 0,0, // dest, bit instruction
535 0, // literal operand
537 0, // fast call/return mode select bit
538 0, // second memory operand
539 0, // second literal operand
541 (PCC_REL_ADDR | PCC_OV), // inCond
542 PCC_NONE , // outCond
546 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
547 {PC_OPCODE, NULL, NULL, 0, NULL,
560 0,0, // dest, bit instruction
562 0, // literal operand
564 0, // fast call/return mode select bit
565 0, // second memory operand
566 0, // second literal operand
568 (PCC_REL_ADDR | PCC_Z), // inCond
569 PCC_NONE , // outCond
573 pCodeInstruction pic16_pciBOV = { // mdubuc - New
574 {PC_OPCODE, NULL, NULL, 0, NULL,
587 0,0, // dest, bit instruction
589 0, // literal operand
591 0, // fast call/return mode select bit
592 0, // second memory operand
593 0, // second literal operand
595 (PCC_REL_ADDR | PCC_OV), // inCond
596 PCC_NONE , // outCond
600 pCodeInstruction pic16_pciBRA = { // mdubuc - New
601 {PC_OPCODE, NULL, NULL, 0, NULL,
614 0,0, // dest, bit instruction
616 0, // literal operand
618 0, // fast call/return mode select bit
619 0, // second memory operand
620 0, // second literal operand
622 PCC_REL_ADDR, // inCond
623 PCC_NONE , // outCond
627 pCodeInstruction pic16_pciBSF = {
628 {PC_OPCODE, NULL, NULL, 0, NULL,
641 1,1, // dest, bit instruction
643 0, // literal operand
645 0, // fast call/return mode select bit
646 0, // second memory operand
647 0, // second literal operand
649 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
650 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
654 pCodeInstruction pic16_pciBTFSC = {
655 {PC_OPCODE, NULL, NULL, 0, NULL,
668 0,1, // dest, bit instruction
670 0, // literal operand
672 0, // fast call/return mode select bit
673 0, // second memory operand
674 0, // second literal operand
676 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
677 PCC_EXAMINE_PCOP, // outCond
681 pCodeInstruction pic16_pciBTFSS = {
682 {PC_OPCODE, NULL, NULL, 0, NULL,
695 0,1, // dest, bit instruction
697 0, // literal operand
699 0, // fast call/return mode select bit
700 0, // second memory operand
701 0, // second literal operand
703 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
704 PCC_EXAMINE_PCOP, // outCond
708 pCodeInstruction pic16_pciBTG = { // mdubuc - New
709 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,1, // dest, bit instruction
724 0, // literal operand
726 0, // fast call/return mode select bit
727 0, // second memory operand
728 0, // second literal operand
730 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
731 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
735 pCodeInstruction pic16_pciBZ = { // mdubuc - New
736 {PC_OPCODE, NULL, NULL, 0, NULL,
749 0,0, // dest, bit instruction
751 0, // literal operand
753 0, // fast call/return mode select bit
754 0, // second memory operand
755 0, // second literal operand
762 pCodeInstruction pic16_pciCALL = {
763 {PC_OPCODE, NULL, NULL, 0, NULL,
776 0,0, // dest, bit instruction
778 0, // literal operand
780 1, // fast call/return mode select bit
781 0, // second memory operand
782 0, // second literal operand
785 PCC_NONE , // outCond
789 pCodeInstruction pic16_pciCOMF = {
790 {PC_OPCODE, NULL, NULL, 0, NULL,
803 1,0, // dest, bit instruction
805 0, // literal operand
807 0, // fast call/return mode select bit
808 0, // second memory operand
809 0, // second literal operand
811 PCC_REGISTER, // inCond
812 PCC_REGISTER , // outCond
816 pCodeInstruction pic16_pciCOMFW = {
817 {PC_OPCODE, NULL, NULL, 0, NULL,
830 0,0, // dest, bit instruction
832 0, // literal operand
834 0, // fast call/return mode select bit
835 0, // second memory operand
836 0, // second literal operand
838 PCC_REGISTER, // inCond
843 pCodeInstruction pic16_pciCLRF = {
844 {PC_OPCODE, NULL, NULL, 0, NULL,
857 0,0, // dest, bit instruction
859 0, // literal operand
861 0, // fast call/return mode select bit
862 0, // second memory operand
863 0, // second literal operand
865 PCC_REGISTER, // inCond
866 PCC_REGISTER , // outCond
870 pCodeInstruction pic16_pciCLRWDT = {
871 {PC_OPCODE, NULL, NULL, 0, NULL,
884 0,0, // dest, bit instruction
886 0, // literal operand
888 0, // fast call/return mode select bit
889 0, // second memory operand
890 0, // second literal operand
893 PCC_NONE , // outCond
897 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
898 {PC_OPCODE, NULL, NULL, 0, NULL,
911 0,0, // dest, bit instruction
913 0, // literal operand
915 0, // fast call/return mode select bit
916 0, // second memory operand
917 0, // second literal operand
919 (PCC_W | PCC_REGISTER), // inCond
920 PCC_NONE , // outCond
924 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
925 {PC_OPCODE, NULL, NULL, 0, NULL,
938 0,0, // dest, bit instruction
940 0, // literal operand
942 0, // fast call/return mode select bit
943 0, // second memory operand
944 0, // second literal operand
946 (PCC_W | PCC_REGISTER), // inCond
947 PCC_NONE , // outCond
951 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
952 {PC_OPCODE, NULL, NULL, 0, NULL,
965 1,0, // dest, bit instruction
967 0, // literal operand
969 0, // fast call/return mode select bit
970 0, // second memory operand
971 0, // second literal operand
973 (PCC_W | PCC_REGISTER), // inCond
974 PCC_NONE , // outCond
978 pCodeInstruction pic16_pciDAW = {
979 {PC_OPCODE, NULL, NULL, 0, NULL,
992 0,0, // dest, bit instruction
994 0, // literal operand
996 0, // fast call/return mode select bit
997 0, // second memory operand
998 0, // second literal operand
1001 (PCC_W | PCC_C), // outCond
1005 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1006 {PC_OPCODE, NULL, NULL, 0, NULL,
1012 NULL, // from branch
1019 1,0, // dest, bit instruction
1020 1,1, // branch, skip
1021 0, // literal operand
1022 1, // RAM access bit
1023 0, // fast call/return mode select bit
1024 0, // second memory operand
1025 0, // second literal operand
1027 PCC_REGISTER, // inCond
1028 PCC_REGISTER , // outCond
1032 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1033 {PC_OPCODE, NULL, NULL, 0, NULL,
1039 NULL, // from branch
1046 0,0, // dest, bit instruction
1047 1,1, // branch, skip
1048 0, // literal operand
1049 1, // RAM access bit
1050 0, // fast call/return mode select bit
1051 0, // second memory operand
1052 0, // second literal operand
1054 PCC_REGISTER, // inCond
1059 pCodeInstruction pic16_pciDECF = {
1060 {PC_OPCODE, NULL, NULL, 0, NULL,
1066 NULL, // from branch
1073 1,0, // dest, bit instruction
1074 0,0, // branch, skip
1075 0, // literal operand
1076 1, // RAM access bit
1077 0, // fast call/return mode select bit
1078 0, // second memory operand
1079 0, // second literal operand
1081 PCC_REGISTER, // inCond
1082 PCC_REGISTER , // outCond
1086 pCodeInstruction pic16_pciDECFW = {
1087 {PC_OPCODE, NULL, NULL, 0, NULL,
1093 NULL, // from branch
1100 0,0, // dest, bit instruction
1101 0,0, // 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_pciDECFSZ = {
1114 {PC_OPCODE, NULL, NULL, 0, NULL,
1120 NULL, // from branch
1127 1,0, // dest, bit instruction
1128 1,1, // branch, skip
1129 0, // literal operand
1130 1, // RAM access bit
1131 0, // fast call/return mode select bit
1132 0, // second memory operand
1133 0, // second literal operand
1135 PCC_REGISTER, // inCond
1136 PCC_REGISTER , // outCond
1140 pCodeInstruction pic16_pciDECFSZW = {
1141 {PC_OPCODE, NULL, NULL, 0, NULL,
1147 NULL, // from branch
1154 0,0, // dest, bit instruction
1155 1,1, // branch, skip
1156 0, // literal operand
1157 1, // RAM access bit
1158 0, // fast call/return mode select bit
1159 0, // second memory operand
1160 0, // second literal operand
1162 PCC_REGISTER, // inCond
1167 pCodeInstruction pic16_pciGOTO = {
1168 {PC_OPCODE, NULL, NULL, 0, NULL,
1174 NULL, // from branch
1181 0,0, // dest, bit instruction
1182 1,0, // branch, skip
1183 0, // literal operand
1184 0, // RAM access bit
1185 0, // fast call/return mode select bit
1186 0, // second memory operand
1187 0, // second literal operand
1189 PCC_REL_ADDR, // inCond
1190 PCC_NONE , // outCond
1194 pCodeInstruction pic16_pciINCF = {
1195 {PC_OPCODE, NULL, NULL, 0, NULL,
1201 NULL, // from branch
1208 1,0, // dest, bit instruction
1209 0,0, // branch, skip
1210 0, // literal operand
1211 1, // RAM access bit
1212 0, // fast call/return mode select bit
1213 0, // second memory operand
1214 0, // second literal operand
1216 PCC_REGISTER, // inCond
1217 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1221 pCodeInstruction pic16_pciINCFW = {
1222 {PC_OPCODE, NULL, NULL, 0, NULL,
1228 NULL, // from branch
1235 0,0, // dest, bit instruction
1236 0,0, // branch, skip
1237 0, // literal operand
1238 1, // RAM access bit
1239 0, // fast call/return mode select bit
1240 0, // second memory operand
1241 0, // second literal operand
1243 PCC_REGISTER, // inCond
1248 pCodeInstruction pic16_pciINCFSZ = {
1249 {PC_OPCODE, NULL, NULL, 0, NULL,
1255 NULL, // from branch
1262 1,0, // dest, bit instruction
1263 1,1, // branch, skip
1264 0, // literal operand
1265 1, // RAM access bit
1266 0, // fast call/return mode select bit
1267 0, // second memory operand
1268 0, // second literal operand
1270 PCC_REGISTER, // inCond
1271 PCC_REGISTER , // outCond
1275 pCodeInstruction pic16_pciINCFSZW = {
1276 {PC_OPCODE, NULL, NULL, 0, NULL,
1282 NULL, // from branch
1289 0,0, // dest, bit instruction
1290 1,1, // branch, skip
1291 0, // literal operand
1292 1, // RAM access bit
1293 0, // fast call/return mode select bit
1294 0, // second memory operand
1295 0, // second literal operand
1297 PCC_REGISTER, // inCond
1302 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1303 {PC_OPCODE, NULL, NULL, 0, NULL,
1309 NULL, // from branch
1316 1,0, // dest, bit instruction
1317 1,1, // branch, skip
1318 0, // literal operand
1319 1, // RAM access bit
1320 0, // fast call/return mode select bit
1321 0, // second memory operand
1322 0, // second literal operand
1324 PCC_REGISTER, // inCond
1325 PCC_REGISTER , // outCond
1329 pCodeInstruction pic16_pciIORWF = {
1330 {PC_OPCODE, NULL, NULL, 0, NULL,
1336 NULL, // from branch
1343 1,0, // dest, bit instruction
1344 0,0, // branch, skip
1345 0, // literal operand
1346 1, // RAM access bit
1347 0, // fast call/return mode select bit
1348 0, // second memory operand
1349 0, // second literal operand
1351 (PCC_W | PCC_REGISTER), // inCond
1352 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1356 pCodeInstruction pic16_pciIORFW = {
1357 {PC_OPCODE, NULL, NULL, 0, NULL,
1363 NULL, // from branch
1370 0,0, // dest, bit instruction
1371 0,0, // branch, skip
1372 0, // literal operand
1373 1, // RAM access bit
1374 0, // fast call/return mode select bit
1375 0, // second memory operand
1376 0, // second literal operand
1378 (PCC_W | PCC_REGISTER), // inCond
1379 (PCC_W | PCC_Z | PCC_N), // outCond
1383 pCodeInstruction pic16_pciIORLW = {
1384 {PC_OPCODE, NULL, NULL, 0, NULL,
1390 NULL, // from branch
1397 0,0, // dest, bit instruction
1398 0,0, // branch, skip
1399 1, // literal operand
1400 0, // RAM access bit
1401 0, // fast call/return mode select bit
1402 0, // second memory operand
1403 0, // second literal operand
1405 (PCC_W | PCC_LITERAL), // inCond
1406 (PCC_W | PCC_Z | PCC_N), // outCond
1410 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1411 {PC_OPCODE, NULL, NULL, 0, NULL,
1417 NULL, // from branch
1424 0,0, // dest, bit instruction
1425 0,0, // branch, skip
1426 1, // literal operand
1427 0, // RAM access bit
1428 0, // fast call/return mode select bit
1429 0, // second memory operand
1430 1, // second literal operand
1432 (PCC_REGISTER | PCC_LITERAL),
1433 PCC_REGISTER, // outCond
1437 pCodeInstruction pic16_pciMOVF = {
1438 {PC_OPCODE, NULL, NULL, 0, NULL,
1444 NULL, // from branch
1451 1,0, // dest, bit instruction
1452 0,0, // branch, skip
1453 0, // literal operand
1454 1, // RAM access bit
1455 0, // fast call/return mode select bit
1456 0, // second memory operand
1457 0, // second literal operand
1459 PCC_REGISTER, // inCond
1460 (PCC_Z | PCC_N), // outCond
1464 pCodeInstruction pic16_pciMOVFW = {
1465 {PC_OPCODE, NULL, NULL, 0, NULL,
1471 NULL, // from branch
1478 0,0, // dest, bit instruction
1479 0,0, // branch, skip
1480 0, // literal operand
1481 1, // RAM access bit
1482 0, // fast call/return mode select bit
1483 0, // second memory operand
1484 0, // second literal operand
1486 PCC_REGISTER, // inCond
1487 (PCC_W | PCC_Z), // outCond
1491 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1492 {PC_OPCODE, NULL, NULL, 0, NULL,
1498 NULL, // from branch
1505 0,0, // dest, bit instruction
1506 0,0, // branch, skip
1507 0, // literal operand
1508 0, // RAM access bit
1509 0, // fast call/return mode select bit
1510 1, // second memory operand
1511 0, // second literal operand
1513 PCC_REGISTER, // inCond
1514 PCC_REGISTER2, // outCond
1518 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1519 {PC_OPCODE, NULL, NULL, 0, NULL,
1524 NULL, // from branch
1531 0,0, // dest, bit instruction
1532 0,0, // branch, skip
1533 1, // literal operand
1534 0, // RAM access bit
1535 0, // fast call/return mode select bit
1536 0, // second memory operand
1537 0, // second literal operand
1539 (PCC_NONE | PCC_LITERAL), // inCond
1540 PCC_REGISTER, // outCond - BSR
1544 pCodeInstruction pic16_pciMOVLW = {
1545 {PC_OPCODE, NULL, NULL, 0, NULL,
1550 NULL, // from branch
1557 0,0, // dest, bit instruction
1558 0,0, // branch, skip
1559 1, // literal operand
1560 0, // RAM access bit
1561 0, // fast call/return mode select bit
1562 0, // second memory operand
1563 0, // second literal operand
1565 (PCC_NONE | PCC_LITERAL), // inCond
1570 pCodeInstruction pic16_pciMOVWF = {
1571 {PC_OPCODE, NULL, NULL, 0, NULL,
1577 NULL, // from branch
1584 0,0, // dest, bit instruction
1585 0,0, // branch, skip
1586 0, // literal operand
1587 1, // RAM access bit
1588 0, // fast call/return mode select bit
1589 0, // second memory operand
1590 0, // second literal operand
1592 PCC_REGISTER, // inCond
1597 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1598 {PC_OPCODE, NULL, NULL, 0, NULL,
1603 NULL, // from branch
1610 0,0, // dest, bit instruction
1611 0,0, // branch, skip
1612 1, // literal operand
1613 0, // RAM access bit
1614 0, // fast call/return mode select bit
1615 0, // second memory operand
1616 0, // second literal operand
1618 (PCC_W | PCC_LITERAL), // inCond
1619 PCC_REGISTER, // outCond - PROD
1623 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1624 {PC_OPCODE, NULL, NULL, 0, NULL,
1629 NULL, // from branch
1636 0,0, // dest, bit instruction
1637 0,0, // branch, skip
1638 0, // literal operand
1639 1, // RAM access bit
1640 0, // fast call/return mode select bit
1641 0, // second memory operand
1642 0, // second literal operand
1644 (PCC_W | PCC_REGISTER), // inCond
1645 PCC_REGISTER, // outCond - PROD
1649 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1650 {PC_OPCODE, NULL, NULL, 0, NULL,
1655 NULL, // from branch
1662 0,0, // dest, bit instruction
1663 0,0, // branch, skip
1664 0, // literal operand
1665 1, // RAM access bit
1666 0, // fast call/return mode select bit
1667 0, // second memory operand
1668 0, // second literal operand
1670 PCC_REGISTER, // inCond
1671 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1675 pCodeInstruction pic16_pciNOP = {
1676 {PC_OPCODE, NULL, NULL, 0, NULL,
1681 NULL, // from branch
1688 0,0, // dest, bit instruction
1689 0,0, // branch, skip
1690 0, // literal operand
1691 0, // RAM access bit
1692 0, // fast call/return mode select bit
1693 0, // second memory operand
1694 0, // second literal operand
1697 PCC_NONE, // outCond
1701 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1702 {PC_OPCODE, NULL, NULL, 0, NULL,
1707 NULL, // from branch
1714 0,0, // dest, bit instruction
1715 0,0, // branch, skip
1716 0, // literal operand
1717 0, // RAM access bit
1718 0, // fast call/return mode select bit
1719 0, // second memory operand
1720 0, // second literal operand
1723 PCC_NONE , // outCond
1727 pCodeInstruction pic16_pciPUSH = {
1728 {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 0, // RAM access bit
1744 0, // fast call/return mode select bit
1745 0, // second memory operand
1746 0, // second literal operand
1749 PCC_NONE , // outCond
1753 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1754 {PC_OPCODE, NULL, NULL, 0, NULL,
1759 NULL, // from branch
1766 0,0, // dest, bit instruction
1767 0,0, // branch, skip
1768 0, // literal operand
1769 0, // RAM access bit
1770 0, // fast call/return mode select bit
1771 0, // second memory operand
1772 0, // second literal operand
1774 PCC_REL_ADDR, // inCond
1775 PCC_NONE , // outCond
1779 pCodeInstruction pic16_pciRETFIE = {
1780 {PC_OPCODE, NULL, NULL, 0, NULL,
1786 NULL, // from branch
1793 0,0, // dest, bit instruction
1794 1,0, // branch, skip
1795 0, // literal operand
1796 0, // RAM access bit
1797 1, // fast call/return mode select bit
1798 0, // second memory operand
1799 0, // second literal operand
1802 PCC_NONE, // outCond (not true... affects the GIE bit too)
1806 pCodeInstruction pic16_pciRETLW = {
1807 {PC_OPCODE, NULL, NULL, 0, NULL,
1813 NULL, // from branch
1820 0,0, // dest, bit instruction
1821 1,0, // branch, skip
1822 1, // literal operand
1823 0, // RAM access bit
1824 0, // fast call/return mode select bit
1825 0, // second memory operand
1826 0, // second literal operand
1828 PCC_LITERAL, // inCond
1833 pCodeInstruction pic16_pciRETURN = {
1834 {PC_OPCODE, NULL, NULL, 0, NULL,
1840 NULL, // from branch
1847 0,0, // dest, bit instruction
1848 1,0, // branch, skip
1849 0, // literal operand
1850 0, // RAM access bit
1851 1, // fast call/return mode select bit
1852 0, // second memory operand
1853 0, // second literal operand
1856 PCC_NONE, // outCond
1859 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1860 {PC_OPCODE, NULL, NULL, 0, NULL,
1866 NULL, // from branch
1873 1,0, // dest, bit instruction
1874 0,0, // branch, skip
1875 0, // literal operand
1876 1, // RAM access bit
1877 0, // fast call/return mode select bit
1878 0, // second memory operand
1879 0, // second literal operand
1881 (PCC_C | PCC_REGISTER), // inCond
1882 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1886 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1887 {PC_OPCODE, NULL, NULL, 0, NULL,
1893 NULL, // from branch
1900 0,0, // dest, bit instruction
1901 0,0, // branch, skip
1902 0, // literal operand
1903 1, // RAM access bit
1904 0, // fast call/return mode select bit
1905 0, // second memory operand
1906 0, // second literal operand
1908 (PCC_C | PCC_REGISTER), // inCond
1909 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1913 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1914 {PC_OPCODE, NULL, NULL, 0, NULL,
1920 NULL, // from branch
1927 1,0, // dest, bit instruction
1928 0,0, // branch, skip
1929 0, // literal operand
1930 1, // RAM access bit
1931 0, // fast call/return mode select bit
1932 0, // second memory operand
1933 0, // second literal operand
1935 PCC_REGISTER, // inCond
1936 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1939 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1940 {PC_OPCODE, NULL, NULL, 0, NULL,
1946 NULL, // from branch
1953 0,0, // dest, bit instruction
1954 0,0, // branch, skip
1955 0, // literal operand
1956 1, // RAM access bit
1957 0, // fast call/return mode select bit
1958 0, // second memory operand
1959 0, // second literal operand
1961 PCC_REGISTER, // inCond
1962 (PCC_W | PCC_Z | PCC_N), // outCond
1965 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1966 {PC_OPCODE, NULL, NULL, 0, NULL,
1972 NULL, // from branch
1979 1,0, // dest, bit instruction
1980 0,0, // branch, skip
1981 0, // literal operand
1982 1, // RAM access bit
1983 0, // fast call/return mode select bit
1984 0, // second memory operand
1985 0, // second literal operand
1987 (PCC_C | PCC_REGISTER), // inCond
1988 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1991 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1992 {PC_OPCODE, NULL, NULL, 0, NULL,
1998 NULL, // from branch
2005 0,0, // dest, bit instruction
2006 0,0, // branch, skip
2007 0, // literal operand
2008 1, // RAM access bit
2009 0, // fast call/return mode select bit
2010 0, // second memory operand
2011 0, // second literal operand
2013 (PCC_C | PCC_REGISTER), // inCond
2014 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2017 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2018 {PC_OPCODE, NULL, NULL, 0, NULL,
2024 NULL, // from branch
2031 1,0, // dest, bit instruction
2032 0,0, // branch, skip
2033 0, // literal operand
2034 1, // RAM access bit
2035 0, // fast call/return mode select bit
2036 0, // second memory operand
2037 0, // second literal operand
2039 PCC_REGISTER, // inCond
2040 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2044 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2045 {PC_OPCODE, NULL, NULL, 0, NULL,
2051 NULL, // from branch
2058 0,0, // dest, bit instruction
2059 0,0, // branch, skip
2060 0, // literal operand
2061 1, // RAM access bit
2062 0, // fast call/return mode select bit
2063 0, // second memory operand
2064 0, // second literal operand
2066 PCC_REGISTER, // inCond
2067 (PCC_W | PCC_Z | PCC_N), // outCond
2071 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2072 {PC_OPCODE, NULL, NULL, 0, NULL,
2078 NULL, // from branch
2085 0,0, // dest, bit instruction
2086 0,0, // branch, skip
2087 0, // literal operand
2088 1, // RAM access bit
2089 0, // fast call/return mode select bit
2090 0, // second memory operand
2091 0, // second literal operand
2093 PCC_REGISTER, // inCond
2094 PCC_REGISTER , // outCond
2098 pCodeInstruction pic16_pciSUBLW = {
2099 {PC_OPCODE, NULL, NULL, 0, NULL,
2105 NULL, // from branch
2112 0,0, // dest, bit instruction
2113 0,0, // branch, skip
2114 1, // literal operand
2115 0, // RAM access bit
2116 0, // fast call/return mode select bit
2117 0, // second memory operand
2118 0, // second literal operand
2120 (PCC_W | PCC_LITERAL), // inCond
2121 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2125 pCodeInstruction pic16_pciSUBFWB = {
2126 {PC_OPCODE, NULL, NULL, 0, NULL,
2132 NULL, // from branch
2139 1,0, // dest, bit instruction
2140 0,0, // branch, skip
2141 0, // literal operand
2142 1, // RAM access bit
2143 0, // fast call/return mode select bit
2144 0, // second memory operand
2145 0, // second literal operand
2147 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2148 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2152 pCodeInstruction pic16_pciSUBWF = {
2153 {PC_OPCODE, NULL, NULL, 0, NULL,
2159 NULL, // from branch
2166 1,0, // dest, bit instruction
2167 0,0, // branch, skip
2168 0, // literal operand
2169 1, // RAM access bit
2170 0, // fast call/return mode select bit
2171 0, // second memory operand
2172 0, // second literal operand
2174 (PCC_W | PCC_REGISTER), // inCond
2175 (PCC_REGISTER | PCC_Z), // outCond
2179 pCodeInstruction pic16_pciSUBFW = {
2180 {PC_OPCODE, NULL, NULL, 0, NULL,
2186 NULL, // from branch
2193 0,0, // dest, bit instruction
2194 0,0, // branch, skip
2195 0, // literal operand
2196 1, // RAM access bit
2197 0, // fast call/return mode select bit
2198 0, // second memory operand
2199 0, // second literal operand
2201 (PCC_W | PCC_REGISTER), // inCond
2202 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2206 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2207 {PC_OPCODE, NULL, NULL, 0, NULL,
2213 NULL, // from branch
2220 1,0, // dest, bit instruction
2221 0,0, // branch, skip
2222 0, // literal operand
2223 1, // RAM access bit
2224 0, // fast call/return mode select bit
2225 0, // second memory operand
2226 0, // second literal operand
2228 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2229 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2233 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2234 {PC_OPCODE, NULL, NULL, 0, NULL,
2240 NULL, // from branch
2247 0,0, // dest, bit instruction
2248 0,0, // branch, skip
2249 0, // literal operand
2250 1, // RAM access bit
2251 0, // fast call/return mode select bit
2252 0, // second memory operand
2253 0, // second literal operand
2255 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2256 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2260 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2261 {PC_OPCODE, NULL, NULL, 0, NULL,
2267 NULL, // from branch
2274 1,0, // dest, bit instruction
2275 0,0, // branch, skip
2276 0, // literal operand
2277 1, // RAM access bit
2278 0, // fast call/return mode select bit
2279 0, // second memory operand
2280 0, // second literal operand
2282 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2283 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2287 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2288 {PC_OPCODE, NULL, NULL, 0, NULL,
2294 NULL, // from branch
2301 0,0, // dest, bit instruction
2302 0,0, // branch, skip
2303 0, // literal operand
2304 1, // RAM access bit
2305 0, // fast call/return mode select bit
2306 0, // second memory operand
2307 0, // second literal operand
2309 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2310 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2314 pCodeInstruction pic16_pciSWAPF = {
2315 {PC_OPCODE, NULL, NULL, 0, NULL,
2321 NULL, // from branch
2328 1,0, // dest, bit instruction
2329 0,0, // branch, skip
2330 0, // literal operand
2331 1, // RAM access bit
2332 0, // fast call/return mode select bit
2333 0, // second memory operand
2334 0, // second literal operand
2336 (PCC_REGISTER), // inCond
2337 (PCC_REGISTER), // outCond
2341 pCodeInstruction pic16_pciSWAPFW = {
2342 {PC_OPCODE, NULL, NULL, 0, NULL,
2348 NULL, // from branch
2355 0,0, // dest, bit instruction
2356 0,0, // branch, skip
2357 0, // literal operand
2358 1, // RAM access bit
2359 0, // fast call/return mode select bit
2360 0, // second memory operand
2361 0, // second literal operand
2363 (PCC_REGISTER), // inCond
2368 pCodeInstruction pic16_pciTBLRD = { // patch 15
2369 {PC_OPCODE, NULL, NULL, 0, NULL,
2374 NULL, // from branch
2381 0,0, // dest, bit instruction
2382 0,0, // branch, skip
2383 0, // literal operand
2384 0, // RAM access bit
2385 0, // fast call/return mode select bit
2386 0, // second memory operand
2387 0, // second literal operand
2390 PCC_NONE , // outCond
2394 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2395 {PC_OPCODE, NULL, NULL, 0, NULL,
2400 NULL, // from branch
2407 0,0, // dest, bit instruction
2408 0,0, // branch, skip
2409 0, // literal operand
2410 0, // RAM access bit
2411 0, // fast call/return mode select bit
2412 0, // second memory operand
2413 0, // second literal operand
2416 PCC_NONE , // outCond
2420 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2421 {PC_OPCODE, NULL, NULL, 0, NULL,
2426 NULL, // from branch
2433 0,0, // dest, bit instruction
2434 0,0, // branch, skip
2435 0, // literal operand
2436 0, // RAM access bit
2437 0, // fast call/return mode select bit
2438 0, // second memory operand
2439 0, // second literal operand
2442 PCC_NONE , // outCond
2446 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2447 {PC_OPCODE, NULL, NULL, 0, NULL,
2452 NULL, // from branch
2459 0,0, // dest, bit instruction
2460 0,0, // branch, skip
2461 0, // literal operand
2462 0, // RAM access bit
2463 0, // fast call/return mode select bit
2464 0, // second memory operand
2465 0, // second literal operand
2468 PCC_NONE , // outCond
2472 pCodeInstruction pic16_pciTBLWT = { // patch 15
2473 {PC_OPCODE, NULL, NULL, 0, NULL,
2478 NULL, // from branch
2485 0,0, // dest, bit instruction
2486 0,0, // branch, skip
2487 0, // literal operand
2488 0, // RAM access bit
2489 0, // fast call/return mode select bit
2490 0, // second memory operand
2491 0, // second literal operand
2494 PCC_NONE , // outCond
2498 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2499 {PC_OPCODE, NULL, NULL, 0, NULL,
2504 NULL, // from branch
2511 0,0, // dest, bit instruction
2512 0,0, // branch, skip
2513 0, // literal operand
2514 0, // RAM access bit
2515 0, // fast call/return mode select bit
2516 0, // second memory operand
2517 0, // second literal operand
2520 PCC_NONE , // outCond
2524 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2525 {PC_OPCODE, NULL, NULL, 0, NULL,
2530 NULL, // from branch
2537 0,0, // dest, bit instruction
2538 0,0, // branch, skip
2539 0, // literal operand
2540 0, // RAM access bit
2541 0, // fast call/return mode select bit
2542 0, // second memory operand
2543 0, // second literal operand
2546 PCC_NONE , // outCond
2550 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2551 {PC_OPCODE, NULL, NULL, 0, NULL,
2556 NULL, // from branch
2563 0,0, // dest, bit instruction
2564 0,0, // branch, skip
2565 0, // literal operand
2566 0, // RAM access bit
2567 0, // fast call/return mode select bit
2568 0, // second memory operand
2569 0, // second literal operand
2572 PCC_NONE , // outCond
2576 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2577 {PC_OPCODE, NULL, NULL, 0, NULL,
2583 NULL, // from branch
2590 0,0, // dest, bit instruction
2591 1,1, // branch, skip
2592 0, // literal operand
2593 1, // RAM access bit
2594 0, // fast call/return mode select bit
2595 0, // second memory operand
2596 0, // second literal operand
2598 PCC_REGISTER, // inCond
2599 PCC_NONE, // outCond
2603 pCodeInstruction pic16_pciXORWF = {
2604 {PC_OPCODE, NULL, NULL, 0, NULL,
2610 NULL, // from branch
2617 1,0, // dest, bit instruction
2618 0,0, // branch, skip
2619 0, // literal operand
2620 1, // RAM access bit
2621 0, // fast call/return mode select bit
2622 0, // second memory operand
2623 0, // second literal operand
2625 (PCC_W | PCC_REGISTER), // inCond
2626 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2630 pCodeInstruction pic16_pciXORFW = {
2631 {PC_OPCODE, NULL, NULL, 0, NULL,
2637 NULL, // from branch
2644 0,0, // dest, bit instruction
2645 0,0, // branch, skip
2646 0, // literal operand
2647 1, // RAM access bit
2648 0, // fast call/return mode select bit
2649 0, // second memory operand
2650 0, // second literal operand
2652 (PCC_W | PCC_REGISTER), // inCond
2653 (PCC_W | PCC_Z | PCC_N), // outCond
2657 pCodeInstruction pic16_pciXORLW = {
2658 {PC_OPCODE, NULL, NULL, 0, NULL,
2664 NULL, // from branch
2671 0,0, // dest, bit instruction
2672 0,0, // branch, skip
2673 1, // literal operand
2674 1, // RAM access bit
2675 0, // fast call/return mode select bit
2676 0, // second memory operand
2677 0, // second literal operand
2679 (PCC_W | PCC_LITERAL), // inCond
2680 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2685 #define MAX_PIC16MNEMONICS 100
2686 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2688 //#define USE_VSNPRINTF
2691 #ifdef USE_VSNPRINTF
2692 // Alas, vsnprintf is not ANSI standard, and does not exist
2693 // on Solaris (and probably other non-Gnu flavored Unixes).
2695 /*-----------------------------------------------------------------*/
2696 /* SAFE_snprintf - like snprintf except the string pointer is */
2697 /* after the string has been printed to. This is */
2698 /* useful for printing to string as though if it */
2699 /* were a stream. */
2700 /*-----------------------------------------------------------------*/
2701 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2709 va_start(val, format);
2711 vsnprintf(*str, *size, format, val);
2717 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2718 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2727 // This version is *not* safe, despite the name.
2729 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2733 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2738 va_start(val, format);
2740 vsprintf(buffer, format, val);
2743 len = strlen(buffer);
2745 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2746 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2749 strcpy(*str, buffer);
2755 #endif // USE_VSNPRINTF
2758 extern void pic16_initStack(int base_address, int size);
2759 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2760 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2761 extern void pic16_init_pic(char *);
2763 void pic16_pCodeInitRegisters(void)
2765 static int initialized=0;
2772 pic16_initStack(0xfff, 8);
2773 pic16_init_pic(port->processor);
2775 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2776 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2777 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2778 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2779 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2780 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2781 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2783 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2784 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2785 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2787 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80); // patch 15
2788 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80); // patch 15
2789 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80); // patch 15
2790 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80); // patch 15
2793 // pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80); // deprecated !
2795 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2796 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2797 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2798 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2799 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2800 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2802 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2803 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2804 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2805 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2806 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2808 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2809 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2810 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2811 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2812 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2814 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2815 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2816 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2817 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2818 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2820 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2821 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2823 pic16_pc_status.rIdx = IDX_STATUS;
2824 pic16_pc_intcon.rIdx = IDX_INTCON;
2825 pic16_pc_pcl.rIdx = IDX_PCL;
2826 pic16_pc_pclath.rIdx = IDX_PCLATH;
2827 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2828 pic16_pc_wreg.rIdx = IDX_WREG;
2829 pic16_pc_bsr.rIdx = IDX_BSR;
2831 pic16_pc_tosl.rIdx = IDX_TOSL;
2832 pic16_pc_tosh.rIdx = IDX_TOSH;
2833 pic16_pc_tosu.rIdx = IDX_TOSU;
2835 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL; // patch 15
2836 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH; // patch 15
2837 pic16_pc_tblptru.rIdx = IDX_TBLPTRU; // patch 15
2838 pic16_pc_tablat.rIdx = IDX_TABLAT; // patch 15
2840 // pic16_pc_fsr0.rIdx = IDX_FSR0;
2841 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2842 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2843 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2844 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2845 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2846 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2847 pic16_pc_indf0.rIdx = IDX_INDF0;
2848 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2849 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2850 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2851 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2852 pic16_pc_indf1.rIdx = IDX_INDF1;
2853 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2854 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2855 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2856 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2857 pic16_pc_indf2.rIdx = IDX_INDF2;
2858 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2859 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2860 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2861 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2862 pic16_pc_prodl.rIdx = IDX_PRODL;
2863 pic16_pc_prodh.rIdx = IDX_PRODH;
2865 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2866 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2867 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2869 pic16_pc_kzero.rIdx = IDX_KZ;
2870 pic16_pc_wsave.rIdx = IDX_WSAVE;
2871 pic16_pc_ssave.rIdx = IDX_SSAVE;
2873 /* probably should put this in a separate initialization routine */
2874 pb_dead_pcodes = newpBlock();
2879 /*-----------------------------------------------------------------*/
2880 /* mnem2key - convert a pic mnemonic into a hash key */
2881 /* (BTW - this spreads the mnemonics quite well) */
2883 /*-----------------------------------------------------------------*/
2885 int mnem2key(char const *mnem)
2894 key += toupper(*mnem++) +1;
2898 return (key & 0x1f);
2903 void pic16initMnemonics(void)
2908 pCodeInstruction *pci;
2910 if(mnemonics_initialized)
2913 // NULL out the array before making the assignments
2914 // since we check the array contents below this initialization.
2916 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2917 pic16Mnemonics[i] = NULL;
2920 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2921 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2922 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2923 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2924 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2925 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2926 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2927 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2928 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2929 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2930 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2931 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2932 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2933 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2934 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2935 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2936 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2937 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2938 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2939 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2940 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2941 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2942 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2943 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2944 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2945 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2946 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2947 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2948 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2949 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2950 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2951 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2952 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2953 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2954 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2955 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2956 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2957 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2958 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2959 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2960 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2961 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2962 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2963 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2964 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2965 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2966 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2967 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2968 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2969 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2970 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2971 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2972 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2973 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2974 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2975 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2976 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2977 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2978 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2979 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2980 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2981 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2982 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2983 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2984 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF; // was [POC_RLCF] !!!
2985 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2986 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2987 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2988 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2989 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2990 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2991 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2992 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2993 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2994 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2995 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2996 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2997 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2998 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2999 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3000 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD; // patch 15
3001 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC; //
3002 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC; //
3003 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC; //
3004 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT; //
3005 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC; //
3006 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC; //
3007 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC; // patch 15
3008 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3009 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3010 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3011 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3013 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3014 if(pic16Mnemonics[i])
3015 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3016 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3019 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3020 pci = hTabNextItem(pic16MnemonicsHash, &key);
3023 mnemonics_initialized = 1;
3026 int pic16_getpCodePeepCommand(char *cmd);
3028 int pic16_getpCode(char *mnem,unsigned dest)
3031 pCodeInstruction *pci;
3032 int key = mnem2key(mnem);
3034 if(!mnemonics_initialized)
3035 pic16initMnemonics();
3037 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3041 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3042 if((pci->num_ops <= 1)
3043 || (pci->isModReg == dest)
3045 || (pci->num_ops <= 2 && pci->isAccess)
3046 || (pci->num_ops <= 2 && pci->isFastCall)
3047 || (pci->num_ops <= 2 && pci->is2MemOp)
3048 || (pci->num_ops <= 2 && pci->is2LitOp) )
3052 pci = hTabNextItemWK (pic16MnemonicsHash);
3059 /*-----------------------------------------------------------------*
3060 * pic16initpCodePeepCommands
3062 *-----------------------------------------------------------------*/
3063 void pic16initpCodePeepCommands(void)
3071 hTabAddItem(&pic16pCodePeepCommandsHash,
3072 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3074 } while (peepCommands[i].cmd);
3076 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3079 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3080 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3085 /*-----------------------------------------------------------------
3088 *-----------------------------------------------------------------*/
3090 int pic16_getpCodePeepCommand(char *cmd)
3094 int key = mnem2key(cmd);
3097 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3100 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3101 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3105 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3112 static char getpBlock_dbName(pBlock *pb)
3118 return pb->cmemmap->dbName;
3122 void pic16_pBlockConvert2ISR(pBlock *pb)
3133 void pic16_pBlockConvert2Absolute(pBlock *pb)
3136 if(pb->cmemmap)pb->cmemmap = NULL;
3141 /*-----------------------------------------------------------------*/
3142 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3143 /* instances to the front of the doubly linked */
3144 /* list of pBlocks */
3145 /*-----------------------------------------------------------------*/
3147 void pic16_movepBlock2Head(char dbName)
3152 /* this can happen in sources without code,
3153 * only variable definitions */
3154 if(!the_pFile)return;
3156 pb = the_pFile->pbHead;
3160 if(getpBlock_dbName(pb) == dbName) {
3161 pBlock *pbn = pb->next;
3162 pb->next = the_pFile->pbHead;
3163 the_pFile->pbHead->prev = pb;
3164 the_pFile->pbHead = pb;
3167 pb->prev->next = pbn;
3169 // If the pBlock that we just moved was the last
3170 // one in the link of all of the pBlocks, then we
3171 // need to point the tail to the block just before
3172 // the one we moved.
3173 // Note: if pb->next is NULL, then pb must have
3174 // been the last pBlock in the chain.
3177 pbn->prev = pb->prev;
3179 the_pFile->pbTail = pb->prev;
3190 void pic16_copypCode(FILE *of, char dbName)
3194 if(!of || !the_pFile)
3197 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3198 if(getpBlock_dbName(pb) == dbName) {
3199 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3201 pic16_printpBlock(of,pb);
3206 void pic16_pcode_test(void)
3209 DFPRINTF((stderr,"pcode is alive!\n"));
3219 /* create the file name */
3220 strcpy(buffer,dstFileName);
3221 strcat(buffer,".p");
3223 if( !(pFile = fopen(buffer, "w" ))) {
3224 werror(E_FILE_OPEN_ERR,buffer);
3228 fprintf(pFile,"pcode dump\n\n");
3230 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3231 fprintf(pFile,"\n\tNew pBlock\n\n");
3233 fprintf(pFile,"%s",pb->cmemmap->sname);
3235 fprintf(pFile,"internal pblock");
3237 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3238 pic16_printpBlock(pFile,pb);
3242 /*-----------------------------------------------------------------*/
3243 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3244 /* ister, RegCond will return the bit being referenced. */
3246 /* fixme - why not just OR in the pcop bit field */
3247 /*-----------------------------------------------------------------*/
3249 static int RegCond(pCodeOp *pcop)
3255 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3256 switch(PCORB(pcop)->bit) {
3270 /*-----------------------------------------------------------------*/
3271 /* pic16_newpCode - create and return a newly initialized pCode */
3273 /* fixme - rename this */
3275 /* The purpose of this routine is to create a new Instruction */
3276 /* pCode. This is called by gen.c while the assembly code is being */
3280 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3281 /* (note that the op is analogous to but not the */
3282 /* same thing as the opcode of the instruction.) */
3283 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3286 /* a pointer to the new malloc'd pCode is returned. */
3290 /*-----------------------------------------------------------------*/
3291 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3293 pCodeInstruction *pci ;
3295 if(!mnemonics_initialized)
3296 pic16initMnemonics();
3298 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3300 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3301 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3304 if(pci->inCond & PCC_EXAMINE_PCOP)
3305 pci->inCond |= RegCond(pcop);
3307 if(pci->outCond & PCC_EXAMINE_PCOP)
3308 pci->outCond |= RegCond(pcop);
3310 pci->pc.prev = pci->pc.next = NULL;
3311 return (pCode *)pci;
3314 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3320 /*-----------------------------------------------------------------*/
3321 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3323 /* Wild pcodes are used during the peep hole optimizer to serve */
3324 /* as place holders for any instruction. When a snippet of code is */
3325 /* compared to a peep hole rule, the wild card opcode will match */
3326 /* any instruction. However, the optional operand and label are */
3327 /* additional qualifiers that must also be matched before the */
3328 /* line (of assembly code) is declared matched. Note that the */
3329 /* operand may be wild too. */
3331 /* Note, a wild instruction is specified just like a wild var: */
3332 /* %4 ; A wild instruction, */
3333 /* See the peeph.def file for additional examples */
3335 /*-----------------------------------------------------------------*/
3337 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3342 pcw = Safe_calloc(1,sizeof(pCodeWild));
3344 pcw->pci.pc.type = PC_WILD;
3345 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3346 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3347 pcw->pci.pc.pb = NULL;
3349 // pcw->pci.pc.analyze = genericAnalyze;
3350 pcw->pci.pc.destruct = genericDestruct;
3351 pcw->pci.pc.print = genericPrint;
3353 pcw->id = pCodeID; // this is the 'n' in %n
3354 pcw->operand = optional_operand;
3355 pcw->label = optional_label;
3357 pcw->mustBeBitSkipInst = 0;
3358 pcw->mustNotBeBitSkipInst = 0;
3359 pcw->invertBitSkipInst = 0;
3361 return ( (pCode *)pcw);
3365 /*-----------------------------------------------------------------*/
3366 /* newPcodeInlineP - create a new pCode from a char string */
3367 /*-----------------------------------------------------------------*/
3370 pCode *pic16_newpCodeInlineP(char *cP)
3375 pcc = Safe_calloc(1,sizeof(pCodeComment));
3377 pcc->pc.type = PC_INLINE;
3378 pcc->pc.prev = pcc->pc.next = NULL;
3379 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3382 // pcc->pc.analyze = genericAnalyze;
3383 pcc->pc.destruct = genericDestruct;
3384 pcc->pc.print = genericPrint;
3387 pcc->comment = Safe_strdup(cP);
3389 pcc->comment = NULL;
3391 return ( (pCode *)pcc);
3395 /*-----------------------------------------------------------------*/
3396 /* newPcodeCharP - create a new pCode from a char string */
3397 /*-----------------------------------------------------------------*/
3399 pCode *pic16_newpCodeCharP(char *cP)
3404 pcc = Safe_calloc(1,sizeof(pCodeComment));
3406 pcc->pc.type = PC_COMMENT;
3407 pcc->pc.prev = pcc->pc.next = NULL;
3408 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3411 // pcc->pc.analyze = genericAnalyze;
3412 pcc->pc.destruct = genericDestruct;
3413 pcc->pc.print = genericPrint;
3416 pcc->comment = Safe_strdup(cP);
3418 pcc->comment = NULL;
3420 return ( (pCode *)pcc);
3424 /*-----------------------------------------------------------------*/
3425 /* pic16_newpCodeFunction - */
3426 /*-----------------------------------------------------------------*/
3429 pCode *pic16_newpCodeFunction(char *mod,char *f)
3433 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3435 pcf->pc.type = PC_FUNCTION;
3436 pcf->pc.prev = pcf->pc.next = NULL;
3437 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3440 // pcf->pc.analyze = genericAnalyze;
3441 pcf->pc.destruct = genericDestruct;
3442 pcf->pc.print = pCodePrintFunction;
3447 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3448 strcpy(pcf->modname,mod);
3450 pcf->modname = NULL;
3453 pcf->fname = Safe_calloc(1,strlen(f)+1);
3454 strcpy(pcf->fname,f);
3458 return ( (pCode *)pcf);
3462 /*-----------------------------------------------------------------*/
3463 /* pic16_newpCodeFlow */
3464 /*-----------------------------------------------------------------*/
3465 static void destructpCodeFlow(pCode *pc)
3467 if(!pc || !isPCFL(pc))
3474 pic16_unlinkpCode(pc);
3476 deleteSet(&PCFL(pc)->registers);
3477 deleteSet(&PCFL(pc)->from);
3478 deleteSet(&PCFL(pc)->to);
3483 pCode *pic16_newpCodeFlow(void )
3487 //_ALLOC(pcflow,sizeof(pCodeFlow));
3488 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3490 pcflow->pc.type = PC_FLOW;
3491 pcflow->pc.prev = pcflow->pc.next = NULL;
3492 pcflow->pc.pb = NULL;
3494 // pcflow->pc.analyze = genericAnalyze;
3495 pcflow->pc.destruct = destructpCodeFlow;
3496 pcflow->pc.print = genericPrint;
3498 pcflow->pc.seq = GpcFlowSeq++;
3500 pcflow->from = pcflow->to = NULL;
3502 pcflow->inCond = PCC_NONE;
3503 pcflow->outCond = PCC_NONE;
3505 pcflow->firstBank = -1;
3506 pcflow->lastBank = -1;
3508 pcflow->FromConflicts = 0;
3509 pcflow->ToConflicts = 0;
3513 pcflow->registers = newSet();
3515 return ( (pCode *)pcflow);
3519 /*-----------------------------------------------------------------*/
3520 /*-----------------------------------------------------------------*/
3521 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3523 pCodeFlowLink *pcflowLink;
3525 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3527 pcflowLink->pcflow = pcflow;
3528 pcflowLink->bank_conflict = 0;
3533 /*-----------------------------------------------------------------*/
3534 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3535 /*-----------------------------------------------------------------*/
3537 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3542 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3544 pccs->pc.type = PC_CSOURCE;
3545 pccs->pc.prev = pccs->pc.next = NULL;
3548 pccs->pc.destruct = genericDestruct;
3549 pccs->pc.print = genericPrint;
3551 pccs->line_number = ln;
3553 pccs->line = Safe_strdup(l);
3558 pccs->file_name = Safe_strdup(f);
3560 pccs->file_name = NULL;
3562 return ( (pCode *)pccs);
3567 /*******************************************************************/
3568 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3569 /* added by VR 6-Jun-2003 */
3570 /*******************************************************************/
3572 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3579 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3580 pcad->pci.pc.type = PC_ASMDIR;
3581 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3582 pcad->pci.pc.pb = NULL;
3584 pcad->pci.pc.destruct = genericDestruct;
3585 pcad->pci.pc.print = genericPrint;
3587 if(asdir && *asdir) {
3589 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3591 pcad->directive = Safe_strdup( asdir );
3594 va_start(ap, argfmt);
3596 memset(buffer, 0, sizeof(buffer));
3597 if(argfmt && *argfmt)
3598 vsprintf(buffer, argfmt, ap);
3602 while(isspace(*lbp))lbp++;
3605 pcad->arg = Safe_strdup( lbp );
3607 return ((pCode *)pcad);
3610 /*-----------------------------------------------------------------*/
3611 /* pCodeLabelDestruct - free memory used by a label. */
3612 /*-----------------------------------------------------------------*/
3613 static void pCodeLabelDestruct(pCode *pc)
3619 if((pc->type == PC_LABEL) && PCL(pc)->label)
3620 free(PCL(pc)->label);
3626 pCode *pic16_newpCodeLabel(char *name, int key)
3632 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3634 pcl->pc.type = PC_LABEL;
3635 pcl->pc.prev = pcl->pc.next = NULL;
3636 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3639 // pcl->pc.analyze = genericAnalyze;
3640 pcl->pc.destruct = pCodeLabelDestruct;
3641 pcl->pc.print = pCodePrintLabel;
3647 sprintf(s,"_%05d_DS_",key);
3652 pcl->label = Safe_strdup(s);
3654 return ( (pCode *)pcl);
3659 /*-----------------------------------------------------------------*/
3660 /* newpBlock - create and return a pointer to a new pBlock */
3661 /*-----------------------------------------------------------------*/
3662 static pBlock *newpBlock(void)
3667 PpB = Safe_calloc(1,sizeof(pBlock) );
3668 PpB->next = PpB->prev = NULL;
3670 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3671 PpB->tregisters = NULL;
3673 PpB->FlowTree = NULL;
3679 /*-----------------------------------------------------------------*/
3680 /* pic16_newpCodeChain - create a new chain of pCodes */
3681 /*-----------------------------------------------------------------*
3683 * This function will create a new pBlock and the pointer to the
3684 * pCode that is passed in will be the first pCode in the block.
3685 *-----------------------------------------------------------------*/
3688 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3691 pBlock *pB = newpBlock();
3693 pB->pcHead = pB->pcTail = pc;
3700 /*-----------------------------------------------------------------*/
3701 /* pic16_newpCodeOpLabel - Create a new label given the key */
3702 /* Note, a negative key means that the label is part of wild card */
3703 /* (and hence a wild card label) used in the pCodePeep */
3704 /* optimizations). */
3705 /*-----------------------------------------------------------------*/
3707 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3710 static int label_key=-1;
3714 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3715 pcop->type = PO_LABEL;
3720 sprintf(s=buffer,"_%05d_DS_",key);
3722 s = name, key = label_key--;
3725 pcop->name = Safe_strdup(s);
3727 ((pCodeOpLabel *)pcop)->key = key;
3729 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3733 /*-----------------------------------------------------------------*/
3734 /*-----------------------------------------------------------------*/
3735 pCodeOp *pic16_newpCodeOpLit(int lit)
3741 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3742 pcop->type = PO_LITERAL;
3746 sprintf(s,"0x%02x",lit);
3748 pcop->name = Safe_strdup(s);
3751 ((pCodeOpLit *)pcop)->lit = lit;
3756 /*-----------------------------------------------------------------*/
3757 /*-----------------------------------------------------------------*/
3758 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3760 char *s = buffer, tbuf[256], *tb=tbuf;
3764 tb = pic16_get_op(arg2, NULL, 0);
3765 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3766 pcop->type = PO_LITERAL;
3770 sprintf(s,"0x%02x, %s",lit, tb);
3772 pcop->name = Safe_strdup(s);
3775 ((pCodeOpLit2 *)pcop)->lit = lit;
3776 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3781 /*-----------------------------------------------------------------*/
3782 /*-----------------------------------------------------------------*/
3783 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3787 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3788 pcop->type = PO_IMMEDIATE;
3790 regs *r = pic16_dirregWithName(name);
3791 pcop->name = Safe_strdup(name);
3795 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3796 PCOI(pcop)->rIdx = r->rIdx;
3798 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3799 // __FILE__, __LINE__, __FUNCTION__, name);
3800 PCOI(pcop)->rIdx = -1;
3802 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3807 PCOI(pcop)->index = index;
3808 PCOI(pcop)->offset = offset;
3809 PCOI(pcop)->_const = code_space;
3814 /*-----------------------------------------------------------------*/
3815 /*-----------------------------------------------------------------*/
3816 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3822 if(!pcwb || !subtype) {
3823 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3827 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3828 pcop->type = PO_WILD;
3829 sprintf(s,"%%%d",id);
3830 pcop->name = Safe_strdup(s);
3832 PCOW(pcop)->id = id;
3833 PCOW(pcop)->pcwb = pcwb;
3834 PCOW(pcop)->subtype = subtype;
3835 PCOW(pcop)->matched = NULL;
3840 /*-----------------------------------------------------------------*/
3841 /*-----------------------------------------------------------------*/
3842 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3846 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3847 pcop->type = PO_GPR_BIT;
3849 pcop->name = Safe_strdup(s);
3853 PCORB(pcop)->bit = bit;
3854 PCORB(pcop)->inBitSpace = inBitSpace;
3856 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3857 PCOR(pcop)->r = NULL;
3858 PCOR(pcop)->rIdx = 0;
3862 /*-----------------------------------------------------------------*
3863 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3865 * If rIdx >=0 then a specific register from the set of registers
3866 * will be selected. If rIdx <0, then a new register will be searched
3868 *-----------------------------------------------------------------*/
3870 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3874 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3879 PCOR(pcop)->rIdx = rIdx;
3880 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3882 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3885 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3887 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3888 __FUNCTION__, __LINE__);
3893 pcop->type = PCOR(pcop)->r->pc_type;
3898 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3903 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3904 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3905 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3906 pcop->type = PCOR(pcop)->r->pc_type;
3907 pcop->name = PCOR(pcop)->r->name;
3909 // if(pic16_pcode_verbose) {
3910 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3911 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3917 /*-----------------------------------------------------------------*/
3918 /*-----------------------------------------------------------------*/
3920 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3927 pcop = pic16_newpCodeOpBit(name, -1,0);
3931 pcop = pic16_newpCodeOpLit(-1);
3935 pcop = pic16_newpCodeOpLabel(NULL,-1);
3938 pcop = pic16_newpCodeOpReg(-1);
3941 case PO_GPR_REGISTER:
3943 pcop = pic16_newpCodeOpRegFromStr(name);
3945 pcop = pic16_newpCodeOpReg(-1);
3949 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3952 pcop->name = Safe_strdup(name);
3961 typedef struct DBdata
3968 static int DBd_init = -1;
3970 /*-----------------------------------------------------------------*/
3971 /* Add "DB" directives to a pBlock */
3972 /*-----------------------------------------------------------------*/
3973 void pic16_emitDB(pBlock *pb, char c)
3976 if (DBd_init<0) // we need to initialize
3980 DBd.buffer[0] = '\0';
3983 l = strlen(DBd.buffer);
3987 sprintf(DBd.buffer+l,", 0x%02x", c & 0xff);
3991 sprintf(DBd.buffer,"0x%02x", c & 0xff);
3998 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4000 DBd.buffer[0] = '\0';
4005 /*-----------------------------------------------------------------*/
4006 /* Flush pending "DB" data to a pBlock */
4007 /*-----------------------------------------------------------------*/
4008 void pic16_flushDB(pBlock *pb)
4012 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4014 DBd.buffer[0] = '\0';
4018 /*-----------------------------------------------------------------*/
4019 /*-----------------------------------------------------------------*/
4020 void pic16_pCodeConstString(char *name, char *value)
4024 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4029 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4031 pic16_addpBlock(pb);
4033 sprintf(buffer,"; %s = %s",name,value);
4035 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4036 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4039 pic16_emitDB(pb, *value);
4044 /*-----------------------------------------------------------------*/
4045 /*-----------------------------------------------------------------*/
4047 static void pCodeReadCodeTable(void)
4051 fprintf(stderr, " %s\n",__FUNCTION__);
4053 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4055 pic16_addpBlock(pb);
4057 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4058 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4059 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4060 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4062 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4063 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4064 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4065 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4070 /*-----------------------------------------------------------------*/
4071 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4072 /*-----------------------------------------------------------------*/
4073 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4080 /* If this is the first pcode to be added to a block that
4081 * was initialized with a NULL pcode, then go ahead and
4082 * make this pcode the head and tail */
4083 pb->pcHead = pb->pcTail = pc;
4086 pb->pcTail->next = pc;
4088 pc->prev = pb->pcTail;
4095 /*-----------------------------------------------------------------*/
4096 /* pic16_addpBlock - place a pBlock into the pFile */
4097 /*-----------------------------------------------------------------*/
4098 void pic16_addpBlock(pBlock *pb)
4100 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4103 /* First time called, we'll pass through here. */
4104 //_ALLOC(the_pFile,sizeof(pFile));
4105 the_pFile = Safe_calloc(1,sizeof(pFile));
4106 the_pFile->pbHead = the_pFile->pbTail = pb;
4107 the_pFile->functions = NULL;
4111 the_pFile->pbTail->next = pb;
4112 pb->prev = the_pFile->pbTail;
4114 the_pFile->pbTail = pb;
4117 /*-----------------------------------------------------------------*/
4118 /* removepBlock - remove a pBlock from the pFile */
4119 /*-----------------------------------------------------------------*/
4120 static void removepBlock(pBlock *pb)
4128 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4130 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4133 if(pbs == the_pFile->pbHead)
4134 the_pFile->pbHead = pbs->next;
4136 if (pbs == the_pFile->pbTail)
4137 the_pFile->pbTail = pbs->prev;
4140 pbs->next->prev = pbs->prev;
4143 pbs->prev->next = pbs->next;
4150 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4154 /*-----------------------------------------------------------------*/
4155 /* printpCode - write the contents of a pCode to a file */
4156 /*-----------------------------------------------------------------*/
4157 static void printpCode(FILE *of, pCode *pc)
4168 fprintf(of,"warning - unable to print pCode\n");
4171 /*-----------------------------------------------------------------*/
4172 /* pic16_printpBlock - write the contents of a pBlock to a file */
4173 /*-----------------------------------------------------------------*/
4174 void pic16_printpBlock(FILE *of, pBlock *pb)
4183 if(pb->dbName == 'A') {
4187 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
4189 // fprintf(of, "%s\tcode\t%d"
4193 for(pc = pb->pcHead; pc; pc = pc->next) {
4194 if(isPCF(pc) && PCF(pc)->fname) {
4195 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4196 if(pb->dbName == 'A') {
4198 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
4199 if(!strcmp(ab->name, PCF(pc)->fname)) {
4200 fprintf(of, "\t0X%06X", ab->address);
4210 /*-----------------------------------------------------------------*/
4212 /* pCode processing */
4216 /*-----------------------------------------------------------------*/
4218 void pic16_unlinkpCode(pCode *pc)
4224 fprintf(stderr,"Unlinking: ");
4225 printpCode(stderr, pc);
4228 pc->prev->next = pc->next;
4230 pc->next->prev = pc->prev;
4232 pc->prev = pc->next = NULL;
4236 /*-----------------------------------------------------------------*/
4237 /*-----------------------------------------------------------------*/
4239 static void genericDestruct(pCode *pc)
4242 pic16_unlinkpCode(pc);
4245 /* For instructions, tell the register (if there's one used)
4246 * that it's no longer needed */
4247 regs *reg = pic16_getRegFromInstruction(pc);
4249 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4251 if(PCI(pc)->is2MemOp) {
4252 reg = pic16_getRegFromInstruction2(pc);
4254 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4258 /* Instead of deleting the memory used by this pCode, mark
4259 * the object as bad so that if there's a pointer to this pCode
4260 * dangling around somewhere then (hopefully) when the type is
4261 * checked we'll catch it.
4266 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4274 /*-----------------------------------------------------------------*/
4275 /*-----------------------------------------------------------------*/
4276 /* modifiers for constant immediate */
4277 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4279 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4284 int use_buffer = 1; // copy the string to the passed buffer pointer
4289 use_buffer = 0; // Don't bother copying the string to the buffer.
4293 switch(pcop->type) {
4299 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4302 return PCOR(pcop)->r->name;
4305 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4307 SAFE_snprintf(&buffer,&size,"%s",r->name);
4314 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4315 if(PCOI(pcop)->index) {
4316 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4317 immdmod[ PCOI(pcop)->offset ],
4321 SAFE_snprintf(&s,&size,"%s(%s)",
4322 immdmod[ PCOI(pcop)->offset ],
4326 if(PCOI(pcop)->index) {
4327 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4332 SAFE_snprintf(&s,&size, "%s(%s)",
4341 // size = sizeof(buffer);
4342 if( PCOR(pcop)->instance) {
4343 SAFE_snprintf(&s,&size,"(%s + %d)",
4345 PCOR(pcop)->instance );
4347 SAFE_snprintf(&s,&size,"%s",pcop->name);
4354 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4363 return "NO operand1";
4366 /*-----------------------------------------------------------------*/
4367 /* pic16_get_op2 - variant to support two memory operand commands */
4368 /*-----------------------------------------------------------------*/
4369 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4374 int use_buffer = 1; // copy the string to the passed buffer pointer
4379 use_buffer = 0; // Don't bother copying the string to the buffer.
4383 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",
4384 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4385 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4389 switch(PCOR2(pcop)->pcop2->type) {
4395 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4398 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4401 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4404 SAFE_snprintf(&buffer,&size,"%s",r->name);
4415 if(PCOI(pcop)->_const) {
4416 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4417 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4420 8 * PCOI(pcop)->offset );
4422 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4424 if( PCOI(pcop)->index) {
4425 SAFE_snprintf(&s,&size,"(%s + %d)",
4427 PCOI(pcop)->index );
4429 if(PCOI(pcop)->offset)
4430 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4432 SAFE_snprintf(&s,&size,"%s",pcop->name);
4439 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4440 SAFE_snprintf(&s,&size,"(%s + %d)",
4441 PCOR(PCOR2(pcop)->pcop2)->r->name,
4442 PCOR(PCOR2(pcop)->pcop2)->instance );
4444 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4449 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4451 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4454 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4459 return "NO operand2";
4462 /*-----------------------------------------------------------------*/
4463 /*-----------------------------------------------------------------*/
4464 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4468 return pic16_get_op(pcc->pcop,NULL,0);
4470 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4471 * return ("ERROR Null: "__FUNCTION__);
4473 return ("ERROR Null: pic16_get_op_from_instruction");
4477 /*-----------------------------------------------------------------*/
4478 /*-----------------------------------------------------------------*/
4479 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4482 fprintf(of,"pcodeopprint- not implemented\n");
4485 /*-----------------------------------------------------------------*/
4486 /* pic16_pCode2str - convert a pCode instruction to string */
4487 /*-----------------------------------------------------------------*/
4488 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4494 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4495 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4496 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4504 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4506 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4508 if(PCI(pc)->is2MemOp) {
4509 SAFE_snprintf(&s,&size, "%s, %s",
4510 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4511 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4515 if(PCI(pc)->is2LitOp) {
4516 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4520 if(PCI(pc)->isBitInst) {
4521 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4522 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4523 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4524 PCI(pc)->pcop->name ,
4525 PCI(pc)->pcop->name );
4527 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4528 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4529 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4530 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4532 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4533 //PCI(pc)->pcop->t.bit );
4536 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4537 if( PCI(pc)->num_ops == 3)
4538 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4540 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4543 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4545 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4546 if(PCI(pc)->num_ops == 3)
4547 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4549 r = pic16_getRegFromInstruction(pc);
4550 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4551 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4553 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4562 /* assuming that comment ends with a \n */
4563 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4567 /* assuming that inline code ends with a \n */
4568 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4572 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4575 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4578 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4581 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4584 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4587 if(PCAD(pc)->directive) {
4588 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4591 /* special case to handle inline labels without a tab */
4592 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4597 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4604 /*-----------------------------------------------------------------*/
4605 /* genericPrint - the contents of a pCode to a file */
4606 /*-----------------------------------------------------------------*/
4607 static void genericPrint(FILE *of, pCode *pc)
4615 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4619 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4623 // If the opcode has a label, print that first
4625 pBranch *pbl = PCI(pc)->label;
4626 while(pbl && pbl->pc) {
4627 if(pbl->pc->type == PC_LABEL)
4628 pCodePrintLabel(of, pbl->pc);
4634 genericPrint(of,PCODE(PCI(pc)->cline));
4639 pic16_pCode2str(str, 256, pc);
4641 fprintf(of,"%s",str);
4643 if(pic16_debug_verbose) {
4644 fprintf(of, "\t;key=%03x",pc->seq);
4646 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4653 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4654 if(PCW(pc)->pci.label)
4655 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4657 if(PCW(pc)->operand) {
4658 fprintf(of,";\toperand ");
4659 pCodeOpPrint(of,PCW(pc)->operand );
4664 if(pic16_debug_verbose) {
4665 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4666 if(PCFL(pc)->ancestor)
4667 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4674 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4679 pBranch *pbl = PCAD(pc)->pci.label;
4680 while(pbl && pbl->pc) {
4681 if(pbl->pc->type == PC_LABEL)
4682 pCodePrintLabel(of, pbl->pc);
4686 if(PCAD(pc)->directive) {
4687 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4690 /* special case to handle inline labels without tab */
4691 fprintf(of, "%s\n", PCAD(pc)->arg);
4697 fprintf(of,"unknown pCode type %d\n",pc->type);
4702 /*-----------------------------------------------------------------*/
4703 /* pCodePrintFunction - prints function begin/end */
4704 /*-----------------------------------------------------------------*/
4706 static void pCodePrintFunction(FILE *of, pCode *pc)
4713 if( ((pCodeFunction *)pc)->modname)
4714 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4717 if(PCF(pc)->fname) {
4718 pBranch *exits = PCF(pc)->to;
4720 fprintf(of,"%s", PCF(pc)->fname);
4722 // if(pic16_pcode_verbose)
4723 fprintf(of, "\t;Function start");
4729 exits = exits->next;
4733 if(pic16_pcode_verbose)
4734 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4737 if((PCF(pc)->from &&
4738 PCF(pc)->from->pc->type == PC_FUNCTION &&
4739 PCF(PCF(pc)->from->pc)->fname) ) {
4741 if(pic16_pcode_verbose)
4742 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4744 if(pic16_pcode_verbose)
4745 fprintf(of,"; exit point [can't find entry point]\n");
4750 /*-----------------------------------------------------------------*/
4751 /* pCodePrintLabel - prints label */
4752 /*-----------------------------------------------------------------*/
4754 static void pCodePrintLabel(FILE *of, pCode *pc)
4761 fprintf(of,"%s:\n",PCL(pc)->label);
4762 else if (PCL(pc)->key >=0)
4763 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4765 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4768 /*-----------------------------------------------------------------*/
4769 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4770 /* remove it if it is found. */
4771 /*-----------------------------------------------------------------*/
4772 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4779 if(pcl->type == PC_OPCODE)
4780 b = PCI(pcl)->label;
4782 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4787 //fprintf (stderr, "%s \n",__FUNCTION__);
4788 //pcl->print(stderr,pcl);
4789 //pc->print(stderr,pc);
4792 //fprintf (stderr, "found label\n");
4793 //pc->print(stderr, pc);
4797 bprev->next = b->next; /* Not first pCode in chain */
4801 PCI(pcl)->label = b->next; /* First pCode in chain */
4804 return; /* A label can't occur more than once */
4812 /*-----------------------------------------------------------------*/
4813 /*-----------------------------------------------------------------*/
4814 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4833 /*-----------------------------------------------------------------*/
4834 /* pBranchLink - given two pcodes, this function will link them */
4835 /* together through their pBranches */
4836 /*-----------------------------------------------------------------*/
4837 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4841 // Declare a new branch object for the 'from' pCode.
4843 //_ALLOC(b,sizeof(pBranch));
4844 b = Safe_calloc(1,sizeof(pBranch));
4845 b->pc = PCODE(t); // The link to the 'to' pCode.
4848 f->to = pic16_pBranchAppend(f->to,b);
4850 // Now do the same for the 'to' pCode.
4852 //_ALLOC(b,sizeof(pBranch));
4853 b = Safe_calloc(1,sizeof(pBranch));
4857 t->from = pic16_pBranchAppend(t->from,b);
4862 /*-----------------------------------------------------------------*/
4863 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4865 /*-----------------------------------------------------------------*/
4866 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4879 /*-----------------------------------------------------------------*/
4880 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4881 /*-----------------------------------------------------------------*/
4882 static void pCodeUnlink(pCode *pc)
4887 if(!pc->prev || !pc->next) {
4888 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4892 /* first remove the pCode from the chain */
4893 pc->prev->next = pc->next;
4894 pc->next->prev = pc->prev;
4896 /* Now for the hard part... */
4898 /* Remove the branches */
4902 pc1 = pb1->pc; /* Get the pCode that branches to the
4903 * one we're unlinking */
4905 /* search for the link back to this pCode (the one we're
4907 if(pb2 = pBranchFind(pc1->to,pc)) {
4908 pb2->pc = pc->to->pc; // make the replacement
4910 /* if the pCode we're unlinking contains multiple 'to'
4911 * branches (e.g. this a skip instruction) then we need
4912 * to copy these extra branches to the chain. */
4914 pic16_pBranchAppend(pb2, pc->to->next);
4923 /*-----------------------------------------------------------------*/
4924 /*-----------------------------------------------------------------*/
4926 static void genericAnalyze(pCode *pc)
4936 // Go through the pCodes that are in pCode chain and link
4937 // them together through the pBranches. Note, the pCodes
4938 // are linked together as a contiguous stream like the
4939 // assembly source code lines. The linking here mimics this
4940 // except that comments are not linked in.
4942 pCode *npc = pc->next;
4944 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4945 pBranchLink(pc,npc);
4950 /* reached the end of the pcode chain without finding
4951 * an instruction we could link to. */
4955 fprintf(stderr,"analyze PC_FLOW\n");
4959 fprintf(stderr,,";A bad pCode is being used\n");
4965 /*-----------------------------------------------------------------*/
4966 /*-----------------------------------------------------------------*/
4967 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4971 if(pc->type == PC_LABEL) {
4972 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4975 if((pc->type == PC_OPCODE)
4976 || (pc->type == PC_ASMDIR)
4978 pbr = PCI(pc)->label;
4980 if(pbr->pc->type == PC_LABEL) {
4981 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4991 /*-----------------------------------------------------------------*/
4992 /*-----------------------------------------------------------------*/
4993 static int checkLabel(pCode *pc)
4997 if(pc && isPCI(pc)) {
4998 pbr = PCI(pc)->label;
5000 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5010 /*-----------------------------------------------------------------*/
5011 /* findLabelinpBlock - Search the pCode for a particular label */
5012 /*-----------------------------------------------------------------*/
5013 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5020 for(pc = pb->pcHead; pc; pc = pc->next)
5021 if(compareLabel(pc,pcop_label))
5027 /*-----------------------------------------------------------------*/
5028 /* findLabel - Search the pCode for a particular label */
5029 /*-----------------------------------------------------------------*/
5030 static pCode * findLabel(pCodeOpLabel *pcop_label)
5038 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5039 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5043 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5047 /*-----------------------------------------------------------------*/
5048 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5049 /* in the linked list */
5050 /*-----------------------------------------------------------------*/
5051 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5064 /*-----------------------------------------------------------------*/
5065 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5066 /* in the linked list */
5067 /*-----------------------------------------------------------------*/
5068 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5082 //#define PCODE_DEBUG
5083 /*-----------------------------------------------------------------*/
5084 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5085 /* in the linked list */
5086 /*-----------------------------------------------------------------*/
5087 pCode * pic16_findNextInstruction(pCode *pci)
5092 if((pc->type == PC_OPCODE)
5093 || (pc->type == PC_WILD)
5094 || (pc->type == PC_ASMDIR)
5099 fprintf(stderr,"pic16_findNextInstruction: ");
5100 printpCode(stderr, pc);
5105 //fprintf(stderr,"Couldn't find instruction\n");
5109 /*-----------------------------------------------------------------*/
5110 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5111 /* in the linked list */
5112 /*-----------------------------------------------------------------*/
5113 pCode * pic16_findPrevInstruction(pCode *pci)
5118 if((pc->type == PC_OPCODE)
5119 || (pc->type == PC_WILD)
5120 || (pc->type == PC_ASMDIR)
5126 fprintf(stderr,"pic16_findPrevInstruction: ");
5127 printpCode(stderr, pc);
5132 //fprintf(stderr,"Couldn't find instruction\n");
5139 /*-----------------------------------------------------------------*/
5140 /* findFunctionEnd - given a pCode find the end of the function */
5141 /* that contains it */
5142 /*-----------------------------------------------------------------*/
5143 static pCode * findFunctionEnd(pCode *pc)
5147 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5153 fprintf(stderr,"Couldn't find function end\n");
5158 /*-----------------------------------------------------------------*/
5159 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5160 /* instruction with which it is associated. */
5161 /*-----------------------------------------------------------------*/
5162 static void AnalyzeLabel(pCode *pc)
5171 static void AnalyzeGOTO(pCode *pc)
5174 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5178 static void AnalyzeSKIP(pCode *pc)
5181 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5182 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5186 static void AnalyzeRETURN(pCode *pc)
5189 // branch_link(pc,findFunctionEnd(pc->next));
5195 /*-----------------------------------------------------------------*/
5196 /*-----------------------------------------------------------------*/
5197 regs * pic16_getRegFromInstruction(pCode *pc)
5203 PCI(pc)->num_ops == 0 ||
5204 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5208 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5209 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5212 switch(PCI(pc)->pcop->type) {
5218 return PCOR(PCI(pc)->pcop)->r;
5220 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5224 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5225 return PCOR(PCI(pc)->pcop)->r;
5228 if(PCOI(PCI(pc)->pcop)->r)
5229 return (PCOI(PCI(pc)->pcop)->r);
5231 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
5232 return pic16_dirregWithName(PCI(pc)->pcop->name);
5233 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5236 return PCOR(PCI(pc)->pcop)->r;
5239 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5240 return PCOR(PCI(pc)->pcop)->r;
5242 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5246 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5247 // genericPrint(stderr, pc);
5255 /*-------------------------------------------------------------------------------*/
5256 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5257 /*-------------------------------------------------------------------------------*/
5258 regs * pic16_getRegFromInstruction2(pCode *pc)
5264 PCI(pc)->num_ops == 0 ||
5265 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5270 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5271 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5275 * operands supported in MOVFF:
5282 switch(PCI(pc)->pcop->type) {
5288 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5290 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5294 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5295 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5300 // if(PCOI(PCI(pc)->pcop)->r)
5301 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5303 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5304 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5305 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5310 // return PCOR2(PCI(pc)->pcop)->r;
5313 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5314 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5318 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5321 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5322 //genericPrint(stderr, pc);
5330 /*-----------------------------------------------------------------*/
5331 /*-----------------------------------------------------------------*/
5333 static void AnalyzepBlock(pBlock *pb)
5340 /* Find all of the registers used in this pBlock
5341 * by looking at each instruction and examining it's
5344 for(pc = pb->pcHead; pc; pc = pc->next) {
5346 /* Is this an instruction with operands? */
5347 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5349 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5351 /* Loop through all of the registers declared so far in
5352 this block and see if we find this one there */
5354 regs *r = setFirstItem(pb->tregisters);
5357 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5358 PCOR(PCI(pc)->pcop)->r = r;
5361 r = setNextItem(pb->tregisters);
5365 /* register wasn't found */
5366 //r = Safe_calloc(1, sizeof(regs));
5367 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5368 //addSet(&pb->tregisters, r);
5369 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5370 //PCOR(PCI(pc)->pcop)->r = r;
5371 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5373 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5376 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5377 if(PCOR(PCI(pc)->pcop)->r) {
5378 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5379 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5381 if(PCI(pc)->pcop->name)
5382 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5384 fprintf(stderr,"ERROR: NULL register\n");
5393 /*-----------------------------------------------------------------*/
5395 /*-----------------------------------------------------------------*/
5396 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5398 static void InsertpFlow(pCode *pc, pCode **pflow)
5401 PCFL(*pflow)->end = pc;
5403 if(!pc || !pc->next)
5406 *pflow = pic16_newpCodeFlow();
5407 pic16_pCodeInsertAfter(pc, *pflow);
5410 /*-----------------------------------------------------------------*/
5411 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5412 /* the flow blocks. */
5414 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5415 * point the instruction flow changes.
5417 /*-----------------------------------------------------------------*/
5418 void pic16_BuildFlow(pBlock *pb)
5421 pCode *last_pci=NULL;
5428 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5429 /* Insert a pCodeFlow object at the beginning of a pBlock */
5431 InsertpFlow(pb->pcHead, &pflow);
5433 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5434 //pflow->next = pb->pcHead; /* Make the current head the next object */
5435 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5436 //pb->pcHead = pflow; /* Make the Flow object the head */
5439 for( pc = pic16_findNextInstruction(pb->pcHead);
5441 pc=pic16_findNextInstruction(pc)) {
5444 PCI(pc)->pcflow = PCFL(pflow);
5446 //fprintf(stderr," build: ");
5447 //pflow->print(stderr,pflow);
5449 if( PCI(pc)->isSkip) {
5451 /* The two instructions immediately following this one
5452 * mark the beginning of a new flow segment */
5454 while(pc && PCI(pc)->isSkip) {
5456 PCI(pc)->pcflow = PCFL(pflow);
5460 InsertpFlow(pc, &pflow);
5461 pc=pic16_findNextInstruction(pc->next);
5469 PCI(pc)->pcflow = PCFL(pflow);
5471 InsertpFlow(pc, &pflow);
5473 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5475 InsertpFlow(pc, &pflow);
5478 } else if (checkLabel(pc)) {
5480 /* This instruction marks the beginning of a
5481 * new flow segment */
5486 /* If the previous pCode is not a flow object, then
5487 * insert a new flow object. (This check prevents
5488 * two consecutive flow objects from being insert in
5489 * the case where a skip instruction preceeds an
5490 * instruction containing a label.) */
5492 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5493 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5495 PCI(pc)->pcflow = PCFL(pflow);
5502 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5504 PCFL(pflow)->end = pb->pcTail;
5507 /*-------------------------------------------------------------------*/
5508 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5509 /* the flow blocks. */
5511 * unBuildFlow removes pCodeFlow objects from a pCode chain
5513 /*-----------------------------------------------------------------*/
5514 static void unBuildFlow(pBlock *pb)
5529 if(PCI(pc)->pcflow) {
5530 //free(PCI(pc)->pcflow);
5531 PCI(pc)->pcflow = NULL;
5534 } else if(isPCFL(pc) )
5543 /*-----------------------------------------------------------------*/
5544 /*-----------------------------------------------------------------*/
5545 static void dumpCond(int cond)
5548 static char *pcc_str[] = {
5563 int ncond = sizeof(pcc_str) / sizeof(char *);
5566 fprintf(stderr, "0x%04X\n",cond);
5568 for(i=0,j=1; i<ncond; i++, j<<=1)
5570 fprintf(stderr, " %s\n",pcc_str[i]);
5576 /*-----------------------------------------------------------------*/
5577 /*-----------------------------------------------------------------*/
5578 static void FlowStats(pCodeFlow *pcflow)
5586 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5588 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5591 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5596 fprintf(stderr, " FlowStats inCond: ");
5597 dumpCond(pcflow->inCond);
5598 fprintf(stderr, " FlowStats outCond: ");
5599 dumpCond(pcflow->outCond);
5603 /*-----------------------------------------------------------------*
5604 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5605 * if it affects the banking bits.
5607 * return: -1 == Banking bits are unaffected by this pCode.
5609 * return: > 0 == Banking bits are affected.
5611 * If the banking bits are affected, then the returned value describes
5612 * which bits are affected and how they're affected. The lower half
5613 * of the integer maps to the bits that are affected, the upper half
5614 * to whether they're set or cleared.
5616 *-----------------------------------------------------------------*/
5618 static int isBankInstruction(pCode *pc)
5626 if( PCI(pc)->op == POC_MOVLB ||
5627 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5628 bank = PCOL(pc)->lit;
5635 /*-----------------------------------------------------------------*/
5636 /*-----------------------------------------------------------------*/
5637 static void FillFlow(pCodeFlow *pcflow)
5646 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5648 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5651 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5658 isBankInstruction(pc);
5660 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5664 fprintf(stderr, " FillFlow - Bad end of flow\n");
5666 fprintf(stderr, " FillFlow - Ending flow with\n ");
5667 pc->print(stderr,pc);
5670 fprintf(stderr, " FillFlow inCond: ");
5671 dumpCond(pcflow->inCond);
5672 fprintf(stderr, " FillFlow outCond: ");
5673 dumpCond(pcflow->outCond);
5677 /*-----------------------------------------------------------------*/
5678 /*-----------------------------------------------------------------*/
5679 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5681 pCodeFlowLink *fromLink, *toLink;
5683 if(!from || !to || !to->pcflow || !from->pcflow)
5686 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5687 toLink = pic16_newpCodeFlowLink(to->pcflow);
5689 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5690 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5694 /*-----------------------------------------------------------------*
5695 * void LinkFlow(pBlock *pb)
5697 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5698 * non-branching segments. In LinkFlow, we determine the execution
5699 * order of these segments. For example, if one of the segments ends
5700 * with a skip, then we know that there are two possible flow segments
5701 * to which control may be passed.
5702 *-----------------------------------------------------------------*/
5703 static void LinkFlow(pBlock *pb)
5709 //fprintf(stderr,"linkflow \n");
5711 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5713 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5716 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5718 //fprintf(stderr," link: ");
5719 //pcflow->print(stderr,pcflow);
5721 //FillFlow(PCFL(pcflow));
5723 pc = PCFL(pcflow)->end;
5725 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5726 if(isPCI_SKIP(pc)) {
5727 //fprintf(stderr, "ends with skip\n");
5728 //pc->print(stderr,pc);
5729 pct=pic16_findNextInstruction(pc->next);
5730 LinkFlow_pCode(PCI(pc),PCI(pct));
5731 pct=pic16_findNextInstruction(pct->next);
5732 LinkFlow_pCode(PCI(pc),PCI(pct));
5736 if(isPCI_BRANCH(pc)) {
5737 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5739 //fprintf(stderr, "ends with branch\n ");
5740 //pc->print(stderr,pc);
5742 if(!(pcol && isPCOLAB(pcol))) {
5743 if((PCI(pc)->op != POC_RETLW)
5744 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5746 /* continue if label is '$' which assembler knows how to parse */
5747 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5749 pc->print(stderr,pc);
5750 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5755 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5756 LinkFlow_pCode(PCI(pc),PCI(pct));
5758 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5759 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5760 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5766 //fprintf(stderr, "ends with non-branching instruction:\n");
5767 //pc->print(stderr,pc);
5769 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5775 //fprintf(stderr, "ends with unknown\n");
5776 //pc->print(stderr,pc);
5780 //fprintf(stderr, "ends with nothing: ERROR\n");
5784 /*-----------------------------------------------------------------*/
5785 /*-----------------------------------------------------------------*/
5787 /*-----------------------------------------------------------------*/
5788 /*-----------------------------------------------------------------*/
5789 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5795 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5798 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5808 /*-----------------------------------------------------------------*/
5809 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5810 /*-----------------------------------------------------------------*/
5811 static void insertBankSwitch(int position, pCode *pc, int bsr)
5820 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5821 * insert a BANKSEL assembler directive for the symbol used by
5822 * the pCode. This will allow the linker to setup the correct
5823 * bank at linking time
5826 if(!pic16_options.gen_banksel || bsr != -1) {
5827 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5830 /* emit the BANKSEL [symbol] */
5833 /* IMPORTANT: The following code does not check if a symbol is
5834 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5836 reg = pic16_getRegFromInstruction(pc);
5838 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5840 position = 0; // position is always before (sanity check!)
5844 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5845 pc->print(stderr, pc);
5849 /* insert the bank switch after this pc instruction */
5850 pCode *pcnext = pic16_findNextInstruction(pc);
5851 pic16_pCodeInsertAfter(pc, new_pc);
5856 pic16_pCodeInsertAfter(pc->prev, new_pc);
5858 /* Move the label, if there is one */
5860 if(PCI(pc)->label) {
5861 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5862 // __FILE__, __LINE__, pc, new_pc);
5863 PCAD(new_pc)->pci.label = PCI(pc)->label;
5864 PCI(pc)->label = NULL;
5867 // fprintf(stderr, "BankSwitch has been inserted\n");
5871 /*-----------------------------------------------------------------*/
5872 /*int compareBankFlow - compare the banking requirements between */
5874 /*-----------------------------------------------------------------*/
5875 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5878 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5881 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5884 if(pcflow->firstBank == -1)
5888 if(pcflowLink->pcflow->firstBank == -1) {
5889 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5890 pcflowLink->pcflow->to :
5891 pcflowLink->pcflow->from);
5892 return compareBankFlow(pcflow, pctl, toORfrom);
5896 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5899 pcflowLink->bank_conflict++;
5900 pcflowLink->pcflow->FromConflicts++;
5901 pcflow->ToConflicts++;
5904 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5907 pcflowLink->bank_conflict++;
5908 pcflowLink->pcflow->ToConflicts++;
5909 pcflow->FromConflicts++;
5913 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5914 pcflowLink->pcflow->pc.seq,
5915 pcflowLink->pcflow->FromConflicts,
5916 pcflowLink->pcflow->ToConflicts);
5923 /*-----------------------------------------------------------------*/
5924 /*-----------------------------------------------------------------*/
5925 static void DumpFlow(pBlock *pb)
5929 pCodeFlowLink *pcfl;
5932 fprintf(stderr,"Dump flow \n");
5933 pb->pcHead->print(stderr, pb->pcHead);
5935 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5936 pcflow->print(stderr,pcflow);
5938 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5940 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5942 if(!isPCFL(pcflow)) {
5943 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5946 fprintf(stderr,"dumping: ");
5947 pcflow->print(stderr,pcflow);
5948 FlowStats(PCFL(pcflow));
5950 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5952 pc = PCODE(pcfl->pcflow);
5954 fprintf(stderr, " from seq %d:\n",pc->seq);
5956 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5957 pc->print(stderr,pc);
5962 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5964 pc = PCODE(pcfl->pcflow);
5966 fprintf(stderr, " to seq %d:\n",pc->seq);
5968 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5969 pc->print(stderr,pc);
5978 /*-----------------------------------------------------------------*/
5979 /*-----------------------------------------------------------------*/
5980 static int OptimizepBlock(pBlock *pb)
5985 if(!pb || !peepOptimizing)
5988 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5990 for(pc = pb->pcHead; pc; pc = pc->next)
5991 matches += pic16_pCodePeepMatchRule(pc);
5994 pc = pic16_findNextInstruction(pb->pcHead);
6002 if(pic16_pCodePeepMatchRule(pc)) {
6007 pc = pic16_findNextInstruction(pcprev->next);
6009 pc = pic16_findNextInstruction(pb->pcHead);
6011 pc = pic16_findNextInstruction(pc->next);
6015 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6020 /*-----------------------------------------------------------------*/
6021 /*-----------------------------------------------------------------*/
6022 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6026 for(pc = pcs; pc; pc = pc->next) {
6028 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6030 (PCI(pc)->pcop->type == PO_LABEL) &&
6031 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6039 /*-----------------------------------------------------------------*/
6040 /*-----------------------------------------------------------------*/
6041 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6048 (PCI(pc)->pcop->type == PO_LABEL)) {
6050 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6052 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6054 free(pcol->pcop.name);
6056 /* If the key is negative, then we (probably) have a label to
6057 * a function and the name is already defined */
6060 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6064 //sprintf(buffer,"_%05d_DS_",pcl->key);
6066 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6068 pcol->pcop.name = Safe_strdup(s);
6069 pcol->key = pcl->key;
6070 //pc->print(stderr,pc);
6077 /*-----------------------------------------------------------------*/
6078 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6079 /* pCode chain if they're not used. */
6080 /*-----------------------------------------------------------------*/
6081 static void pBlockRemoveUnusedLabels(pBlock *pb)
6083 pCode *pc; pCodeLabel *pcl;
6088 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6090 pBranch *pbr = PCI(pc)->label;
6091 if(pbr && pbr->next) {
6092 pCode *pcd = pb->pcHead;
6094 //fprintf(stderr, "multiple labels\n");
6095 //pc->print(stderr,pc);
6100 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6101 //fprintf(stderr,"Used by:\n");
6102 //pcd->print(stderr,pcd);
6104 exchangeLabels(PCL(pbr->pc),pcd);
6113 for(pc = pb->pcHead; pc; pc = pc->next) {
6115 if(isPCL(pc)) // pc->type == PC_LABEL)
6117 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6118 pcl = PCL(PCI(pc)->label->pc);
6121 //fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6123 /* This pCode is a label, so search the pBlock to see if anyone
6126 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
6127 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6128 /* Couldn't find an instruction that refers to this label
6129 * So, unlink the pCode label from it's pCode chain
6130 * and destroy the label */
6131 //fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6133 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6134 if(pc->type == PC_LABEL) {
6135 pic16_unlinkpCode(pc);
6136 pCodeLabelDestruct(pc);
6138 unlinkpCodeFromBranch(pc, PCODE(pcl));
6139 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6150 /*-----------------------------------------------------------------*/
6151 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6152 /* chain and put them into pBranches that are */
6153 /* associated with the appropriate pCode */
6155 /*-----------------------------------------------------------------*/
6156 void pic16_pBlockMergeLabels(pBlock *pb)
6159 pCode *pc, *pcnext=NULL;
6164 /* First, Try to remove any unused labels */
6165 //pBlockRemoveUnusedLabels(pb);
6167 /* Now loop through the pBlock and merge the labels with the opcodes */
6170 // for(pc = pb->pcHead; pc; pc = pc->next) {
6173 pCode *pcn = pc->next;
6175 if(pc->type == PC_LABEL) {
6177 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6178 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6180 if((pcnext = pic16_findNextInstruction(pc) )) {
6182 // pcnext->print(stderr, pcnext);
6184 // Unlink the pCode label from it's pCode chain
6185 pic16_unlinkpCode(pc);
6187 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6188 // And link it into the instruction's pBranch labels. (Note, since
6189 // it's possible to have multiple labels associated with one instruction
6190 // we must provide a means to accomodate the additional labels. Thus
6191 // the labels are placed into the singly-linked list "label" as
6192 // opposed to being a single member of the pCodeInstruction.)
6194 //_ALLOC(pbr,sizeof(pBranch));
6196 pbr = Safe_calloc(1,sizeof(pBranch));
6200 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6203 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6205 } else if(pc->type == PC_CSOURCE) {
6207 /* merge the source line symbolic info into the next instruction */
6208 if((pcnext = pic16_findNextInstruction(pc) )) {
6210 // Unlink the pCode label from it's pCode chain
6211 pic16_unlinkpCode(pc);
6212 PCI(pcnext)->cline = PCCS(pc);
6213 //fprintf(stderr, "merging CSRC\n");
6214 //genericPrint(stderr,pcnext);
6220 pBlockRemoveUnusedLabels(pb);
6224 /*-----------------------------------------------------------------*/
6225 /*-----------------------------------------------------------------*/
6226 static int OptimizepCode(char dbName)
6228 #define MAX_PASSES 4
6237 DFPRINTF((stderr," Optimizing pCode\n"));
6241 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6242 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6243 matches += OptimizepBlock(pb);
6246 while(matches && ++passes < MAX_PASSES);
6251 /*-----------------------------------------------------------------*/
6252 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6253 /*-----------------------------------------------------------------*/
6255 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6259 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
6261 if( !( (pcop->type == PO_LABEL) ||
6262 (pcop->type == PO_LITERAL) ||
6263 (pcop->type == PO_STR) ))
6264 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6265 PCOR(pcop)->r->wasUsed = 1;
6271 /*----------------------------------------------------------------------*
6272 * pic16_areRegsSame - check to see if the names of two registers match *
6273 *----------------------------------------------------------------------*/
6274 int pic16_areRegsSame(regs *r1, regs *r2)
6276 if(!strcmp(r1->name, r2->name))return 1;
6282 /*-----------------------------------------------------------------*/
6283 /*-----------------------------------------------------------------*/
6284 static void pic16_FixRegisterBanking(pBlock *pb)
6288 regs *reg, *prevreg;
6293 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6297 /* loop through all of the flow blocks with in one pblock */
6299 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6303 /* at this point, pc should point to a PC_FLOW object */
6304 /* for each flow block, determine the register banking
6307 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
6308 reg = pic16_getRegFromInstruction(pc);
6311 fprintf(stderr, "reg = %p\n", reg);
6313 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6314 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
6315 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
6316 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
6320 /* we can be 99% that within a pBlock, between two consequtive
6321 * refernces to the same register, the extra banksel is needless */
6323 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6325 && (PCI(pc)->op != POC_CALL)
6327 && ( ((pic16_options.opt_banksel>0)
6328 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6329 || (!pic16_options.opt_banksel)
6333 /* Examine the instruction before this one to make sure it is
6334 * not a skip type instruction */
6335 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6337 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6338 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6339 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6341 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
6353 if(pcprev && cur_bank) {
6355 int pos = 1; /* Assume that the bank switch instruction(s)
6356 * are inserted after this instruction */
6358 if((PCI(pcprev)->op == POC_RETLW) ||
6359 (PCI(pcprev)->op == POC_RETURN) ||
6360 (PCI(pcprev)->op == POC_RETFIE)) {
6362 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6368 /* Brute force - make sure that we point to bank 0 at the
6369 * end of each flow block */
6371 // insertBankSwitch(pos, pcprev, 0);
6373 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6374 pic16_pCodeInsertAfter(pcprev, new_pc);
6377 //fprintf(stderr, "Brute force switch\n");
6384 static void pBlockDestruct(pBlock *pb)
6395 /*-----------------------------------------------------------------*/
6396 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6397 /* name dbName and combine them */
6398 /* into one block */
6399 /*-----------------------------------------------------------------*/
6400 static void mergepBlocks(char dbName)
6403 pBlock *pb, *pbmerged = NULL,*pbn;
6405 pb = the_pFile->pbHead;
6407 //fprintf(stderr," merging blocks named %c\n",dbName);
6411 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6412 if( getpBlock_dbName(pb) == dbName) {
6414 //fprintf(stderr," merged block %c\n",dbName);
6419 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6420 /* pic16_addpCode2pBlock doesn't handle the tail: */
6421 pbmerged->pcTail = pb->pcTail;
6423 pb->prev->next = pbn;
6425 pbn->prev = pb->prev;
6430 //pic16_printpBlock(stderr, pbmerged);
6437 /*-----------------------------------------------------------------*/
6438 /* AnalyzeFlow - Examine the flow of the code and optimize */
6440 /* level 0 == minimal optimization */
6441 /* optimize registers that are used only by two instructions */
6442 /* level 1 == maximal optimization */
6443 /* optimize by looking at pairs of instructions that use the */
6445 /*-----------------------------------------------------------------*/
6447 static void AnalyzeFlow(int level)
6449 static int times_called=0;
6454 /* remove unused allocated registers before exiting */
6455 pic16_RemoveUnusedRegisters();
6461 /* if this is not the first time this function has been called,
6462 then clean up old flow information */
6463 if(times_called++) {
6464 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6467 pic16_RegsUnMapLiveRanges();
6472 /* Phase 2 - Flow Analysis - Register Banking
6474 * In this phase, the individual flow blocks are examined
6475 * and register banking is fixed.
6479 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6480 pic16_FixRegisterBanking(pb);
6483 /* Phase 2 - Flow Analysis
6485 * In this phase, the pCode is partition into pCodeFlow
6486 * blocks. The flow blocks mark the points where a continuous
6487 * stream of instructions changes flow (e.g. because of
6488 * a call or goto or whatever).
6491 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6492 pic16_BuildFlow(pb);
6495 /* Phase 2 - Flow Analysis - linking flow blocks
6497 * In this phase, the individual flow blocks are examined
6498 * to determine their order of excution.
6501 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6504 /* Phase 3 - Flow Analysis - Flow Tree
6506 * In this phase, the individual flow blocks are examined
6507 * to determine their order of execution.
6510 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6511 pic16_BuildFlowTree(pb);
6514 /* Phase x - Flow Analysis - Used Banks
6516 * In this phase, the individual flow blocks are examined
6517 * to determine the Register Banks they use
6521 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6526 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6527 pic16_pCodeRegMapLiveRanges(pb);
6529 pic16_RemoveUnusedRegisters();
6531 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6532 pic16_pCodeRegOptimizeRegUsage(level);
6540 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6545 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6547 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6548 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6549 pcflow = pcflow->next) {
6551 FillFlow(PCFL(pcflow));
6556 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6559 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6560 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6561 pcflow = pcflow->next) {
6563 FlowStats(PCFL(pcflow));
6569 /* VR -- no need to analyze banking in flow, but left here :
6570 * 1. because it may be used in the future for other purposes
6571 * 2. because if omitted we'll miss some optimization done here
6573 * Perhaps I should rename it to something else
6576 /*-----------------------------------------------------------------*/
6577 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6578 /* assigned to the registers. */
6580 /*-----------------------------------------------------------------*/
6582 void pic16_AnalyzeBanking(void)
6586 if(!pic16_picIsInitialized()) {
6587 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6588 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6589 fprintf(stderr,"support/scripts/inc2h.pl\n");
6590 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6592 /* I think it took a long long time to fix this bug! ;-) -- VR */
6598 /* Phase x - Flow Analysis - Used Banks
6600 * In this phase, the individual flow blocks are examined
6601 * to determine the Register Banks they use
6607 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6608 // BanksUsedFlow(pb);
6610 if(!the_pFile)return;
6612 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6613 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6614 pic16_FixRegisterBanking(pb);
6619 /*-----------------------------------------------------------------*/
6620 /* buildCallTree - Look at the flow and extract all of the calls. */
6621 /*-----------------------------------------------------------------*/
6622 static set *register_usage(pBlock *pb);
6624 static void buildCallTree(void )
6635 /* Now build the call tree.
6636 First we examine all of the pCodes for functions.
6637 Keep in mind that the function boundaries coincide
6638 with pBlock boundaries.
6640 The algorithm goes something like this:
6641 We have two nested loops. The outer loop iterates
6642 through all of the pBlocks/functions. The inner
6643 loop iterates through all of the pCodes for
6644 a given pBlock. When we begin iterating through
6645 a pBlock, the variable pc_fstart, pCode of the start
6646 of a function, is cleared. We then search for pCodes
6647 of type PC_FUNCTION. When one is encountered, we
6648 initialize pc_fstart to this and at the same time
6649 associate a new pBranch object that signifies a
6650 branch entry. If a return is found, then this signifies
6651 a function exit point. We'll link the pCodes of these
6652 returns to the matching pc_fstart.
6654 When we're done, a doubly linked list of pBranches
6655 will exist. The head of this list is stored in
6656 `the_pFile', which is the meta structure for all
6657 of the pCode. Look at the pic16_printCallTree function
6658 on how the pBranches are linked together.
6661 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6662 pCode *pc_fstart=NULL;
6663 for(pc = pb->pcHead; pc; pc = pc->next) {
6665 if (PCF(pc)->fname) {
6667 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6668 //fprintf(stderr," found main \n");
6669 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6673 pbr = Safe_calloc(1,sizeof(pBranch));
6674 pbr->pc = pc_fstart = pc;
6677 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6679 // Here's a better way of doing the same:
6680 addSet(&pb->function_entries, pc);
6683 // Found an exit point in a function, e.g. return
6684 // (Note, there may be more than one return per function)
6686 pBranchLink(PCF(pc_fstart), PCF(pc));
6688 addSet(&pb->function_exits, pc);
6690 } else if(isCALL(pc)) {
6691 addSet(&pb->function_calls,pc);
6696 /* Re-allocate the registers so that there are no collisions
6697 * between local variables when one function call another */
6700 // pic16_deallocateAllRegs();
6702 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6709 /*-----------------------------------------------------------------*/
6710 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6711 /* all of the logical connections. */
6713 /* Essentially what's done here is that the pCode flow is */
6715 /*-----------------------------------------------------------------*/
6717 void pic16_AnalyzepCode(char dbName)
6728 /* Phase 1 - Register allocation and peep hole optimization
6730 * The first part of the analysis is to determine the registers
6731 * that are used in the pCode. Once that is done, the peep rules
6732 * are applied to the code. We continue to loop until no more
6733 * peep rule optimizations are found (or until we exceed the
6734 * MAX_PASSES threshold).
6736 * When done, the required registers will be determined.
6742 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6743 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6745 /* First, merge the labels with the instructions */
6746 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6747 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6749 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6750 //fprintf(stderr," analyze and merging block %c\n",dbName);
6751 pic16_pBlockMergeLabels(pb);
6754 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6759 changes = OptimizepCode(dbName);
6762 } while(changes && (i++ < MAX_PASSES));
6767 /*-----------------------------------------------------------------*/
6768 /* ispCodeFunction - returns true if *pc is the pCode of a */
6770 /*-----------------------------------------------------------------*/
6771 static bool ispCodeFunction(pCode *pc)
6774 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6780 /*-----------------------------------------------------------------*/
6781 /* findFunction - Search for a function by name (given the name) */
6782 /* in the set of all functions that are in a pBlock */
6783 /* (note - I expect this to change because I'm planning to limit */
6784 /* pBlock's to just one function declaration */
6785 /*-----------------------------------------------------------------*/
6786 static pCode *findFunction(char *fname)
6793 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6795 pc = setFirstItem(pb->function_entries);
6798 if((pc->type == PC_FUNCTION) &&
6800 (strcmp(fname, PCF(pc)->fname)==0))
6803 pc = setNextItem(pb->function_entries);
6811 static void MarkUsedRegisters(set *regset)
6816 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6817 // fprintf(stderr, "marking register = %s\t", r1->name);
6818 r2 = pic16_regWithIdx(r1->rIdx);
6819 // fprintf(stderr, "to register = %s\n", r2->name);
6825 static void pBlockStats(FILE *of, pBlock *pb)
6831 if(!pic16_pcode_verbose)return;
6833 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6835 // for now just print the first element of each set
6836 pc = setFirstItem(pb->function_entries);
6838 fprintf(of,";entry: ");
6841 pc = setFirstItem(pb->function_exits);
6843 fprintf(of,";has an exit\n");
6847 pc = setFirstItem(pb->function_calls);
6849 fprintf(of,";functions called:\n");
6852 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6853 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6855 pc = setNextItem(pb->function_calls);
6859 r = setFirstItem(pb->tregisters);
6861 int n = elementsInSet(pb->tregisters);
6863 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6866 fprintf(of,"; %s\n",r->name);
6867 r = setNextItem(pb->tregisters);
6872 /*-----------------------------------------------------------------*/
6873 /*-----------------------------------------------------------------*/
6875 static void sequencepCode(void)
6881 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6883 pb->seq = GpCodeSequenceNumber+1;
6885 for( pc = pb->pcHead; pc; pc = pc->next)
6886 pc->seq = ++GpCodeSequenceNumber;
6892 /*-----------------------------------------------------------------*/
6893 /*-----------------------------------------------------------------*/
6894 static set *register_usage(pBlock *pb)
6897 set *registers=NULL;
6898 set *registersInCallPath = NULL;
6900 /* check recursion */
6902 pc = setFirstItem(pb->function_entries);
6909 if(pc->type != PC_FUNCTION)
6910 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6912 pc = setFirstItem(pb->function_calls);
6913 for( ; pc; pc = setNextItem(pb->function_calls)) {
6915 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6916 char *dest = pic16_get_op_from_instruction(PCI(pc));
6918 pcn = findFunction(dest);
6920 registersInCallPath = register_usage(pcn->pb);
6922 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6927 pBlockStats(stderr,pb); // debug
6930 // Mark the registers in this block as used.
6932 MarkUsedRegisters(pb->tregisters);
6933 if(registersInCallPath) {
6934 /* registers were used in the functions this pBlock has called */
6935 /* so now, we need to see if these collide with the ones we are */
6938 regs *r1,*r2, *newreg;
6940 DFPRINTF((stderr,"comparing registers\n"));
6942 r1 = setFirstItem(registersInCallPath);
6945 r2 = setFirstItem(pb->tregisters);
6947 while(r2 && (r1->type != REG_STK)) {
6949 if(r2->rIdx == r1->rIdx) {
6950 newreg = pic16_findFreeReg(REG_GPR);
6954 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6958 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6959 r1->rIdx, newreg->rIdx));
6960 r2->rIdx = newreg->rIdx;
6961 //if(r2->name) free(r2->name);
6963 r2->name = Safe_strdup(newreg->name);
6967 newreg->wasUsed = 1;
6969 r2 = setNextItem(pb->tregisters);
6972 r1 = setNextItem(registersInCallPath);
6975 /* Collisions have been resolved. Now free the registers in the call path */
6976 r1 = setFirstItem(registersInCallPath);
6978 if(r1->type != REG_STK) {
6979 newreg = pic16_regWithIdx(r1->rIdx);
6982 r1 = setNextItem(registersInCallPath);
6986 // MarkUsedRegisters(pb->registers);
6988 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6991 DFPRINTF((stderr,"returning regs\n"));
6993 DFPRINTF((stderr,"not returning regs\n"));
6995 DFPRINTF((stderr,"pBlock after register optim.\n"));
6996 pBlockStats(stderr,pb); // debug
7002 /*-----------------------------------------------------------------*/
7003 /* pct2 - writes the call tree to a file */
7005 /*-----------------------------------------------------------------*/
7006 static void pct2(FILE *of,pBlock *pb,int indent)
7010 // set *registersInCallPath = NULL;
7016 return; //recursion ?
7018 pc = setFirstItem(pb->function_entries);
7025 for(i=0;i<indent;i++) // Indentation
7028 if(pc->type == PC_FUNCTION)
7029 fprintf(of,"%s\n",PCF(pc)->fname);
7034 pc = setFirstItem(pb->function_calls);
7035 for( ; pc; pc = setNextItem(pb->function_calls)) {
7037 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7038 char *dest = pic16_get_op_from_instruction(PCI(pc));
7040 pcn = findFunction(dest);
7042 pct2(of,pcn->pb,indent+1);
7044 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7052 /*-----------------------------------------------------------------*/
7053 /* pic16_printCallTree - writes the call tree to a file */
7055 /*-----------------------------------------------------------------*/
7057 void pic16_printCallTree(FILE *of)
7069 fprintf(of, "\npBlock statistics\n");
7070 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7075 fprintf(of,"Call Tree\n");
7076 pbr = the_pFile->functions;
7080 if(!ispCodeFunction(pc))
7081 fprintf(of,"bug in call tree");
7084 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7086 while(pc->next && !ispCodeFunction(pc->next)) {
7088 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7089 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7097 fprintf(of,"\n**************\n\na better call tree\n");
7098 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7103 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7104 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7110 /*-----------------------------------------------------------------*/
7112 /*-----------------------------------------------------------------*/
7114 static void InlineFunction(pBlock *pb)
7122 pc = setFirstItem(pb->function_calls);
7124 for( ; pc; pc = setNextItem(pb->function_calls)) {
7127 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7133 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7135 //fprintf(stderr,"Cool can inline:\n");
7136 //pcn->print(stderr,pcn);
7138 //fprintf(stderr,"recursive call Inline\n");
7139 InlineFunction(pcn->pb);
7140 //fprintf(stderr,"return from recursive call Inline\n");
7143 At this point, *pc points to a CALL mnemonic, and
7144 *pcn points to the function that is being called.
7146 To in-line this call, we need to remove the CALL
7147 and RETURN(s), and link the function pCode in with
7153 /* Remove the CALL */
7157 /* remove callee pBlock from the pBlock linked list */
7158 removepBlock(pcn->pb);
7166 /* Remove the Function pCode */
7167 pct = pic16_findNextInstruction(pcn->next);
7169 /* Link the function with the callee */
7170 pc->next = pcn->next;
7171 pcn->next->prev = pc;
7173 /* Convert the function name into a label */
7175 pbr = Safe_calloc(1,sizeof(pBranch));
7176 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7178 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7179 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7181 /* turn all of the return's except the last into goto's */
7182 /* check case for 2 instruction pBlocks */
7183 pce = pic16_findNextInstruction(pcn->next);
7185 pCode *pce_next = pic16_findNextInstruction(pce->next);
7187 if(pce_next == NULL) {
7188 /* found the last return */
7189 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7191 //fprintf(stderr,"found last return\n");
7192 //pce->print(stderr,pce);
7193 pce->prev->next = pc_call->next;
7194 pc_call->next->prev = pce->prev;
7195 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7205 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7211 /*-----------------------------------------------------------------*/
7213 /*-----------------------------------------------------------------*/
7215 void pic16_InlinepCode(void)
7224 if(!functionInlining)
7227 /* Loop through all of the function definitions and count the
7228 * number of times each one is called */
7229 //fprintf(stderr,"inlining %d\n",__LINE__);
7231 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7233 pc = setFirstItem(pb->function_calls);
7235 for( ; pc; pc = setNextItem(pb->function_calls)) {
7238 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7239 if(pcn && isPCF(pcn)) {
7240 PCF(pcn)->ncalled++;
7243 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7248 //fprintf(stderr,"inlining %d\n",__LINE__);
7250 /* Now, Loop through the function definitions again, but this
7251 * time inline those functions that have only been called once. */
7253 InlineFunction(the_pFile->pbHead);
7254 //fprintf(stderr,"inlining %d\n",__LINE__);
7256 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7261 char *pic_optype_names[]={
7262 "PO_NONE", // No operand e.g. NOP
7263 "PO_W", // The working register (as a destination)
7264 "PO_WREG", // The working register (as a file register)
7265 "PO_STATUS", // The 'STATUS' register
7266 "PO_BSR", // The 'BSR' register
7267 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7269 "PO_INDF0", // The Indirect register
7270 "PO_INTCON", // Interrupt Control register
7271 "PO_GPR_REGISTER", // A general purpose register
7272 "PO_GPR_BIT", // A bit of a general purpose register
7273 "PO_GPR_TEMP", // A general purpose temporary register
7274 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7275 "PO_PCL", // Program counter Low register
7276 "PO_PCLATH", // Program counter Latch high register
7277 "PO_PCLATU", // Program counter Latch upper register
7278 "PO_PRODL", // Product Register Low
7279 "PO_PRODH", // Product Register High
7280 "PO_LITERAL", // A constant
7281 "PO_REL_ADDR", // A relative address
7282 "PO_IMMEDIATE", // (8051 legacy)
7283 "PO_DIR", // Direct memory (8051 legacy)
7284 "PO_CRY", // bit memory (8051 legacy)
7285 "PO_BIT", // bit operand.
7286 "PO_STR", // (8051 legacy)
7288 "PO_WILD" // Wild card operand in peep optimizer
7292 char *dumpPicOptype(PIC_OPTYPE type)
7294 return (pic_optype_names[ type ]);