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)
3126 if(pb->cmemmap)pb->cmemmap = NULL;
3130 if(pic16_pcode_verbose)
3131 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3134 void pic16_pBlockConvert2Absolute(pBlock *pb)
3137 if(pb->cmemmap)pb->cmemmap = NULL;
3141 if(pic16_pcode_verbose)
3142 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3145 /*-----------------------------------------------------------------*/
3146 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3147 /* instances to the front of the doubly linked */
3148 /* list of pBlocks */
3149 /*-----------------------------------------------------------------*/
3151 void pic16_movepBlock2Head(char dbName)
3156 /* this can happen in sources without code,
3157 * only variable definitions */
3158 if(!the_pFile)return;
3160 pb = the_pFile->pbHead;
3164 if(getpBlock_dbName(pb) == dbName) {
3165 pBlock *pbn = pb->next;
3166 pb->next = the_pFile->pbHead;
3167 the_pFile->pbHead->prev = pb;
3168 the_pFile->pbHead = pb;
3171 pb->prev->next = pbn;
3173 // If the pBlock that we just moved was the last
3174 // one in the link of all of the pBlocks, then we
3175 // need to point the tail to the block just before
3176 // the one we moved.
3177 // Note: if pb->next is NULL, then pb must have
3178 // been the last pBlock in the chain.
3181 pbn->prev = pb->prev;
3183 the_pFile->pbTail = pb->prev;
3194 void pic16_copypCode(FILE *of, char dbName)
3198 if(!of || !the_pFile)
3201 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3202 if(getpBlock_dbName(pb) == dbName) {
3203 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3205 pic16_printpBlock(of,pb);
3210 void pic16_pcode_test(void)
3213 DFPRINTF((stderr,"pcode is alive!\n"));
3223 /* create the file name */
3224 strcpy(buffer,dstFileName);
3225 strcat(buffer,".p");
3227 if( !(pFile = fopen(buffer, "w" ))) {
3228 werror(E_FILE_OPEN_ERR,buffer);
3232 fprintf(pFile,"pcode dump\n\n");
3234 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3235 fprintf(pFile,"\n\tNew pBlock\n\n");
3237 fprintf(pFile,"%s",pb->cmemmap->sname);
3239 fprintf(pFile,"internal pblock");
3241 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3242 pic16_printpBlock(pFile,pb);
3246 /*-----------------------------------------------------------------*/
3247 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3248 /* ister, RegCond will return the bit being referenced. */
3250 /* fixme - why not just OR in the pcop bit field */
3251 /*-----------------------------------------------------------------*/
3253 static int RegCond(pCodeOp *pcop)
3259 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3260 switch(PCORB(pcop)->bit) {
3274 /*-----------------------------------------------------------------*/
3275 /* pic16_newpCode - create and return a newly initialized pCode */
3277 /* fixme - rename this */
3279 /* The purpose of this routine is to create a new Instruction */
3280 /* pCode. This is called by gen.c while the assembly code is being */
3284 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3285 /* (note that the op is analogous to but not the */
3286 /* same thing as the opcode of the instruction.) */
3287 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3290 /* a pointer to the new malloc'd pCode is returned. */
3294 /*-----------------------------------------------------------------*/
3295 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3297 pCodeInstruction *pci ;
3299 if(!mnemonics_initialized)
3300 pic16initMnemonics();
3302 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3304 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3305 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3308 if(pci->inCond & PCC_EXAMINE_PCOP)
3309 pci->inCond |= RegCond(pcop);
3311 if(pci->outCond & PCC_EXAMINE_PCOP)
3312 pci->outCond |= RegCond(pcop);
3314 pci->pc.prev = pci->pc.next = NULL;
3315 return (pCode *)pci;
3318 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3324 /*-----------------------------------------------------------------*/
3325 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3327 /* Wild pcodes are used during the peep hole optimizer to serve */
3328 /* as place holders for any instruction. When a snippet of code is */
3329 /* compared to a peep hole rule, the wild card opcode will match */
3330 /* any instruction. However, the optional operand and label are */
3331 /* additional qualifiers that must also be matched before the */
3332 /* line (of assembly code) is declared matched. Note that the */
3333 /* operand may be wild too. */
3335 /* Note, a wild instruction is specified just like a wild var: */
3336 /* %4 ; A wild instruction, */
3337 /* See the peeph.def file for additional examples */
3339 /*-----------------------------------------------------------------*/
3341 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3346 pcw = Safe_calloc(1,sizeof(pCodeWild));
3348 pcw->pci.pc.type = PC_WILD;
3349 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3350 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3351 pcw->pci.pc.pb = NULL;
3353 // pcw->pci.pc.analyze = genericAnalyze;
3354 pcw->pci.pc.destruct = genericDestruct;
3355 pcw->pci.pc.print = genericPrint;
3357 pcw->id = pCodeID; // this is the 'n' in %n
3358 pcw->operand = optional_operand;
3359 pcw->label = optional_label;
3361 pcw->mustBeBitSkipInst = 0;
3362 pcw->mustNotBeBitSkipInst = 0;
3363 pcw->invertBitSkipInst = 0;
3365 return ( (pCode *)pcw);
3369 /*-----------------------------------------------------------------*/
3370 /* newPcodeInlineP - create a new pCode from a char string */
3371 /*-----------------------------------------------------------------*/
3374 pCode *pic16_newpCodeInlineP(char *cP)
3379 pcc = Safe_calloc(1,sizeof(pCodeComment));
3381 pcc->pc.type = PC_INLINE;
3382 pcc->pc.prev = pcc->pc.next = NULL;
3383 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3386 // pcc->pc.analyze = genericAnalyze;
3387 pcc->pc.destruct = genericDestruct;
3388 pcc->pc.print = genericPrint;
3391 pcc->comment = Safe_strdup(cP);
3393 pcc->comment = NULL;
3395 return ( (pCode *)pcc);
3399 /*-----------------------------------------------------------------*/
3400 /* newPcodeCharP - create a new pCode from a char string */
3401 /*-----------------------------------------------------------------*/
3403 pCode *pic16_newpCodeCharP(char *cP)
3408 pcc = Safe_calloc(1,sizeof(pCodeComment));
3410 pcc->pc.type = PC_COMMENT;
3411 pcc->pc.prev = pcc->pc.next = NULL;
3412 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3415 // pcc->pc.analyze = genericAnalyze;
3416 pcc->pc.destruct = genericDestruct;
3417 pcc->pc.print = genericPrint;
3420 pcc->comment = Safe_strdup(cP);
3422 pcc->comment = NULL;
3424 return ( (pCode *)pcc);
3428 /*-----------------------------------------------------------------*/
3429 /* pic16_newpCodeFunction - */
3430 /*-----------------------------------------------------------------*/
3433 pCode *pic16_newpCodeFunction(char *mod,char *f)
3437 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3439 pcf->pc.type = PC_FUNCTION;
3440 pcf->pc.prev = pcf->pc.next = NULL;
3441 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3444 // pcf->pc.analyze = genericAnalyze;
3445 pcf->pc.destruct = genericDestruct;
3446 pcf->pc.print = pCodePrintFunction;
3451 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3452 strcpy(pcf->modname,mod);
3454 pcf->modname = NULL;
3457 pcf->fname = Safe_calloc(1,strlen(f)+1);
3458 strcpy(pcf->fname,f);
3462 return ( (pCode *)pcf);
3466 /*-----------------------------------------------------------------*/
3467 /* pic16_newpCodeFlow */
3468 /*-----------------------------------------------------------------*/
3469 static void destructpCodeFlow(pCode *pc)
3471 if(!pc || !isPCFL(pc))
3478 pic16_unlinkpCode(pc);
3480 deleteSet(&PCFL(pc)->registers);
3481 deleteSet(&PCFL(pc)->from);
3482 deleteSet(&PCFL(pc)->to);
3487 pCode *pic16_newpCodeFlow(void )
3491 //_ALLOC(pcflow,sizeof(pCodeFlow));
3492 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3494 pcflow->pc.type = PC_FLOW;
3495 pcflow->pc.prev = pcflow->pc.next = NULL;
3496 pcflow->pc.pb = NULL;
3498 // pcflow->pc.analyze = genericAnalyze;
3499 pcflow->pc.destruct = destructpCodeFlow;
3500 pcflow->pc.print = genericPrint;
3502 pcflow->pc.seq = GpcFlowSeq++;
3504 pcflow->from = pcflow->to = NULL;
3506 pcflow->inCond = PCC_NONE;
3507 pcflow->outCond = PCC_NONE;
3509 pcflow->firstBank = -1;
3510 pcflow->lastBank = -1;
3512 pcflow->FromConflicts = 0;
3513 pcflow->ToConflicts = 0;
3517 pcflow->registers = newSet();
3519 return ( (pCode *)pcflow);
3523 /*-----------------------------------------------------------------*/
3524 /*-----------------------------------------------------------------*/
3525 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3527 pCodeFlowLink *pcflowLink;
3529 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3531 pcflowLink->pcflow = pcflow;
3532 pcflowLink->bank_conflict = 0;
3537 /*-----------------------------------------------------------------*/
3538 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3539 /*-----------------------------------------------------------------*/
3541 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3546 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3548 pccs->pc.type = PC_CSOURCE;
3549 pccs->pc.prev = pccs->pc.next = NULL;
3552 pccs->pc.destruct = genericDestruct;
3553 pccs->pc.print = genericPrint;
3555 pccs->line_number = ln;
3557 pccs->line = Safe_strdup(l);
3562 pccs->file_name = Safe_strdup(f);
3564 pccs->file_name = NULL;
3566 return ( (pCode *)pccs);
3571 /*******************************************************************/
3572 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3573 /* added by VR 6-Jun-2003 */
3574 /*******************************************************************/
3576 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3583 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3584 pcad->pci.pc.type = PC_ASMDIR;
3585 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3586 pcad->pci.pc.pb = NULL;
3588 pcad->pci.pc.destruct = genericDestruct;
3589 pcad->pci.pc.print = genericPrint;
3591 if(asdir && *asdir) {
3593 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3595 pcad->directive = Safe_strdup( asdir );
3598 va_start(ap, argfmt);
3600 memset(buffer, 0, sizeof(buffer));
3601 if(argfmt && *argfmt)
3602 vsprintf(buffer, argfmt, ap);
3606 while(isspace(*lbp))lbp++;
3609 pcad->arg = Safe_strdup( lbp );
3611 return ((pCode *)pcad);
3614 /*-----------------------------------------------------------------*/
3615 /* pCodeLabelDestruct - free memory used by a label. */
3616 /*-----------------------------------------------------------------*/
3617 static void pCodeLabelDestruct(pCode *pc)
3623 if((pc->type == PC_LABEL) && PCL(pc)->label)
3624 free(PCL(pc)->label);
3630 pCode *pic16_newpCodeLabel(char *name, int key)
3636 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3638 pcl->pc.type = PC_LABEL;
3639 pcl->pc.prev = pcl->pc.next = NULL;
3640 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3643 // pcl->pc.analyze = genericAnalyze;
3644 pcl->pc.destruct = pCodeLabelDestruct;
3645 pcl->pc.print = pCodePrintLabel;
3651 sprintf(s,"_%05d_DS_",key);
3656 pcl->label = Safe_strdup(s);
3658 // if(pic16_pcode_verbose)
3659 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3662 return ( (pCode *)pcl);
3667 /*-----------------------------------------------------------------*/
3668 /* newpBlock - create and return a pointer to a new pBlock */
3669 /*-----------------------------------------------------------------*/
3670 static pBlock *newpBlock(void)
3675 PpB = Safe_calloc(1,sizeof(pBlock) );
3676 PpB->next = PpB->prev = NULL;
3678 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3679 PpB->tregisters = NULL;
3681 PpB->FlowTree = NULL;
3687 /*-----------------------------------------------------------------*/
3688 /* pic16_newpCodeChain - create a new chain of pCodes */
3689 /*-----------------------------------------------------------------*
3691 * This function will create a new pBlock and the pointer to the
3692 * pCode that is passed in will be the first pCode in the block.
3693 *-----------------------------------------------------------------*/
3696 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3699 pBlock *pB = newpBlock();
3701 pB->pcHead = pB->pcTail = pc;
3708 /*-----------------------------------------------------------------*/
3709 /* pic16_newpCodeOpLabel - Create a new label given the key */
3710 /* Note, a negative key means that the label is part of wild card */
3711 /* (and hence a wild card label) used in the pCodePeep */
3712 /* optimizations). */
3713 /*-----------------------------------------------------------------*/
3715 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3718 static int label_key=-1;
3722 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3723 pcop->type = PO_LABEL;
3728 sprintf(s=buffer,"_%05d_DS_",key);
3730 s = name, key = label_key--;
3733 pcop->name = Safe_strdup(s);
3735 ((pCodeOpLabel *)pcop)->key = key;
3737 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3741 /*-----------------------------------------------------------------*/
3742 /*-----------------------------------------------------------------*/
3743 pCodeOp *pic16_newpCodeOpLit(int lit)
3749 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3750 pcop->type = PO_LITERAL;
3754 sprintf(s,"0x%02x",lit);
3756 pcop->name = Safe_strdup(s);
3759 ((pCodeOpLit *)pcop)->lit = lit;
3764 /*-----------------------------------------------------------------*/
3765 /*-----------------------------------------------------------------*/
3766 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3768 char *s = buffer, tbuf[256], *tb=tbuf;
3772 tb = pic16_get_op(arg2, NULL, 0);
3773 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3774 pcop->type = PO_LITERAL;
3778 sprintf(s,"0x%02x, %s",lit, tb);
3780 pcop->name = Safe_strdup(s);
3783 ((pCodeOpLit2 *)pcop)->lit = lit;
3784 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3789 /*-----------------------------------------------------------------*/
3790 /*-----------------------------------------------------------------*/
3791 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3795 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3796 pcop->type = PO_IMMEDIATE;
3798 regs *r = pic16_dirregWithName(name);
3799 pcop->name = Safe_strdup(name);
3803 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3804 PCOI(pcop)->rIdx = r->rIdx;
3806 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3807 // __FILE__, __LINE__, __FUNCTION__, name);
3808 PCOI(pcop)->rIdx = -1;
3810 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3815 PCOI(pcop)->index = index;
3816 PCOI(pcop)->offset = offset;
3817 PCOI(pcop)->_const = code_space;
3822 /*-----------------------------------------------------------------*/
3823 /*-----------------------------------------------------------------*/
3824 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3830 if(!pcwb || !subtype) {
3831 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3835 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3836 pcop->type = PO_WILD;
3837 sprintf(s,"%%%d",id);
3838 pcop->name = Safe_strdup(s);
3840 PCOW(pcop)->id = id;
3841 PCOW(pcop)->pcwb = pcwb;
3842 PCOW(pcop)->subtype = subtype;
3843 PCOW(pcop)->matched = NULL;
3848 /*-----------------------------------------------------------------*/
3849 /*-----------------------------------------------------------------*/
3850 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3854 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3855 pcop->type = PO_GPR_BIT;
3857 pcop->name = Safe_strdup(s);
3861 PCORB(pcop)->bit = bit;
3862 PCORB(pcop)->inBitSpace = inBitSpace;
3864 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3865 PCOR(pcop)->r = NULL;
3866 PCOR(pcop)->rIdx = 0;
3870 /*-----------------------------------------------------------------*
3871 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3873 * If rIdx >=0 then a specific register from the set of registers
3874 * will be selected. If rIdx <0, then a new register will be searched
3876 *-----------------------------------------------------------------*/
3878 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3882 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3887 PCOR(pcop)->rIdx = rIdx;
3888 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3890 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3893 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3895 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3896 __FUNCTION__, __LINE__);
3901 pcop->type = PCOR(pcop)->r->pc_type;
3906 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3911 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3912 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1);
3913 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3914 pcop->type = PCOR(pcop)->r->pc_type;
3915 pcop->name = PCOR(pcop)->r->name;
3917 // if(pic16_pcode_verbose) {
3918 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3919 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3925 /*-----------------------------------------------------------------*/
3926 /*-----------------------------------------------------------------*/
3928 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3935 pcop = pic16_newpCodeOpBit(name, -1,0);
3939 pcop = pic16_newpCodeOpLit(-1);
3943 pcop = pic16_newpCodeOpLabel(NULL,-1);
3946 pcop = pic16_newpCodeOpReg(-1);
3949 case PO_GPR_REGISTER:
3951 pcop = pic16_newpCodeOpRegFromStr(name);
3953 pcop = pic16_newpCodeOpReg(-1);
3957 pcop = Safe_calloc(1,sizeof(pCodeOp) );
3960 pcop->name = Safe_strdup(name);
3969 typedef struct DBdata
3976 static int DBd_init = -1;
3978 /*-----------------------------------------------------------------*/
3979 /* Add "DB" directives to a pBlock */
3980 /*-----------------------------------------------------------------*/
3981 void pic16_emitDB(pBlock *pb, char c)
3984 if (DBd_init<0) // we need to initialize
3988 DBd.buffer[0] = '\0';
3991 l = strlen(DBd.buffer);
3995 sprintf(DBd.buffer+l,", 0x%02x", c & 0xff);
3999 sprintf(DBd.buffer,"0x%02x", c & 0xff);
4006 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4008 DBd.buffer[0] = '\0';
4013 /*-----------------------------------------------------------------*/
4014 /* Flush pending "DB" data to a pBlock */
4015 /*-----------------------------------------------------------------*/
4016 void pic16_flushDB(pBlock *pb)
4020 pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4022 DBd.buffer[0] = '\0';
4026 /*-----------------------------------------------------------------*/
4027 /*-----------------------------------------------------------------*/
4028 void pic16_pCodeConstString(char *name, char *value)
4032 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4037 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4039 pic16_addpBlock(pb);
4041 sprintf(buffer,"; %s = %s",name,value);
4043 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4044 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4047 pic16_emitDB(pb, *value);
4052 /*-----------------------------------------------------------------*/
4053 /*-----------------------------------------------------------------*/
4055 static void pCodeReadCodeTable(void)
4059 fprintf(stderr, " %s\n",__FUNCTION__);
4061 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4063 pic16_addpBlock(pb);
4065 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4066 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4067 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4068 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4070 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4071 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4072 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4073 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4078 /*-----------------------------------------------------------------*/
4079 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4080 /*-----------------------------------------------------------------*/
4081 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4088 /* If this is the first pcode to be added to a block that
4089 * was initialized with a NULL pcode, then go ahead and
4090 * make this pcode the head and tail */
4091 pb->pcHead = pb->pcTail = pc;
4094 pb->pcTail->next = pc;
4096 pc->prev = pb->pcTail;
4103 /*-----------------------------------------------------------------*/
4104 /* pic16_addpBlock - place a pBlock into the pFile */
4105 /*-----------------------------------------------------------------*/
4106 void pic16_addpBlock(pBlock *pb)
4108 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4111 /* First time called, we'll pass through here. */
4112 //_ALLOC(the_pFile,sizeof(pFile));
4113 the_pFile = Safe_calloc(1,sizeof(pFile));
4114 the_pFile->pbHead = the_pFile->pbTail = pb;
4115 the_pFile->functions = NULL;
4119 the_pFile->pbTail->next = pb;
4120 pb->prev = the_pFile->pbTail;
4122 the_pFile->pbTail = pb;
4125 /*-----------------------------------------------------------------*/
4126 /* removepBlock - remove a pBlock from the pFile */
4127 /*-----------------------------------------------------------------*/
4128 static void removepBlock(pBlock *pb)
4136 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4138 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4141 if(pbs == the_pFile->pbHead)
4142 the_pFile->pbHead = pbs->next;
4144 if (pbs == the_pFile->pbTail)
4145 the_pFile->pbTail = pbs->prev;
4148 pbs->next->prev = pbs->prev;
4151 pbs->prev->next = pbs->next;
4158 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4162 /*-----------------------------------------------------------------*/
4163 /* printpCode - write the contents of a pCode to a file */
4164 /*-----------------------------------------------------------------*/
4165 static void printpCode(FILE *of, pCode *pc)
4176 fprintf(of,"warning - unable to print pCode\n");
4179 /*-----------------------------------------------------------------*/
4180 /* pic16_printpBlock - write the contents of a pBlock to a file */
4181 /*-----------------------------------------------------------------*/
4182 void pic16_printpBlock(FILE *of, pBlock *pb)
4190 for(pc = pb->pcHead; pc; pc = pc->next) {
4191 if(isPCF(pc) && PCF(pc)->fname) {
4192 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4193 if(pb->dbName == 'A') {
4195 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4196 if(!strcmp(ab->name, PCF(pc)->fname)) {
4197 fprintf(of, "\t0X%06X\n", ab->address);
4208 /*-----------------------------------------------------------------*/
4210 /* pCode processing */
4214 /*-----------------------------------------------------------------*/
4216 void pic16_unlinkpCode(pCode *pc)
4222 fprintf(stderr,"Unlinking: ");
4223 printpCode(stderr, pc);
4226 pc->prev->next = pc->next;
4228 pc->next->prev = pc->prev;
4230 pc->prev = pc->next = NULL;
4234 /*-----------------------------------------------------------------*/
4235 /*-----------------------------------------------------------------*/
4237 static void genericDestruct(pCode *pc)
4240 pic16_unlinkpCode(pc);
4243 /* For instructions, tell the register (if there's one used)
4244 * that it's no longer needed */
4245 regs *reg = pic16_getRegFromInstruction(pc);
4247 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4249 if(PCI(pc)->is2MemOp) {
4250 reg = pic16_getRegFromInstruction2(pc);
4252 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4256 /* Instead of deleting the memory used by this pCode, mark
4257 * the object as bad so that if there's a pointer to this pCode
4258 * dangling around somewhere then (hopefully) when the type is
4259 * checked we'll catch it.
4264 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4272 /*-----------------------------------------------------------------*/
4273 /*-----------------------------------------------------------------*/
4274 /* modifiers for constant immediate */
4275 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4277 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4282 int use_buffer = 1; // copy the string to the passed buffer pointer
4287 use_buffer = 0; // Don't bother copying the string to the buffer.
4291 switch(pcop->type) {
4297 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4300 return PCOR(pcop)->r->name;
4303 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4305 SAFE_snprintf(&buffer,&size,"%s",r->name);
4312 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4313 if(PCOI(pcop)->index) {
4314 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4315 immdmod[ PCOI(pcop)->offset ],
4319 SAFE_snprintf(&s,&size,"%s(%s)",
4320 immdmod[ PCOI(pcop)->offset ],
4324 if(PCOI(pcop)->index) {
4325 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4330 SAFE_snprintf(&s,&size, "%s(%s)",
4339 // size = sizeof(buffer);
4340 if( PCOR(pcop)->instance) {
4341 SAFE_snprintf(&s,&size,"(%s + %d)",
4343 PCOR(pcop)->instance );
4345 SAFE_snprintf(&s,&size,"%s",pcop->name);
4352 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4361 return "NO operand1";
4364 /*-----------------------------------------------------------------*/
4365 /* pic16_get_op2 - variant to support two memory operand commands */
4366 /*-----------------------------------------------------------------*/
4367 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4372 int use_buffer = 1; // copy the string to the passed buffer pointer
4377 use_buffer = 0; // Don't bother copying the string to the buffer.
4381 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",
4382 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4383 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4387 switch(PCOR2(pcop)->pcop2->type) {
4393 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4396 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4399 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4402 SAFE_snprintf(&buffer,&size,"%s",r->name);
4413 if(PCOI(pcop)->_const) {
4414 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4415 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4418 8 * PCOI(pcop)->offset );
4420 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4422 if( PCOI(pcop)->index) {
4423 SAFE_snprintf(&s,&size,"(%s + %d)",
4425 PCOI(pcop)->index );
4427 if(PCOI(pcop)->offset)
4428 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4430 SAFE_snprintf(&s,&size,"%s",pcop->name);
4437 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4438 SAFE_snprintf(&s,&size,"(%s + %d)",
4439 PCOR(PCOR2(pcop)->pcop2)->r->name,
4440 PCOR(PCOR2(pcop)->pcop2)->instance );
4442 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4447 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4449 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4452 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4457 return "NO operand2";
4460 /*-----------------------------------------------------------------*/
4461 /*-----------------------------------------------------------------*/
4462 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4466 return pic16_get_op(pcc->pcop,NULL,0);
4468 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4469 * return ("ERROR Null: "__FUNCTION__);
4471 return ("ERROR Null: pic16_get_op_from_instruction");
4475 /*-----------------------------------------------------------------*/
4476 /*-----------------------------------------------------------------*/
4477 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4480 fprintf(of,"pcodeopprint- not implemented\n");
4483 /*-----------------------------------------------------------------*/
4484 /* pic16_pCode2str - convert a pCode instruction to string */
4485 /*-----------------------------------------------------------------*/
4486 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4492 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4493 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4494 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4502 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4504 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4506 if(PCI(pc)->is2MemOp) {
4507 SAFE_snprintf(&s,&size, "%s, %s",
4508 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4509 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4513 if(PCI(pc)->is2LitOp) {
4514 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4518 if(PCI(pc)->isBitInst) {
4519 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4520 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4521 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4522 PCI(pc)->pcop->name ,
4523 PCI(pc)->pcop->name );
4525 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4526 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4527 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4528 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4530 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4531 //PCI(pc)->pcop->t.bit );
4534 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4535 if( PCI(pc)->num_ops == 3)
4536 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4538 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4541 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4543 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4544 if(PCI(pc)->num_ops == 3)
4545 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4547 r = pic16_getRegFromInstruction(pc);
4548 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4549 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4551 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4560 /* assuming that comment ends with a \n */
4561 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4565 /* assuming that inline code ends with a \n */
4566 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4570 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4573 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4576 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4579 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4582 SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4585 if(PCAD(pc)->directive) {
4586 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4589 /* special case to handle inline labels without a tab */
4590 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4595 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4602 /*-----------------------------------------------------------------*/
4603 /* genericPrint - the contents of a pCode to a file */
4604 /*-----------------------------------------------------------------*/
4605 static void genericPrint(FILE *of, pCode *pc)
4613 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4617 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4621 // If the opcode has a label, print that first
4623 pBranch *pbl = PCI(pc)->label;
4624 while(pbl && pbl->pc) {
4625 if(pbl->pc->type == PC_LABEL)
4626 pCodePrintLabel(of, pbl->pc);
4632 genericPrint(of,PCODE(PCI(pc)->cline));
4637 pic16_pCode2str(str, 256, pc);
4639 fprintf(of,"%s",str);
4641 if(pic16_debug_verbose) {
4642 fprintf(of, "\t;key=%03x",pc->seq);
4644 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4651 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4652 if(PCW(pc)->pci.label)
4653 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4655 if(PCW(pc)->operand) {
4656 fprintf(of,";\toperand ");
4657 pCodeOpPrint(of,PCW(pc)->operand );
4662 if(pic16_debug_verbose) {
4663 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4664 if(PCFL(pc)->ancestor)
4665 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4672 fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4677 pBranch *pbl = PCAD(pc)->pci.label;
4678 while(pbl && pbl->pc) {
4679 if(pbl->pc->type == PC_LABEL)
4680 pCodePrintLabel(of, pbl->pc);
4684 if(PCAD(pc)->directive) {
4685 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4688 /* special case to handle inline labels without tab */
4689 fprintf(of, "%s\n", PCAD(pc)->arg);
4695 fprintf(of,"unknown pCode type %d\n",pc->type);
4700 /*-----------------------------------------------------------------*/
4701 /* pCodePrintFunction - prints function begin/end */
4702 /*-----------------------------------------------------------------*/
4704 static void pCodePrintFunction(FILE *of, pCode *pc)
4711 if( ((pCodeFunction *)pc)->modname)
4712 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4715 if(PCF(pc)->fname) {
4716 pBranch *exits = PCF(pc)->to;
4718 fprintf(of,"%s", PCF(pc)->fname);
4720 // if(pic16_pcode_verbose)
4721 fprintf(of, "\t;Function start");
4727 exits = exits->next;
4731 if(pic16_pcode_verbose)
4732 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4735 if((PCF(pc)->from &&
4736 PCF(pc)->from->pc->type == PC_FUNCTION &&
4737 PCF(PCF(pc)->from->pc)->fname) ) {
4739 if(pic16_pcode_verbose)
4740 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4742 if(pic16_pcode_verbose)
4743 fprintf(of,"; exit point [can't find entry point]\n");
4748 /*-----------------------------------------------------------------*/
4749 /* pCodePrintLabel - prints label */
4750 /*-----------------------------------------------------------------*/
4752 static void pCodePrintLabel(FILE *of, pCode *pc)
4759 fprintf(of,"%s:\n",PCL(pc)->label);
4760 else if (PCL(pc)->key >=0)
4761 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4763 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4766 /*-----------------------------------------------------------------*/
4767 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4768 /* remove it if it is found. */
4769 /*-----------------------------------------------------------------*/
4770 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4777 if(pcl->type == PC_OPCODE)
4778 b = PCI(pcl)->label;
4780 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4785 //fprintf (stderr, "%s \n",__FUNCTION__);
4786 //pcl->print(stderr,pcl);
4787 //pc->print(stderr,pc);
4790 //fprintf (stderr, "found label\n");
4791 //pc->print(stderr, pc);
4795 bprev->next = b->next; /* Not first pCode in chain */
4799 PCI(pcl)->label = b->next; /* First pCode in chain */
4802 return; /* A label can't occur more than once */
4810 /*-----------------------------------------------------------------*/
4811 /*-----------------------------------------------------------------*/
4812 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4831 /*-----------------------------------------------------------------*/
4832 /* pBranchLink - given two pcodes, this function will link them */
4833 /* together through their pBranches */
4834 /*-----------------------------------------------------------------*/
4835 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4839 // Declare a new branch object for the 'from' pCode.
4841 //_ALLOC(b,sizeof(pBranch));
4842 b = Safe_calloc(1,sizeof(pBranch));
4843 b->pc = PCODE(t); // The link to the 'to' pCode.
4846 f->to = pic16_pBranchAppend(f->to,b);
4848 // Now do the same for the 'to' pCode.
4850 //_ALLOC(b,sizeof(pBranch));
4851 b = Safe_calloc(1,sizeof(pBranch));
4855 t->from = pic16_pBranchAppend(t->from,b);
4860 /*-----------------------------------------------------------------*/
4861 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4863 /*-----------------------------------------------------------------*/
4864 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4877 /*-----------------------------------------------------------------*/
4878 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4879 /*-----------------------------------------------------------------*/
4880 static void pCodeUnlink(pCode *pc)
4885 if(!pc->prev || !pc->next) {
4886 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4890 /* first remove the pCode from the chain */
4891 pc->prev->next = pc->next;
4892 pc->next->prev = pc->prev;
4894 /* Now for the hard part... */
4896 /* Remove the branches */
4900 pc1 = pb1->pc; /* Get the pCode that branches to the
4901 * one we're unlinking */
4903 /* search for the link back to this pCode (the one we're
4905 if(pb2 = pBranchFind(pc1->to,pc)) {
4906 pb2->pc = pc->to->pc; // make the replacement
4908 /* if the pCode we're unlinking contains multiple 'to'
4909 * branches (e.g. this a skip instruction) then we need
4910 * to copy these extra branches to the chain. */
4912 pic16_pBranchAppend(pb2, pc->to->next);
4921 /*-----------------------------------------------------------------*/
4922 /*-----------------------------------------------------------------*/
4924 static void genericAnalyze(pCode *pc)
4934 // Go through the pCodes that are in pCode chain and link
4935 // them together through the pBranches. Note, the pCodes
4936 // are linked together as a contiguous stream like the
4937 // assembly source code lines. The linking here mimics this
4938 // except that comments are not linked in.
4940 pCode *npc = pc->next;
4942 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4943 pBranchLink(pc,npc);
4948 /* reached the end of the pcode chain without finding
4949 * an instruction we could link to. */
4953 fprintf(stderr,"analyze PC_FLOW\n");
4957 fprintf(stderr,,";A bad pCode is being used\n");
4963 /*-----------------------------------------------------------------*/
4964 /*-----------------------------------------------------------------*/
4965 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4969 if(pc->type == PC_LABEL) {
4970 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4973 if((pc->type == PC_OPCODE)
4974 || (pc->type == PC_ASMDIR)
4976 pbr = PCI(pc)->label;
4978 if(pbr->pc->type == PC_LABEL) {
4979 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4989 /*-----------------------------------------------------------------*/
4990 /*-----------------------------------------------------------------*/
4991 static int checkLabel(pCode *pc)
4995 if(pc && isPCI(pc)) {
4996 pbr = PCI(pc)->label;
4998 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5008 /*-----------------------------------------------------------------*/
5009 /* findLabelinpBlock - Search the pCode for a particular label */
5010 /*-----------------------------------------------------------------*/
5011 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5018 for(pc = pb->pcHead; pc; pc = pc->next)
5019 if(compareLabel(pc,pcop_label))
5025 /*-----------------------------------------------------------------*/
5026 /* findLabel - Search the pCode for a particular label */
5027 /*-----------------------------------------------------------------*/
5028 static pCode * findLabel(pCodeOpLabel *pcop_label)
5036 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5037 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5041 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5045 /*-----------------------------------------------------------------*/
5046 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5047 /* in the linked list */
5048 /*-----------------------------------------------------------------*/
5049 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5062 /*-----------------------------------------------------------------*/
5063 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5064 /* in the linked list */
5065 /*-----------------------------------------------------------------*/
5066 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5080 //#define PCODE_DEBUG
5081 /*-----------------------------------------------------------------*/
5082 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5083 /* in the linked list */
5084 /*-----------------------------------------------------------------*/
5085 pCode * pic16_findNextInstruction(pCode *pci)
5090 if((pc->type == PC_OPCODE)
5091 || (pc->type == PC_WILD)
5092 || (pc->type == PC_ASMDIR)
5097 fprintf(stderr,"pic16_findNextInstruction: ");
5098 printpCode(stderr, pc);
5103 //fprintf(stderr,"Couldn't find instruction\n");
5107 /*-----------------------------------------------------------------*/
5108 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5109 /* in the linked list */
5110 /*-----------------------------------------------------------------*/
5111 pCode * pic16_findPrevInstruction(pCode *pci)
5116 if((pc->type == PC_OPCODE)
5117 || (pc->type == PC_WILD)
5118 || (pc->type == PC_ASMDIR)
5124 fprintf(stderr,"pic16_findPrevInstruction: ");
5125 printpCode(stderr, pc);
5130 //fprintf(stderr,"Couldn't find instruction\n");
5137 /*-----------------------------------------------------------------*/
5138 /* findFunctionEnd - given a pCode find the end of the function */
5139 /* that contains it */
5140 /*-----------------------------------------------------------------*/
5141 static pCode * findFunctionEnd(pCode *pc)
5145 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5151 fprintf(stderr,"Couldn't find function end\n");
5156 /*-----------------------------------------------------------------*/
5157 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5158 /* instruction with which it is associated. */
5159 /*-----------------------------------------------------------------*/
5160 static void AnalyzeLabel(pCode *pc)
5169 static void AnalyzeGOTO(pCode *pc)
5172 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5176 static void AnalyzeSKIP(pCode *pc)
5179 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5180 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5184 static void AnalyzeRETURN(pCode *pc)
5187 // branch_link(pc,findFunctionEnd(pc->next));
5193 /*-----------------------------------------------------------------*/
5194 /*-----------------------------------------------------------------*/
5195 regs * pic16_getRegFromInstruction(pCode *pc)
5201 PCI(pc)->num_ops == 0 ||
5202 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5206 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5207 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5210 switch(PCI(pc)->pcop->type) {
5216 return PCOR(PCI(pc)->pcop)->r;
5218 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5222 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5223 return PCOR(PCI(pc)->pcop)->r;
5226 if(PCOI(PCI(pc)->pcop)->r)
5227 return (PCOI(PCI(pc)->pcop)->r);
5229 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
5230 return pic16_dirregWithName(PCI(pc)->pcop->name);
5231 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5234 return PCOR(PCI(pc)->pcop)->r;
5237 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5238 return PCOR(PCI(pc)->pcop)->r;
5240 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5244 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5245 // genericPrint(stderr, pc);
5253 /*-------------------------------------------------------------------------------*/
5254 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5255 /*-------------------------------------------------------------------------------*/
5256 regs * pic16_getRegFromInstruction2(pCode *pc)
5262 PCI(pc)->num_ops == 0 ||
5263 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5268 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5269 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5273 * operands supported in MOVFF:
5280 switch(PCI(pc)->pcop->type) {
5286 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5288 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5292 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5293 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5298 // if(PCOI(PCI(pc)->pcop)->r)
5299 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5301 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5302 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5303 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5308 // return PCOR2(PCI(pc)->pcop)->r;
5311 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5312 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5316 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5319 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5320 //genericPrint(stderr, pc);
5328 /*-----------------------------------------------------------------*/
5329 /*-----------------------------------------------------------------*/
5331 static void AnalyzepBlock(pBlock *pb)
5338 /* Find all of the registers used in this pBlock
5339 * by looking at each instruction and examining it's
5342 for(pc = pb->pcHead; pc; pc = pc->next) {
5344 /* Is this an instruction with operands? */
5345 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5347 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5349 /* Loop through all of the registers declared so far in
5350 this block and see if we find this one there */
5352 regs *r = setFirstItem(pb->tregisters);
5355 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5356 PCOR(PCI(pc)->pcop)->r = r;
5359 r = setNextItem(pb->tregisters);
5363 /* register wasn't found */
5364 //r = Safe_calloc(1, sizeof(regs));
5365 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5366 //addSet(&pb->tregisters, r);
5367 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5368 //PCOR(PCI(pc)->pcop)->r = r;
5369 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5371 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5374 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5375 if(PCOR(PCI(pc)->pcop)->r) {
5376 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5377 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5379 if(PCI(pc)->pcop->name)
5380 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5382 fprintf(stderr,"ERROR: NULL register\n");
5391 /*-----------------------------------------------------------------*/
5393 /*-----------------------------------------------------------------*/
5394 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5396 static void InsertpFlow(pCode *pc, pCode **pflow)
5399 PCFL(*pflow)->end = pc;
5401 if(!pc || !pc->next)
5404 *pflow = pic16_newpCodeFlow();
5405 pic16_pCodeInsertAfter(pc, *pflow);
5408 /*-----------------------------------------------------------------*/
5409 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5410 /* the flow blocks. */
5412 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5413 * point the instruction flow changes.
5415 /*-----------------------------------------------------------------*/
5416 void pic16_BuildFlow(pBlock *pb)
5419 pCode *last_pci=NULL;
5426 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5427 /* Insert a pCodeFlow object at the beginning of a pBlock */
5429 InsertpFlow(pb->pcHead, &pflow);
5431 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5432 //pflow->next = pb->pcHead; /* Make the current head the next object */
5433 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5434 //pb->pcHead = pflow; /* Make the Flow object the head */
5437 for( pc = pic16_findNextInstruction(pb->pcHead);
5439 pc=pic16_findNextInstruction(pc)) {
5442 PCI(pc)->pcflow = PCFL(pflow);
5444 //fprintf(stderr," build: ");
5445 //pflow->print(stderr,pflow);
5447 if( PCI(pc)->isSkip) {
5449 /* The two instructions immediately following this one
5450 * mark the beginning of a new flow segment */
5452 while(pc && PCI(pc)->isSkip) {
5454 PCI(pc)->pcflow = PCFL(pflow);
5458 InsertpFlow(pc, &pflow);
5459 pc=pic16_findNextInstruction(pc->next);
5467 PCI(pc)->pcflow = PCFL(pflow);
5469 InsertpFlow(pc, &pflow);
5471 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5473 InsertpFlow(pc, &pflow);
5476 } else if (checkLabel(pc)) {
5478 /* This instruction marks the beginning of a
5479 * new flow segment */
5484 /* If the previous pCode is not a flow object, then
5485 * insert a new flow object. (This check prevents
5486 * two consecutive flow objects from being insert in
5487 * the case where a skip instruction preceeds an
5488 * instruction containing a label.) */
5490 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5491 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5493 PCI(pc)->pcflow = PCFL(pflow);
5500 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5502 PCFL(pflow)->end = pb->pcTail;
5505 /*-------------------------------------------------------------------*/
5506 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5507 /* the flow blocks. */
5509 * unBuildFlow removes pCodeFlow objects from a pCode chain
5511 /*-----------------------------------------------------------------*/
5512 static void unBuildFlow(pBlock *pb)
5527 if(PCI(pc)->pcflow) {
5528 //free(PCI(pc)->pcflow);
5529 PCI(pc)->pcflow = NULL;
5532 } else if(isPCFL(pc) )
5541 /*-----------------------------------------------------------------*/
5542 /*-----------------------------------------------------------------*/
5543 static void dumpCond(int cond)
5546 static char *pcc_str[] = {
5561 int ncond = sizeof(pcc_str) / sizeof(char *);
5564 fprintf(stderr, "0x%04X\n",cond);
5566 for(i=0,j=1; i<ncond; i++, j<<=1)
5568 fprintf(stderr, " %s\n",pcc_str[i]);
5574 /*-----------------------------------------------------------------*/
5575 /*-----------------------------------------------------------------*/
5576 static void FlowStats(pCodeFlow *pcflow)
5584 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5586 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5589 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5594 fprintf(stderr, " FlowStats inCond: ");
5595 dumpCond(pcflow->inCond);
5596 fprintf(stderr, " FlowStats outCond: ");
5597 dumpCond(pcflow->outCond);
5601 /*-----------------------------------------------------------------*
5602 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5603 * if it affects the banking bits.
5605 * return: -1 == Banking bits are unaffected by this pCode.
5607 * return: > 0 == Banking bits are affected.
5609 * If the banking bits are affected, then the returned value describes
5610 * which bits are affected and how they're affected. The lower half
5611 * of the integer maps to the bits that are affected, the upper half
5612 * to whether they're set or cleared.
5614 *-----------------------------------------------------------------*/
5616 static int isBankInstruction(pCode *pc)
5624 if( PCI(pc)->op == POC_MOVLB ||
5625 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5626 bank = PCOL(pc)->lit;
5633 /*-----------------------------------------------------------------*/
5634 /*-----------------------------------------------------------------*/
5635 static void FillFlow(pCodeFlow *pcflow)
5644 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5646 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5649 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5656 isBankInstruction(pc);
5658 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5662 fprintf(stderr, " FillFlow - Bad end of flow\n");
5664 fprintf(stderr, " FillFlow - Ending flow with\n ");
5665 pc->print(stderr,pc);
5668 fprintf(stderr, " FillFlow inCond: ");
5669 dumpCond(pcflow->inCond);
5670 fprintf(stderr, " FillFlow outCond: ");
5671 dumpCond(pcflow->outCond);
5675 /*-----------------------------------------------------------------*/
5676 /*-----------------------------------------------------------------*/
5677 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5679 pCodeFlowLink *fromLink, *toLink;
5681 if(!from || !to || !to->pcflow || !from->pcflow)
5684 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5685 toLink = pic16_newpCodeFlowLink(to->pcflow);
5687 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5688 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5692 /*-----------------------------------------------------------------*
5693 * void LinkFlow(pBlock *pb)
5695 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5696 * non-branching segments. In LinkFlow, we determine the execution
5697 * order of these segments. For example, if one of the segments ends
5698 * with a skip, then we know that there are two possible flow segments
5699 * to which control may be passed.
5700 *-----------------------------------------------------------------*/
5701 static void LinkFlow(pBlock *pb)
5707 //fprintf(stderr,"linkflow \n");
5709 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5711 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5714 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5716 //fprintf(stderr," link: ");
5717 //pcflow->print(stderr,pcflow);
5719 //FillFlow(PCFL(pcflow));
5721 pc = PCFL(pcflow)->end;
5723 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5724 if(isPCI_SKIP(pc)) {
5725 //fprintf(stderr, "ends with skip\n");
5726 //pc->print(stderr,pc);
5727 pct=pic16_findNextInstruction(pc->next);
5728 LinkFlow_pCode(PCI(pc),PCI(pct));
5729 pct=pic16_findNextInstruction(pct->next);
5730 LinkFlow_pCode(PCI(pc),PCI(pct));
5734 if(isPCI_BRANCH(pc)) {
5735 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5737 //fprintf(stderr, "ends with branch\n ");
5738 //pc->print(stderr,pc);
5740 if(!(pcol && isPCOLAB(pcol))) {
5741 if((PCI(pc)->op != POC_RETLW)
5742 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5744 /* continue if label is '$' which assembler knows how to parse */
5745 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5747 pc->print(stderr,pc);
5748 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5753 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5754 LinkFlow_pCode(PCI(pc),PCI(pct));
5756 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5757 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5759 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5765 //fprintf(stderr, "ends with non-branching instruction:\n");
5766 //pc->print(stderr,pc);
5768 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5774 //fprintf(stderr, "ends with unknown\n");
5775 //pc->print(stderr,pc);
5779 //fprintf(stderr, "ends with nothing: ERROR\n");
5783 /*-----------------------------------------------------------------*/
5784 /*-----------------------------------------------------------------*/
5786 /*-----------------------------------------------------------------*/
5787 /*-----------------------------------------------------------------*/
5788 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5794 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5797 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5807 /*-----------------------------------------------------------------*/
5808 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5809 /*-----------------------------------------------------------------*/
5810 static void insertBankSwitch(int position, pCode *pc, int bsr)
5819 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5820 * insert a BANKSEL assembler directive for the symbol used by
5821 * the pCode. This will allow the linker to setup the correct
5822 * bank at linking time
5825 if(pic16_options.no_banksel || bsr != -1) {
5826 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5829 /* emit the BANKSEL [symbol] */
5832 /* IMPORTANT: The following code does not check if a symbol is
5833 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5835 reg = pic16_getRegFromInstruction(pc);
5837 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5839 position = 0; // position is always before (sanity check!)
5843 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5844 pc->print(stderr, pc);
5848 /* insert the bank switch after this pc instruction */
5849 pCode *pcnext = pic16_findNextInstruction(pc);
5850 pic16_pCodeInsertAfter(pc, new_pc);
5855 pic16_pCodeInsertAfter(pc->prev, new_pc);
5857 /* Move the label, if there is one */
5859 if(PCI(pc)->label) {
5860 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5861 // __FILE__, __LINE__, pc, new_pc);
5862 PCAD(new_pc)->pci.label = PCI(pc)->label;
5863 PCI(pc)->label = NULL;
5866 // fprintf(stderr, "BankSwitch has been inserted\n");
5870 /*-----------------------------------------------------------------*/
5871 /*int compareBankFlow - compare the banking requirements between */
5873 /*-----------------------------------------------------------------*/
5874 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5877 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5880 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5883 if(pcflow->firstBank == -1)
5887 if(pcflowLink->pcflow->firstBank == -1) {
5888 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5889 pcflowLink->pcflow->to :
5890 pcflowLink->pcflow->from);
5891 return compareBankFlow(pcflow, pctl, toORfrom);
5895 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5898 pcflowLink->bank_conflict++;
5899 pcflowLink->pcflow->FromConflicts++;
5900 pcflow->ToConflicts++;
5903 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5906 pcflowLink->bank_conflict++;
5907 pcflowLink->pcflow->ToConflicts++;
5908 pcflow->FromConflicts++;
5912 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5913 pcflowLink->pcflow->pc.seq,
5914 pcflowLink->pcflow->FromConflicts,
5915 pcflowLink->pcflow->ToConflicts);
5922 /*-----------------------------------------------------------------*/
5923 /*-----------------------------------------------------------------*/
5924 static void DumpFlow(pBlock *pb)
5928 pCodeFlowLink *pcfl;
5931 fprintf(stderr,"Dump flow \n");
5932 pb->pcHead->print(stderr, pb->pcHead);
5934 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5935 pcflow->print(stderr,pcflow);
5937 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5939 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5941 if(!isPCFL(pcflow)) {
5942 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5945 fprintf(stderr,"dumping: ");
5946 pcflow->print(stderr,pcflow);
5947 FlowStats(PCFL(pcflow));
5949 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5951 pc = PCODE(pcfl->pcflow);
5953 fprintf(stderr, " from seq %d:\n",pc->seq);
5955 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5956 pc->print(stderr,pc);
5961 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5963 pc = PCODE(pcfl->pcflow);
5965 fprintf(stderr, " to seq %d:\n",pc->seq);
5967 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5968 pc->print(stderr,pc);
5977 /*-----------------------------------------------------------------*/
5978 /*-----------------------------------------------------------------*/
5979 static int OptimizepBlock(pBlock *pb)
5984 if(!pb || !peepOptimizing)
5987 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5989 for(pc = pb->pcHead; pc; pc = pc->next)
5990 matches += pic16_pCodePeepMatchRule(pc);
5993 pc = pic16_findNextInstruction(pb->pcHead);
6001 if(pic16_pCodePeepMatchRule(pc)) {
6006 pc = pic16_findNextInstruction(pcprev->next);
6008 pc = pic16_findNextInstruction(pb->pcHead);
6010 pc = pic16_findNextInstruction(pc->next);
6014 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6019 /*-----------------------------------------------------------------*/
6020 /*-----------------------------------------------------------------*/
6021 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6025 for(pc = pcs; pc; pc = pc->next) {
6027 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6029 (PCI(pc)->pcop->type == PO_LABEL) &&
6030 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6038 /*-----------------------------------------------------------------*/
6039 /*-----------------------------------------------------------------*/
6040 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6047 (PCI(pc)->pcop->type == PO_LABEL)) {
6049 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6051 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6053 free(pcol->pcop.name);
6055 /* If the key is negative, then we (probably) have a label to
6056 * a function and the name is already defined */
6059 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6063 //sprintf(buffer,"_%05d_DS_",pcl->key);
6065 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6067 pcol->pcop.name = Safe_strdup(s);
6068 pcol->key = pcl->key;
6069 //pc->print(stderr,pc);
6076 /*-----------------------------------------------------------------*/
6077 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6078 /* pCode chain if they're not used. */
6079 /*-----------------------------------------------------------------*/
6080 static void pBlockRemoveUnusedLabels(pBlock *pb)
6082 pCode *pc; pCodeLabel *pcl;
6087 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6089 pBranch *pbr = PCI(pc)->label;
6090 if(pbr && pbr->next) {
6091 pCode *pcd = pb->pcHead;
6093 // fprintf(stderr, "multiple labels\n");
6094 // pc->print(stderr,pc);
6099 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6100 //fprintf(stderr,"Used by:\n");
6101 //pcd->print(stderr,pcd);
6103 exchangeLabels(PCL(pbr->pc),pcd);
6112 for(pc = pb->pcHead; pc; pc = pc->next) {
6114 if(isPCL(pc)) // pc->type == PC_LABEL)
6116 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6117 pcl = PCL(PCI(pc)->label->pc);
6120 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6122 /* This pCode is a label, so search the pBlock to see if anyone
6125 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
6126 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6127 /* Couldn't find an instruction that refers to this label
6128 * So, unlink the pCode label from it's pCode chain
6129 * and destroy the label */
6130 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6132 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6133 if(pc->type == PC_LABEL) {
6134 pic16_unlinkpCode(pc);
6135 pCodeLabelDestruct(pc);
6137 unlinkpCodeFromBranch(pc, PCODE(pcl));
6138 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6149 /*-----------------------------------------------------------------*/
6150 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6151 /* chain and put them into pBranches that are */
6152 /* associated with the appropriate pCode */
6154 /*-----------------------------------------------------------------*/
6155 void pic16_pBlockMergeLabels(pBlock *pb)
6158 pCode *pc, *pcnext=NULL;
6163 /* First, Try to remove any unused labels */
6164 //pBlockRemoveUnusedLabels(pb);
6166 /* Now loop through the pBlock and merge the labels with the opcodes */
6169 // for(pc = pb->pcHead; pc; pc = pc->next) {
6172 pCode *pcn = pc->next;
6174 if(pc->type == PC_LABEL) {
6176 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6177 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6179 if((pcnext = pic16_findNextInstruction(pc) )) {
6181 // pcnext->print(stderr, pcnext);
6183 // Unlink the pCode label from it's pCode chain
6184 pic16_unlinkpCode(pc);
6186 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6187 // And link it into the instruction's pBranch labels. (Note, since
6188 // it's possible to have multiple labels associated with one instruction
6189 // we must provide a means to accomodate the additional labels. Thus
6190 // the labels are placed into the singly-linked list "label" as
6191 // opposed to being a single member of the pCodeInstruction.)
6193 //_ALLOC(pbr,sizeof(pBranch));
6195 pbr = Safe_calloc(1,sizeof(pBranch));
6199 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6202 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6204 } else if(pc->type == PC_CSOURCE) {
6206 /* merge the source line symbolic info into the next instruction */
6207 if((pcnext = pic16_findNextInstruction(pc) )) {
6209 // Unlink the pCode label from it's pCode chain
6210 pic16_unlinkpCode(pc);
6211 PCI(pcnext)->cline = PCCS(pc);
6212 //fprintf(stderr, "merging CSRC\n");
6213 //genericPrint(stderr,pcnext);
6219 pBlockRemoveUnusedLabels(pb);
6223 /*-----------------------------------------------------------------*/
6224 /*-----------------------------------------------------------------*/
6225 static int OptimizepCode(char dbName)
6227 #define MAX_PASSES 4
6236 DFPRINTF((stderr," Optimizing pCode\n"));
6240 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6241 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6242 matches += OptimizepBlock(pb);
6245 while(matches && ++passes < MAX_PASSES);
6250 /*-----------------------------------------------------------------*/
6251 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6252 /*-----------------------------------------------------------------*/
6254 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6258 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
6260 if( !( (pcop->type == PO_LABEL) ||
6261 (pcop->type == PO_LITERAL) ||
6262 (pcop->type == PO_STR) ))
6263 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6264 PCOR(pcop)->r->wasUsed = 1;
6270 /*----------------------------------------------------------------------*
6271 * pic16_areRegsSame - check to see if the names of two registers match *
6272 *----------------------------------------------------------------------*/
6273 int pic16_areRegsSame(regs *r1, regs *r2)
6275 if(!strcmp(r1->name, r2->name))return 1;
6281 /*-----------------------------------------------------------------*/
6282 /*-----------------------------------------------------------------*/
6283 static void pic16_FixRegisterBanking(pBlock *pb)
6287 regs *reg, *prevreg;
6292 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6296 /* loop through all of the flow blocks with in one pblock */
6298 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6302 /* at this point, pc should point to a PC_FLOW object */
6303 /* for each flow block, determine the register banking
6306 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
6307 reg = pic16_getRegFromInstruction(pc);
6310 fprintf(stderr, "reg = %p\n", reg);
6312 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6313 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
6314 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
6315 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
6319 /* we can be 99% that within a pBlock, between two consequtive
6320 * refernces to the same register, the extra banksel is needless */
6322 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6324 && (PCI(pc)->op != POC_CALL)
6326 && ( ((pic16_options.opt_banksel>0)
6327 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6328 || (!pic16_options.opt_banksel)
6332 /* Examine the instruction before this one to make sure it is
6333 * not a skip type instruction */
6334 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6336 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6337 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6338 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6340 insertBankSwitch(0, pc, (pic16_options.no_banksel)?0:-1);
6352 if(pcprev && cur_bank) {
6354 int pos = 1; /* Assume that the bank switch instruction(s)
6355 * are inserted after this instruction */
6357 if((PCI(pcprev)->op == POC_RETLW) ||
6358 (PCI(pcprev)->op == POC_RETURN) ||
6359 (PCI(pcprev)->op == POC_RETFIE)) {
6361 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6367 /* Brute force - make sure that we point to bank 0 at the
6368 * end of each flow block */
6370 // insertBankSwitch(pos, pcprev, 0);
6372 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6373 pic16_pCodeInsertAfter(pcprev, new_pc);
6376 //fprintf(stderr, "Brute force switch\n");
6383 static void pBlockDestruct(pBlock *pb)
6394 /*-----------------------------------------------------------------*/
6395 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6396 /* name dbName and combine them */
6397 /* into one block */
6398 /*-----------------------------------------------------------------*/
6399 static void mergepBlocks(char dbName)
6402 pBlock *pb, *pbmerged = NULL,*pbn;
6404 pb = the_pFile->pbHead;
6406 //fprintf(stderr," merging blocks named %c\n",dbName);
6410 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6411 if( getpBlock_dbName(pb) == dbName) {
6413 //fprintf(stderr," merged block %c\n",dbName);
6418 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6419 /* pic16_addpCode2pBlock doesn't handle the tail: */
6420 pbmerged->pcTail = pb->pcTail;
6422 pb->prev->next = pbn;
6424 pbn->prev = pb->prev;
6429 //pic16_printpBlock(stderr, pbmerged);
6436 /*-----------------------------------------------------------------*/
6437 /* AnalyzeFlow - Examine the flow of the code and optimize */
6439 /* level 0 == minimal optimization */
6440 /* optimize registers that are used only by two instructions */
6441 /* level 1 == maximal optimization */
6442 /* optimize by looking at pairs of instructions that use the */
6444 /*-----------------------------------------------------------------*/
6446 static void AnalyzeFlow(int level)
6448 static int times_called=0;
6453 /* remove unused allocated registers before exiting */
6454 pic16_RemoveUnusedRegisters();
6460 /* if this is not the first time this function has been called,
6461 then clean up old flow information */
6462 if(times_called++) {
6463 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6466 pic16_RegsUnMapLiveRanges();
6471 /* Phase 2 - Flow Analysis - Register Banking
6473 * In this phase, the individual flow blocks are examined
6474 * and register banking is fixed.
6478 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6479 pic16_FixRegisterBanking(pb);
6482 /* Phase 2 - Flow Analysis
6484 * In this phase, the pCode is partition into pCodeFlow
6485 * blocks. The flow blocks mark the points where a continuous
6486 * stream of instructions changes flow (e.g. because of
6487 * a call or goto or whatever).
6490 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6491 pic16_BuildFlow(pb);
6494 /* Phase 2 - Flow Analysis - linking flow blocks
6496 * In this phase, the individual flow blocks are examined
6497 * to determine their order of excution.
6500 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6503 /* Phase 3 - Flow Analysis - Flow Tree
6505 * In this phase, the individual flow blocks are examined
6506 * to determine their order of execution.
6509 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6510 pic16_BuildFlowTree(pb);
6513 /* Phase x - Flow Analysis - Used Banks
6515 * In this phase, the individual flow blocks are examined
6516 * to determine the Register Banks they use
6520 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6525 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6526 pic16_pCodeRegMapLiveRanges(pb);
6528 pic16_RemoveUnusedRegisters();
6530 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6531 pic16_pCodeRegOptimizeRegUsage(level);
6539 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6544 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6546 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6547 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6548 pcflow = pcflow->next) {
6550 FillFlow(PCFL(pcflow));
6555 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6558 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6559 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6560 pcflow = pcflow->next) {
6562 FlowStats(PCFL(pcflow));
6568 /* VR -- no need to analyze banking in flow, but left here :
6569 * 1. because it may be used in the future for other purposes
6570 * 2. because if omitted we'll miss some optimization done here
6572 * Perhaps I should rename it to something else
6575 /*-----------------------------------------------------------------*/
6576 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6577 /* assigned to the registers. */
6579 /*-----------------------------------------------------------------*/
6581 void pic16_AnalyzeBanking(void)
6585 if(!pic16_picIsInitialized()) {
6586 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6587 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6588 fprintf(stderr,"support/scripts/inc2h.pl\n");
6589 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6591 /* I think it took a long long time to fix this bug! ;-) -- VR */
6597 /* Phase x - Flow Analysis - Used Banks
6599 * In this phase, the individual flow blocks are examined
6600 * to determine the Register Banks they use
6606 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6607 // BanksUsedFlow(pb);
6609 if(!the_pFile)return;
6611 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6612 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6613 pic16_FixRegisterBanking(pb);
6618 /*-----------------------------------------------------------------*/
6619 /* buildCallTree - Look at the flow and extract all of the calls. */
6620 /*-----------------------------------------------------------------*/
6621 static set *register_usage(pBlock *pb);
6623 static void buildCallTree(void )
6634 /* Now build the call tree.
6635 First we examine all of the pCodes for functions.
6636 Keep in mind that the function boundaries coincide
6637 with pBlock boundaries.
6639 The algorithm goes something like this:
6640 We have two nested loops. The outer loop iterates
6641 through all of the pBlocks/functions. The inner
6642 loop iterates through all of the pCodes for
6643 a given pBlock. When we begin iterating through
6644 a pBlock, the variable pc_fstart, pCode of the start
6645 of a function, is cleared. We then search for pCodes
6646 of type PC_FUNCTION. When one is encountered, we
6647 initialize pc_fstart to this and at the same time
6648 associate a new pBranch object that signifies a
6649 branch entry. If a return is found, then this signifies
6650 a function exit point. We'll link the pCodes of these
6651 returns to the matching pc_fstart.
6653 When we're done, a doubly linked list of pBranches
6654 will exist. The head of this list is stored in
6655 `the_pFile', which is the meta structure for all
6656 of the pCode. Look at the pic16_printCallTree function
6657 on how the pBranches are linked together.
6660 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6661 pCode *pc_fstart=NULL;
6662 for(pc = pb->pcHead; pc; pc = pc->next) {
6664 if (PCF(pc)->fname) {
6666 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6667 //fprintf(stderr," found main \n");
6668 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6672 pbr = Safe_calloc(1,sizeof(pBranch));
6673 pbr->pc = pc_fstart = pc;
6676 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6678 // Here's a better way of doing the same:
6679 addSet(&pb->function_entries, pc);
6682 // Found an exit point in a function, e.g. return
6683 // (Note, there may be more than one return per function)
6685 pBranchLink(PCF(pc_fstart), PCF(pc));
6687 addSet(&pb->function_exits, pc);
6689 } else if(isCALL(pc)) {
6690 addSet(&pb->function_calls,pc);
6697 /* This is not needed because currently all register used
6698 * by a function are stored in stack -- VR */
6700 /* Re-allocate the registers so that there are no collisions
6701 * between local variables when one function call another */
6704 // pic16_deallocateAllRegs();
6706 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6714 /*-----------------------------------------------------------------*/
6715 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6716 /* all of the logical connections. */
6718 /* Essentially what's done here is that the pCode flow is */
6720 /*-----------------------------------------------------------------*/
6722 void pic16_AnalyzepCode(char dbName)
6733 /* Phase 1 - Register allocation and peep hole optimization
6735 * The first part of the analysis is to determine the registers
6736 * that are used in the pCode. Once that is done, the peep rules
6737 * are applied to the code. We continue to loop until no more
6738 * peep rule optimizations are found (or until we exceed the
6739 * MAX_PASSES threshold).
6741 * When done, the required registers will be determined.
6747 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6748 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6750 /* First, merge the labels with the instructions */
6751 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6752 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6754 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6755 //fprintf(stderr," analyze and merging block %c\n",dbName);
6756 pic16_pBlockMergeLabels(pb);
6759 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6764 changes = OptimizepCode(dbName);
6767 } while(changes && (i++ < MAX_PASSES));
6772 /*-----------------------------------------------------------------*/
6773 /* ispCodeFunction - returns true if *pc is the pCode of a */
6775 /*-----------------------------------------------------------------*/
6776 static bool ispCodeFunction(pCode *pc)
6779 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6785 /*-----------------------------------------------------------------*/
6786 /* findFunction - Search for a function by name (given the name) */
6787 /* in the set of all functions that are in a pBlock */
6788 /* (note - I expect this to change because I'm planning to limit */
6789 /* pBlock's to just one function declaration */
6790 /*-----------------------------------------------------------------*/
6791 static pCode *findFunction(char *fname)
6798 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6800 pc = setFirstItem(pb->function_entries);
6803 if((pc->type == PC_FUNCTION) &&
6805 (strcmp(fname, PCF(pc)->fname)==0))
6808 pc = setNextItem(pb->function_entries);
6816 static void MarkUsedRegisters(set *regset)
6821 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6822 // fprintf(stderr, "marking register = %s\t", r1->name);
6823 r2 = pic16_regWithIdx(r1->rIdx);
6824 // fprintf(stderr, "to register = %s\n", r2->name);
6830 static void pBlockStats(FILE *of, pBlock *pb)
6836 if(!pic16_pcode_verbose)return;
6838 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6840 // for now just print the first element of each set
6841 pc = setFirstItem(pb->function_entries);
6843 fprintf(of,";entry: ");
6846 pc = setFirstItem(pb->function_exits);
6848 fprintf(of,";has an exit\n");
6852 pc = setFirstItem(pb->function_calls);
6854 fprintf(of,";functions called:\n");
6857 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6858 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6860 pc = setNextItem(pb->function_calls);
6864 r = setFirstItem(pb->tregisters);
6866 int n = elementsInSet(pb->tregisters);
6868 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6871 fprintf(of,"; %s\n",r->name);
6872 r = setNextItem(pb->tregisters);
6877 /*-----------------------------------------------------------------*/
6878 /*-----------------------------------------------------------------*/
6880 static void sequencepCode(void)
6886 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6888 pb->seq = GpCodeSequenceNumber+1;
6890 for( pc = pb->pcHead; pc; pc = pc->next)
6891 pc->seq = ++GpCodeSequenceNumber;
6897 /*-----------------------------------------------------------------*/
6898 /*-----------------------------------------------------------------*/
6899 static set *register_usage(pBlock *pb)
6902 set *registers=NULL;
6903 set *registersInCallPath = NULL;
6905 /* check recursion */
6907 pc = setFirstItem(pb->function_entries);
6914 if(pc->type != PC_FUNCTION)
6915 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6917 pc = setFirstItem(pb->function_calls);
6918 for( ; pc; pc = setNextItem(pb->function_calls)) {
6920 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6921 char *dest = pic16_get_op_from_instruction(PCI(pc));
6923 pcn = findFunction(dest);
6925 registersInCallPath = register_usage(pcn->pb);
6927 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6932 pBlockStats(stderr,pb); // debug
6935 // Mark the registers in this block as used.
6937 MarkUsedRegisters(pb->tregisters);
6938 if(registersInCallPath) {
6939 /* registers were used in the functions this pBlock has called */
6940 /* so now, we need to see if these collide with the ones we are */
6943 regs *r1,*r2, *newreg;
6945 DFPRINTF((stderr,"comparing registers\n"));
6947 r1 = setFirstItem(registersInCallPath);
6950 r2 = setFirstItem(pb->tregisters);
6952 while(r2 && (r1->type != REG_STK)) {
6954 if(r2->rIdx == r1->rIdx) {
6955 newreg = pic16_findFreeReg(REG_GPR);
6959 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6963 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6964 r1->rIdx, newreg->rIdx));
6965 r2->rIdx = newreg->rIdx;
6966 //if(r2->name) free(r2->name);
6968 r2->name = Safe_strdup(newreg->name);
6972 newreg->wasUsed = 1;
6974 r2 = setNextItem(pb->tregisters);
6977 r1 = setNextItem(registersInCallPath);
6980 /* Collisions have been resolved. Now free the registers in the call path */
6981 r1 = setFirstItem(registersInCallPath);
6983 if(r1->type != REG_STK) {
6984 newreg = pic16_regWithIdx(r1->rIdx);
6987 r1 = setNextItem(registersInCallPath);
6991 // MarkUsedRegisters(pb->registers);
6993 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6996 DFPRINTF((stderr,"returning regs\n"));
6998 DFPRINTF((stderr,"not returning regs\n"));
7000 DFPRINTF((stderr,"pBlock after register optim.\n"));
7001 pBlockStats(stderr,pb); // debug
7007 /*-----------------------------------------------------------------*/
7008 /* pct2 - writes the call tree to a file */
7010 /*-----------------------------------------------------------------*/
7011 static void pct2(FILE *of,pBlock *pb,int indent)
7015 // set *registersInCallPath = NULL;
7021 return; //recursion ?
7023 pc = setFirstItem(pb->function_entries);
7030 for(i=0;i<indent;i++) // Indentation
7033 if(pc->type == PC_FUNCTION)
7034 fprintf(of,"%s\n",PCF(pc)->fname);
7039 pc = setFirstItem(pb->function_calls);
7040 for( ; pc; pc = setNextItem(pb->function_calls)) {
7042 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7043 char *dest = pic16_get_op_from_instruction(PCI(pc));
7045 pcn = findFunction(dest);
7047 pct2(of,pcn->pb,indent+1);
7049 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7057 /*-----------------------------------------------------------------*/
7058 /* pic16_printCallTree - writes the call tree to a file */
7060 /*-----------------------------------------------------------------*/
7062 void pic16_printCallTree(FILE *of)
7074 fprintf(of, "\npBlock statistics\n");
7075 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7080 fprintf(of,"Call Tree\n");
7081 pbr = the_pFile->functions;
7085 if(!ispCodeFunction(pc))
7086 fprintf(of,"bug in call tree");
7089 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7091 while(pc->next && !ispCodeFunction(pc->next)) {
7093 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7094 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7102 fprintf(of,"\n**************\n\na better call tree\n");
7103 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7108 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7109 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7115 /*-----------------------------------------------------------------*/
7117 /*-----------------------------------------------------------------*/
7119 static void InlineFunction(pBlock *pb)
7127 pc = setFirstItem(pb->function_calls);
7129 for( ; pc; pc = setNextItem(pb->function_calls)) {
7132 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7138 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7140 //fprintf(stderr,"Cool can inline:\n");
7141 //pcn->print(stderr,pcn);
7143 //fprintf(stderr,"recursive call Inline\n");
7144 InlineFunction(pcn->pb);
7145 //fprintf(stderr,"return from recursive call Inline\n");
7148 At this point, *pc points to a CALL mnemonic, and
7149 *pcn points to the function that is being called.
7151 To in-line this call, we need to remove the CALL
7152 and RETURN(s), and link the function pCode in with
7158 /* Remove the CALL */
7162 /* remove callee pBlock from the pBlock linked list */
7163 removepBlock(pcn->pb);
7171 /* Remove the Function pCode */
7172 pct = pic16_findNextInstruction(pcn->next);
7174 /* Link the function with the callee */
7175 pc->next = pcn->next;
7176 pcn->next->prev = pc;
7178 /* Convert the function name into a label */
7180 pbr = Safe_calloc(1,sizeof(pBranch));
7181 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7183 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7184 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7186 /* turn all of the return's except the last into goto's */
7187 /* check case for 2 instruction pBlocks */
7188 pce = pic16_findNextInstruction(pcn->next);
7190 pCode *pce_next = pic16_findNextInstruction(pce->next);
7192 if(pce_next == NULL) {
7193 /* found the last return */
7194 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7196 //fprintf(stderr,"found last return\n");
7197 //pce->print(stderr,pce);
7198 pce->prev->next = pc_call->next;
7199 pc_call->next->prev = pce->prev;
7200 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7210 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7216 /*-----------------------------------------------------------------*/
7218 /*-----------------------------------------------------------------*/
7220 void pic16_InlinepCode(void)
7229 if(!functionInlining)
7232 /* Loop through all of the function definitions and count the
7233 * number of times each one is called */
7234 //fprintf(stderr,"inlining %d\n",__LINE__);
7236 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7238 pc = setFirstItem(pb->function_calls);
7240 for( ; pc; pc = setNextItem(pb->function_calls)) {
7243 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7244 if(pcn && isPCF(pcn)) {
7245 PCF(pcn)->ncalled++;
7248 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7253 //fprintf(stderr,"inlining %d\n",__LINE__);
7255 /* Now, Loop through the function definitions again, but this
7256 * time inline those functions that have only been called once. */
7258 InlineFunction(the_pFile->pbHead);
7259 //fprintf(stderr,"inlining %d\n",__LINE__);
7261 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7266 char *pic_optype_names[]={
7267 "PO_NONE", // No operand e.g. NOP
7268 "PO_W", // The working register (as a destination)
7269 "PO_WREG", // The working register (as a file register)
7270 "PO_STATUS", // The 'STATUS' register
7271 "PO_BSR", // The 'BSR' register
7272 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7274 "PO_INDF0", // The Indirect register
7275 "PO_INTCON", // Interrupt Control register
7276 "PO_GPR_REGISTER", // A general purpose register
7277 "PO_GPR_BIT", // A bit of a general purpose register
7278 "PO_GPR_TEMP", // A general purpose temporary register
7279 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7280 "PO_PCL", // Program counter Low register
7281 "PO_PCLATH", // Program counter Latch high register
7282 "PO_PCLATU", // Program counter Latch upper register
7283 "PO_PRODL", // Product Register Low
7284 "PO_PRODH", // Product Register High
7285 "PO_LITERAL", // A constant
7286 "PO_REL_ADDR", // A relative address
7287 "PO_IMMEDIATE", // (8051 legacy)
7288 "PO_DIR", // Direct memory (8051 legacy)
7289 "PO_CRY", // bit memory (8051 legacy)
7290 "PO_BIT", // bit operand.
7291 "PO_STR", // (8051 legacy)
7293 "PO_WILD" // Wild card operand in peep optimizer
7297 char *dumpPicOptype(PIC_OPTYPE type)
7299 return (pic_optype_names[ type ]);