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);
4583 SAFE_snprintf(&s,&size,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4586 if(PCAD(pc)->directive) {
4587 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4590 /* special case to handle inline labels without a tab */
4591 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4596 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4603 /*-----------------------------------------------------------------*/
4604 /* genericPrint - the contents of a pCode to a file */
4605 /*-----------------------------------------------------------------*/
4606 static void genericPrint(FILE *of, pCode *pc)
4614 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4618 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4622 // If the opcode has a label, print that first
4624 pBranch *pbl = PCI(pc)->label;
4625 while(pbl && pbl->pc) {
4626 if(pbl->pc->type == PC_LABEL)
4627 pCodePrintLabel(of, pbl->pc);
4633 genericPrint(of,PCODE(PCI(pc)->cline));
4638 pic16_pCode2str(str, 256, pc);
4640 fprintf(of,"%s",str);
4642 if(pic16_debug_verbose) {
4643 fprintf(of, "\t;key=%03x",pc->seq);
4645 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4652 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4653 if(PCW(pc)->pci.label)
4654 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4656 if(PCW(pc)->operand) {
4657 fprintf(of,";\toperand ");
4658 pCodeOpPrint(of,PCW(pc)->operand );
4663 if(pic16_debug_verbose) {
4664 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4665 if(PCFL(pc)->ancestor)
4666 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4673 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4674 fprintf(of,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4680 pBranch *pbl = PCAD(pc)->pci.label;
4681 while(pbl && pbl->pc) {
4682 if(pbl->pc->type == PC_LABEL)
4683 pCodePrintLabel(of, pbl->pc);
4687 if(PCAD(pc)->directive) {
4688 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4691 /* special case to handle inline labels without tab */
4692 fprintf(of, "%s\n", PCAD(pc)->arg);
4698 fprintf(of,"unknown pCode type %d\n",pc->type);
4703 /*-----------------------------------------------------------------*/
4704 /* pCodePrintFunction - prints function begin/end */
4705 /*-----------------------------------------------------------------*/
4707 static void pCodePrintFunction(FILE *of, pCode *pc)
4714 if( ((pCodeFunction *)pc)->modname)
4715 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4718 if(PCF(pc)->fname) {
4719 pBranch *exits = PCF(pc)->to;
4721 fprintf(of,"%s", PCF(pc)->fname);
4723 // if(pic16_pcode_verbose)
4724 fprintf(of, "\t;Function start");
4730 exits = exits->next;
4734 if(pic16_pcode_verbose)
4735 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4738 if((PCF(pc)->from &&
4739 PCF(pc)->from->pc->type == PC_FUNCTION &&
4740 PCF(PCF(pc)->from->pc)->fname) ) {
4742 if(pic16_pcode_verbose)
4743 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4745 if(pic16_pcode_verbose)
4746 fprintf(of,"; exit point [can't find entry point]\n");
4751 /*-----------------------------------------------------------------*/
4752 /* pCodePrintLabel - prints label */
4753 /*-----------------------------------------------------------------*/
4755 static void pCodePrintLabel(FILE *of, pCode *pc)
4762 fprintf(of,"%s:\n",PCL(pc)->label);
4763 else if (PCL(pc)->key >=0)
4764 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4766 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4769 /*-----------------------------------------------------------------*/
4770 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4771 /* remove it if it is found. */
4772 /*-----------------------------------------------------------------*/
4773 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4780 if(pcl->type == PC_OPCODE)
4781 b = PCI(pcl)->label;
4783 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4788 //fprintf (stderr, "%s \n",__FUNCTION__);
4789 //pcl->print(stderr,pcl);
4790 //pc->print(stderr,pc);
4793 //fprintf (stderr, "found label\n");
4794 //pc->print(stderr, pc);
4798 bprev->next = b->next; /* Not first pCode in chain */
4802 PCI(pcl)->label = b->next; /* First pCode in chain */
4805 return; /* A label can't occur more than once */
4813 /*-----------------------------------------------------------------*/
4814 /*-----------------------------------------------------------------*/
4815 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4834 /*-----------------------------------------------------------------*/
4835 /* pBranchLink - given two pcodes, this function will link them */
4836 /* together through their pBranches */
4837 /*-----------------------------------------------------------------*/
4838 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4842 // Declare a new branch object for the 'from' pCode.
4844 //_ALLOC(b,sizeof(pBranch));
4845 b = Safe_calloc(1,sizeof(pBranch));
4846 b->pc = PCODE(t); // The link to the 'to' pCode.
4849 f->to = pic16_pBranchAppend(f->to,b);
4851 // Now do the same for the 'to' pCode.
4853 //_ALLOC(b,sizeof(pBranch));
4854 b = Safe_calloc(1,sizeof(pBranch));
4858 t->from = pic16_pBranchAppend(t->from,b);
4863 /*-----------------------------------------------------------------*/
4864 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4866 /*-----------------------------------------------------------------*/
4867 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4880 /*-----------------------------------------------------------------*/
4881 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4882 /*-----------------------------------------------------------------*/
4883 static void pCodeUnlink(pCode *pc)
4888 if(!pc->prev || !pc->next) {
4889 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4893 /* first remove the pCode from the chain */
4894 pc->prev->next = pc->next;
4895 pc->next->prev = pc->prev;
4897 /* Now for the hard part... */
4899 /* Remove the branches */
4903 pc1 = pb1->pc; /* Get the pCode that branches to the
4904 * one we're unlinking */
4906 /* search for the link back to this pCode (the one we're
4908 if(pb2 = pBranchFind(pc1->to,pc)) {
4909 pb2->pc = pc->to->pc; // make the replacement
4911 /* if the pCode we're unlinking contains multiple 'to'
4912 * branches (e.g. this a skip instruction) then we need
4913 * to copy these extra branches to the chain. */
4915 pic16_pBranchAppend(pb2, pc->to->next);
4924 /*-----------------------------------------------------------------*/
4925 /*-----------------------------------------------------------------*/
4927 static void genericAnalyze(pCode *pc)
4937 // Go through the pCodes that are in pCode chain and link
4938 // them together through the pBranches. Note, the pCodes
4939 // are linked together as a contiguous stream like the
4940 // assembly source code lines. The linking here mimics this
4941 // except that comments are not linked in.
4943 pCode *npc = pc->next;
4945 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4946 pBranchLink(pc,npc);
4951 /* reached the end of the pcode chain without finding
4952 * an instruction we could link to. */
4956 fprintf(stderr,"analyze PC_FLOW\n");
4960 fprintf(stderr,,";A bad pCode is being used\n");
4966 /*-----------------------------------------------------------------*/
4967 /*-----------------------------------------------------------------*/
4968 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4972 if(pc->type == PC_LABEL) {
4973 if( ((pCodeLabel *)pc)->key == pcop_label->key)
4976 if((pc->type == PC_OPCODE)
4977 || (pc->type == PC_ASMDIR)
4979 pbr = PCI(pc)->label;
4981 if(pbr->pc->type == PC_LABEL) {
4982 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
4992 /*-----------------------------------------------------------------*/
4993 /*-----------------------------------------------------------------*/
4994 static int checkLabel(pCode *pc)
4998 if(pc && isPCI(pc)) {
4999 pbr = PCI(pc)->label;
5001 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5011 /*-----------------------------------------------------------------*/
5012 /* findLabelinpBlock - Search the pCode for a particular label */
5013 /*-----------------------------------------------------------------*/
5014 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5021 for(pc = pb->pcHead; pc; pc = pc->next)
5022 if(compareLabel(pc,pcop_label))
5028 /*-----------------------------------------------------------------*/
5029 /* findLabel - Search the pCode for a particular label */
5030 /*-----------------------------------------------------------------*/
5031 static pCode * findLabel(pCodeOpLabel *pcop_label)
5039 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5040 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5044 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5048 /*-----------------------------------------------------------------*/
5049 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5050 /* in the linked list */
5051 /*-----------------------------------------------------------------*/
5052 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5065 /*-----------------------------------------------------------------*/
5066 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5067 /* in the linked list */
5068 /*-----------------------------------------------------------------*/
5069 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5083 //#define PCODE_DEBUG
5084 /*-----------------------------------------------------------------*/
5085 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5086 /* in the linked list */
5087 /*-----------------------------------------------------------------*/
5088 pCode * pic16_findNextInstruction(pCode *pci)
5093 if((pc->type == PC_OPCODE)
5094 || (pc->type == PC_WILD)
5095 || (pc->type == PC_ASMDIR)
5100 fprintf(stderr,"pic16_findNextInstruction: ");
5101 printpCode(stderr, pc);
5106 //fprintf(stderr,"Couldn't find instruction\n");
5110 /*-----------------------------------------------------------------*/
5111 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5112 /* in the linked list */
5113 /*-----------------------------------------------------------------*/
5114 pCode * pic16_findPrevInstruction(pCode *pci)
5119 if((pc->type == PC_OPCODE)
5120 || (pc->type == PC_WILD)
5121 || (pc->type == PC_ASMDIR)
5127 fprintf(stderr,"pic16_findPrevInstruction: ");
5128 printpCode(stderr, pc);
5133 //fprintf(stderr,"Couldn't find instruction\n");
5140 /*-----------------------------------------------------------------*/
5141 /* findFunctionEnd - given a pCode find the end of the function */
5142 /* that contains it */
5143 /*-----------------------------------------------------------------*/
5144 static pCode * findFunctionEnd(pCode *pc)
5148 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5154 fprintf(stderr,"Couldn't find function end\n");
5159 /*-----------------------------------------------------------------*/
5160 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5161 /* instruction with which it is associated. */
5162 /*-----------------------------------------------------------------*/
5163 static void AnalyzeLabel(pCode *pc)
5172 static void AnalyzeGOTO(pCode *pc)
5175 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5179 static void AnalyzeSKIP(pCode *pc)
5182 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5183 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5187 static void AnalyzeRETURN(pCode *pc)
5190 // branch_link(pc,findFunctionEnd(pc->next));
5196 /*-----------------------------------------------------------------*/
5197 /*-----------------------------------------------------------------*/
5198 regs * pic16_getRegFromInstruction(pCode *pc)
5204 PCI(pc)->num_ops == 0 ||
5205 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5209 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5210 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5213 switch(PCI(pc)->pcop->type) {
5219 return PCOR(PCI(pc)->pcop)->r;
5221 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5225 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5226 return PCOR(PCI(pc)->pcop)->r;
5229 if(PCOI(PCI(pc)->pcop)->r)
5230 return (PCOI(PCI(pc)->pcop)->r);
5232 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
5233 return pic16_dirregWithName(PCI(pc)->pcop->name);
5234 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5237 return PCOR(PCI(pc)->pcop)->r;
5240 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5241 return PCOR(PCI(pc)->pcop)->r;
5243 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5247 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5248 // genericPrint(stderr, pc);
5256 /*-------------------------------------------------------------------------------*/
5257 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5258 /*-------------------------------------------------------------------------------*/
5259 regs * pic16_getRegFromInstruction2(pCode *pc)
5265 PCI(pc)->num_ops == 0 ||
5266 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5271 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5272 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5276 * operands supported in MOVFF:
5283 switch(PCI(pc)->pcop->type) {
5289 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5291 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5295 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5296 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5301 // if(PCOI(PCI(pc)->pcop)->r)
5302 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5304 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5305 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5306 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5311 // return PCOR2(PCI(pc)->pcop)->r;
5314 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5315 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5319 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5322 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5323 //genericPrint(stderr, pc);
5331 /*-----------------------------------------------------------------*/
5332 /*-----------------------------------------------------------------*/
5334 static void AnalyzepBlock(pBlock *pb)
5341 /* Find all of the registers used in this pBlock
5342 * by looking at each instruction and examining it's
5345 for(pc = pb->pcHead; pc; pc = pc->next) {
5347 /* Is this an instruction with operands? */
5348 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5350 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5352 /* Loop through all of the registers declared so far in
5353 this block and see if we find this one there */
5355 regs *r = setFirstItem(pb->tregisters);
5358 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5359 PCOR(PCI(pc)->pcop)->r = r;
5362 r = setNextItem(pb->tregisters);
5366 /* register wasn't found */
5367 //r = Safe_calloc(1, sizeof(regs));
5368 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5369 //addSet(&pb->tregisters, r);
5370 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5371 //PCOR(PCI(pc)->pcop)->r = r;
5372 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5374 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5377 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5378 if(PCOR(PCI(pc)->pcop)->r) {
5379 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5380 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5382 if(PCI(pc)->pcop->name)
5383 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5385 fprintf(stderr,"ERROR: NULL register\n");
5394 /*-----------------------------------------------------------------*/
5396 /*-----------------------------------------------------------------*/
5397 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5399 static void InsertpFlow(pCode *pc, pCode **pflow)
5402 PCFL(*pflow)->end = pc;
5404 if(!pc || !pc->next)
5407 *pflow = pic16_newpCodeFlow();
5408 pic16_pCodeInsertAfter(pc, *pflow);
5411 /*-----------------------------------------------------------------*/
5412 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5413 /* the flow blocks. */
5415 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5416 * point the instruction flow changes.
5418 /*-----------------------------------------------------------------*/
5419 void pic16_BuildFlow(pBlock *pb)
5422 pCode *last_pci=NULL;
5429 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5430 /* Insert a pCodeFlow object at the beginning of a pBlock */
5432 InsertpFlow(pb->pcHead, &pflow);
5434 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5435 //pflow->next = pb->pcHead; /* Make the current head the next object */
5436 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5437 //pb->pcHead = pflow; /* Make the Flow object the head */
5440 for( pc = pic16_findNextInstruction(pb->pcHead);
5442 pc=pic16_findNextInstruction(pc)) {
5445 PCI(pc)->pcflow = PCFL(pflow);
5447 //fprintf(stderr," build: ");
5448 //pflow->print(stderr,pflow);
5450 if( PCI(pc)->isSkip) {
5452 /* The two instructions immediately following this one
5453 * mark the beginning of a new flow segment */
5455 while(pc && PCI(pc)->isSkip) {
5457 PCI(pc)->pcflow = PCFL(pflow);
5461 InsertpFlow(pc, &pflow);
5462 pc=pic16_findNextInstruction(pc->next);
5470 PCI(pc)->pcflow = PCFL(pflow);
5472 InsertpFlow(pc, &pflow);
5474 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5476 InsertpFlow(pc, &pflow);
5479 } else if (checkLabel(pc)) {
5481 /* This instruction marks the beginning of a
5482 * new flow segment */
5487 /* If the previous pCode is not a flow object, then
5488 * insert a new flow object. (This check prevents
5489 * two consecutive flow objects from being insert in
5490 * the case where a skip instruction preceeds an
5491 * instruction containing a label.) */
5493 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5494 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5496 PCI(pc)->pcflow = PCFL(pflow);
5503 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5505 PCFL(pflow)->end = pb->pcTail;
5508 /*-------------------------------------------------------------------*/
5509 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5510 /* the flow blocks. */
5512 * unBuildFlow removes pCodeFlow objects from a pCode chain
5514 /*-----------------------------------------------------------------*/
5515 static void unBuildFlow(pBlock *pb)
5530 if(PCI(pc)->pcflow) {
5531 //free(PCI(pc)->pcflow);
5532 PCI(pc)->pcflow = NULL;
5535 } else if(isPCFL(pc) )
5544 /*-----------------------------------------------------------------*/
5545 /*-----------------------------------------------------------------*/
5546 static void dumpCond(int cond)
5549 static char *pcc_str[] = {
5564 int ncond = sizeof(pcc_str) / sizeof(char *);
5567 fprintf(stderr, "0x%04X\n",cond);
5569 for(i=0,j=1; i<ncond; i++, j<<=1)
5571 fprintf(stderr, " %s\n",pcc_str[i]);
5577 /*-----------------------------------------------------------------*/
5578 /*-----------------------------------------------------------------*/
5579 static void FlowStats(pCodeFlow *pcflow)
5587 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5589 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5592 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5597 fprintf(stderr, " FlowStats inCond: ");
5598 dumpCond(pcflow->inCond);
5599 fprintf(stderr, " FlowStats outCond: ");
5600 dumpCond(pcflow->outCond);
5604 /*-----------------------------------------------------------------*
5605 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5606 * if it affects the banking bits.
5608 * return: -1 == Banking bits are unaffected by this pCode.
5610 * return: > 0 == Banking bits are affected.
5612 * If the banking bits are affected, then the returned value describes
5613 * which bits are affected and how they're affected. The lower half
5614 * of the integer maps to the bits that are affected, the upper half
5615 * to whether they're set or cleared.
5617 *-----------------------------------------------------------------*/
5619 static int isBankInstruction(pCode *pc)
5627 if( PCI(pc)->op == POC_MOVLB ||
5628 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5629 bank = PCOL(pc)->lit;
5636 /*-----------------------------------------------------------------*/
5637 /*-----------------------------------------------------------------*/
5638 static void FillFlow(pCodeFlow *pcflow)
5647 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5649 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5652 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5659 isBankInstruction(pc);
5661 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5665 fprintf(stderr, " FillFlow - Bad end of flow\n");
5667 fprintf(stderr, " FillFlow - Ending flow with\n ");
5668 pc->print(stderr,pc);
5671 fprintf(stderr, " FillFlow inCond: ");
5672 dumpCond(pcflow->inCond);
5673 fprintf(stderr, " FillFlow outCond: ");
5674 dumpCond(pcflow->outCond);
5678 /*-----------------------------------------------------------------*/
5679 /*-----------------------------------------------------------------*/
5680 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5682 pCodeFlowLink *fromLink, *toLink;
5684 if(!from || !to || !to->pcflow || !from->pcflow)
5687 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5688 toLink = pic16_newpCodeFlowLink(to->pcflow);
5690 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5691 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5695 /*-----------------------------------------------------------------*
5696 * void LinkFlow(pBlock *pb)
5698 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5699 * non-branching segments. In LinkFlow, we determine the execution
5700 * order of these segments. For example, if one of the segments ends
5701 * with a skip, then we know that there are two possible flow segments
5702 * to which control may be passed.
5703 *-----------------------------------------------------------------*/
5704 static void LinkFlow(pBlock *pb)
5710 //fprintf(stderr,"linkflow \n");
5712 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5714 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5717 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5719 //fprintf(stderr," link: ");
5720 //pcflow->print(stderr,pcflow);
5722 //FillFlow(PCFL(pcflow));
5724 pc = PCFL(pcflow)->end;
5726 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5727 if(isPCI_SKIP(pc)) {
5728 //fprintf(stderr, "ends with skip\n");
5729 //pc->print(stderr,pc);
5730 pct=pic16_findNextInstruction(pc->next);
5731 LinkFlow_pCode(PCI(pc),PCI(pct));
5732 pct=pic16_findNextInstruction(pct->next);
5733 LinkFlow_pCode(PCI(pc),PCI(pct));
5737 if(isPCI_BRANCH(pc)) {
5738 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5740 //fprintf(stderr, "ends with branch\n ");
5741 //pc->print(stderr,pc);
5743 if(!(pcol && isPCOLAB(pcol))) {
5744 if((PCI(pc)->op != POC_RETLW)
5745 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5747 /* continue if label is '$' which assembler knows how to parse */
5748 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5750 pc->print(stderr,pc);
5751 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5756 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5757 LinkFlow_pCode(PCI(pc),PCI(pct));
5759 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5760 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5762 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5768 //fprintf(stderr, "ends with non-branching instruction:\n");
5769 //pc->print(stderr,pc);
5771 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5777 //fprintf(stderr, "ends with unknown\n");
5778 //pc->print(stderr,pc);
5782 //fprintf(stderr, "ends with nothing: ERROR\n");
5786 /*-----------------------------------------------------------------*/
5787 /*-----------------------------------------------------------------*/
5789 /*-----------------------------------------------------------------*/
5790 /*-----------------------------------------------------------------*/
5791 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5797 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5800 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5810 /*-----------------------------------------------------------------*/
5811 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5812 /*-----------------------------------------------------------------*/
5813 static void insertBankSwitch(int position, pCode *pc, int bsr)
5822 * if bsr == -1 then do not insert a MOVLB instruction, but rather
5823 * insert a BANKSEL assembler directive for the symbol used by
5824 * the pCode. This will allow the linker to setup the correct
5825 * bank at linking time
5828 if(pic16_options.no_banksel || bsr != -1) {
5829 // new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5832 /* emit the BANKSEL [symbol] */
5835 /* IMPORTANT: The following code does not check if a symbol is
5836 * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5838 reg = pic16_getRegFromInstruction(pc);
5840 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5842 position = 0; // position is always before (sanity check!)
5846 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5847 pc->print(stderr, pc);
5851 /* insert the bank switch after this pc instruction */
5852 pCode *pcnext = pic16_findNextInstruction(pc);
5853 pic16_pCodeInsertAfter(pc, new_pc);
5858 pic16_pCodeInsertAfter(pc->prev, new_pc);
5860 /* Move the label, if there is one */
5862 if(PCI(pc)->label) {
5863 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5864 // __FILE__, __LINE__, pc, new_pc);
5865 PCAD(new_pc)->pci.label = PCI(pc)->label;
5866 PCI(pc)->label = NULL;
5869 // fprintf(stderr, "BankSwitch has been inserted\n");
5873 /*-----------------------------------------------------------------*/
5874 /*int compareBankFlow - compare the banking requirements between */
5876 /*-----------------------------------------------------------------*/
5877 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5880 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5883 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5886 if(pcflow->firstBank == -1)
5890 if(pcflowLink->pcflow->firstBank == -1) {
5891 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5892 pcflowLink->pcflow->to :
5893 pcflowLink->pcflow->from);
5894 return compareBankFlow(pcflow, pctl, toORfrom);
5898 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5901 pcflowLink->bank_conflict++;
5902 pcflowLink->pcflow->FromConflicts++;
5903 pcflow->ToConflicts++;
5906 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5909 pcflowLink->bank_conflict++;
5910 pcflowLink->pcflow->ToConflicts++;
5911 pcflow->FromConflicts++;
5915 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5916 pcflowLink->pcflow->pc.seq,
5917 pcflowLink->pcflow->FromConflicts,
5918 pcflowLink->pcflow->ToConflicts);
5925 /*-----------------------------------------------------------------*/
5926 /*-----------------------------------------------------------------*/
5927 static void DumpFlow(pBlock *pb)
5931 pCodeFlowLink *pcfl;
5934 fprintf(stderr,"Dump flow \n");
5935 pb->pcHead->print(stderr, pb->pcHead);
5937 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5938 pcflow->print(stderr,pcflow);
5940 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5942 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5944 if(!isPCFL(pcflow)) {
5945 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5948 fprintf(stderr,"dumping: ");
5949 pcflow->print(stderr,pcflow);
5950 FlowStats(PCFL(pcflow));
5952 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5954 pc = PCODE(pcfl->pcflow);
5956 fprintf(stderr, " from seq %d:\n",pc->seq);
5958 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5959 pc->print(stderr,pc);
5964 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5966 pc = PCODE(pcfl->pcflow);
5968 fprintf(stderr, " to seq %d:\n",pc->seq);
5970 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5971 pc->print(stderr,pc);
5980 /*-----------------------------------------------------------------*/
5981 /*-----------------------------------------------------------------*/
5982 static int OptimizepBlock(pBlock *pb)
5987 if(!pb || !peepOptimizing)
5990 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5992 for(pc = pb->pcHead; pc; pc = pc->next)
5993 matches += pic16_pCodePeepMatchRule(pc);
5996 pc = pic16_findNextInstruction(pb->pcHead);
6004 if(pic16_pCodePeepMatchRule(pc)) {
6009 pc = pic16_findNextInstruction(pcprev->next);
6011 pc = pic16_findNextInstruction(pb->pcHead);
6013 pc = pic16_findNextInstruction(pc->next);
6017 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6022 /*-----------------------------------------------------------------*/
6023 /*-----------------------------------------------------------------*/
6024 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6028 for(pc = pcs; pc; pc = pc->next) {
6030 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6032 (PCI(pc)->pcop->type == PO_LABEL) &&
6033 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6041 /*-----------------------------------------------------------------*/
6042 /*-----------------------------------------------------------------*/
6043 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6050 (PCI(pc)->pcop->type == PO_LABEL)) {
6052 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6054 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6056 free(pcol->pcop.name);
6058 /* If the key is negative, then we (probably) have a label to
6059 * a function and the name is already defined */
6062 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6066 //sprintf(buffer,"_%05d_DS_",pcl->key);
6068 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6070 pcol->pcop.name = Safe_strdup(s);
6071 pcol->key = pcl->key;
6072 //pc->print(stderr,pc);
6079 /*-----------------------------------------------------------------*/
6080 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6081 /* pCode chain if they're not used. */
6082 /*-----------------------------------------------------------------*/
6083 static void pBlockRemoveUnusedLabels(pBlock *pb)
6085 pCode *pc; pCodeLabel *pcl;
6090 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6092 pBranch *pbr = PCI(pc)->label;
6093 if(pbr && pbr->next) {
6094 pCode *pcd = pb->pcHead;
6096 // fprintf(stderr, "multiple labels\n");
6097 // pc->print(stderr,pc);
6102 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6103 //fprintf(stderr,"Used by:\n");
6104 //pcd->print(stderr,pcd);
6106 exchangeLabels(PCL(pbr->pc),pcd);
6115 for(pc = pb->pcHead; pc; pc = pc->next) {
6117 if(isPCL(pc)) // pc->type == PC_LABEL)
6119 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6120 pcl = PCL(PCI(pc)->label->pc);
6123 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6125 /* This pCode is a label, so search the pBlock to see if anyone
6128 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
6129 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6130 /* Couldn't find an instruction that refers to this label
6131 * So, unlink the pCode label from it's pCode chain
6132 * and destroy the label */
6133 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6135 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6136 if(pc->type == PC_LABEL) {
6137 pic16_unlinkpCode(pc);
6138 pCodeLabelDestruct(pc);
6140 unlinkpCodeFromBranch(pc, PCODE(pcl));
6141 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6152 /*-----------------------------------------------------------------*/
6153 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6154 /* chain and put them into pBranches that are */
6155 /* associated with the appropriate pCode */
6157 /*-----------------------------------------------------------------*/
6158 void pic16_pBlockMergeLabels(pBlock *pb)
6161 pCode *pc, *pcnext=NULL;
6166 /* First, Try to remove any unused labels */
6167 //pBlockRemoveUnusedLabels(pb);
6169 /* Now loop through the pBlock and merge the labels with the opcodes */
6172 // for(pc = pb->pcHead; pc; pc = pc->next) {
6175 pCode *pcn = pc->next;
6177 if(pc->type == PC_LABEL) {
6179 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6180 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6182 if((pcnext = pic16_findNextInstruction(pc) )) {
6184 // pcnext->print(stderr, pcnext);
6186 // Unlink the pCode label from it's pCode chain
6187 pic16_unlinkpCode(pc);
6189 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6190 // And link it into the instruction's pBranch labels. (Note, since
6191 // it's possible to have multiple labels associated with one instruction
6192 // we must provide a means to accomodate the additional labels. Thus
6193 // the labels are placed into the singly-linked list "label" as
6194 // opposed to being a single member of the pCodeInstruction.)
6196 //_ALLOC(pbr,sizeof(pBranch));
6198 pbr = Safe_calloc(1,sizeof(pBranch));
6202 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6205 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6207 } else if(pc->type == PC_CSOURCE) {
6209 /* merge the source line symbolic info into the next instruction */
6210 if((pcnext = pic16_findNextInstruction(pc) )) {
6212 // Unlink the pCode label from it's pCode chain
6213 pic16_unlinkpCode(pc);
6214 PCI(pcnext)->cline = PCCS(pc);
6215 //fprintf(stderr, "merging CSRC\n");
6216 //genericPrint(stderr,pcnext);
6222 pBlockRemoveUnusedLabels(pb);
6226 /*-----------------------------------------------------------------*/
6227 /*-----------------------------------------------------------------*/
6228 static int OptimizepCode(char dbName)
6230 #define MAX_PASSES 4
6239 DFPRINTF((stderr," Optimizing pCode\n"));
6243 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6244 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6245 matches += OptimizepBlock(pb);
6248 while(matches && ++passes < MAX_PASSES);
6253 /*-----------------------------------------------------------------*/
6254 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6255 /*-----------------------------------------------------------------*/
6257 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6261 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
6263 if( !( (pcop->type == PO_LABEL) ||
6264 (pcop->type == PO_LITERAL) ||
6265 (pcop->type == PO_STR) ))
6266 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6267 PCOR(pcop)->r->wasUsed = 1;
6273 /*----------------------------------------------------------------------*
6274 * pic16_areRegsSame - check to see if the names of two registers match *
6275 *----------------------------------------------------------------------*/
6276 int pic16_areRegsSame(regs *r1, regs *r2)
6278 if(!strcmp(r1->name, r2->name))return 1;
6284 /*-----------------------------------------------------------------*/
6285 /*-----------------------------------------------------------------*/
6286 static void pic16_FixRegisterBanking(pBlock *pb)
6290 regs *reg, *prevreg;
6295 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6299 /* loop through all of the flow blocks with in one pblock */
6301 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6305 /* at this point, pc should point to a PC_FLOW object */
6306 /* for each flow block, determine the register banking
6309 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
6310 reg = pic16_getRegFromInstruction(pc);
6313 fprintf(stderr, "reg = %p\n", reg);
6315 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6316 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
6317 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
6318 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
6322 /* we can be 99% that within a pBlock, between two consequtive
6323 * refernces to the same register, the extra banksel is needless */
6325 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6327 && (PCI(pc)->op != POC_CALL)
6329 && ( ((pic16_options.opt_banksel>0)
6330 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6331 || (!pic16_options.opt_banksel)
6335 /* Examine the instruction before this one to make sure it is
6336 * not a skip type instruction */
6337 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6339 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6340 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6341 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6343 insertBankSwitch(0, pc, (pic16_options.no_banksel)?0:-1);
6355 if(pcprev && cur_bank) {
6357 int pos = 1; /* Assume that the bank switch instruction(s)
6358 * are inserted after this instruction */
6360 if((PCI(pcprev)->op == POC_RETLW) ||
6361 (PCI(pcprev)->op == POC_RETURN) ||
6362 (PCI(pcprev)->op == POC_RETFIE)) {
6364 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6370 /* Brute force - make sure that we point to bank 0 at the
6371 * end of each flow block */
6373 // insertBankSwitch(pos, pcprev, 0);
6375 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6376 pic16_pCodeInsertAfter(pcprev, new_pc);
6379 //fprintf(stderr, "Brute force switch\n");
6386 static void pBlockDestruct(pBlock *pb)
6397 /*-----------------------------------------------------------------*/
6398 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6399 /* name dbName and combine them */
6400 /* into one block */
6401 /*-----------------------------------------------------------------*/
6402 static void mergepBlocks(char dbName)
6405 pBlock *pb, *pbmerged = NULL,*pbn;
6407 pb = the_pFile->pbHead;
6409 //fprintf(stderr," merging blocks named %c\n",dbName);
6413 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6414 if( getpBlock_dbName(pb) == dbName) {
6416 //fprintf(stderr," merged block %c\n",dbName);
6421 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6422 /* pic16_addpCode2pBlock doesn't handle the tail: */
6423 pbmerged->pcTail = pb->pcTail;
6425 pb->prev->next = pbn;
6427 pbn->prev = pb->prev;
6432 //pic16_printpBlock(stderr, pbmerged);
6439 /*-----------------------------------------------------------------*/
6440 /* AnalyzeFlow - Examine the flow of the code and optimize */
6442 /* level 0 == minimal optimization */
6443 /* optimize registers that are used only by two instructions */
6444 /* level 1 == maximal optimization */
6445 /* optimize by looking at pairs of instructions that use the */
6447 /*-----------------------------------------------------------------*/
6449 static void AnalyzeFlow(int level)
6451 static int times_called=0;
6456 /* remove unused allocated registers before exiting */
6457 pic16_RemoveUnusedRegisters();
6463 /* if this is not the first time this function has been called,
6464 then clean up old flow information */
6465 if(times_called++) {
6466 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6469 pic16_RegsUnMapLiveRanges();
6474 /* Phase 2 - Flow Analysis - Register Banking
6476 * In this phase, the individual flow blocks are examined
6477 * and register banking is fixed.
6481 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6482 pic16_FixRegisterBanking(pb);
6485 /* Phase 2 - Flow Analysis
6487 * In this phase, the pCode is partition into pCodeFlow
6488 * blocks. The flow blocks mark the points where a continuous
6489 * stream of instructions changes flow (e.g. because of
6490 * a call or goto or whatever).
6493 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6494 pic16_BuildFlow(pb);
6497 /* Phase 2 - Flow Analysis - linking flow blocks
6499 * In this phase, the individual flow blocks are examined
6500 * to determine their order of excution.
6503 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6506 /* Phase 3 - Flow Analysis - Flow Tree
6508 * In this phase, the individual flow blocks are examined
6509 * to determine their order of execution.
6512 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6513 pic16_BuildFlowTree(pb);
6516 /* Phase x - Flow Analysis - Used Banks
6518 * In this phase, the individual flow blocks are examined
6519 * to determine the Register Banks they use
6523 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6528 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6529 pic16_pCodeRegMapLiveRanges(pb);
6531 pic16_RemoveUnusedRegisters();
6533 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6534 pic16_pCodeRegOptimizeRegUsage(level);
6542 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6547 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6549 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6550 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6551 pcflow = pcflow->next) {
6553 FillFlow(PCFL(pcflow));
6558 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6561 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6562 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6563 pcflow = pcflow->next) {
6565 FlowStats(PCFL(pcflow));
6571 /* VR -- no need to analyze banking in flow, but left here :
6572 * 1. because it may be used in the future for other purposes
6573 * 2. because if omitted we'll miss some optimization done here
6575 * Perhaps I should rename it to something else
6578 /*-----------------------------------------------------------------*/
6579 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6580 /* assigned to the registers. */
6582 /*-----------------------------------------------------------------*/
6584 void pic16_AnalyzeBanking(void)
6588 if(!pic16_picIsInitialized()) {
6589 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6590 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6591 fprintf(stderr,"support/scripts/inc2h.pl\n");
6592 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6594 /* I think it took a long long time to fix this bug! ;-) -- VR */
6600 /* Phase x - Flow Analysis - Used Banks
6602 * In this phase, the individual flow blocks are examined
6603 * to determine the Register Banks they use
6609 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6610 // BanksUsedFlow(pb);
6612 if(!the_pFile)return;
6614 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6615 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6616 pic16_FixRegisterBanking(pb);
6621 /*-----------------------------------------------------------------*/
6622 /* buildCallTree - Look at the flow and extract all of the calls. */
6623 /*-----------------------------------------------------------------*/
6624 static set *register_usage(pBlock *pb);
6626 static void buildCallTree(void )
6637 /* Now build the call tree.
6638 First we examine all of the pCodes for functions.
6639 Keep in mind that the function boundaries coincide
6640 with pBlock boundaries.
6642 The algorithm goes something like this:
6643 We have two nested loops. The outer loop iterates
6644 through all of the pBlocks/functions. The inner
6645 loop iterates through all of the pCodes for
6646 a given pBlock. When we begin iterating through
6647 a pBlock, the variable pc_fstart, pCode of the start
6648 of a function, is cleared. We then search for pCodes
6649 of type PC_FUNCTION. When one is encountered, we
6650 initialize pc_fstart to this and at the same time
6651 associate a new pBranch object that signifies a
6652 branch entry. If a return is found, then this signifies
6653 a function exit point. We'll link the pCodes of these
6654 returns to the matching pc_fstart.
6656 When we're done, a doubly linked list of pBranches
6657 will exist. The head of this list is stored in
6658 `the_pFile', which is the meta structure for all
6659 of the pCode. Look at the pic16_printCallTree function
6660 on how the pBranches are linked together.
6663 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6664 pCode *pc_fstart=NULL;
6665 for(pc = pb->pcHead; pc; pc = pc->next) {
6667 if (PCF(pc)->fname) {
6669 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6670 //fprintf(stderr," found main \n");
6671 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6675 pbr = Safe_calloc(1,sizeof(pBranch));
6676 pbr->pc = pc_fstart = pc;
6679 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6681 // Here's a better way of doing the same:
6682 addSet(&pb->function_entries, pc);
6685 // Found an exit point in a function, e.g. return
6686 // (Note, there may be more than one return per function)
6688 pBranchLink(PCF(pc_fstart), PCF(pc));
6690 addSet(&pb->function_exits, pc);
6692 } else if(isCALL(pc)) {
6693 addSet(&pb->function_calls,pc);
6700 /* This is not needed because currently all register used
6701 * by a function are stored in stack -- VR */
6703 /* Re-allocate the registers so that there are no collisions
6704 * between local variables when one function call another */
6707 // pic16_deallocateAllRegs();
6709 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6717 /*-----------------------------------------------------------------*/
6718 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6719 /* all of the logical connections. */
6721 /* Essentially what's done here is that the pCode flow is */
6723 /*-----------------------------------------------------------------*/
6725 void pic16_AnalyzepCode(char dbName)
6736 /* Phase 1 - Register allocation and peep hole optimization
6738 * The first part of the analysis is to determine the registers
6739 * that are used in the pCode. Once that is done, the peep rules
6740 * are applied to the code. We continue to loop until no more
6741 * peep rule optimizations are found (or until we exceed the
6742 * MAX_PASSES threshold).
6744 * When done, the required registers will be determined.
6750 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6751 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6753 /* First, merge the labels with the instructions */
6754 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6755 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6757 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6758 //fprintf(stderr," analyze and merging block %c\n",dbName);
6759 pic16_pBlockMergeLabels(pb);
6762 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6767 changes = OptimizepCode(dbName);
6770 } while(changes && (i++ < MAX_PASSES));
6775 /*-----------------------------------------------------------------*/
6776 /* ispCodeFunction - returns true if *pc is the pCode of a */
6778 /*-----------------------------------------------------------------*/
6779 static bool ispCodeFunction(pCode *pc)
6782 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6788 /*-----------------------------------------------------------------*/
6789 /* findFunction - Search for a function by name (given the name) */
6790 /* in the set of all functions that are in a pBlock */
6791 /* (note - I expect this to change because I'm planning to limit */
6792 /* pBlock's to just one function declaration */
6793 /*-----------------------------------------------------------------*/
6794 static pCode *findFunction(char *fname)
6801 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6803 pc = setFirstItem(pb->function_entries);
6806 if((pc->type == PC_FUNCTION) &&
6808 (strcmp(fname, PCF(pc)->fname)==0))
6811 pc = setNextItem(pb->function_entries);
6819 static void MarkUsedRegisters(set *regset)
6824 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6825 // fprintf(stderr, "marking register = %s\t", r1->name);
6826 r2 = pic16_regWithIdx(r1->rIdx);
6827 // fprintf(stderr, "to register = %s\n", r2->name);
6833 static void pBlockStats(FILE *of, pBlock *pb)
6839 if(!pic16_pcode_verbose)return;
6841 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6843 // for now just print the first element of each set
6844 pc = setFirstItem(pb->function_entries);
6846 fprintf(of,";entry: ");
6849 pc = setFirstItem(pb->function_exits);
6851 fprintf(of,";has an exit\n");
6855 pc = setFirstItem(pb->function_calls);
6857 fprintf(of,";functions called:\n");
6860 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6861 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6863 pc = setNextItem(pb->function_calls);
6867 r = setFirstItem(pb->tregisters);
6869 int n = elementsInSet(pb->tregisters);
6871 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6874 fprintf(of,"; %s\n",r->name);
6875 r = setNextItem(pb->tregisters);
6880 /*-----------------------------------------------------------------*/
6881 /*-----------------------------------------------------------------*/
6883 static void sequencepCode(void)
6889 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6891 pb->seq = GpCodeSequenceNumber+1;
6893 for( pc = pb->pcHead; pc; pc = pc->next)
6894 pc->seq = ++GpCodeSequenceNumber;
6900 /*-----------------------------------------------------------------*/
6901 /*-----------------------------------------------------------------*/
6902 static set *register_usage(pBlock *pb)
6905 set *registers=NULL;
6906 set *registersInCallPath = NULL;
6908 /* check recursion */
6910 pc = setFirstItem(pb->function_entries);
6917 if(pc->type != PC_FUNCTION)
6918 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6920 pc = setFirstItem(pb->function_calls);
6921 for( ; pc; pc = setNextItem(pb->function_calls)) {
6923 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6924 char *dest = pic16_get_op_from_instruction(PCI(pc));
6926 pcn = findFunction(dest);
6928 registersInCallPath = register_usage(pcn->pb);
6930 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6935 pBlockStats(stderr,pb); // debug
6938 // Mark the registers in this block as used.
6940 MarkUsedRegisters(pb->tregisters);
6941 if(registersInCallPath) {
6942 /* registers were used in the functions this pBlock has called */
6943 /* so now, we need to see if these collide with the ones we are */
6946 regs *r1,*r2, *newreg;
6948 DFPRINTF((stderr,"comparing registers\n"));
6950 r1 = setFirstItem(registersInCallPath);
6953 r2 = setFirstItem(pb->tregisters);
6955 while(r2 && (r1->type != REG_STK)) {
6957 if(r2->rIdx == r1->rIdx) {
6958 newreg = pic16_findFreeReg(REG_GPR);
6962 DFPRINTF((stderr,"Bummer, no more registers.\n"));
6966 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6967 r1->rIdx, newreg->rIdx));
6968 r2->rIdx = newreg->rIdx;
6969 //if(r2->name) free(r2->name);
6971 r2->name = Safe_strdup(newreg->name);
6975 newreg->wasUsed = 1;
6977 r2 = setNextItem(pb->tregisters);
6980 r1 = setNextItem(registersInCallPath);
6983 /* Collisions have been resolved. Now free the registers in the call path */
6984 r1 = setFirstItem(registersInCallPath);
6986 if(r1->type != REG_STK) {
6987 newreg = pic16_regWithIdx(r1->rIdx);
6990 r1 = setNextItem(registersInCallPath);
6994 // MarkUsedRegisters(pb->registers);
6996 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6999 DFPRINTF((stderr,"returning regs\n"));
7001 DFPRINTF((stderr,"not returning regs\n"));
7003 DFPRINTF((stderr,"pBlock after register optim.\n"));
7004 pBlockStats(stderr,pb); // debug
7010 /*-----------------------------------------------------------------*/
7011 /* pct2 - writes the call tree to a file */
7013 /*-----------------------------------------------------------------*/
7014 static void pct2(FILE *of,pBlock *pb,int indent)
7018 // set *registersInCallPath = NULL;
7024 return; //recursion ?
7026 pc = setFirstItem(pb->function_entries);
7033 for(i=0;i<indent;i++) // Indentation
7036 if(pc->type == PC_FUNCTION)
7037 fprintf(of,"%s\n",PCF(pc)->fname);
7042 pc = setFirstItem(pb->function_calls);
7043 for( ; pc; pc = setNextItem(pb->function_calls)) {
7045 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7046 char *dest = pic16_get_op_from_instruction(PCI(pc));
7048 pcn = findFunction(dest);
7050 pct2(of,pcn->pb,indent+1);
7052 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7060 /*-----------------------------------------------------------------*/
7061 /* pic16_printCallTree - writes the call tree to a file */
7063 /*-----------------------------------------------------------------*/
7065 void pic16_printCallTree(FILE *of)
7077 fprintf(of, "\npBlock statistics\n");
7078 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7083 fprintf(of,"Call Tree\n");
7084 pbr = the_pFile->functions;
7088 if(!ispCodeFunction(pc))
7089 fprintf(of,"bug in call tree");
7092 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7094 while(pc->next && !ispCodeFunction(pc->next)) {
7096 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7097 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7105 fprintf(of,"\n**************\n\na better call tree\n");
7106 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7111 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7112 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7118 /*-----------------------------------------------------------------*/
7120 /*-----------------------------------------------------------------*/
7122 static void InlineFunction(pBlock *pb)
7130 pc = setFirstItem(pb->function_calls);
7132 for( ; pc; pc = setNextItem(pb->function_calls)) {
7135 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7141 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7143 //fprintf(stderr,"Cool can inline:\n");
7144 //pcn->print(stderr,pcn);
7146 //fprintf(stderr,"recursive call Inline\n");
7147 InlineFunction(pcn->pb);
7148 //fprintf(stderr,"return from recursive call Inline\n");
7151 At this point, *pc points to a CALL mnemonic, and
7152 *pcn points to the function that is being called.
7154 To in-line this call, we need to remove the CALL
7155 and RETURN(s), and link the function pCode in with
7161 /* Remove the CALL */
7165 /* remove callee pBlock from the pBlock linked list */
7166 removepBlock(pcn->pb);
7174 /* Remove the Function pCode */
7175 pct = pic16_findNextInstruction(pcn->next);
7177 /* Link the function with the callee */
7178 pc->next = pcn->next;
7179 pcn->next->prev = pc;
7181 /* Convert the function name into a label */
7183 pbr = Safe_calloc(1,sizeof(pBranch));
7184 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7186 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7187 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7189 /* turn all of the return's except the last into goto's */
7190 /* check case for 2 instruction pBlocks */
7191 pce = pic16_findNextInstruction(pcn->next);
7193 pCode *pce_next = pic16_findNextInstruction(pce->next);
7195 if(pce_next == NULL) {
7196 /* found the last return */
7197 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7199 //fprintf(stderr,"found last return\n");
7200 //pce->print(stderr,pce);
7201 pce->prev->next = pc_call->next;
7202 pc_call->next->prev = pce->prev;
7203 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7213 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7219 /*-----------------------------------------------------------------*/
7221 /*-----------------------------------------------------------------*/
7223 void pic16_InlinepCode(void)
7232 if(!functionInlining)
7235 /* Loop through all of the function definitions and count the
7236 * number of times each one is called */
7237 //fprintf(stderr,"inlining %d\n",__LINE__);
7239 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7241 pc = setFirstItem(pb->function_calls);
7243 for( ; pc; pc = setNextItem(pb->function_calls)) {
7246 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7247 if(pcn && isPCF(pcn)) {
7248 PCF(pcn)->ncalled++;
7251 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7256 //fprintf(stderr,"inlining %d\n",__LINE__);
7258 /* Now, Loop through the function definitions again, but this
7259 * time inline those functions that have only been called once. */
7261 InlineFunction(the_pFile->pbHead);
7262 //fprintf(stderr,"inlining %d\n",__LINE__);
7264 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7269 char *pic_optype_names[]={
7270 "PO_NONE", // No operand e.g. NOP
7271 "PO_W", // The working register (as a destination)
7272 "PO_WREG", // The working register (as a file register)
7273 "PO_STATUS", // The 'STATUS' register
7274 "PO_BSR", // The 'BSR' register
7275 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7277 "PO_INDF0", // The Indirect register
7278 "PO_INTCON", // Interrupt Control register
7279 "PO_GPR_REGISTER", // A general purpose register
7280 "PO_GPR_BIT", // A bit of a general purpose register
7281 "PO_GPR_TEMP", // A general purpose temporary register
7282 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7283 "PO_PCL", // Program counter Low register
7284 "PO_PCLATH", // Program counter Latch high register
7285 "PO_PCLATU", // Program counter Latch upper register
7286 "PO_PRODL", // Product Register Low
7287 "PO_PRODH", // Product Register High
7288 "PO_LITERAL", // A constant
7289 "PO_REL_ADDR", // A relative address
7290 "PO_IMMEDIATE", // (8051 legacy)
7291 "PO_DIR", // Direct memory (8051 legacy)
7292 "PO_CRY", // bit memory (8051 legacy)
7293 "PO_BIT", // bit operand.
7294 "PO_STR", // (8051 legacy)
7296 "PO_WILD" // Wild card operand in peep optimizer
7300 char *dumpPicOptype(PIC_OPTYPE type)
7302 return (pic_optype_names[ type ]);