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;
3452 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3453 strcpy(pcf->modname,mod);
3455 pcf->modname = NULL;
3458 pcf->fname = Safe_calloc(1,strlen(f)+1);
3459 strcpy(pcf->fname,f);
3463 return ( (pCode *)pcf);
3467 /*-----------------------------------------------------------------*/
3468 /* pic16_newpCodeFlow */
3469 /*-----------------------------------------------------------------*/
3470 static void destructpCodeFlow(pCode *pc)
3472 if(!pc || !isPCFL(pc))
3479 pic16_unlinkpCode(pc);
3481 deleteSet(&PCFL(pc)->registers);
3482 deleteSet(&PCFL(pc)->from);
3483 deleteSet(&PCFL(pc)->to);
3488 pCode *pic16_newpCodeFlow(void )
3492 //_ALLOC(pcflow,sizeof(pCodeFlow));
3493 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3495 pcflow->pc.type = PC_FLOW;
3496 pcflow->pc.prev = pcflow->pc.next = NULL;
3497 pcflow->pc.pb = NULL;
3499 // pcflow->pc.analyze = genericAnalyze;
3500 pcflow->pc.destruct = destructpCodeFlow;
3501 pcflow->pc.print = genericPrint;
3503 pcflow->pc.seq = GpcFlowSeq++;
3505 pcflow->from = pcflow->to = NULL;
3507 pcflow->inCond = PCC_NONE;
3508 pcflow->outCond = PCC_NONE;
3510 pcflow->firstBank = -1;
3511 pcflow->lastBank = -1;
3513 pcflow->FromConflicts = 0;
3514 pcflow->ToConflicts = 0;
3518 pcflow->registers = newSet();
3520 return ( (pCode *)pcflow);
3524 /*-----------------------------------------------------------------*/
3525 /*-----------------------------------------------------------------*/
3526 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3528 pCodeFlowLink *pcflowLink;
3530 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3532 pcflowLink->pcflow = pcflow;
3533 pcflowLink->bank_conflict = 0;
3538 /*-----------------------------------------------------------------*/
3539 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3540 /*-----------------------------------------------------------------*/
3542 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3547 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3549 pccs->pc.type = PC_CSOURCE;
3550 pccs->pc.prev = pccs->pc.next = NULL;
3553 pccs->pc.destruct = genericDestruct;
3554 pccs->pc.print = genericPrint;
3556 pccs->line_number = ln;
3558 pccs->line = Safe_strdup(l);
3563 pccs->file_name = Safe_strdup(f);
3565 pccs->file_name = NULL;
3567 return ( (pCode *)pccs);
3572 /*******************************************************************/
3573 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3574 /* added by VR 6-Jun-2003 */
3575 /*******************************************************************/
3577 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3584 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3585 pcad->pci.pc.type = PC_ASMDIR;
3586 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3587 pcad->pci.pc.pb = NULL;
3589 pcad->pci.pc.destruct = genericDestruct;
3590 pcad->pci.pc.print = genericPrint;
3592 if(asdir && *asdir) {
3594 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3596 pcad->directive = Safe_strdup( asdir );
3599 va_start(ap, argfmt);
3601 memset(buffer, 0, sizeof(buffer));
3602 if(argfmt && *argfmt)
3603 vsprintf(buffer, argfmt, ap);
3607 while(isspace(*lbp))lbp++;
3610 pcad->arg = Safe_strdup( lbp );
3612 return ((pCode *)pcad);
3615 /*-----------------------------------------------------------------*/
3616 /* pCodeLabelDestruct - free memory used by a label. */
3617 /*-----------------------------------------------------------------*/
3618 static void pCodeLabelDestruct(pCode *pc)
3624 if((pc->type == PC_LABEL) && PCL(pc)->label)
3625 free(PCL(pc)->label);
3631 pCode *pic16_newpCodeLabel(char *name, int key)
3637 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3639 pcl->pc.type = PC_LABEL;
3640 pcl->pc.prev = pcl->pc.next = NULL;
3641 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3644 // pcl->pc.analyze = genericAnalyze;
3645 pcl->pc.destruct = pCodeLabelDestruct;
3646 pcl->pc.print = pCodePrintLabel;
3653 sprintf(s,"_%05d_DS_",key);
3658 pcl->label = Safe_strdup(s);
3660 // if(pic16_pcode_verbose)
3661 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3664 return ( (pCode *)pcl);
3668 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3670 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3674 return ( (pCode *)pcl );
3678 /*-----------------------------------------------------------------*/
3679 /* newpBlock - create and return a pointer to a new pBlock */
3680 /*-----------------------------------------------------------------*/
3681 static pBlock *newpBlock(void)
3686 PpB = Safe_calloc(1,sizeof(pBlock) );
3687 PpB->next = PpB->prev = NULL;
3689 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3690 PpB->tregisters = NULL;
3692 PpB->FlowTree = NULL;
3698 /*-----------------------------------------------------------------*/
3699 /* pic16_newpCodeChain - create a new chain of pCodes */
3700 /*-----------------------------------------------------------------*
3702 * This function will create a new pBlock and the pointer to the
3703 * pCode that is passed in will be the first pCode in the block.
3704 *-----------------------------------------------------------------*/
3707 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3710 pBlock *pB = newpBlock();
3712 pB->pcHead = pB->pcTail = pc;
3719 /*-----------------------------------------------------------------*/
3720 /* pic16_newpCodeOpLabel - Create a new label given the key */
3721 /* Note, a negative key means that the label is part of wild card */
3722 /* (and hence a wild card label) used in the pCodePeep */
3723 /* optimizations). */
3724 /*-----------------------------------------------------------------*/
3726 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3729 static int label_key=-1;
3733 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3734 pcop->type = PO_LABEL;
3739 sprintf(s=buffer,"_%05d_DS_",key);
3741 s = name, key = label_key--;
3744 pcop->name = Safe_strdup(s);
3746 ((pCodeOpLabel *)pcop)->key = key;
3748 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3752 /*-----------------------------------------------------------------*/
3753 /*-----------------------------------------------------------------*/
3754 pCodeOp *pic16_newpCodeOpLit(int lit)
3760 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3761 pcop->type = PO_LITERAL;
3765 sprintf(s,"0x%02x",lit);
3767 pcop->name = Safe_strdup(s);
3770 ((pCodeOpLit *)pcop)->lit = lit;
3775 /*-----------------------------------------------------------------*/
3776 /*-----------------------------------------------------------------*/
3777 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3779 char *s = buffer, tbuf[256], *tb=tbuf;
3783 tb = pic16_get_op(arg2, NULL, 0);
3784 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3785 pcop->type = PO_LITERAL;
3789 sprintf(s,"0x%02x, %s",lit, tb);
3791 pcop->name = Safe_strdup(s);
3794 ((pCodeOpLit2 *)pcop)->lit = lit;
3795 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3800 /*-----------------------------------------------------------------*/
3801 /*-----------------------------------------------------------------*/
3802 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3806 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3807 pcop->type = PO_IMMEDIATE;
3809 regs *r = pic16_dirregWithName(name);
3810 pcop->name = Safe_strdup(name);
3814 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3815 PCOI(pcop)->rIdx = r->rIdx;
3817 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3818 // __FILE__, __LINE__, __FUNCTION__, name);
3819 PCOI(pcop)->rIdx = -1;
3821 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3826 PCOI(pcop)->index = index;
3827 PCOI(pcop)->offset = offset;
3828 PCOI(pcop)->_const = code_space;
3833 /*-----------------------------------------------------------------*/
3834 /*-----------------------------------------------------------------*/
3835 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3841 if(!pcwb || !subtype) {
3842 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3846 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3847 pcop->type = PO_WILD;
3848 sprintf(s,"%%%d",id);
3849 pcop->name = Safe_strdup(s);
3851 PCOW(pcop)->id = id;
3852 PCOW(pcop)->pcwb = pcwb;
3853 PCOW(pcop)->subtype = subtype;
3854 PCOW(pcop)->matched = NULL;
3856 PCOW(pcop)->pcop2 = NULL;
3861 /*-----------------------------------------------------------------*/
3862 /*-----------------------------------------------------------------*/
3863 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3869 if(!pcwb || !subtype || !subtype2) {
3870 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3874 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3875 pcop->type = PO_WILD;
3876 sprintf(s,"%%%d",id);
3877 pcop->name = Safe_strdup(s);
3879 PCOW(pcop)->id = id;
3880 PCOW(pcop)->pcwb = pcwb;
3881 PCOW(pcop)->subtype = subtype;
3882 PCOW(pcop)->matched = NULL;
3884 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3886 if(!subtype2->name) {
3887 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3888 PCOW2(pcop)->pcop.type = PO_WILD;
3889 sprintf(s, "%%%d", id2);
3890 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3891 PCOW2(pcop)->id = id2;
3892 PCOW2(pcop)->subtype = subtype2;
3894 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3895 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3897 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
3899 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3900 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3908 /*-----------------------------------------------------------------*/
3909 /*-----------------------------------------------------------------*/
3910 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3914 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3915 pcop->type = PO_GPR_BIT;
3917 pcop->name = Safe_strdup(s);
3921 PCORB(pcop)->bit = bit;
3922 PCORB(pcop)->inBitSpace = inBitSpace;
3924 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3925 PCOR(pcop)->r = NULL;
3926 PCOR(pcop)->rIdx = 0;
3930 /*-----------------------------------------------------------------*
3931 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3933 * If rIdx >=0 then a specific register from the set of registers
3934 * will be selected. If rIdx <0, then a new register will be searched
3936 *-----------------------------------------------------------------*/
3938 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3942 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3947 PCOR(pcop)->rIdx = rIdx;
3948 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3950 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3953 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3955 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3956 __FUNCTION__, __LINE__);
3961 pcop->type = PCOR(pcop)->r->pc_type;
3966 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3971 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3972 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
3973 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3974 pcop->type = PCOR(pcop)->r->pc_type;
3975 pcop->name = PCOR(pcop)->r->name;
3977 // if(pic16_pcode_verbose) {
3978 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3979 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3985 /*-----------------------------------------------------------------*/
3986 /*-----------------------------------------------------------------*/
3988 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3995 pcop = pic16_newpCodeOpBit(name, -1,0);
3999 pcop = pic16_newpCodeOpLit(-1);
4003 pcop = pic16_newpCodeOpLabel(NULL,-1);
4006 pcop = pic16_newpCodeOpReg(-1);
4009 case PO_GPR_REGISTER:
4011 pcop = pic16_newpCodeOpRegFromStr(name);
4013 pcop = pic16_newpCodeOpReg(-1);
4017 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4020 pcop->name = Safe_strdup(name);
4029 typedef struct DBdata
4036 static int DBd_init = -1;
4038 /*-----------------------------------------------------------------*/
4039 /* Initialiase "DB" data buffer */
4040 /*-----------------------------------------------------------------*/
4041 void pic16_initDB(void)
4047 /*-----------------------------------------------------------------*/
4048 /* Flush pending "DB" data to a pBlock */
4050 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4051 /*-----------------------------------------------------------------*/
4052 void pic16_flushDB(char ptype, void *p)
4056 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4059 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4062 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4066 DBd.buffer[0] = '\0';
4071 /*-----------------------------------------------------------------*/
4072 /* Add "DB" directives to a pBlock */
4073 /*-----------------------------------------------------------------*/
4074 void pic16_emitDB(char c, char ptype, void *p)
4079 // we need to initialize
4082 DBd.buffer[0] = '\0';
4085 l = strlen(DBd.buffer);
4086 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4090 pic16_flushDB(ptype, p);
4093 void pic16_emitDS(char *s, char ptype, void *p)
4098 // we need to initialize
4101 DBd.buffer[0] = '\0';
4104 l = strlen(DBd.buffer);
4105 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4107 DBd.count++; //=strlen(s);
4109 pic16_flushDB(ptype, p);
4113 /*-----------------------------------------------------------------*/
4114 /*-----------------------------------------------------------------*/
4115 void pic16_pCodeConstString(char *name, char *value)
4119 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4124 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4126 pic16_addpBlock(pb);
4128 sprintf(buffer,"; %s = %s",name,value);
4130 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4131 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4134 pic16_emitDB(*value, 'p', (void *)pb);
4136 pic16_flushDB('p', (void *)pb);
4139 /*-----------------------------------------------------------------*/
4140 /*-----------------------------------------------------------------*/
4142 static void pCodeReadCodeTable(void)
4146 fprintf(stderr, " %s\n",__FUNCTION__);
4148 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4150 pic16_addpBlock(pb);
4152 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4153 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4154 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4155 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4157 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4158 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4159 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4160 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4165 /*-----------------------------------------------------------------*/
4166 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4167 /*-----------------------------------------------------------------*/
4168 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4175 /* If this is the first pcode to be added to a block that
4176 * was initialized with a NULL pcode, then go ahead and
4177 * make this pcode the head and tail */
4178 pb->pcHead = pb->pcTail = pc;
4181 pb->pcTail->next = pc;
4183 pc->prev = pb->pcTail;
4190 /*-----------------------------------------------------------------*/
4191 /* pic16_addpBlock - place a pBlock into the pFile */
4192 /*-----------------------------------------------------------------*/
4193 void pic16_addpBlock(pBlock *pb)
4195 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4198 /* First time called, we'll pass through here. */
4199 //_ALLOC(the_pFile,sizeof(pFile));
4200 the_pFile = Safe_calloc(1,sizeof(pFile));
4201 the_pFile->pbHead = the_pFile->pbTail = pb;
4202 the_pFile->functions = NULL;
4206 the_pFile->pbTail->next = pb;
4207 pb->prev = the_pFile->pbTail;
4209 the_pFile->pbTail = pb;
4212 /*-----------------------------------------------------------------*/
4213 /* removepBlock - remove a pBlock from the pFile */
4214 /*-----------------------------------------------------------------*/
4215 static void removepBlock(pBlock *pb)
4223 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4225 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4228 if(pbs == the_pFile->pbHead)
4229 the_pFile->pbHead = pbs->next;
4231 if (pbs == the_pFile->pbTail)
4232 the_pFile->pbTail = pbs->prev;
4235 pbs->next->prev = pbs->prev;
4238 pbs->prev->next = pbs->next;
4245 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4249 /*-----------------------------------------------------------------*/
4250 /* printpCode - write the contents of a pCode to a file */
4251 /*-----------------------------------------------------------------*/
4252 static void printpCode(FILE *of, pCode *pc)
4263 fprintf(of,"warning - unable to print pCode\n");
4266 /*-----------------------------------------------------------------*/
4267 /* pic16_printpBlock - write the contents of a pBlock to a file */
4268 /*-----------------------------------------------------------------*/
4269 void pic16_printpBlock(FILE *of, pBlock *pb)
4277 for(pc = pb->pcHead; pc; pc = pc->next) {
4278 if(isPCF(pc) && PCF(pc)->fname) {
4279 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4280 if(pb->dbName == 'A') {
4282 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4283 if(!strcmp(ab->name, PCF(pc)->fname)) {
4284 fprintf(of, "\t0X%06X", ab->address);
4295 /*-----------------------------------------------------------------*/
4297 /* pCode processing */
4301 /*-----------------------------------------------------------------*/
4303 void pic16_unlinkpCode(pCode *pc)
4309 fprintf(stderr,"Unlinking: ");
4310 printpCode(stderr, pc);
4313 pc->prev->next = pc->next;
4315 pc->next->prev = pc->prev;
4317 pc->prev = pc->next = NULL;
4321 /*-----------------------------------------------------------------*/
4322 /*-----------------------------------------------------------------*/
4324 static void genericDestruct(pCode *pc)
4327 pic16_unlinkpCode(pc);
4330 /* For instructions, tell the register (if there's one used)
4331 * that it's no longer needed */
4332 regs *reg = pic16_getRegFromInstruction(pc);
4334 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4336 if(PCI(pc)->is2MemOp) {
4337 reg = pic16_getRegFromInstruction2(pc);
4339 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4343 /* Instead of deleting the memory used by this pCode, mark
4344 * the object as bad so that if there's a pointer to this pCode
4345 * dangling around somewhere then (hopefully) when the type is
4346 * checked we'll catch it.
4351 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4359 /*-----------------------------------------------------------------*/
4360 /*-----------------------------------------------------------------*/
4361 /* modifiers for constant immediate */
4362 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4364 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4369 int use_buffer = 1; // copy the string to the passed buffer pointer
4374 use_buffer = 0; // Don't bother copying the string to the buffer.
4378 switch(pcop->type) {
4384 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4387 return PCOR(pcop)->r->name;
4390 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4392 SAFE_snprintf(&buffer,&size,"%s",r->name);
4399 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4400 if(PCOI(pcop)->index) {
4401 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4402 immdmod[ PCOI(pcop)->offset ],
4406 SAFE_snprintf(&s,&size,"%s(%s)",
4407 immdmod[ PCOI(pcop)->offset ],
4411 if(PCOI(pcop)->index) {
4412 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4417 SAFE_snprintf(&s,&size, "%s(%s)",
4426 // size = sizeof(buffer);
4427 if( PCOR(pcop)->instance) {
4428 SAFE_snprintf(&s,&size,"(%s + %d)",
4430 PCOR(pcop)->instance );
4432 SAFE_snprintf(&s,&size,"%s",pcop->name);
4439 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4448 return "NO operand1";
4451 /*-----------------------------------------------------------------*/
4452 /* pic16_get_op2 - variant to support two memory operand commands */
4453 /*-----------------------------------------------------------------*/
4454 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4459 int use_buffer = 1; // copy the string to the passed buffer pointer
4464 use_buffer = 0; // Don't bother copying the string to the buffer.
4468 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",
4469 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4470 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4474 switch(PCOR2(pcop)->pcop2->type) {
4480 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4483 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4486 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4489 SAFE_snprintf(&buffer,&size,"%s",r->name);
4500 if(PCOI(pcop)->_const) {
4501 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4502 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4505 8 * PCOI(pcop)->offset );
4507 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4509 if( PCOI(pcop)->index) {
4510 SAFE_snprintf(&s,&size,"(%s + %d)",
4512 PCOI(pcop)->index );
4514 if(PCOI(pcop)->offset)
4515 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4517 SAFE_snprintf(&s,&size,"%s",pcop->name);
4524 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4525 SAFE_snprintf(&s,&size,"(%s + %d)",
4526 PCOR(PCOR2(pcop)->pcop2)->r->name,
4527 PCOR(PCOR2(pcop)->pcop2)->instance );
4529 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4534 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4536 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4539 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4544 return "NO operand2";
4547 /*-----------------------------------------------------------------*/
4548 /*-----------------------------------------------------------------*/
4549 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4553 return pic16_get_op(pcc->pcop,NULL,0);
4555 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4556 * return ("ERROR Null: "__FUNCTION__);
4558 return ("ERROR Null: pic16_get_op_from_instruction");
4562 /*-----------------------------------------------------------------*/
4563 /*-----------------------------------------------------------------*/
4564 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4567 fprintf(of,"pcodeopprint- not implemented\n");
4570 /*-----------------------------------------------------------------*/
4571 /* pic16_pCode2str - convert a pCode instruction to string */
4572 /*-----------------------------------------------------------------*/
4573 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4579 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4580 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4581 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4589 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4591 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4593 if(PCI(pc)->is2MemOp) {
4594 SAFE_snprintf(&s,&size, "%s, %s",
4595 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4596 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4600 if(PCI(pc)->is2LitOp) {
4601 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4605 if(PCI(pc)->isBitInst) {
4606 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4607 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4608 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4609 PCI(pc)->pcop->name ,
4610 PCI(pc)->pcop->name );
4612 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4613 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4614 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4615 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4617 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4618 //PCI(pc)->pcop->t.bit );
4621 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4622 if( PCI(pc)->num_ops == 3)
4623 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4625 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4628 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4630 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4631 if(PCI(pc)->num_ops == 3)
4632 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4634 r = pic16_getRegFromInstruction(pc);
4635 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4636 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4638 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4647 /* assuming that comment ends with a \n */
4648 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4652 /* assuming that inline code ends with a \n */
4653 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4657 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4660 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4663 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4666 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4669 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4670 SAFE_snprintf(&s,&size,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4673 if(PCAD(pc)->directive) {
4674 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4677 /* special case to handle inline labels without a tab */
4678 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4683 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4690 /*-----------------------------------------------------------------*/
4691 /* genericPrint - the contents of a pCode to a file */
4692 /*-----------------------------------------------------------------*/
4693 static void genericPrint(FILE *of, pCode *pc)
4701 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4705 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4709 // If the opcode has a label, print that first
4711 pBranch *pbl = PCI(pc)->label;
4712 while(pbl && pbl->pc) {
4713 if(pbl->pc->type == PC_LABEL)
4714 pCodePrintLabel(of, pbl->pc);
4720 genericPrint(of,PCODE(PCI(pc)->cline));
4725 pic16_pCode2str(str, 256, pc);
4727 fprintf(of,"%s",str);
4729 if(pic16_debug_verbose) {
4730 fprintf(of, "\t;key=%03x",pc->seq);
4732 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4739 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4740 if(PCW(pc)->pci.label)
4741 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4743 if(PCW(pc)->operand) {
4744 fprintf(of,";\toperand ");
4745 pCodeOpPrint(of,PCW(pc)->operand );
4750 if(pic16_debug_verbose) {
4751 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4752 if(PCFL(pc)->ancestor)
4753 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4760 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4761 fprintf(of,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4767 pBranch *pbl = PCAD(pc)->pci.label;
4768 while(pbl && pbl->pc) {
4769 if(pbl->pc->type == PC_LABEL)
4770 pCodePrintLabel(of, pbl->pc);
4774 if(PCAD(pc)->directive) {
4775 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4778 /* special case to handle inline labels without tab */
4779 fprintf(of, "%s\n", PCAD(pc)->arg);
4785 fprintf(of,"unknown pCode type %d\n",pc->type);
4790 /*-----------------------------------------------------------------*/
4791 /* pCodePrintFunction - prints function begin/end */
4792 /*-----------------------------------------------------------------*/
4794 static void pCodePrintFunction(FILE *of, pCode *pc)
4801 if( ((pCodeFunction *)pc)->modname)
4802 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4805 if(!PCF(pc)->absblock) {
4806 if(PCF(pc)->fname) {
4807 pBranch *exits = PCF(pc)->to;
4810 fprintf(of,"%s:", PCF(pc)->fname);
4812 if(pic16_pcode_verbose)
4813 fprintf(of, "\t;Function start");
4819 exits = exits->next;
4823 if(pic16_pcode_verbose)
4824 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4827 if((PCF(pc)->from &&
4828 PCF(pc)->from->pc->type == PC_FUNCTION &&
4829 PCF(PCF(pc)->from->pc)->fname) ) {
4831 if(pic16_pcode_verbose)
4832 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4834 if(pic16_pcode_verbose)
4835 fprintf(of,"; exit point [can't find entry point]\n");
4841 /*-----------------------------------------------------------------*/
4842 /* pCodePrintLabel - prints label */
4843 /*-----------------------------------------------------------------*/
4845 static void pCodePrintLabel(FILE *of, pCode *pc)
4852 fprintf(of,"%s:\n",PCL(pc)->label);
4853 else if (PCL(pc)->key >=0)
4854 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4856 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4859 /*-----------------------------------------------------------------*/
4860 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4861 /* remove it if it is found. */
4862 /*-----------------------------------------------------------------*/
4863 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4870 if(pcl->type == PC_OPCODE)
4871 b = PCI(pcl)->label;
4873 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4878 //fprintf (stderr, "%s \n",__FUNCTION__);
4879 //pcl->print(stderr,pcl);
4880 //pc->print(stderr,pc);
4883 //fprintf (stderr, "found label\n");
4884 //pc->print(stderr, pc);
4888 bprev->next = b->next; /* Not first pCode in chain */
4892 PCI(pcl)->label = b->next; /* First pCode in chain */
4895 return; /* A label can't occur more than once */
4903 /*-----------------------------------------------------------------*/
4904 /*-----------------------------------------------------------------*/
4905 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4924 /*-----------------------------------------------------------------*/
4925 /* pBranchLink - given two pcodes, this function will link them */
4926 /* together through their pBranches */
4927 /*-----------------------------------------------------------------*/
4928 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4932 // Declare a new branch object for the 'from' pCode.
4934 //_ALLOC(b,sizeof(pBranch));
4935 b = Safe_calloc(1,sizeof(pBranch));
4936 b->pc = PCODE(t); // The link to the 'to' pCode.
4939 f->to = pic16_pBranchAppend(f->to,b);
4941 // Now do the same for the 'to' pCode.
4943 //_ALLOC(b,sizeof(pBranch));
4944 b = Safe_calloc(1,sizeof(pBranch));
4948 t->from = pic16_pBranchAppend(t->from,b);
4953 /*-----------------------------------------------------------------*/
4954 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4956 /*-----------------------------------------------------------------*/
4957 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4970 /*-----------------------------------------------------------------*/
4971 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4972 /*-----------------------------------------------------------------*/
4973 static void pCodeUnlink(pCode *pc)
4978 if(!pc->prev || !pc->next) {
4979 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4983 /* first remove the pCode from the chain */
4984 pc->prev->next = pc->next;
4985 pc->next->prev = pc->prev;
4987 /* Now for the hard part... */
4989 /* Remove the branches */
4993 pc1 = pb1->pc; /* Get the pCode that branches to the
4994 * one we're unlinking */
4996 /* search for the link back to this pCode (the one we're
4998 if(pb2 = pBranchFind(pc1->to,pc)) {
4999 pb2->pc = pc->to->pc; // make the replacement
5001 /* if the pCode we're unlinking contains multiple 'to'
5002 * branches (e.g. this a skip instruction) then we need
5003 * to copy these extra branches to the chain. */
5005 pic16_pBranchAppend(pb2, pc->to->next);
5014 /*-----------------------------------------------------------------*/
5015 /*-----------------------------------------------------------------*/
5017 static void genericAnalyze(pCode *pc)
5027 // Go through the pCodes that are in pCode chain and link
5028 // them together through the pBranches. Note, the pCodes
5029 // are linked together as a contiguous stream like the
5030 // assembly source code lines. The linking here mimics this
5031 // except that comments are not linked in.
5033 pCode *npc = pc->next;
5035 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5036 pBranchLink(pc,npc);
5041 /* reached the end of the pcode chain without finding
5042 * an instruction we could link to. */
5046 fprintf(stderr,"analyze PC_FLOW\n");
5050 fprintf(stderr,,";A bad pCode is being used\n");
5056 /*-----------------------------------------------------------------*/
5057 /*-----------------------------------------------------------------*/
5058 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5062 if(pc->type == PC_LABEL) {
5063 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5066 if((pc->type == PC_OPCODE)
5067 || (pc->type == PC_ASMDIR)
5069 pbr = PCI(pc)->label;
5071 if(pbr->pc->type == PC_LABEL) {
5072 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5082 /*-----------------------------------------------------------------*/
5083 /*-----------------------------------------------------------------*/
5084 static int checkLabel(pCode *pc)
5088 if(pc && isPCI(pc)) {
5089 pbr = PCI(pc)->label;
5091 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5101 /*-----------------------------------------------------------------*/
5102 /* findLabelinpBlock - Search the pCode for a particular label */
5103 /*-----------------------------------------------------------------*/
5104 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5111 for(pc = pb->pcHead; pc; pc = pc->next)
5112 if(compareLabel(pc,pcop_label))
5118 /*-----------------------------------------------------------------*/
5119 /* findLabel - Search the pCode for a particular label */
5120 /*-----------------------------------------------------------------*/
5121 static pCode * findLabel(pCodeOpLabel *pcop_label)
5129 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5130 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5134 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5138 /*-----------------------------------------------------------------*/
5139 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5140 /* in the linked list */
5141 /*-----------------------------------------------------------------*/
5142 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5155 /*-----------------------------------------------------------------*/
5156 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5157 /* in the linked list */
5158 /*-----------------------------------------------------------------*/
5159 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5173 //#define PCODE_DEBUG
5174 /*-----------------------------------------------------------------*/
5175 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5176 /* in the linked list */
5177 /*-----------------------------------------------------------------*/
5178 pCode * pic16_findNextInstruction(pCode *pci)
5183 if((pc->type == PC_OPCODE)
5184 || (pc->type == PC_WILD)
5185 || (pc->type == PC_ASMDIR)
5190 fprintf(stderr,"pic16_findNextInstruction: ");
5191 printpCode(stderr, pc);
5196 //fprintf(stderr,"Couldn't find instruction\n");
5200 /*-----------------------------------------------------------------*/
5201 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5202 /* in the linked list */
5203 /*-----------------------------------------------------------------*/
5204 pCode * pic16_findPrevInstruction(pCode *pci)
5209 if((pc->type == PC_OPCODE)
5210 || (pc->type == PC_WILD)
5211 || (pc->type == PC_ASMDIR)
5217 fprintf(stderr,"pic16_findPrevInstruction: ");
5218 printpCode(stderr, pc);
5223 //fprintf(stderr,"Couldn't find instruction\n");
5230 /*-----------------------------------------------------------------*/
5231 /* findFunctionEnd - given a pCode find the end of the function */
5232 /* that contains it */
5233 /*-----------------------------------------------------------------*/
5234 static pCode * findFunctionEnd(pCode *pc)
5238 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5244 fprintf(stderr,"Couldn't find function end\n");
5249 /*-----------------------------------------------------------------*/
5250 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5251 /* instruction with which it is associated. */
5252 /*-----------------------------------------------------------------*/
5253 static void AnalyzeLabel(pCode *pc)
5262 static void AnalyzeGOTO(pCode *pc)
5265 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5269 static void AnalyzeSKIP(pCode *pc)
5272 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5273 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5277 static void AnalyzeRETURN(pCode *pc)
5280 // branch_link(pc,findFunctionEnd(pc->next));
5286 /*-----------------------------------------------------------------*/
5287 /*-----------------------------------------------------------------*/
5288 regs * pic16_getRegFromInstruction(pCode *pc)
5294 PCI(pc)->num_ops == 0 ||
5295 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5299 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5300 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5303 switch(PCI(pc)->pcop->type) {
5309 return PCOR(PCI(pc)->pcop)->r;
5311 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5315 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5316 return PCOR(PCI(pc)->pcop)->r;
5319 if(PCOI(PCI(pc)->pcop)->r)
5320 return (PCOI(PCI(pc)->pcop)->r);
5322 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
5323 return pic16_dirregWithName(PCI(pc)->pcop->name);
5324 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5327 return PCOR(PCI(pc)->pcop)->r;
5330 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5331 return PCOR(PCI(pc)->pcop)->r;
5333 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5337 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5338 // genericPrint(stderr, pc);
5346 /*-------------------------------------------------------------------------------*/
5347 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5348 /*-------------------------------------------------------------------------------*/
5349 regs * pic16_getRegFromInstruction2(pCode *pc)
5355 PCI(pc)->num_ops == 0 ||
5356 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5361 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5362 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5366 * operands supported in MOVFF:
5373 switch(PCI(pc)->pcop->type) {
5379 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5381 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5385 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5386 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5391 // if(PCOI(PCI(pc)->pcop)->r)
5392 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5394 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5395 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5396 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5401 // return PCOR2(PCI(pc)->pcop)->r;
5404 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5405 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5409 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5412 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5413 //genericPrint(stderr, pc);
5421 /*-----------------------------------------------------------------*/
5422 /*-----------------------------------------------------------------*/
5424 static void AnalyzepBlock(pBlock *pb)
5431 /* Find all of the registers used in this pBlock
5432 * by looking at each instruction and examining it's
5435 for(pc = pb->pcHead; pc; pc = pc->next) {
5437 /* Is this an instruction with operands? */
5438 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5440 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5442 /* Loop through all of the registers declared so far in
5443 this block and see if we find this one there */
5445 regs *r = setFirstItem(pb->tregisters);
5448 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5449 PCOR(PCI(pc)->pcop)->r = r;
5452 r = setNextItem(pb->tregisters);
5456 /* register wasn't found */
5457 //r = Safe_calloc(1, sizeof(regs));
5458 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5459 //addSet(&pb->tregisters, r);
5460 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5461 //PCOR(PCI(pc)->pcop)->r = r;
5462 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5464 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5467 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5468 if(PCOR(PCI(pc)->pcop)->r) {
5469 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5470 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5472 if(PCI(pc)->pcop->name)
5473 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5475 fprintf(stderr,"ERROR: NULL register\n");
5484 /*-----------------------------------------------------------------*/
5486 /*-----------------------------------------------------------------*/
5487 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5489 static void InsertpFlow(pCode *pc, pCode **pflow)
5492 PCFL(*pflow)->end = pc;
5494 if(!pc || !pc->next)
5497 *pflow = pic16_newpCodeFlow();
5498 pic16_pCodeInsertAfter(pc, *pflow);
5501 /*-----------------------------------------------------------------*/
5502 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5503 /* the flow blocks. */
5505 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5506 * point the instruction flow changes.
5508 /*-----------------------------------------------------------------*/
5509 void pic16_BuildFlow(pBlock *pb)
5512 pCode *last_pci=NULL;
5519 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5520 /* Insert a pCodeFlow object at the beginning of a pBlock */
5522 InsertpFlow(pb->pcHead, &pflow);
5524 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5525 //pflow->next = pb->pcHead; /* Make the current head the next object */
5526 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5527 //pb->pcHead = pflow; /* Make the Flow object the head */
5530 for( pc = pic16_findNextInstruction(pb->pcHead);
5532 pc=pic16_findNextInstruction(pc)) {
5535 PCI(pc)->pcflow = PCFL(pflow);
5537 //fprintf(stderr," build: ");
5538 //pflow->print(stderr,pflow);
5540 if( PCI(pc)->isSkip) {
5542 /* The two instructions immediately following this one
5543 * mark the beginning of a new flow segment */
5545 while(pc && PCI(pc)->isSkip) {
5547 PCI(pc)->pcflow = PCFL(pflow);
5551 InsertpFlow(pc, &pflow);
5552 pc=pic16_findNextInstruction(pc->next);
5560 PCI(pc)->pcflow = PCFL(pflow);
5562 InsertpFlow(pc, &pflow);
5564 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5566 InsertpFlow(pc, &pflow);
5569 } else if (checkLabel(pc)) {
5571 /* This instruction marks the beginning of a
5572 * new flow segment */
5577 /* If the previous pCode is not a flow object, then
5578 * insert a new flow object. (This check prevents
5579 * two consecutive flow objects from being insert in
5580 * the case where a skip instruction preceeds an
5581 * instruction containing a label.) */
5583 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5584 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5586 PCI(pc)->pcflow = PCFL(pflow);
5593 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5595 PCFL(pflow)->end = pb->pcTail;
5598 /*-------------------------------------------------------------------*/
5599 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5600 /* the flow blocks. */
5602 * unBuildFlow removes pCodeFlow objects from a pCode chain
5604 /*-----------------------------------------------------------------*/
5605 static void unBuildFlow(pBlock *pb)
5620 if(PCI(pc)->pcflow) {
5621 //free(PCI(pc)->pcflow);
5622 PCI(pc)->pcflow = NULL;
5625 } else if(isPCFL(pc) )
5634 /*-----------------------------------------------------------------*/
5635 /*-----------------------------------------------------------------*/
5636 static void dumpCond(int cond)
5639 static char *pcc_str[] = {
5654 int ncond = sizeof(pcc_str) / sizeof(char *);
5657 fprintf(stderr, "0x%04X\n",cond);
5659 for(i=0,j=1; i<ncond; i++, j<<=1)
5661 fprintf(stderr, " %s\n",pcc_str[i]);
5667 /*-----------------------------------------------------------------*/
5668 /*-----------------------------------------------------------------*/
5669 static void FlowStats(pCodeFlow *pcflow)
5677 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5679 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5682 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5687 fprintf(stderr, " FlowStats inCond: ");
5688 dumpCond(pcflow->inCond);
5689 fprintf(stderr, " FlowStats outCond: ");
5690 dumpCond(pcflow->outCond);
5694 /*-----------------------------------------------------------------*
5695 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5696 * if it affects the banking bits.
5698 * return: -1 == Banking bits are unaffected by this pCode.
5700 * return: > 0 == Banking bits are affected.
5702 * If the banking bits are affected, then the returned value describes
5703 * which bits are affected and how they're affected. The lower half
5704 * of the integer maps to the bits that are affected, the upper half
5705 * to whether they're set or cleared.
5707 *-----------------------------------------------------------------*/
5709 static int isBankInstruction(pCode *pc)
5717 if( PCI(pc)->op == POC_MOVLB ||
5718 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5719 bank = PCOL(pc)->lit;
5726 /*-----------------------------------------------------------------*/
5727 /*-----------------------------------------------------------------*/
5728 static void FillFlow(pCodeFlow *pcflow)
5737 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5739 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5742 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5749 isBankInstruction(pc);
5751 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5755 fprintf(stderr, " FillFlow - Bad end of flow\n");
5757 fprintf(stderr, " FillFlow - Ending flow with\n ");
5758 pc->print(stderr,pc);
5761 fprintf(stderr, " FillFlow inCond: ");
5762 dumpCond(pcflow->inCond);
5763 fprintf(stderr, " FillFlow outCond: ");
5764 dumpCond(pcflow->outCond);
5768 /*-----------------------------------------------------------------*/
5769 /*-----------------------------------------------------------------*/
5770 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5772 pCodeFlowLink *fromLink, *toLink;
5774 if(!from || !to || !to->pcflow || !from->pcflow)
5777 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5778 toLink = pic16_newpCodeFlowLink(to->pcflow);
5780 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5781 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5785 /*-----------------------------------------------------------------*
5786 * void LinkFlow(pBlock *pb)
5788 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5789 * non-branching segments. In LinkFlow, we determine the execution
5790 * order of these segments. For example, if one of the segments ends
5791 * with a skip, then we know that there are two possible flow segments
5792 * to which control may be passed.
5793 *-----------------------------------------------------------------*/
5794 static void LinkFlow(pBlock *pb)
5800 //fprintf(stderr,"linkflow \n");
5802 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5804 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5807 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5809 //fprintf(stderr," link: ");
5810 //pcflow->print(stderr,pcflow);
5812 //FillFlow(PCFL(pcflow));
5814 pc = PCFL(pcflow)->end;
5816 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5817 if(isPCI_SKIP(pc)) {
5818 //fprintf(stderr, "ends with skip\n");
5819 //pc->print(stderr,pc);
5820 pct=pic16_findNextInstruction(pc->next);
5821 LinkFlow_pCode(PCI(pc),PCI(pct));
5822 pct=pic16_findNextInstruction(pct->next);
5823 LinkFlow_pCode(PCI(pc),PCI(pct));
5827 if(isPCI_BRANCH(pc)) {
5828 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5830 //fprintf(stderr, "ends with branch\n ");
5831 //pc->print(stderr,pc);
5833 if(!(pcol && isPCOLAB(pcol))) {
5834 if((PCI(pc)->op != POC_RETLW)
5835 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5837 /* continue if label is '$' which assembler knows how to parse */
5838 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5840 if(pic16_pcode_verbose) {
5841 pc->print(stderr,pc);
5842 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5848 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5849 LinkFlow_pCode(PCI(pc),PCI(pct));
5851 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5852 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5854 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5860 //fprintf(stderr, "ends with non-branching instruction:\n");
5861 //pc->print(stderr,pc);
5863 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5869 //fprintf(stderr, "ends with unknown\n");
5870 //pc->print(stderr,pc);
5874 //fprintf(stderr, "ends with nothing: ERROR\n");
5878 /*-----------------------------------------------------------------*/
5879 /*-----------------------------------------------------------------*/
5881 /*-----------------------------------------------------------------*/
5882 /*-----------------------------------------------------------------*/
5883 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5889 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5892 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5902 /*-----------------------------------------------------------------*/
5903 /* insertBankSwitch - inserts a bank switch statement in the */
5904 /* assembly listing */
5906 /* position == 0: insert before */
5907 /* position == 1: insert after pc */
5908 /* position == 2: 0 previous was a skip instruction */
5909 /*-----------------------------------------------------------------*/
5910 static void insertBankSwitch(int position, pCode *pc)
5918 /* emit BANKSEL [symbol] */
5920 reg = pic16_getRegFromInstruction(pc);
5922 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5924 // position = 0; // position is always before (sanity check!)
5927 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5928 pc->print(stderr, pc);
5933 /* insert the bank switch after this pc instruction */
5934 pCode *pcnext = pic16_findNextInstruction(pc);
5935 pic16_pCodeInsertAfter(pc, new_pc);
5936 if(pcnext)pc = pcnext;
5940 /* insert the bank switch BEFORE this pc instruction */
5941 pic16_pCodeInsertAfter(pc->prev, new_pc);
5946 /* Move the label, if there is one */
5948 if(PCI(pc)->label) {
5949 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5950 // __FILE__, __LINE__, pc, new_pc);
5951 PCAD(new_pc)->pci.label = PCI(pc)->label;
5952 PCI(pc)->label = NULL;
5955 // fprintf(stderr, "BankSwitch has been inserted\n");
5959 /*-----------------------------------------------------------------*/
5960 /*int compareBankFlow - compare the banking requirements between */
5962 /*-----------------------------------------------------------------*/
5963 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5966 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5969 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5972 if(pcflow->firstBank == -1)
5976 if(pcflowLink->pcflow->firstBank == -1) {
5977 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5978 pcflowLink->pcflow->to :
5979 pcflowLink->pcflow->from);
5980 return compareBankFlow(pcflow, pctl, toORfrom);
5984 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5987 pcflowLink->bank_conflict++;
5988 pcflowLink->pcflow->FromConflicts++;
5989 pcflow->ToConflicts++;
5992 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5995 pcflowLink->bank_conflict++;
5996 pcflowLink->pcflow->ToConflicts++;
5997 pcflow->FromConflicts++;
6001 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6002 pcflowLink->pcflow->pc.seq,
6003 pcflowLink->pcflow->FromConflicts,
6004 pcflowLink->pcflow->ToConflicts);
6011 /*-----------------------------------------------------------------*/
6012 /*-----------------------------------------------------------------*/
6013 static void DumpFlow(pBlock *pb)
6017 pCodeFlowLink *pcfl;
6020 fprintf(stderr,"Dump flow \n");
6021 pb->pcHead->print(stderr, pb->pcHead);
6023 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6024 pcflow->print(stderr,pcflow);
6026 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6028 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6030 if(!isPCFL(pcflow)) {
6031 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6034 fprintf(stderr,"dumping: ");
6035 pcflow->print(stderr,pcflow);
6036 FlowStats(PCFL(pcflow));
6038 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6040 pc = PCODE(pcfl->pcflow);
6042 fprintf(stderr, " from seq %d:\n",pc->seq);
6044 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6045 pc->print(stderr,pc);
6050 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6052 pc = PCODE(pcfl->pcflow);
6054 fprintf(stderr, " to seq %d:\n",pc->seq);
6056 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6057 pc->print(stderr,pc);
6066 /*-----------------------------------------------------------------*/
6067 /*-----------------------------------------------------------------*/
6068 static int OptimizepBlock(pBlock *pb)
6073 if(!pb || !peepOptimizing)
6076 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6078 for(pc = pb->pcHead; pc; pc = pc->next)
6079 matches += pic16_pCodePeepMatchRule(pc);
6082 pc = pic16_findNextInstruction(pb->pcHead);
6090 if(pic16_pCodePeepMatchRule(pc)) {
6095 pc = pic16_findNextInstruction(pcprev->next);
6097 pc = pic16_findNextInstruction(pb->pcHead);
6099 pc = pic16_findNextInstruction(pc->next);
6103 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6108 /*-----------------------------------------------------------------*/
6109 /*-----------------------------------------------------------------*/
6110 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6114 for(pc = pcs; pc; pc = pc->next) {
6116 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6118 (PCI(pc)->pcop->type == PO_LABEL) &&
6119 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6127 /*-----------------------------------------------------------------*/
6128 /*-----------------------------------------------------------------*/
6129 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6136 (PCI(pc)->pcop->type == PO_LABEL)) {
6138 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6140 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6142 free(pcol->pcop.name);
6144 /* If the key is negative, then we (probably) have a label to
6145 * a function and the name is already defined */
6148 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6152 //sprintf(buffer,"_%05d_DS_",pcl->key);
6154 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6156 pcol->pcop.name = Safe_strdup(s);
6157 pcol->key = pcl->key;
6158 //pc->print(stderr,pc);
6165 /*-----------------------------------------------------------------*/
6166 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6167 /* pCode chain if they're not used. */
6168 /*-----------------------------------------------------------------*/
6169 static void pBlockRemoveUnusedLabels(pBlock *pb)
6171 pCode *pc; pCodeLabel *pcl;
6176 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6178 pBranch *pbr = PCI(pc)->label;
6179 if(pbr && pbr->next) {
6180 pCode *pcd = pb->pcHead;
6182 // fprintf(stderr, "multiple labels\n");
6183 // pc->print(stderr,pc);
6188 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6189 //fprintf(stderr,"Used by:\n");
6190 //pcd->print(stderr,pcd);
6192 exchangeLabels(PCL(pbr->pc),pcd);
6201 for(pc = pb->pcHead; pc; pc = pc->next) {
6203 if(isPCL(pc)) // pc->type == PC_LABEL)
6205 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6206 pcl = PCL(PCI(pc)->label->pc);
6209 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6211 /* This pCode is a label, so search the pBlock to see if anyone
6214 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6216 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6217 /* Couldn't find an instruction that refers to this label
6218 * So, unlink the pCode label from it's pCode chain
6219 * and destroy the label */
6220 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6222 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6223 if(pc->type == PC_LABEL) {
6224 pic16_unlinkpCode(pc);
6225 pCodeLabelDestruct(pc);
6227 unlinkpCodeFromBranch(pc, PCODE(pcl));
6228 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6239 /*-----------------------------------------------------------------*/
6240 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6241 /* chain and put them into pBranches that are */
6242 /* associated with the appropriate pCode */
6244 /*-----------------------------------------------------------------*/
6245 void pic16_pBlockMergeLabels(pBlock *pb)
6248 pCode *pc, *pcnext=NULL;
6253 /* First, Try to remove any unused labels */
6254 //pBlockRemoveUnusedLabels(pb);
6256 /* Now loop through the pBlock and merge the labels with the opcodes */
6259 // for(pc = pb->pcHead; pc; pc = pc->next) {
6262 pCode *pcn = pc->next;
6264 if(pc->type == PC_LABEL) {
6266 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6267 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6269 if((pcnext = pic16_findNextInstruction(pc) )) {
6271 // pcnext->print(stderr, pcnext);
6273 // Unlink the pCode label from it's pCode chain
6274 pic16_unlinkpCode(pc);
6276 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6277 // And link it into the instruction's pBranch labels. (Note, since
6278 // it's possible to have multiple labels associated with one instruction
6279 // we must provide a means to accomodate the additional labels. Thus
6280 // the labels are placed into the singly-linked list "label" as
6281 // opposed to being a single member of the pCodeInstruction.)
6283 //_ALLOC(pbr,sizeof(pBranch));
6285 pbr = Safe_calloc(1,sizeof(pBranch));
6289 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6292 if(pic16_pcode_verbose)
6293 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6295 } else if(pc->type == PC_CSOURCE) {
6297 /* merge the source line symbolic info into the next instruction */
6298 if((pcnext = pic16_findNextInstruction(pc) )) {
6300 // Unlink the pCode label from it's pCode chain
6301 pic16_unlinkpCode(pc);
6302 PCI(pcnext)->cline = PCCS(pc);
6303 //fprintf(stderr, "merging CSRC\n");
6304 //genericPrint(stderr,pcnext);
6310 pBlockRemoveUnusedLabels(pb);
6314 /*-----------------------------------------------------------------*/
6315 /*-----------------------------------------------------------------*/
6316 static int OptimizepCode(char dbName)
6318 #define MAX_PASSES 4
6327 DFPRINTF((stderr," Optimizing pCode\n"));
6331 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6332 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6333 matches += OptimizepBlock(pb);
6336 while(matches && ++passes < MAX_PASSES);
6341 /*-----------------------------------------------------------------*/
6342 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6343 /*-----------------------------------------------------------------*/
6345 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6349 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
6351 if( !( (pcop->type == PO_LABEL) ||
6352 (pcop->type == PO_LITERAL) ||
6353 (pcop->type == PO_STR) ))
6354 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6355 PCOR(pcop)->r->wasUsed = 1;
6361 /*----------------------------------------------------------------------*
6362 * pic16_areRegsSame - check to see if the names of two registers match *
6363 *----------------------------------------------------------------------*/
6364 int pic16_areRegsSame(regs *r1, regs *r2)
6366 if(!strcmp(r1->name, r2->name))return 1;
6372 /*-----------------------------------------------------------------*/
6373 /*-----------------------------------------------------------------*/
6374 static void pic16_FixRegisterBanking(pBlock *pb)
6378 regs *reg, *prevreg;
6383 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6387 /* loop through all of the flow blocks with in one pblock */
6389 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6393 /* at this point, pc should point to a PC_FLOW object */
6394 /* for each flow block, determine the register banking
6397 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
6398 reg = pic16_getRegFromInstruction(pc);
6401 fprintf(stderr, "reg = %p\n", reg);
6403 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6404 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
6405 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
6406 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
6410 /* we can be 99% that within a pBlock, between two consequtive
6411 * refernces to the same register, the extra banksel is needless */
6413 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6415 && (PCI(pc)->op != POC_CALL)
6417 && ( ((pic16_options.opt_banksel>0)
6418 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6419 || (!pic16_options.opt_banksel)
6423 /* Examine the instruction before this one to make sure it is
6424 * not a skip type instruction */
6425 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6427 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6428 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6429 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6431 if(!pic16_options.no_banksel)
6432 insertBankSwitch(0, pc);
6444 if(pcprev && cur_bank) {
6446 int pos = 1; /* Assume that the bank switch instruction(s)
6447 * are inserted after this instruction */
6449 if((PCI(pcprev)->op == POC_RETLW) ||
6450 (PCI(pcprev)->op == POC_RETURN) ||
6451 (PCI(pcprev)->op == POC_RETFIE)) {
6453 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6459 /* Brute force - make sure that we point to bank 0 at the
6460 * end of each flow block */
6462 // insertBankSwitch(pos, pcprev, 0);
6464 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6465 pic16_pCodeInsertAfter(pcprev, new_pc);
6468 //fprintf(stderr, "Brute force switch\n");
6475 static void pBlockDestruct(pBlock *pb)
6486 /*-----------------------------------------------------------------*/
6487 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6488 /* name dbName and combine them */
6489 /* into one block */
6490 /*-----------------------------------------------------------------*/
6491 static void mergepBlocks(char dbName)
6494 pBlock *pb, *pbmerged = NULL,*pbn;
6496 pb = the_pFile->pbHead;
6498 //fprintf(stderr," merging blocks named %c\n",dbName);
6502 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6503 if( getpBlock_dbName(pb) == dbName) {
6505 //fprintf(stderr," merged block %c\n",dbName);
6510 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6511 /* pic16_addpCode2pBlock doesn't handle the tail: */
6512 pbmerged->pcTail = pb->pcTail;
6514 pb->prev->next = pbn;
6516 pbn->prev = pb->prev;
6521 //pic16_printpBlock(stderr, pbmerged);
6528 /*-----------------------------------------------------------------*/
6529 /* AnalyzeFlow - Examine the flow of the code and optimize */
6531 /* level 0 == minimal optimization */
6532 /* optimize registers that are used only by two instructions */
6533 /* level 1 == maximal optimization */
6534 /* optimize by looking at pairs of instructions that use the */
6536 /*-----------------------------------------------------------------*/
6538 static void AnalyzeFlow(int level)
6540 static int times_called=0;
6545 /* remove unused allocated registers before exiting */
6546 pic16_RemoveUnusedRegisters();
6552 /* if this is not the first time this function has been called,
6553 then clean up old flow information */
6554 if(times_called++) {
6555 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6558 pic16_RegsUnMapLiveRanges();
6563 /* Phase 2 - Flow Analysis - Register Banking
6565 * In this phase, the individual flow blocks are examined
6566 * and register banking is fixed.
6570 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6571 pic16_FixRegisterBanking(pb);
6574 /* Phase 2 - Flow Analysis
6576 * In this phase, the pCode is partition into pCodeFlow
6577 * blocks. The flow blocks mark the points where a continuous
6578 * stream of instructions changes flow (e.g. because of
6579 * a call or goto or whatever).
6582 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6583 pic16_BuildFlow(pb);
6586 /* Phase 2 - Flow Analysis - linking flow blocks
6588 * In this phase, the individual flow blocks are examined
6589 * to determine their order of excution.
6592 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6595 /* Phase 3 - Flow Analysis - Flow Tree
6597 * In this phase, the individual flow blocks are examined
6598 * to determine their order of execution.
6601 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6602 pic16_BuildFlowTree(pb);
6605 /* Phase x - Flow Analysis - Used Banks
6607 * In this phase, the individual flow blocks are examined
6608 * to determine the Register Banks they use
6612 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6617 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6618 pic16_pCodeRegMapLiveRanges(pb);
6620 pic16_RemoveUnusedRegisters();
6622 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6623 pic16_pCodeRegOptimizeRegUsage(level);
6631 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6636 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6638 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6639 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6640 pcflow = pcflow->next) {
6642 FillFlow(PCFL(pcflow));
6647 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6650 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6651 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6652 pcflow = pcflow->next) {
6654 FlowStats(PCFL(pcflow));
6660 /* VR -- no need to analyze banking in flow, but left here :
6661 * 1. because it may be used in the future for other purposes
6662 * 2. because if omitted we'll miss some optimization done here
6664 * Perhaps I should rename it to something else
6667 /*-----------------------------------------------------------------*/
6668 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6669 /* assigned to the registers. */
6671 /*-----------------------------------------------------------------*/
6673 void pic16_AnalyzeBanking(void)
6677 if(!pic16_picIsInitialized()) {
6678 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6679 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6680 fprintf(stderr,"support/scripts/inc2h.pl\n");
6681 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6683 /* I think it took a long long time to fix this bug! ;-) -- VR */
6689 /* Phase x - Flow Analysis - Used Banks
6691 * In this phase, the individual flow blocks are examined
6692 * to determine the Register Banks they use
6698 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6699 // BanksUsedFlow(pb);
6701 if(!the_pFile)return;
6703 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6704 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6705 pic16_FixRegisterBanking(pb);
6710 /*-----------------------------------------------------------------*/
6711 /* buildCallTree - Look at the flow and extract all of the calls. */
6712 /*-----------------------------------------------------------------*/
6713 static set *register_usage(pBlock *pb);
6715 static void buildCallTree(void )
6726 /* Now build the call tree.
6727 First we examine all of the pCodes for functions.
6728 Keep in mind that the function boundaries coincide
6729 with pBlock boundaries.
6731 The algorithm goes something like this:
6732 We have two nested loops. The outer loop iterates
6733 through all of the pBlocks/functions. The inner
6734 loop iterates through all of the pCodes for
6735 a given pBlock. When we begin iterating through
6736 a pBlock, the variable pc_fstart, pCode of the start
6737 of a function, is cleared. We then search for pCodes
6738 of type PC_FUNCTION. When one is encountered, we
6739 initialize pc_fstart to this and at the same time
6740 associate a new pBranch object that signifies a
6741 branch entry. If a return is found, then this signifies
6742 a function exit point. We'll link the pCodes of these
6743 returns to the matching pc_fstart.
6745 When we're done, a doubly linked list of pBranches
6746 will exist. The head of this list is stored in
6747 `the_pFile', which is the meta structure for all
6748 of the pCode. Look at the pic16_printCallTree function
6749 on how the pBranches are linked together.
6752 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6753 pCode *pc_fstart=NULL;
6754 for(pc = pb->pcHead; pc; pc = pc->next) {
6756 if (PCF(pc)->fname) {
6758 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6759 //fprintf(stderr," found main \n");
6760 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6764 pbr = Safe_calloc(1,sizeof(pBranch));
6765 pbr->pc = pc_fstart = pc;
6768 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6770 // Here's a better way of doing the same:
6771 addSet(&pb->function_entries, pc);
6774 // Found an exit point in a function, e.g. return
6775 // (Note, there may be more than one return per function)
6777 pBranchLink(PCF(pc_fstart), PCF(pc));
6779 addSet(&pb->function_exits, pc);
6781 } else if(isCALL(pc)) {
6782 addSet(&pb->function_calls,pc);
6789 /* This is not needed because currently all register used
6790 * by a function are stored in stack -- VR */
6792 /* Re-allocate the registers so that there are no collisions
6793 * between local variables when one function call another */
6796 // pic16_deallocateAllRegs();
6798 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6806 /*-----------------------------------------------------------------*/
6807 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6808 /* all of the logical connections. */
6810 /* Essentially what's done here is that the pCode flow is */
6812 /*-----------------------------------------------------------------*/
6814 void pic16_AnalyzepCode(char dbName)
6825 /* Phase 1 - Register allocation and peep hole optimization
6827 * The first part of the analysis is to determine the registers
6828 * that are used in the pCode. Once that is done, the peep rules
6829 * are applied to the code. We continue to loop until no more
6830 * peep rule optimizations are found (or until we exceed the
6831 * MAX_PASSES threshold).
6833 * When done, the required registers will be determined.
6839 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6840 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6842 /* First, merge the labels with the instructions */
6843 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6844 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6846 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6847 //fprintf(stderr," analyze and merging block %c\n",dbName);
6848 pic16_pBlockMergeLabels(pb);
6851 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6856 changes = OptimizepCode(dbName);
6859 } while(changes && (i++ < MAX_PASSES));
6864 /*-----------------------------------------------------------------*/
6865 /* ispCodeFunction - returns true if *pc is the pCode of a */
6867 /*-----------------------------------------------------------------*/
6868 static bool ispCodeFunction(pCode *pc)
6871 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6877 /*-----------------------------------------------------------------*/
6878 /* findFunction - Search for a function by name (given the name) */
6879 /* in the set of all functions that are in a pBlock */
6880 /* (note - I expect this to change because I'm planning to limit */
6881 /* pBlock's to just one function declaration */
6882 /*-----------------------------------------------------------------*/
6883 static pCode *findFunction(char *fname)
6890 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6892 pc = setFirstItem(pb->function_entries);
6895 if((pc->type == PC_FUNCTION) &&
6897 (strcmp(fname, PCF(pc)->fname)==0))
6900 pc = setNextItem(pb->function_entries);
6908 static void MarkUsedRegisters(set *regset)
6913 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6914 // fprintf(stderr, "marking register = %s\t", r1->name);
6915 r2 = pic16_regWithIdx(r1->rIdx);
6916 // fprintf(stderr, "to register = %s\n", r2->name);
6922 static void pBlockStats(FILE *of, pBlock *pb)
6928 if(!pic16_pcode_verbose)return;
6930 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6932 // for now just print the first element of each set
6933 pc = setFirstItem(pb->function_entries);
6935 fprintf(of,";entry: ");
6938 pc = setFirstItem(pb->function_exits);
6940 fprintf(of,";has an exit\n");
6944 pc = setFirstItem(pb->function_calls);
6946 fprintf(of,";functions called:\n");
6949 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6950 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6952 pc = setNextItem(pb->function_calls);
6956 r = setFirstItem(pb->tregisters);
6958 int n = elementsInSet(pb->tregisters);
6960 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6963 fprintf(of,"; %s\n",r->name);
6964 r = setNextItem(pb->tregisters);
6969 /*-----------------------------------------------------------------*/
6970 /*-----------------------------------------------------------------*/
6972 static void sequencepCode(void)
6978 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6980 pb->seq = GpCodeSequenceNumber+1;
6982 for( pc = pb->pcHead; pc; pc = pc->next)
6983 pc->seq = ++GpCodeSequenceNumber;
6989 /*-----------------------------------------------------------------*/
6990 /*-----------------------------------------------------------------*/
6991 static set *register_usage(pBlock *pb)
6994 set *registers=NULL;
6995 set *registersInCallPath = NULL;
6997 /* check recursion */
6999 pc = setFirstItem(pb->function_entries);
7006 if(pc->type != PC_FUNCTION)
7007 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7009 pc = setFirstItem(pb->function_calls);
7010 for( ; pc; pc = setNextItem(pb->function_calls)) {
7012 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7013 char *dest = pic16_get_op_from_instruction(PCI(pc));
7015 pcn = findFunction(dest);
7017 registersInCallPath = register_usage(pcn->pb);
7019 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7024 pBlockStats(stderr,pb); // debug
7027 // Mark the registers in this block as used.
7029 MarkUsedRegisters(pb->tregisters);
7030 if(registersInCallPath) {
7031 /* registers were used in the functions this pBlock has called */
7032 /* so now, we need to see if these collide with the ones we are */
7035 regs *r1,*r2, *newreg;
7037 DFPRINTF((stderr,"comparing registers\n"));
7039 r1 = setFirstItem(registersInCallPath);
7042 r2 = setFirstItem(pb->tregisters);
7044 while(r2 && (r1->type != REG_STK)) {
7046 if(r2->rIdx == r1->rIdx) {
7047 newreg = pic16_findFreeReg(REG_GPR);
7051 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7055 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7056 r1->rIdx, newreg->rIdx));
7057 r2->rIdx = newreg->rIdx;
7058 //if(r2->name) free(r2->name);
7060 r2->name = Safe_strdup(newreg->name);
7064 newreg->wasUsed = 1;
7066 r2 = setNextItem(pb->tregisters);
7069 r1 = setNextItem(registersInCallPath);
7072 /* Collisions have been resolved. Now free the registers in the call path */
7073 r1 = setFirstItem(registersInCallPath);
7075 if(r1->type != REG_STK) {
7076 newreg = pic16_regWithIdx(r1->rIdx);
7079 r1 = setNextItem(registersInCallPath);
7083 // MarkUsedRegisters(pb->registers);
7085 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7088 DFPRINTF((stderr,"returning regs\n"));
7090 DFPRINTF((stderr,"not returning regs\n"));
7092 DFPRINTF((stderr,"pBlock after register optim.\n"));
7093 pBlockStats(stderr,pb); // debug
7099 /*-----------------------------------------------------------------*/
7100 /* pct2 - writes the call tree to a file */
7102 /*-----------------------------------------------------------------*/
7103 static void pct2(FILE *of,pBlock *pb,int indent)
7107 // set *registersInCallPath = NULL;
7113 return; //recursion ?
7115 pc = setFirstItem(pb->function_entries);
7122 for(i=0;i<indent;i++) // Indentation
7125 if(pc->type == PC_FUNCTION)
7126 fprintf(of,"%s\n",PCF(pc)->fname);
7131 pc = setFirstItem(pb->function_calls);
7132 for( ; pc; pc = setNextItem(pb->function_calls)) {
7134 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7135 char *dest = pic16_get_op_from_instruction(PCI(pc));
7137 pcn = findFunction(dest);
7139 pct2(of,pcn->pb,indent+1);
7141 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7149 /*-----------------------------------------------------------------*/
7150 /* pic16_printCallTree - writes the call tree to a file */
7152 /*-----------------------------------------------------------------*/
7154 void pic16_printCallTree(FILE *of)
7166 fprintf(of, "\npBlock statistics\n");
7167 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7172 fprintf(of,"Call Tree\n");
7173 pbr = the_pFile->functions;
7177 if(!ispCodeFunction(pc))
7178 fprintf(of,"bug in call tree");
7181 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7183 while(pc->next && !ispCodeFunction(pc->next)) {
7185 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7186 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7194 fprintf(of,"\n**************\n\na better call tree\n");
7195 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7200 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7201 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7207 /*-----------------------------------------------------------------*/
7209 /*-----------------------------------------------------------------*/
7211 static void InlineFunction(pBlock *pb)
7219 pc = setFirstItem(pb->function_calls);
7221 for( ; pc; pc = setNextItem(pb->function_calls)) {
7224 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7230 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7232 //fprintf(stderr,"Cool can inline:\n");
7233 //pcn->print(stderr,pcn);
7235 //fprintf(stderr,"recursive call Inline\n");
7236 InlineFunction(pcn->pb);
7237 //fprintf(stderr,"return from recursive call Inline\n");
7240 At this point, *pc points to a CALL mnemonic, and
7241 *pcn points to the function that is being called.
7243 To in-line this call, we need to remove the CALL
7244 and RETURN(s), and link the function pCode in with
7250 /* Remove the CALL */
7254 /* remove callee pBlock from the pBlock linked list */
7255 removepBlock(pcn->pb);
7263 /* Remove the Function pCode */
7264 pct = pic16_findNextInstruction(pcn->next);
7266 /* Link the function with the callee */
7267 pc->next = pcn->next;
7268 pcn->next->prev = pc;
7270 /* Convert the function name into a label */
7272 pbr = Safe_calloc(1,sizeof(pBranch));
7273 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7275 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7276 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7278 /* turn all of the return's except the last into goto's */
7279 /* check case for 2 instruction pBlocks */
7280 pce = pic16_findNextInstruction(pcn->next);
7282 pCode *pce_next = pic16_findNextInstruction(pce->next);
7284 if(pce_next == NULL) {
7285 /* found the last return */
7286 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7288 //fprintf(stderr,"found last return\n");
7289 //pce->print(stderr,pce);
7290 pce->prev->next = pc_call->next;
7291 pc_call->next->prev = pce->prev;
7292 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7302 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7308 /*-----------------------------------------------------------------*/
7310 /*-----------------------------------------------------------------*/
7312 void pic16_InlinepCode(void)
7321 if(!functionInlining)
7324 /* Loop through all of the function definitions and count the
7325 * number of times each one is called */
7326 //fprintf(stderr,"inlining %d\n",__LINE__);
7328 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7330 pc = setFirstItem(pb->function_calls);
7332 for( ; pc; pc = setNextItem(pb->function_calls)) {
7335 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7336 if(pcn && isPCF(pcn)) {
7337 PCF(pcn)->ncalled++;
7340 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7345 //fprintf(stderr,"inlining %d\n",__LINE__);
7347 /* Now, Loop through the function definitions again, but this
7348 * time inline those functions that have only been called once. */
7350 InlineFunction(the_pFile->pbHead);
7351 //fprintf(stderr,"inlining %d\n",__LINE__);
7353 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7358 char *pic_optype_names[]={
7359 "PO_NONE", // No operand e.g. NOP
7360 "PO_W", // The working register (as a destination)
7361 "PO_WREG", // The working register (as a file register)
7362 "PO_STATUS", // The 'STATUS' register
7363 "PO_BSR", // The 'BSR' register
7364 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7366 "PO_INDF0", // The Indirect register
7367 "PO_INTCON", // Interrupt Control register
7368 "PO_GPR_REGISTER", // A general purpose register
7369 "PO_GPR_BIT", // A bit of a general purpose register
7370 "PO_GPR_TEMP", // A general purpose temporary register
7371 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7372 "PO_PCL", // Program counter Low register
7373 "PO_PCLATH", // Program counter Latch high register
7374 "PO_PCLATU", // Program counter Latch upper register
7375 "PO_PRODL", // Product Register Low
7376 "PO_PRODH", // Product Register High
7377 "PO_LITERAL", // A constant
7378 "PO_REL_ADDR", // A relative address
7379 "PO_IMMEDIATE", // (8051 legacy)
7380 "PO_DIR", // Direct memory (8051 legacy)
7381 "PO_CRY", // bit memory (8051 legacy)
7382 "PO_BIT", // bit operand.
7383 "PO_STR", // (8051 legacy)
7385 "PO_WILD" // Wild card operand in peep optimizer
7389 char *dumpPicOptype(PIC_OPTYPE type)
7391 return (pic_optype_names[ type ]);