1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 static int mnemonics_initialized = 0;
118 static hTab *pic16MnemonicsHash = NULL;
119 static hTab *pic16pCodePeepCommandsHash = NULL;
121 static pFile *the_pFile = NULL;
122 static pBlock *pb_dead_pcodes = NULL;
124 /* Hardcoded flags to change the behavior of the PIC port */
125 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
126 static int functionInlining = 1; /* inline functions if nonzero */
127 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
129 int pic16_pcode_verbose = 0;
131 //static int GpCodeSequenceNumber = 1;
132 static int GpcFlowSeq = 1;
134 extern void pic16_RemoveUnusedRegisters(void);
135 extern void pic16_RegsUnMapLiveRanges(void);
136 extern void pic16_BuildFlowTree(pBlock *pb);
137 extern void pic16_pCodeRegOptimizeRegUsage(int level);
138 extern int pic16_picIsInitialized(void);
139 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
140 extern int mnem2key(char const *mnem);
142 /****************************************************************/
143 /* Forward declarations */
144 /****************************************************************/
146 void pic16_unlinkpCode(pCode *pc);
148 static void genericAnalyze(pCode *pc);
149 static void AnalyzeGOTO(pCode *pc);
150 static void AnalyzeSKIP(pCode *pc);
151 static void AnalyzeRETURN(pCode *pc);
154 static void genericDestruct(pCode *pc);
155 static void genericPrint(FILE *of,pCode *pc);
157 static void pCodePrintLabel(FILE *of, pCode *pc);
158 static void pCodePrintFunction(FILE *of, pCode *pc);
159 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
160 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
161 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
162 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
163 int pic16_pCodePeepMatchRule(pCode *pc);
164 static void pBlockStats(FILE *of, pBlock *pb);
165 static pBlock *newpBlock(void);
166 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
167 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
168 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
169 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
171 char *dumpPicOptype(PIC_OPTYPE type);
173 /****************************************************************/
174 /* PIC Instructions */
175 /****************************************************************/
177 pCodeInstruction pic16_pciADDWF = {
178 {PC_OPCODE, NULL, NULL, 0, NULL,
191 1,0, // dest, bit instruction
193 0, // literal operand
195 0, // fast call/return mode select bit
196 0, // second memory operand
197 0, // second literal operand
199 (PCC_W | PCC_REGISTER), // inCond
200 (PCC_REGISTER | PCC_Z), // outCond
204 pCodeInstruction pic16_pciADDFW = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
223 0, // second memory operand
224 0, // second literal operand
226 (PCC_W | PCC_REGISTER), // inCond
227 (PCC_W | PCC_Z), // outCond
231 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
232 {PC_OPCODE, NULL, NULL, 0, NULL,
245 1,0, // dest, bit instruction
247 0, // literal operand
249 0, // fast call/return mode select bit
250 0, // second memory operand
251 0, // second literal operand
253 (PCC_W | PCC_REGISTER | PCC_C), // inCond
254 (PCC_REGISTER | PCC_Z), // outCond
258 pCodeInstruction pic16_pciADDFWC = {
259 {PC_OPCODE, NULL, NULL, 0, NULL,
272 0,0, // dest, bit instruction
274 0, // literal operand
276 0, // fast call/return mode select bit
277 0, // second memory operand
278 0, // second literal operand
280 (PCC_W | PCC_REGISTER | PCC_C), // inCond
281 (PCC_W | PCC_Z), // outCond
285 pCodeInstruction pic16_pciADDLW = {
286 {PC_OPCODE, NULL, NULL, 0, NULL,
299 0,0, // dest, bit instruction
301 1, // literal operand
303 0, // fast call/return mode select bit
304 0, // second memory operand
305 0, // second literal operand
307 (PCC_W | PCC_LITERAL), // inCond
308 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
312 pCodeInstruction pic16_pciANDLW = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,0, // dest, bit instruction
328 1, // literal operand
330 0, // fast call/return mode select bit
331 0, // second memory operand
332 0, // second literal operand
334 (PCC_W | PCC_LITERAL), // inCond
335 (PCC_W | PCC_Z | PCC_N), // outCond
339 pCodeInstruction pic16_pciANDWF = {
340 {PC_OPCODE, NULL, NULL, 0, NULL,
353 1,0, // dest, bit instruction
355 0, // literal operand
357 0, // fast call/return mode select bit
358 0, // second memory operand
359 0, // second literal operand
361 (PCC_W | PCC_REGISTER), // inCond
362 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
366 pCodeInstruction pic16_pciANDFW = {
367 {PC_OPCODE, NULL, NULL, 0, NULL,
380 0,0, // dest, bit instruction
382 0, // literal operand
384 0, // fast call/return mode select bit
385 0, // second memory operand
386 0, // second literal operand
388 (PCC_W | PCC_REGISTER), // inCond
389 (PCC_W | PCC_Z) // outCond
392 pCodeInstruction pic16_pciBC = { // mdubuc - New
393 {PC_OPCODE, NULL, NULL, 0, NULL,
406 0,0, // dest, bit instruction
408 0, // literal operand
410 0, // fast call/return mode select bit
411 0, // second memory operand
412 0, // second literal operand
414 (PCC_REL_ADDR | PCC_C), // inCond
419 pCodeInstruction pic16_pciBCF = {
420 {PC_OPCODE, NULL, NULL, 0, NULL,
433 1,1, // dest, bit instruction
435 0, // literal operand
437 0, // fast call/return mode select bit
438 0, // second memory operand
439 0, // second literal operand
441 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
442 PCC_REGISTER, // outCond
446 pCodeInstruction pic16_pciBN = { // mdubuc - New
447 {PC_OPCODE, NULL, NULL, 0, NULL,
460 0,0, // dest, bit instruction
462 0, // literal operand
464 0, // fast call/return mode select bit
465 0, // second memory operand
466 0, // second literal operand
468 (PCC_REL_ADDR | PCC_N), // inCond
469 PCC_NONE , // outCond
473 pCodeInstruction pic16_pciBNC = { // mdubuc - New
474 {PC_OPCODE, NULL, NULL, 0, NULL,
487 0,0, // dest, bit instruction
489 0, // literal operand
491 0, // fast call/return mode select bit
492 0, // second memory operand
493 0, // second literal operand
495 (PCC_REL_ADDR | PCC_C), // inCond
496 PCC_NONE , // outCond
500 pCodeInstruction pic16_pciBNN = { // mdubuc - New
501 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 0, // fast call/return mode select bit
519 0, // second memory operand
520 0, // second literal operand
522 (PCC_REL_ADDR | PCC_N), // inCond
523 PCC_NONE , // outCond
527 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
528 {PC_OPCODE, NULL, NULL, 0, NULL,
541 0,0, // dest, bit instruction
543 0, // literal operand
545 0, // fast call/return mode select bit
546 0, // second memory operand
547 0, // second literal operand
549 (PCC_REL_ADDR | PCC_OV), // inCond
550 PCC_NONE , // outCond
554 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
555 {PC_OPCODE, NULL, NULL, 0, NULL,
568 0,0, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
574 0, // second literal operand
576 (PCC_REL_ADDR | PCC_Z), // inCond
577 PCC_NONE , // outCond
581 pCodeInstruction pic16_pciBOV = { // mdubuc - New
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 0,0, // dest, bit instruction
597 0, // literal operand
599 0, // fast call/return mode select bit
600 0, // second memory operand
601 0, // second literal operand
603 (PCC_REL_ADDR | PCC_OV), // inCond
604 PCC_NONE , // outCond
608 pCodeInstruction pic16_pciBRA = { // mdubuc - New
609 {PC_OPCODE, NULL, NULL, 0, NULL,
622 0,0, // dest, bit instruction
624 0, // literal operand
626 0, // fast call/return mode select bit
627 0, // second memory operand
628 0, // second literal operand
630 PCC_REL_ADDR, // inCond
631 PCC_NONE , // outCond
635 pCodeInstruction pic16_pciBSF = {
636 {PC_OPCODE, NULL, NULL, 0, NULL,
649 1,1, // dest, bit instruction
651 0, // literal operand
653 0, // fast call/return mode select bit
654 0, // second memory operand
655 0, // second literal operand
657 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
658 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
662 pCodeInstruction pic16_pciBTFSC = {
663 {PC_OPCODE, NULL, NULL, 0, NULL,
676 0,1, // dest, bit instruction
678 0, // literal operand
680 0, // fast call/return mode select bit
681 0, // second memory operand
682 0, // second literal operand
684 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
685 PCC_EXAMINE_PCOP, // outCond
689 pCodeInstruction pic16_pciBTFSS = {
690 {PC_OPCODE, NULL, NULL, 0, NULL,
703 0,1, // dest, bit instruction
705 0, // literal operand
707 0, // fast call/return mode select bit
708 0, // second memory operand
709 0, // second literal operand
711 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
712 PCC_EXAMINE_PCOP, // outCond
716 pCodeInstruction pic16_pciBTG = { // mdubuc - New
717 {PC_OPCODE, NULL, NULL, 0, NULL,
730 0,1, // dest, bit instruction
732 0, // literal operand
734 0, // fast call/return mode select bit
735 0, // second memory operand
736 0, // second literal operand
738 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
739 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
743 pCodeInstruction pic16_pciBZ = { // mdubuc - New
744 {PC_OPCODE, NULL, NULL, 0, NULL,
757 0,0, // dest, bit instruction
759 0, // literal operand
761 0, // fast call/return mode select bit
762 0, // second memory operand
763 0, // second literal operand
770 pCodeInstruction pic16_pciCALL = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
786 0, // literal operand
788 1, // fast call/return mode select bit
789 0, // second memory operand
790 0, // second literal operand
793 PCC_NONE , // outCond
797 pCodeInstruction pic16_pciCOMF = {
798 {PC_OPCODE, NULL, NULL, 0, NULL,
811 1,0, // dest, bit instruction
813 0, // literal operand
815 0, // fast call/return mode select bit
816 0, // second memory operand
817 0, // second literal operand
819 PCC_REGISTER, // inCond
820 PCC_REGISTER , // outCond
824 pCodeInstruction pic16_pciCOMFW = {
825 {PC_OPCODE, NULL, NULL, 0, NULL,
838 0,0, // dest, bit instruction
840 0, // literal operand
842 0, // fast call/return mode select bit
843 0, // second memory operand
844 0, // second literal operand
846 PCC_REGISTER, // inCond
851 pCodeInstruction pic16_pciCLRF = {
852 {PC_OPCODE, NULL, NULL, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
869 0, // fast call/return mode select bit
870 0, // second memory operand
871 0, // second literal operand
873 PCC_REGISTER, // inCond
874 PCC_REGISTER , // outCond
878 pCodeInstruction pic16_pciCLRWDT = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
894 0, // literal operand
896 0, // fast call/return mode select bit
897 0, // second memory operand
898 0, // second literal operand
901 PCC_NONE , // outCond
905 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
906 {PC_OPCODE, NULL, NULL, 0, NULL,
919 0,0, // dest, bit instruction
921 0, // literal operand
923 0, // fast call/return mode select bit
924 0, // second memory operand
925 0, // second literal operand
927 (PCC_W | PCC_REGISTER), // inCond
928 PCC_NONE , // outCond
932 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
933 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
954 (PCC_W | PCC_REGISTER), // inCond
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 1,0, // dest, bit instruction
975 0, // literal operand
977 0, // fast call/return mode select bit
978 0, // second memory operand
979 0, // second literal operand
981 (PCC_W | PCC_REGISTER), // inCond
982 PCC_NONE , // outCond
986 pCodeInstruction pic16_pciDAW = {
987 {PC_OPCODE, NULL, NULL, 0, NULL,
1000 0,0, // dest, bit instruction
1001 0,0, // branch, skip
1002 0, // literal operand
1003 0, // RAM access bit
1004 0, // fast call/return mode select bit
1005 0, // second memory operand
1006 0, // second literal operand
1009 (PCC_W | PCC_C), // outCond
1013 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1014 {PC_OPCODE, NULL, NULL, 0, NULL,
1020 NULL, // from branch
1027 1,0, // dest, bit instruction
1028 1,1, // branch, skip
1029 0, // literal operand
1030 1, // RAM access bit
1031 0, // fast call/return mode select bit
1032 0, // second memory operand
1033 0, // second literal operand
1035 PCC_REGISTER, // inCond
1036 PCC_REGISTER , // outCond
1040 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1041 {PC_OPCODE, NULL, NULL, 0, NULL,
1047 NULL, // from branch
1054 0,0, // dest, bit instruction
1055 1,1, // branch, skip
1056 0, // literal operand
1057 1, // RAM access bit
1058 0, // fast call/return mode select bit
1059 0, // second memory operand
1060 0, // second literal operand
1062 PCC_REGISTER, // inCond
1067 pCodeInstruction pic16_pciDECF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1084 1, // RAM access bit
1085 0, // fast call/return mode select bit
1086 0, // second memory operand
1087 0, // second literal operand
1089 PCC_REGISTER, // inCond
1090 PCC_REGISTER , // outCond
1094 pCodeInstruction pic16_pciDECFW = {
1095 {PC_OPCODE, NULL, NULL, 0, NULL,
1101 NULL, // from branch
1108 0,0, // dest, bit instruction
1109 0,0, // branch, skip
1110 0, // literal operand
1111 1, // RAM access bit
1112 0, // fast call/return mode select bit
1113 0, // second memory operand
1114 0, // second literal operand
1116 PCC_REGISTER, // inCond
1121 pCodeInstruction pic16_pciDECFSZ = {
1122 {PC_OPCODE, NULL, NULL, 0, NULL,
1128 NULL, // from branch
1135 1,0, // dest, bit instruction
1136 1,1, // branch, skip
1137 0, // literal operand
1138 1, // RAM access bit
1139 0, // fast call/return mode select bit
1140 0, // second memory operand
1141 0, // second literal operand
1143 PCC_REGISTER, // inCond
1144 PCC_REGISTER , // outCond
1148 pCodeInstruction pic16_pciDECFSZW = {
1149 {PC_OPCODE, NULL, NULL, 0, NULL,
1155 NULL, // from branch
1162 0,0, // dest, bit instruction
1163 1,1, // branch, skip
1164 0, // literal operand
1165 1, // RAM access bit
1166 0, // fast call/return mode select bit
1167 0, // second memory operand
1168 0, // second literal operand
1170 PCC_REGISTER, // inCond
1175 pCodeInstruction pic16_pciGOTO = {
1176 {PC_OPCODE, NULL, NULL, 0, NULL,
1182 NULL, // from branch
1189 0,0, // dest, bit instruction
1190 1,0, // branch, skip
1191 0, // literal operand
1192 0, // RAM access bit
1193 0, // fast call/return mode select bit
1194 0, // second memory operand
1195 0, // second literal operand
1197 PCC_REL_ADDR, // inCond
1198 PCC_NONE , // outCond
1202 pCodeInstruction pic16_pciINCF = {
1203 {PC_OPCODE, NULL, NULL, 0, NULL,
1209 NULL, // from branch
1216 1,0, // dest, bit instruction
1217 0,0, // branch, skip
1218 0, // literal operand
1219 1, // RAM access bit
1220 0, // fast call/return mode select bit
1221 0, // second memory operand
1222 0, // second literal operand
1224 PCC_REGISTER, // inCond
1225 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1229 pCodeInstruction pic16_pciINCFW = {
1230 {PC_OPCODE, NULL, NULL, 0, NULL,
1236 NULL, // from branch
1243 0,0, // dest, bit instruction
1244 0,0, // branch, skip
1245 0, // literal operand
1246 1, // RAM access bit
1247 0, // fast call/return mode select bit
1248 0, // second memory operand
1249 0, // second literal operand
1251 PCC_REGISTER, // inCond
1256 pCodeInstruction pic16_pciINCFSZ = {
1257 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 1,0, // dest, bit instruction
1271 1,1, // branch, skip
1272 0, // literal operand
1273 1, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1276 0, // second literal operand
1278 PCC_REGISTER, // inCond
1279 PCC_REGISTER , // outCond
1283 pCodeInstruction pic16_pciINCFSZW = {
1284 {PC_OPCODE, NULL, NULL, 0, NULL,
1290 NULL, // from branch
1297 0,0, // dest, bit instruction
1298 1,1, // branch, skip
1299 0, // literal operand
1300 1, // RAM access bit
1301 0, // fast call/return mode select bit
1302 0, // second memory operand
1303 0, // second literal operand
1305 PCC_REGISTER, // inCond
1310 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1311 {PC_OPCODE, NULL, NULL, 0, NULL,
1317 NULL, // from branch
1324 1,0, // dest, bit instruction
1325 1,1, // branch, skip
1326 0, // literal operand
1327 1, // RAM access bit
1328 0, // fast call/return mode select bit
1329 0, // second memory operand
1330 0, // second literal operand
1332 PCC_REGISTER, // inCond
1333 PCC_REGISTER , // outCond
1337 pCodeInstruction pic16_pciIORWF = {
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1344 NULL, // from branch
1351 1,0, // dest, bit instruction
1352 0,0, // branch, skip
1353 0, // literal operand
1354 1, // RAM access bit
1355 0, // fast call/return mode select bit
1356 0, // second memory operand
1357 0, // second literal operand
1359 (PCC_W | PCC_REGISTER), // inCond
1360 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1364 pCodeInstruction pic16_pciIORFW = {
1365 {PC_OPCODE, NULL, NULL, 0, NULL,
1371 NULL, // from branch
1378 0,0, // dest, bit instruction
1379 0,0, // branch, skip
1380 0, // literal operand
1381 1, // RAM access bit
1382 0, // fast call/return mode select bit
1383 0, // second memory operand
1384 0, // second literal operand
1386 (PCC_W | PCC_REGISTER), // inCond
1387 (PCC_W | PCC_Z | PCC_N), // outCond
1391 pCodeInstruction pic16_pciIORLW = {
1392 {PC_OPCODE, NULL, NULL, 0, NULL,
1398 NULL, // from branch
1405 0,0, // dest, bit instruction
1406 0,0, // branch, skip
1407 1, // literal operand
1408 0, // RAM access bit
1409 0, // fast call/return mode select bit
1410 0, // second memory operand
1411 0, // second literal operand
1413 (PCC_W | PCC_LITERAL), // inCond
1414 (PCC_W | PCC_Z | PCC_N), // outCond
1418 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1419 {PC_OPCODE, NULL, NULL, 0, NULL,
1425 NULL, // from branch
1432 0,0, // dest, bit instruction
1433 0,0, // branch, skip
1434 1, // literal operand
1435 0, // RAM access bit
1436 0, // fast call/return mode select bit
1437 0, // second memory operand
1438 1, // second literal operand
1440 (PCC_REGISTER | PCC_LITERAL),
1441 PCC_REGISTER, // outCond
1445 pCodeInstruction pic16_pciMOVF = {
1446 {PC_OPCODE, NULL, NULL, 0, NULL,
1452 NULL, // from branch
1459 1,0, // dest, bit instruction
1460 0,0, // branch, skip
1461 0, // literal operand
1462 1, // RAM access bit
1463 0, // fast call/return mode select bit
1464 0, // second memory operand
1465 0, // second literal operand
1467 PCC_REGISTER, // inCond
1468 (PCC_Z | PCC_N), // outCond
1472 pCodeInstruction pic16_pciMOVFW = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1479 NULL, // from branch
1486 0,0, // dest, bit instruction
1487 0,0, // branch, skip
1488 0, // literal operand
1489 1, // RAM access bit
1490 0, // fast call/return mode select bit
1491 0, // second memory operand
1492 0, // second literal operand
1494 PCC_REGISTER, // inCond
1495 (PCC_W | PCC_Z), // outCond
1499 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1500 {PC_OPCODE, NULL, NULL, 0, NULL,
1506 NULL, // from branch
1513 0,0, // dest, bit instruction
1514 0,0, // branch, skip
1515 0, // literal operand
1516 0, // RAM access bit
1517 0, // fast call/return mode select bit
1518 1, // second memory operand
1519 0, // second literal operand
1521 PCC_REGISTER, // inCond
1522 PCC_REGISTER2, // outCond
1526 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1532 NULL, // from branch
1539 0,0, // dest, bit instruction
1540 0,0, // branch, skip
1541 1, // literal operand
1542 0, // RAM access bit
1543 0, // fast call/return mode select bit
1544 0, // second memory operand
1545 0, // second literal operand
1547 (PCC_NONE | PCC_LITERAL), // inCond
1548 PCC_REGISTER, // outCond - BSR
1552 pCodeInstruction pic16_pciMOVLW = {
1553 {PC_OPCODE, NULL, NULL, 0, NULL,
1558 NULL, // from branch
1565 0,0, // dest, bit instruction
1566 0,0, // branch, skip
1567 1, // literal operand
1568 0, // RAM access bit
1569 0, // fast call/return mode select bit
1570 0, // second memory operand
1571 0, // second literal operand
1573 (PCC_NONE | PCC_LITERAL), // inCond
1578 pCodeInstruction pic16_pciMOVWF = {
1579 {PC_OPCODE, NULL, NULL, 0, NULL,
1585 NULL, // from branch
1592 0,0, // dest, bit instruction
1593 0,0, // branch, skip
1594 0, // literal operand
1595 1, // RAM access bit
1596 0, // fast call/return mode select bit
1597 0, // second memory operand
1598 0, // second literal operand
1600 PCC_REGISTER, // inCond
1605 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1606 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 1, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 0, // second memory operand
1624 0, // second literal operand
1626 (PCC_W | PCC_LITERAL), // inCond
1627 PCC_REGISTER, // outCond - PROD
1631 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1637 NULL, // from branch
1644 0,0, // dest, bit instruction
1645 0,0, // branch, skip
1646 0, // literal operand
1647 1, // RAM access bit
1648 0, // fast call/return mode select bit
1649 0, // second memory operand
1650 0, // second literal operand
1652 (PCC_W | PCC_REGISTER), // inCond
1653 PCC_REGISTER, // outCond - PROD
1657 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1658 {PC_OPCODE, NULL, NULL, 0, NULL,
1663 NULL, // from branch
1670 0,0, // dest, bit instruction
1671 0,0, // branch, skip
1672 0, // literal operand
1673 1, // RAM access bit
1674 0, // fast call/return mode select bit
1675 0, // second memory operand
1676 0, // second literal operand
1678 PCC_REGISTER, // inCond
1679 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1683 pCodeInstruction pic16_pciNOP = {
1684 {PC_OPCODE, NULL, NULL, 0, NULL,
1689 NULL, // from branch
1696 0,0, // dest, bit instruction
1697 0,0, // branch, skip
1698 0, // literal operand
1699 0, // RAM access bit
1700 0, // fast call/return mode select bit
1701 0, // second memory operand
1702 0, // second literal operand
1705 PCC_NONE, // outCond
1709 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1710 {PC_OPCODE, NULL, NULL, 0, NULL,
1715 NULL, // from branch
1722 0,0, // dest, bit instruction
1723 0,0, // branch, skip
1724 0, // literal operand
1725 0, // RAM access bit
1726 0, // fast call/return mode select bit
1727 0, // second memory operand
1728 0, // second literal operand
1731 PCC_NONE , // outCond
1735 pCodeInstruction pic16_pciPUSH = {
1736 {PC_OPCODE, NULL, NULL, 0, NULL,
1741 NULL, // from branch
1748 0,0, // dest, bit instruction
1749 0,0, // branch, skip
1750 0, // literal operand
1751 0, // RAM access bit
1752 0, // fast call/return mode select bit
1753 0, // second memory operand
1754 0, // second literal operand
1757 PCC_NONE , // outCond
1761 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1762 {PC_OPCODE, NULL, NULL, 0, NULL,
1767 NULL, // from branch
1774 0,0, // dest, bit instruction
1775 0,0, // branch, skip
1776 0, // literal operand
1777 0, // RAM access bit
1778 0, // fast call/return mode select bit
1779 0, // second memory operand
1780 0, // second literal operand
1782 PCC_REL_ADDR, // inCond
1783 PCC_NONE , // outCond
1787 pCodeInstruction pic16_pciRETFIE = {
1788 {PC_OPCODE, NULL, NULL, 0, NULL,
1794 NULL, // from branch
1801 0,0, // dest, bit instruction
1802 1,0, // branch, skip
1803 0, // literal operand
1804 0, // RAM access bit
1805 1, // fast call/return mode select bit
1806 0, // second memory operand
1807 0, // second literal operand
1810 PCC_NONE, // outCond (not true... affects the GIE bit too)
1814 pCodeInstruction pic16_pciRETLW = {
1815 {PC_OPCODE, NULL, NULL, 0, NULL,
1821 NULL, // from branch
1828 0,0, // dest, bit instruction
1829 1,0, // branch, skip
1830 1, // literal operand
1831 0, // RAM access bit
1832 0, // fast call/return mode select bit
1833 0, // second memory operand
1834 0, // second literal operand
1836 PCC_LITERAL, // inCond
1841 pCodeInstruction pic16_pciRETURN = {
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 0,0, // dest, bit instruction
1856 1,0, // branch, skip
1857 0, // literal operand
1858 0, // RAM access bit
1859 1, // fast call/return mode select bit
1860 0, // second memory operand
1861 0, // second literal operand
1864 PCC_NONE, // outCond
1867 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1868 {PC_OPCODE, NULL, NULL, 0, NULL,
1874 NULL, // from branch
1881 1,0, // dest, bit instruction
1882 0,0, // branch, skip
1883 0, // literal operand
1884 1, // RAM access bit
1885 0, // fast call/return mode select bit
1886 0, // second memory operand
1887 0, // second literal operand
1889 (PCC_C | PCC_REGISTER), // inCond
1890 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1894 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1895 {PC_OPCODE, NULL, NULL, 0, NULL,
1901 NULL, // from branch
1908 0,0, // dest, bit instruction
1909 0,0, // branch, skip
1910 0, // literal operand
1911 1, // RAM access bit
1912 0, // fast call/return mode select bit
1913 0, // second memory operand
1914 0, // second literal operand
1916 (PCC_C | PCC_REGISTER), // inCond
1917 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1921 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1922 {PC_OPCODE, NULL, NULL, 0, NULL,
1928 NULL, // from branch
1935 1,0, // dest, bit instruction
1936 0,0, // branch, skip
1937 0, // literal operand
1938 1, // RAM access bit
1939 0, // fast call/return mode select bit
1940 0, // second memory operand
1941 0, // second literal operand
1943 PCC_REGISTER, // inCond
1944 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1947 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1948 {PC_OPCODE, NULL, NULL, 0, NULL,
1954 NULL, // from branch
1961 0,0, // dest, bit instruction
1962 0,0, // branch, skip
1963 0, // literal operand
1964 1, // RAM access bit
1965 0, // fast call/return mode select bit
1966 0, // second memory operand
1967 0, // second literal operand
1969 PCC_REGISTER, // inCond
1970 (PCC_W | PCC_Z | PCC_N), // outCond
1973 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1974 {PC_OPCODE, NULL, NULL, 0, NULL,
1980 NULL, // from branch
1987 1,0, // dest, bit instruction
1988 0,0, // branch, skip
1989 0, // literal operand
1990 1, // RAM access bit
1991 0, // fast call/return mode select bit
1992 0, // second memory operand
1993 0, // second literal operand
1995 (PCC_C | PCC_REGISTER), // inCond
1996 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1999 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2000 {PC_OPCODE, NULL, NULL, 0, NULL,
2006 NULL, // from branch
2013 0,0, // dest, bit instruction
2014 0,0, // branch, skip
2015 0, // literal operand
2016 1, // RAM access bit
2017 0, // fast call/return mode select bit
2018 0, // second memory operand
2019 0, // second literal operand
2021 (PCC_C | PCC_REGISTER), // inCond
2022 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2025 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2026 {PC_OPCODE, NULL, NULL, 0, NULL,
2032 NULL, // from branch
2039 1,0, // dest, bit instruction
2040 0,0, // branch, skip
2041 0, // literal operand
2042 1, // RAM access bit
2043 0, // fast call/return mode select bit
2044 0, // second memory operand
2045 0, // second literal operand
2047 PCC_REGISTER, // inCond
2048 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2052 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2053 {PC_OPCODE, NULL, NULL, 0, NULL,
2059 NULL, // from branch
2066 0,0, // dest, bit instruction
2067 0,0, // branch, skip
2068 0, // literal operand
2069 1, // RAM access bit
2070 0, // fast call/return mode select bit
2071 0, // second memory operand
2072 0, // second literal operand
2074 PCC_REGISTER, // inCond
2075 (PCC_W | PCC_Z | PCC_N), // outCond
2079 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2080 {PC_OPCODE, NULL, NULL, 0, NULL,
2086 NULL, // from branch
2093 0,0, // dest, bit instruction
2094 0,0, // branch, skip
2095 0, // literal operand
2096 1, // RAM access bit
2097 0, // fast call/return mode select bit
2098 0, // second memory operand
2099 0, // second literal operand
2101 PCC_REGISTER, // inCond
2102 PCC_REGISTER , // outCond
2106 pCodeInstruction pic16_pciSUBLW = {
2107 {PC_OPCODE, NULL, NULL, 0, NULL,
2113 NULL, // from branch
2120 0,0, // dest, bit instruction
2121 0,0, // branch, skip
2122 1, // literal operand
2123 0, // RAM access bit
2124 0, // fast call/return mode select bit
2125 0, // second memory operand
2126 0, // second literal operand
2128 (PCC_W | PCC_LITERAL), // inCond
2129 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2133 pCodeInstruction pic16_pciSUBFWB = {
2134 {PC_OPCODE, NULL, NULL, 0, NULL,
2140 NULL, // from branch
2147 1,0, // dest, bit instruction
2148 0,0, // branch, skip
2149 0, // literal operand
2150 1, // RAM access bit
2151 0, // fast call/return mode select bit
2152 0, // second memory operand
2153 0, // second literal operand
2155 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2156 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2160 pCodeInstruction pic16_pciSUBWF = {
2161 {PC_OPCODE, NULL, NULL, 0, NULL,
2167 NULL, // from branch
2174 1,0, // dest, bit instruction
2175 0,0, // branch, skip
2176 0, // literal operand
2177 1, // RAM access bit
2178 0, // fast call/return mode select bit
2179 0, // second memory operand
2180 0, // second literal operand
2182 (PCC_W | PCC_REGISTER), // inCond
2183 (PCC_REGISTER | PCC_Z), // outCond
2187 pCodeInstruction pic16_pciSUBFW = {
2188 {PC_OPCODE, NULL, NULL, 0, NULL,
2194 NULL, // from branch
2201 0,0, // dest, bit instruction
2202 0,0, // branch, skip
2203 0, // literal operand
2204 1, // RAM access bit
2205 0, // fast call/return mode select bit
2206 0, // second memory operand
2207 0, // second literal operand
2209 (PCC_W | PCC_REGISTER), // inCond
2210 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2214 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2215 {PC_OPCODE, NULL, NULL, 0, NULL,
2221 NULL, // from branch
2228 1,0, // dest, bit instruction
2229 0,0, // branch, skip
2230 0, // literal operand
2231 1, // RAM access bit
2232 0, // fast call/return mode select bit
2233 0, // second memory operand
2234 0, // second literal operand
2236 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2237 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2241 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2242 {PC_OPCODE, NULL, NULL, 0, NULL,
2248 NULL, // from branch
2255 0,0, // dest, bit instruction
2256 0,0, // branch, skip
2257 0, // literal operand
2258 1, // RAM access bit
2259 0, // fast call/return mode select bit
2260 0, // second memory operand
2261 0, // second literal operand
2263 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2264 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2268 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2269 {PC_OPCODE, NULL, NULL, 0, NULL,
2275 NULL, // from branch
2282 1,0, // dest, bit instruction
2283 0,0, // branch, skip
2284 0, // literal operand
2285 1, // RAM access bit
2286 0, // fast call/return mode select bit
2287 0, // second memory operand
2288 0, // second literal operand
2290 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2291 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2295 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2296 {PC_OPCODE, NULL, NULL, 0, NULL,
2302 NULL, // from branch
2309 0,0, // dest, bit instruction
2310 0,0, // branch, skip
2311 0, // literal operand
2312 1, // RAM access bit
2313 0, // fast call/return mode select bit
2314 0, // second memory operand
2315 0, // second literal operand
2317 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2318 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2322 pCodeInstruction pic16_pciSWAPF = {
2323 {PC_OPCODE, NULL, NULL, 0, NULL,
2329 NULL, // from branch
2336 1,0, // dest, bit instruction
2337 0,0, // branch, skip
2338 0, // literal operand
2339 1, // RAM access bit
2340 0, // fast call/return mode select bit
2341 0, // second memory operand
2342 0, // second literal operand
2344 (PCC_REGISTER), // inCond
2345 (PCC_REGISTER), // outCond
2349 pCodeInstruction pic16_pciSWAPFW = {
2350 {PC_OPCODE, NULL, NULL, 0, NULL,
2356 NULL, // from branch
2363 0,0, // dest, bit instruction
2364 0,0, // branch, skip
2365 0, // literal operand
2366 1, // RAM access bit
2367 0, // fast call/return mode select bit
2368 0, // second memory operand
2369 0, // second literal operand
2371 (PCC_REGISTER), // inCond
2376 pCodeInstruction pic16_pciTBLRD = { // patch 15
2377 {PC_OPCODE, NULL, NULL, 0, NULL,
2382 NULL, // from branch
2389 0,0, // dest, bit instruction
2390 0,0, // branch, skip
2391 0, // literal operand
2392 0, // RAM access bit
2393 0, // fast call/return mode select bit
2394 0, // second memory operand
2395 0, // second literal operand
2398 PCC_NONE , // outCond
2402 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2403 {PC_OPCODE, NULL, NULL, 0, NULL,
2408 NULL, // from branch
2415 0,0, // dest, bit instruction
2416 0,0, // branch, skip
2417 0, // literal operand
2418 0, // RAM access bit
2419 0, // fast call/return mode select bit
2420 0, // second memory operand
2421 0, // second literal operand
2424 PCC_NONE , // outCond
2428 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2429 {PC_OPCODE, NULL, NULL, 0, NULL,
2434 NULL, // from branch
2441 0,0, // dest, bit instruction
2442 0,0, // branch, skip
2443 0, // literal operand
2444 0, // RAM access bit
2445 0, // fast call/return mode select bit
2446 0, // second memory operand
2447 0, // second literal operand
2450 PCC_NONE , // outCond
2454 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2455 {PC_OPCODE, NULL, NULL, 0, NULL,
2460 NULL, // from branch
2467 0,0, // dest, bit instruction
2468 0,0, // branch, skip
2469 0, // literal operand
2470 0, // RAM access bit
2471 0, // fast call/return mode select bit
2472 0, // second memory operand
2473 0, // second literal operand
2476 PCC_NONE , // outCond
2480 pCodeInstruction pic16_pciTBLWT = { // patch 15
2481 {PC_OPCODE, NULL, NULL, 0, NULL,
2486 NULL, // from branch
2493 0,0, // dest, bit instruction
2494 0,0, // branch, skip
2495 0, // literal operand
2496 0, // RAM access bit
2497 0, // fast call/return mode select bit
2498 0, // second memory operand
2499 0, // second literal operand
2502 PCC_NONE , // outCond
2506 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2507 {PC_OPCODE, NULL, NULL, 0, NULL,
2512 NULL, // from branch
2519 0,0, // dest, bit instruction
2520 0,0, // branch, skip
2521 0, // literal operand
2522 0, // RAM access bit
2523 0, // fast call/return mode select bit
2524 0, // second memory operand
2525 0, // second literal operand
2528 PCC_NONE , // outCond
2532 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2533 {PC_OPCODE, NULL, NULL, 0, NULL,
2538 NULL, // from branch
2545 0,0, // dest, bit instruction
2546 0,0, // branch, skip
2547 0, // literal operand
2548 0, // RAM access bit
2549 0, // fast call/return mode select bit
2550 0, // second memory operand
2551 0, // second literal operand
2554 PCC_NONE , // outCond
2558 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2559 {PC_OPCODE, NULL, NULL, 0, NULL,
2564 NULL, // from branch
2571 0,0, // dest, bit instruction
2572 0,0, // branch, skip
2573 0, // literal operand
2574 0, // RAM access bit
2575 0, // fast call/return mode select bit
2576 0, // second memory operand
2577 0, // second literal operand
2580 PCC_NONE , // outCond
2584 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2585 {PC_OPCODE, NULL, NULL, 0, NULL,
2591 NULL, // from branch
2598 0,0, // dest, bit instruction
2599 1,1, // branch, skip
2600 0, // literal operand
2601 1, // RAM access bit
2602 0, // fast call/return mode select bit
2603 0, // second memory operand
2604 0, // second literal operand
2606 PCC_REGISTER, // inCond
2607 PCC_NONE, // outCond
2611 pCodeInstruction pic16_pciXORWF = {
2612 {PC_OPCODE, NULL, NULL, 0, NULL,
2618 NULL, // from branch
2625 1,0, // dest, bit instruction
2626 0,0, // branch, skip
2627 0, // literal operand
2628 1, // RAM access bit
2629 0, // fast call/return mode select bit
2630 0, // second memory operand
2631 0, // second literal operand
2633 (PCC_W | PCC_REGISTER), // inCond
2634 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2638 pCodeInstruction pic16_pciXORFW = {
2639 {PC_OPCODE, NULL, NULL, 0, NULL,
2645 NULL, // from branch
2652 0,0, // dest, bit instruction
2653 0,0, // branch, skip
2654 0, // literal operand
2655 1, // RAM access bit
2656 0, // fast call/return mode select bit
2657 0, // second memory operand
2658 0, // second literal operand
2660 (PCC_W | PCC_REGISTER), // inCond
2661 (PCC_W | PCC_Z | PCC_N), // outCond
2665 pCodeInstruction pic16_pciXORLW = {
2666 {PC_OPCODE, NULL, NULL, 0, NULL,
2672 NULL, // from branch
2679 0,0, // dest, bit instruction
2680 0,0, // branch, skip
2681 1, // literal operand
2682 1, // RAM access bit
2683 0, // fast call/return mode select bit
2684 0, // second memory operand
2685 0, // second literal operand
2687 (PCC_W | PCC_LITERAL), // inCond
2688 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2693 #define MAX_PIC16MNEMONICS 100
2694 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2696 //#define USE_VSNPRINTF
2699 #ifdef USE_VSNPRINTF
2700 // Alas, vsnprintf is not ANSI standard, and does not exist
2701 // on Solaris (and probably other non-Gnu flavored Unixes).
2703 /*-----------------------------------------------------------------*/
2704 /* SAFE_snprintf - like snprintf except the string pointer is */
2705 /* after the string has been printed to. This is */
2706 /* useful for printing to string as though if it */
2707 /* were a stream. */
2708 /*-----------------------------------------------------------------*/
2709 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2717 va_start(val, format);
2719 vsnprintf(*str, *size, format, val);
2725 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2726 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2735 // This version is *not* safe, despite the name.
2737 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2741 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2746 va_start(val, format);
2748 vsprintf(buffer, format, val);
2751 len = strlen(buffer);
2753 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2754 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2757 strcpy(*str, buffer);
2763 #endif // USE_VSNPRINTF
2766 extern void pic16_initStack(int base_address, int size);
2767 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2768 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2769 extern void pic16_init_pic(char *);
2771 void pic16_pCodeInitRegisters(void)
2773 static int initialized=0;
2780 pic16_initStack(0xfff, 8);
2781 pic16_init_pic(port->processor);
2783 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2784 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2785 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2786 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2787 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2788 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2789 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2791 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2792 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2793 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2795 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2796 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2797 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2798 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2800 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2801 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2802 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2803 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2804 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2805 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2807 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2808 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2809 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2810 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2811 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2813 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2814 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2815 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2816 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2817 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2819 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2820 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2821 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2822 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2823 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2825 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2826 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2829 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2830 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2831 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2832 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2835 pic16_pc_status.rIdx = IDX_STATUS;
2836 pic16_pc_intcon.rIdx = IDX_INTCON;
2837 pic16_pc_pcl.rIdx = IDX_PCL;
2838 pic16_pc_pclath.rIdx = IDX_PCLATH;
2839 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2840 pic16_pc_wreg.rIdx = IDX_WREG;
2841 pic16_pc_bsr.rIdx = IDX_BSR;
2843 pic16_pc_tosl.rIdx = IDX_TOSL;
2844 pic16_pc_tosh.rIdx = IDX_TOSH;
2845 pic16_pc_tosu.rIdx = IDX_TOSU;
2847 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL; // patch 15
2848 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH; // patch 15
2849 pic16_pc_tblptru.rIdx = IDX_TBLPTRU; // patch 15
2850 pic16_pc_tablat.rIdx = IDX_TABLAT; // patch 15
2852 // pic16_pc_fsr0.rIdx = IDX_FSR0;
2853 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2854 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2855 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2856 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2857 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2858 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2859 pic16_pc_indf0.rIdx = IDX_INDF0;
2860 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2861 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2862 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2863 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2864 pic16_pc_indf1.rIdx = IDX_INDF1;
2865 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2866 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2867 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2868 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2869 pic16_pc_indf2.rIdx = IDX_INDF2;
2870 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2871 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2872 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2873 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2874 pic16_pc_prodl.rIdx = IDX_PRODL;
2875 pic16_pc_prodh.rIdx = IDX_PRODH;
2877 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2878 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2879 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2881 pic16_pc_kzero.rIdx = IDX_KZ;
2882 pic16_pc_wsave.rIdx = IDX_WSAVE;
2883 pic16_pc_ssave.rIdx = IDX_SSAVE;
2885 pic16_pc_eecon1.rIdx = IDX_EECON1;
2886 pic16_pc_eecon2.rIdx = IDX_EECON2;
2887 pic16_pc_eedata.rIdx = IDX_EEDATA;
2888 pic16_pc_eeadr.rIdx = IDX_EEADR;
2891 /* probably should put this in a separate initialization routine */
2892 pb_dead_pcodes = newpBlock();
2897 /*-----------------------------------------------------------------*/
2898 /* mnem2key - convert a pic mnemonic into a hash key */
2899 /* (BTW - this spreads the mnemonics quite well) */
2901 /*-----------------------------------------------------------------*/
2903 int mnem2key(char const *mnem)
2912 key += toupper(*mnem++) +1;
2916 return (key & 0x1f);
2921 void pic16initMnemonics(void)
2926 pCodeInstruction *pci;
2928 if(mnemonics_initialized)
2931 // NULL out the array before making the assignments
2932 // since we check the array contents below this initialization.
2934 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2935 pic16Mnemonics[i] = NULL;
2938 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2939 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2940 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2941 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2942 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2943 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2944 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2945 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2946 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2947 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2948 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2949 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2950 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2951 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2952 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2953 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2954 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2955 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2956 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2957 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2958 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2959 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2960 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2961 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2962 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2963 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2964 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2965 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2966 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2967 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2968 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2969 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2970 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2971 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2972 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2973 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2974 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2975 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2976 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2977 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2978 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2979 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2980 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2981 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2982 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2983 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2984 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2985 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2986 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2987 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2988 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2989 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2990 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2991 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2992 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2993 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2994 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2995 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2996 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2997 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2998 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2999 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3000 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3001 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3002 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF; // was [POC_RLCF] !!!
3003 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3004 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3005 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3006 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3007 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3008 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3009 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3010 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3011 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3012 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3013 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3014 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3015 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3016 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3017 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3018 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD; // patch 15
3019 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC; //
3020 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC; //
3021 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC; //
3022 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT; //
3023 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC; //
3024 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC; //
3025 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC; // patch 15
3026 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3027 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3028 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3029 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3031 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3032 if(pic16Mnemonics[i])
3033 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3034 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3037 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3038 pci = hTabNextItem(pic16MnemonicsHash, &key);
3041 mnemonics_initialized = 1;
3044 int pic16_getpCodePeepCommand(char *cmd);
3046 int pic16_getpCode(char *mnem,unsigned dest)
3049 pCodeInstruction *pci;
3050 int key = mnem2key(mnem);
3052 if(!mnemonics_initialized)
3053 pic16initMnemonics();
3055 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3059 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3060 if((pci->num_ops <= 1)
3061 || (pci->isModReg == dest)
3063 || (pci->num_ops <= 2 && pci->isAccess)
3064 || (pci->num_ops <= 2 && pci->isFastCall)
3065 || (pci->num_ops <= 2 && pci->is2MemOp)
3066 || (pci->num_ops <= 2 && pci->is2LitOp) )
3070 pci = hTabNextItemWK (pic16MnemonicsHash);
3077 /*-----------------------------------------------------------------*
3078 * pic16initpCodePeepCommands
3080 *-----------------------------------------------------------------*/
3081 void pic16initpCodePeepCommands(void)
3089 hTabAddItem(&pic16pCodePeepCommandsHash,
3090 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3092 } while (peepCommands[i].cmd);
3094 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3097 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3098 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3103 /*-----------------------------------------------------------------
3106 *-----------------------------------------------------------------*/
3108 int pic16_getpCodePeepCommand(char *cmd)
3112 int key = mnem2key(cmd);
3115 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3118 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3119 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3123 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3130 static char getpBlock_dbName(pBlock *pb)
3136 return pb->cmemmap->dbName;
3140 void pic16_pBlockConvert2ISR(pBlock *pb)
3144 if(pb->cmemmap)pb->cmemmap = NULL;
3148 if(pic16_pcode_verbose)
3149 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3152 void pic16_pBlockConvert2Absolute(pBlock *pb)
3155 if(pb->cmemmap)pb->cmemmap = NULL;
3159 if(pic16_pcode_verbose)
3160 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3163 /*-----------------------------------------------------------------*/
3164 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3165 /* instances to the front of the doubly linked */
3166 /* list of pBlocks */
3167 /*-----------------------------------------------------------------*/
3169 void pic16_movepBlock2Head(char dbName)
3174 /* this can happen in sources without code,
3175 * only variable definitions */
3176 if(!the_pFile)return;
3178 pb = the_pFile->pbHead;
3182 if(getpBlock_dbName(pb) == dbName) {
3183 pBlock *pbn = pb->next;
3184 pb->next = the_pFile->pbHead;
3185 the_pFile->pbHead->prev = pb;
3186 the_pFile->pbHead = pb;
3189 pb->prev->next = pbn;
3191 // If the pBlock that we just moved was the last
3192 // one in the link of all of the pBlocks, then we
3193 // need to point the tail to the block just before
3194 // the one we moved.
3195 // Note: if pb->next is NULL, then pb must have
3196 // been the last pBlock in the chain.
3199 pbn->prev = pb->prev;
3201 the_pFile->pbTail = pb->prev;
3212 void pic16_copypCode(FILE *of, char dbName)
3216 if(!of || !the_pFile)
3219 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3220 if(getpBlock_dbName(pb) == dbName) {
3221 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3223 pic16_printpBlock(of,pb);
3228 void pic16_pcode_test(void)
3231 DFPRINTF((stderr,"pcode is alive!\n"));
3241 /* create the file name */
3242 strcpy(buffer,dstFileName);
3243 strcat(buffer,".p");
3245 if( !(pFile = fopen(buffer, "w" ))) {
3246 werror(E_FILE_OPEN_ERR,buffer);
3250 fprintf(pFile,"pcode dump\n\n");
3252 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3253 fprintf(pFile,"\n\tNew pBlock\n\n");
3255 fprintf(pFile,"%s",pb->cmemmap->sname);
3257 fprintf(pFile,"internal pblock");
3259 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3260 pic16_printpBlock(pFile,pb);
3264 /*-----------------------------------------------------------------*/
3265 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3266 /* ister, RegCond will return the bit being referenced. */
3268 /* fixme - why not just OR in the pcop bit field */
3269 /*-----------------------------------------------------------------*/
3271 static int RegCond(pCodeOp *pcop)
3277 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3278 switch(PCORB(pcop)->bit) {
3292 /*-----------------------------------------------------------------*/
3293 /* pic16_newpCode - create and return a newly initialized pCode */
3295 /* fixme - rename this */
3297 /* The purpose of this routine is to create a new Instruction */
3298 /* pCode. This is called by gen.c while the assembly code is being */
3302 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3303 /* (note that the op is analogous to but not the */
3304 /* same thing as the opcode of the instruction.) */
3305 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3308 /* a pointer to the new malloc'd pCode is returned. */
3312 /*-----------------------------------------------------------------*/
3313 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3315 pCodeInstruction *pci ;
3317 if(!mnemonics_initialized)
3318 pic16initMnemonics();
3320 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3322 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3323 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3326 if(pci->inCond & PCC_EXAMINE_PCOP)
3327 pci->inCond |= RegCond(pcop);
3329 if(pci->outCond & PCC_EXAMINE_PCOP)
3330 pci->outCond |= RegCond(pcop);
3332 pci->pc.prev = pci->pc.next = NULL;
3333 return (pCode *)pci;
3336 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3342 /*-----------------------------------------------------------------*/
3343 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3345 /* Wild pcodes are used during the peep hole optimizer to serve */
3346 /* as place holders for any instruction. When a snippet of code is */
3347 /* compared to a peep hole rule, the wild card opcode will match */
3348 /* any instruction. However, the optional operand and label are */
3349 /* additional qualifiers that must also be matched before the */
3350 /* line (of assembly code) is declared matched. Note that the */
3351 /* operand may be wild too. */
3353 /* Note, a wild instruction is specified just like a wild var: */
3354 /* %4 ; A wild instruction, */
3355 /* See the peeph.def file for additional examples */
3357 /*-----------------------------------------------------------------*/
3359 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3364 pcw = Safe_calloc(1,sizeof(pCodeWild));
3366 pcw->pci.pc.type = PC_WILD;
3367 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3368 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3369 pcw->pci.pc.pb = NULL;
3371 // pcw->pci.pc.analyze = genericAnalyze;
3372 pcw->pci.pc.destruct = genericDestruct;
3373 pcw->pci.pc.print = genericPrint;
3375 pcw->id = pCodeID; // this is the 'n' in %n
3376 pcw->operand = optional_operand;
3377 pcw->label = optional_label;
3379 pcw->mustBeBitSkipInst = 0;
3380 pcw->mustNotBeBitSkipInst = 0;
3381 pcw->invertBitSkipInst = 0;
3383 return ( (pCode *)pcw);
3387 /*-----------------------------------------------------------------*/
3388 /* newPcodeInlineP - create a new pCode from a char string */
3389 /*-----------------------------------------------------------------*/
3392 pCode *pic16_newpCodeInlineP(char *cP)
3397 pcc = Safe_calloc(1,sizeof(pCodeComment));
3399 pcc->pc.type = PC_INLINE;
3400 pcc->pc.prev = pcc->pc.next = NULL;
3401 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3404 // pcc->pc.analyze = genericAnalyze;
3405 pcc->pc.destruct = genericDestruct;
3406 pcc->pc.print = genericPrint;
3409 pcc->comment = Safe_strdup(cP);
3411 pcc->comment = NULL;
3413 return ( (pCode *)pcc);
3417 /*-----------------------------------------------------------------*/
3418 /* newPcodeCharP - create a new pCode from a char string */
3419 /*-----------------------------------------------------------------*/
3421 pCode *pic16_newpCodeCharP(char *cP)
3426 pcc = Safe_calloc(1,sizeof(pCodeComment));
3428 pcc->pc.type = PC_COMMENT;
3429 pcc->pc.prev = pcc->pc.next = NULL;
3430 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3433 // pcc->pc.analyze = genericAnalyze;
3434 pcc->pc.destruct = genericDestruct;
3435 pcc->pc.print = genericPrint;
3438 pcc->comment = Safe_strdup(cP);
3440 pcc->comment = NULL;
3442 return ( (pCode *)pcc);
3446 /*-----------------------------------------------------------------*/
3447 /* pic16_newpCodeFunction - */
3448 /*-----------------------------------------------------------------*/
3451 pCode *pic16_newpCodeFunction(char *mod,char *f)
3455 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3457 pcf->pc.type = PC_FUNCTION;
3458 pcf->pc.prev = pcf->pc.next = NULL;
3459 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3462 // pcf->pc.analyze = genericAnalyze;
3463 pcf->pc.destruct = genericDestruct;
3464 pcf->pc.print = pCodePrintFunction;
3470 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3471 strcpy(pcf->modname,mod);
3473 pcf->modname = NULL;
3476 pcf->fname = Safe_calloc(1,strlen(f)+1);
3477 strcpy(pcf->fname,f);
3481 return ( (pCode *)pcf);
3485 /*-----------------------------------------------------------------*/
3486 /* pic16_newpCodeFlow */
3487 /*-----------------------------------------------------------------*/
3488 static void destructpCodeFlow(pCode *pc)
3490 if(!pc || !isPCFL(pc))
3497 pic16_unlinkpCode(pc);
3499 deleteSet(&PCFL(pc)->registers);
3500 deleteSet(&PCFL(pc)->from);
3501 deleteSet(&PCFL(pc)->to);
3506 pCode *pic16_newpCodeFlow(void )
3510 //_ALLOC(pcflow,sizeof(pCodeFlow));
3511 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3513 pcflow->pc.type = PC_FLOW;
3514 pcflow->pc.prev = pcflow->pc.next = NULL;
3515 pcflow->pc.pb = NULL;
3517 // pcflow->pc.analyze = genericAnalyze;
3518 pcflow->pc.destruct = destructpCodeFlow;
3519 pcflow->pc.print = genericPrint;
3521 pcflow->pc.seq = GpcFlowSeq++;
3523 pcflow->from = pcflow->to = NULL;
3525 pcflow->inCond = PCC_NONE;
3526 pcflow->outCond = PCC_NONE;
3528 pcflow->firstBank = -1;
3529 pcflow->lastBank = -1;
3531 pcflow->FromConflicts = 0;
3532 pcflow->ToConflicts = 0;
3536 pcflow->registers = newSet();
3538 return ( (pCode *)pcflow);
3542 /*-----------------------------------------------------------------*/
3543 /*-----------------------------------------------------------------*/
3544 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3546 pCodeFlowLink *pcflowLink;
3548 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3550 pcflowLink->pcflow = pcflow;
3551 pcflowLink->bank_conflict = 0;
3556 /*-----------------------------------------------------------------*/
3557 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3558 /*-----------------------------------------------------------------*/
3560 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3565 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3567 pccs->pc.type = PC_CSOURCE;
3568 pccs->pc.prev = pccs->pc.next = NULL;
3571 pccs->pc.destruct = genericDestruct;
3572 pccs->pc.print = genericPrint;
3574 pccs->line_number = ln;
3576 pccs->line = Safe_strdup(l);
3581 pccs->file_name = Safe_strdup(f);
3583 pccs->file_name = NULL;
3585 return ( (pCode *)pccs);
3590 /*******************************************************************/
3591 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3592 /* added by VR 6-Jun-2003 */
3593 /*******************************************************************/
3595 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3602 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3603 pcad->pci.pc.type = PC_ASMDIR;
3604 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3605 pcad->pci.pc.pb = NULL;
3607 pcad->pci.pc.destruct = genericDestruct;
3608 pcad->pci.pc.print = genericPrint;
3610 if(asdir && *asdir) {
3612 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3614 pcad->directive = Safe_strdup( asdir );
3617 va_start(ap, argfmt);
3619 memset(buffer, 0, sizeof(buffer));
3620 if(argfmt && *argfmt)
3621 vsprintf(buffer, argfmt, ap);
3625 while(isspace(*lbp))lbp++;
3628 pcad->arg = Safe_strdup( lbp );
3630 return ((pCode *)pcad);
3633 /*-----------------------------------------------------------------*/
3634 /* pCodeLabelDestruct - free memory used by a label. */
3635 /*-----------------------------------------------------------------*/
3636 static void pCodeLabelDestruct(pCode *pc)
3642 if((pc->type == PC_LABEL) && PCL(pc)->label)
3643 free(PCL(pc)->label);
3649 pCode *pic16_newpCodeLabel(char *name, int key)
3655 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3657 pcl->pc.type = PC_LABEL;
3658 pcl->pc.prev = pcl->pc.next = NULL;
3659 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3662 // pcl->pc.analyze = genericAnalyze;
3663 pcl->pc.destruct = pCodeLabelDestruct;
3664 pcl->pc.print = pCodePrintLabel;
3671 sprintf(s,"_%05d_DS_",key);
3676 pcl->label = Safe_strdup(s);
3678 // if(pic16_pcode_verbose)
3679 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3682 return ( (pCode *)pcl);
3686 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3688 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3692 return ( (pCode *)pcl );
3696 /*-----------------------------------------------------------------*/
3697 /* newpBlock - create and return a pointer to a new pBlock */
3698 /*-----------------------------------------------------------------*/
3699 static pBlock *newpBlock(void)
3704 PpB = Safe_calloc(1,sizeof(pBlock) );
3705 PpB->next = PpB->prev = NULL;
3707 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3708 PpB->tregisters = NULL;
3710 PpB->FlowTree = NULL;
3716 /*-----------------------------------------------------------------*/
3717 /* pic16_newpCodeChain - create a new chain of pCodes */
3718 /*-----------------------------------------------------------------*
3720 * This function will create a new pBlock and the pointer to the
3721 * pCode that is passed in will be the first pCode in the block.
3722 *-----------------------------------------------------------------*/
3725 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3728 pBlock *pB = newpBlock();
3730 pB->pcHead = pB->pcTail = pc;
3737 /*-----------------------------------------------------------------*/
3738 /* pic16_newpCodeOpLabel - Create a new label given the key */
3739 /* Note, a negative key means that the label is part of wild card */
3740 /* (and hence a wild card label) used in the pCodePeep */
3741 /* optimizations). */
3742 /*-----------------------------------------------------------------*/
3744 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3747 static int label_key=-1;
3751 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3752 pcop->type = PO_LABEL;
3757 sprintf(s=buffer,"_%05d_DS_",key);
3759 s = name, key = label_key--;
3762 pcop->name = Safe_strdup(s);
3764 ((pCodeOpLabel *)pcop)->key = key;
3766 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3770 /*-----------------------------------------------------------------*/
3771 /*-----------------------------------------------------------------*/
3772 pCodeOp *pic16_newpCodeOpLit(int lit)
3778 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3779 pcop->type = PO_LITERAL;
3783 sprintf(s,"0x%02x",lit);
3785 pcop->name = Safe_strdup(s);
3788 ((pCodeOpLit *)pcop)->lit = lit;
3793 /*-----------------------------------------------------------------*/
3794 /*-----------------------------------------------------------------*/
3795 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3797 char *s = buffer, tbuf[256], *tb=tbuf;
3801 tb = pic16_get_op(arg2, NULL, 0);
3802 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3803 pcop->type = PO_LITERAL;
3807 sprintf(s,"0x%02x, %s",lit, tb);
3809 pcop->name = Safe_strdup(s);
3812 ((pCodeOpLit2 *)pcop)->lit = lit;
3813 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3818 /*-----------------------------------------------------------------*/
3819 /*-----------------------------------------------------------------*/
3820 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3824 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3825 pcop->type = PO_IMMEDIATE;
3827 regs *r = pic16_dirregWithName(name);
3828 pcop->name = Safe_strdup(name);
3832 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3833 PCOI(pcop)->rIdx = r->rIdx;
3835 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3836 // __FILE__, __LINE__, __FUNCTION__, name);
3837 PCOI(pcop)->rIdx = -1;
3839 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3844 PCOI(pcop)->index = index;
3845 PCOI(pcop)->offset = offset;
3846 PCOI(pcop)->_const = code_space;
3851 /*-----------------------------------------------------------------*/
3852 /*-----------------------------------------------------------------*/
3853 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3859 if(!pcwb || !subtype) {
3860 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3864 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3865 pcop->type = PO_WILD;
3866 sprintf(s,"%%%d",id);
3867 pcop->name = Safe_strdup(s);
3869 PCOW(pcop)->id = id;
3870 PCOW(pcop)->pcwb = pcwb;
3871 PCOW(pcop)->subtype = subtype;
3872 PCOW(pcop)->matched = NULL;
3874 PCOW(pcop)->pcop2 = NULL;
3879 /*-----------------------------------------------------------------*/
3880 /*-----------------------------------------------------------------*/
3881 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3887 if(!pcwb || !subtype || !subtype2) {
3888 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3892 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3893 pcop->type = PO_WILD;
3894 sprintf(s,"%%%d",id);
3895 pcop->name = Safe_strdup(s);
3897 PCOW(pcop)->id = id;
3898 PCOW(pcop)->pcwb = pcwb;
3899 PCOW(pcop)->subtype = subtype;
3900 PCOW(pcop)->matched = NULL;
3902 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3904 if(!subtype2->name) {
3905 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3906 PCOW2(pcop)->pcop.type = PO_WILD;
3907 sprintf(s, "%%%d", id2);
3908 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3909 PCOW2(pcop)->id = id2;
3910 PCOW2(pcop)->subtype = subtype2;
3912 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3913 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3915 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
3917 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3918 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3926 /*-----------------------------------------------------------------*/
3927 /*-----------------------------------------------------------------*/
3928 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3932 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3933 pcop->type = PO_GPR_BIT;
3935 pcop->name = Safe_strdup(s);
3939 PCORB(pcop)->bit = bit;
3940 PCORB(pcop)->inBitSpace = inBitSpace;
3942 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3943 PCOR(pcop)->r = NULL;
3944 PCOR(pcop)->rIdx = 0;
3948 /*-----------------------------------------------------------------*
3949 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3951 * If rIdx >=0 then a specific register from the set of registers
3952 * will be selected. If rIdx <0, then a new register will be searched
3954 *-----------------------------------------------------------------*/
3956 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3960 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3965 PCOR(pcop)->rIdx = rIdx;
3966 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3968 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3971 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3973 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
3974 __FUNCTION__, __LINE__);
3979 pcop->type = PCOR(pcop)->r->pc_type;
3984 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3989 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3990 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
3991 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3992 pcop->type = PCOR(pcop)->r->pc_type;
3993 pcop->name = PCOR(pcop)->r->name;
3995 // if(pic16_pcode_verbose) {
3996 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3997 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4003 /*-----------------------------------------------------------------*/
4004 /*-----------------------------------------------------------------*/
4006 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4013 pcop = pic16_newpCodeOpBit(name, -1,0);
4017 pcop = pic16_newpCodeOpLit(-1);
4021 pcop = pic16_newpCodeOpLabel(NULL,-1);
4024 pcop = pic16_newpCodeOpReg(-1);
4027 case PO_GPR_REGISTER:
4029 pcop = pic16_newpCodeOpRegFromStr(name);
4031 pcop = pic16_newpCodeOpReg(-1);
4035 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4038 pcop->name = Safe_strdup(name);
4046 #define DB_ITEMS_PER_LINE 8
4048 typedef struct DBdata
4055 static int DBd_init = -1;
4057 /*-----------------------------------------------------------------*/
4058 /* Initialiase "DB" data buffer */
4059 /*-----------------------------------------------------------------*/
4060 void pic16_initDB(void)
4066 /*-----------------------------------------------------------------*/
4067 /* Flush pending "DB" data to a pBlock */
4069 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4070 /*-----------------------------------------------------------------*/
4071 void pic16_flushDB(char ptype, void *p)
4075 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4078 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4081 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4085 DBd.buffer[0] = '\0';
4090 /*-----------------------------------------------------------------*/
4091 /* Add "DB" directives to a pBlock */
4092 /*-----------------------------------------------------------------*/
4093 void pic16_emitDB(char c, char ptype, void *p)
4098 // we need to initialize
4101 DBd.buffer[0] = '\0';
4104 l = strlen(DBd.buffer);
4105 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4108 if (DBd.count>= DB_ITEMS_PER_LINE)
4109 pic16_flushDB(ptype, p);
4112 void pic16_emitDS(char *s, char ptype, void *p)
4117 // we need to initialize
4120 DBd.buffer[0] = '\0';
4123 l = strlen(DBd.buffer);
4124 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4126 DBd.count++; //=strlen(s);
4128 pic16_flushDB(ptype, p);
4132 /*-----------------------------------------------------------------*/
4133 /*-----------------------------------------------------------------*/
4134 void pic16_pCodeConstString(char *name, char *value)
4138 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4143 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4145 pic16_addpBlock(pb);
4147 sprintf(buffer,"; %s = %s",name,value);
4149 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4150 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4153 pic16_emitDB(*value, 'p', (void *)pb);
4155 pic16_flushDB('p', (void *)pb);
4158 /*-----------------------------------------------------------------*/
4159 /*-----------------------------------------------------------------*/
4161 static void pCodeReadCodeTable(void)
4165 fprintf(stderr, " %s\n",__FUNCTION__);
4167 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4169 pic16_addpBlock(pb);
4171 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4172 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4173 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4174 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4176 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4177 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4178 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4179 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4184 /*-----------------------------------------------------------------*/
4185 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4186 /*-----------------------------------------------------------------*/
4187 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4194 /* If this is the first pcode to be added to a block that
4195 * was initialized with a NULL pcode, then go ahead and
4196 * make this pcode the head and tail */
4197 pb->pcHead = pb->pcTail = pc;
4200 pb->pcTail->next = pc;
4202 pc->prev = pb->pcTail;
4209 /*-----------------------------------------------------------------*/
4210 /* pic16_addpBlock - place a pBlock into the pFile */
4211 /*-----------------------------------------------------------------*/
4212 void pic16_addpBlock(pBlock *pb)
4214 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4217 /* First time called, we'll pass through here. */
4218 //_ALLOC(the_pFile,sizeof(pFile));
4219 the_pFile = Safe_calloc(1,sizeof(pFile));
4220 the_pFile->pbHead = the_pFile->pbTail = pb;
4221 the_pFile->functions = NULL;
4225 the_pFile->pbTail->next = pb;
4226 pb->prev = the_pFile->pbTail;
4228 the_pFile->pbTail = pb;
4231 /*-----------------------------------------------------------------*/
4232 /* removepBlock - remove a pBlock from the pFile */
4233 /*-----------------------------------------------------------------*/
4234 static void removepBlock(pBlock *pb)
4242 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4244 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4247 if(pbs == the_pFile->pbHead)
4248 the_pFile->pbHead = pbs->next;
4250 if (pbs == the_pFile->pbTail)
4251 the_pFile->pbTail = pbs->prev;
4254 pbs->next->prev = pbs->prev;
4257 pbs->prev->next = pbs->next;
4264 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4268 /*-----------------------------------------------------------------*/
4269 /* printpCode - write the contents of a pCode to a file */
4270 /*-----------------------------------------------------------------*/
4271 static void printpCode(FILE *of, pCode *pc)
4282 fprintf(of,"warning - unable to print pCode\n");
4285 /*-----------------------------------------------------------------*/
4286 /* pic16_printpBlock - write the contents of a pBlock to a file */
4287 /*-----------------------------------------------------------------*/
4288 void pic16_printpBlock(FILE *of, pBlock *pb)
4296 for(pc = pb->pcHead; pc; pc = pc->next) {
4297 if(isPCF(pc) && PCF(pc)->fname) {
4298 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4299 if(pb->dbName == 'A') {
4301 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4302 if(!strcmp(ab->name, PCF(pc)->fname)) {
4303 fprintf(of, "\t0X%06X", ab->address);
4314 /*-----------------------------------------------------------------*/
4316 /* pCode processing */
4320 /*-----------------------------------------------------------------*/
4322 void pic16_unlinkpCode(pCode *pc)
4328 fprintf(stderr,"Unlinking: ");
4329 printpCode(stderr, pc);
4332 pc->prev->next = pc->next;
4334 pc->next->prev = pc->prev;
4336 pc->prev = pc->next = NULL;
4340 /*-----------------------------------------------------------------*/
4341 /*-----------------------------------------------------------------*/
4343 static void genericDestruct(pCode *pc)
4346 pic16_unlinkpCode(pc);
4349 /* For instructions, tell the register (if there's one used)
4350 * that it's no longer needed */
4351 regs *reg = pic16_getRegFromInstruction(pc);
4353 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4355 if(PCI(pc)->is2MemOp) {
4356 reg = pic16_getRegFromInstruction2(pc);
4358 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4362 /* Instead of deleting the memory used by this pCode, mark
4363 * the object as bad so that if there's a pointer to this pCode
4364 * dangling around somewhere then (hopefully) when the type is
4365 * checked we'll catch it.
4370 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4378 /*-----------------------------------------------------------------*/
4379 /*-----------------------------------------------------------------*/
4380 /* modifiers for constant immediate */
4381 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4383 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4388 int use_buffer = 1; // copy the string to the passed buffer pointer
4393 use_buffer = 0; // Don't bother copying the string to the buffer.
4397 switch(pcop->type) {
4403 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4406 return PCOR(pcop)->r->name;
4409 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4411 SAFE_snprintf(&buffer,&size,"%s",r->name);
4418 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4419 if(PCOI(pcop)->index) {
4420 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4421 immdmod[ PCOI(pcop)->offset ],
4425 SAFE_snprintf(&s,&size,"%s(%s)",
4426 immdmod[ PCOI(pcop)->offset ],
4430 if(PCOI(pcop)->index) {
4431 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4436 SAFE_snprintf(&s,&size, "%s(%s)",
4445 // size = sizeof(buffer);
4446 if( PCOR(pcop)->instance) {
4447 SAFE_snprintf(&s,&size,"(%s + %d)",
4449 PCOR(pcop)->instance );
4451 SAFE_snprintf(&s,&size,"%s",pcop->name);
4458 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4467 return "NO operand1";
4470 /*-----------------------------------------------------------------*/
4471 /* pic16_get_op2 - variant to support two memory operand commands */
4472 /*-----------------------------------------------------------------*/
4473 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4478 int use_buffer = 1; // copy the string to the passed buffer pointer
4483 use_buffer = 0; // Don't bother copying the string to the buffer.
4487 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",
4488 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4489 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4493 switch(PCOR2(pcop)->pcop2->type) {
4499 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4502 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4505 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4508 SAFE_snprintf(&buffer,&size,"%s",r->name);
4519 if(PCOI(pcop)->_const) {
4520 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4521 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4524 8 * PCOI(pcop)->offset );
4526 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4528 if( PCOI(pcop)->index) {
4529 SAFE_snprintf(&s,&size,"(%s + %d)",
4531 PCOI(pcop)->index );
4533 if(PCOI(pcop)->offset)
4534 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4536 SAFE_snprintf(&s,&size,"%s",pcop->name);
4543 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4544 SAFE_snprintf(&s,&size,"(%s + %d)",
4545 PCOR(PCOR2(pcop)->pcop2)->r->name,
4546 PCOR(PCOR2(pcop)->pcop2)->instance );
4548 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4553 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4555 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4558 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4563 return "NO operand2";
4566 /*-----------------------------------------------------------------*/
4567 /*-----------------------------------------------------------------*/
4568 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4572 return pic16_get_op(pcc->pcop,NULL,0);
4574 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4575 * return ("ERROR Null: "__FUNCTION__);
4577 return ("ERROR Null: pic16_get_op_from_instruction");
4581 /*-----------------------------------------------------------------*/
4582 /*-----------------------------------------------------------------*/
4583 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4586 fprintf(of,"pcodeopprint- not implemented\n");
4589 /*-----------------------------------------------------------------*/
4590 /* pic16_pCode2str - convert a pCode instruction to string */
4591 /*-----------------------------------------------------------------*/
4592 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4598 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4599 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4600 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4608 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4610 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4612 if(PCI(pc)->is2MemOp) {
4613 SAFE_snprintf(&s,&size, "%s, %s",
4614 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4615 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4619 if(PCI(pc)->is2LitOp) {
4620 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4624 if(PCI(pc)->isBitInst) {
4625 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4626 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4627 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4628 PCI(pc)->pcop->name ,
4629 PCI(pc)->pcop->name );
4631 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4632 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4633 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4634 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4636 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4637 //PCI(pc)->pcop->t.bit );
4640 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4641 if( PCI(pc)->num_ops == 3)
4642 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4644 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4647 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4649 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4650 if(PCI(pc)->num_ops == 3)
4651 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4653 r = pic16_getRegFromInstruction(pc);
4654 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4655 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4657 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4666 /* assuming that comment ends with a \n */
4667 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4671 /* assuming that inline code ends with a \n */
4672 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4676 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4679 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4682 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4685 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4688 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4689 SAFE_snprintf(&s,&size,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4692 if(PCAD(pc)->directive) {
4693 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4696 /* special case to handle inline labels without a tab */
4697 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4702 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4709 /*-----------------------------------------------------------------*/
4710 /* genericPrint - the contents of a pCode to a file */
4711 /*-----------------------------------------------------------------*/
4712 static void genericPrint(FILE *of, pCode *pc)
4720 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4724 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4728 // If the opcode has a label, print that first
4730 pBranch *pbl = PCI(pc)->label;
4731 while(pbl && pbl->pc) {
4732 if(pbl->pc->type == PC_LABEL)
4733 pCodePrintLabel(of, pbl->pc);
4739 genericPrint(of,PCODE(PCI(pc)->cline));
4744 pic16_pCode2str(str, 256, pc);
4746 fprintf(of,"%s",str);
4748 if(pic16_debug_verbose) {
4749 fprintf(of, "\t;key=%03x",pc->seq);
4751 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4758 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4759 if(PCW(pc)->pci.label)
4760 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4762 if(PCW(pc)->operand) {
4763 fprintf(of,";\toperand ");
4764 pCodeOpPrint(of,PCW(pc)->operand );
4769 if(pic16_debug_verbose) {
4770 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4771 if(PCFL(pc)->ancestor)
4772 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4779 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4780 fprintf(of,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4786 pBranch *pbl = PCAD(pc)->pci.label;
4787 while(pbl && pbl->pc) {
4788 if(pbl->pc->type == PC_LABEL)
4789 pCodePrintLabel(of, pbl->pc);
4793 if(PCAD(pc)->directive) {
4794 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4797 /* special case to handle inline labels without tab */
4798 fprintf(of, "%s\n", PCAD(pc)->arg);
4804 fprintf(of,"unknown pCode type %d\n",pc->type);
4809 /*-----------------------------------------------------------------*/
4810 /* pCodePrintFunction - prints function begin/end */
4811 /*-----------------------------------------------------------------*/
4813 static void pCodePrintFunction(FILE *of, pCode *pc)
4820 if( ((pCodeFunction *)pc)->modname)
4821 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4824 if(!PCF(pc)->absblock) {
4825 if(PCF(pc)->fname) {
4826 pBranch *exits = PCF(pc)->to;
4829 fprintf(of,"%s:", PCF(pc)->fname);
4831 if(pic16_pcode_verbose)
4832 fprintf(of, "\t;Function start");
4838 exits = exits->next;
4842 if(pic16_pcode_verbose)
4843 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4846 if((PCF(pc)->from &&
4847 PCF(pc)->from->pc->type == PC_FUNCTION &&
4848 PCF(PCF(pc)->from->pc)->fname) ) {
4850 if(pic16_pcode_verbose)
4851 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4853 if(pic16_pcode_verbose)
4854 fprintf(of,"; exit point [can't find entry point]\n");
4860 /*-----------------------------------------------------------------*/
4861 /* pCodePrintLabel - prints label */
4862 /*-----------------------------------------------------------------*/
4864 static void pCodePrintLabel(FILE *of, pCode *pc)
4871 fprintf(of,"%s:\n",PCL(pc)->label);
4872 else if (PCL(pc)->key >=0)
4873 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4875 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4878 /*-----------------------------------------------------------------*/
4879 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4880 /* remove it if it is found. */
4881 /*-----------------------------------------------------------------*/
4882 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4889 if(pcl->type == PC_OPCODE)
4890 b = PCI(pcl)->label;
4892 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4897 //fprintf (stderr, "%s \n",__FUNCTION__);
4898 //pcl->print(stderr,pcl);
4899 //pc->print(stderr,pc);
4902 //fprintf (stderr, "found label\n");
4903 //pc->print(stderr, pc);
4907 bprev->next = b->next; /* Not first pCode in chain */
4911 PCI(pcl)->label = b->next; /* First pCode in chain */
4914 return; /* A label can't occur more than once */
4922 /*-----------------------------------------------------------------*/
4923 /*-----------------------------------------------------------------*/
4924 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4943 /*-----------------------------------------------------------------*/
4944 /* pBranchLink - given two pcodes, this function will link them */
4945 /* together through their pBranches */
4946 /*-----------------------------------------------------------------*/
4947 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4951 // Declare a new branch object for the 'from' pCode.
4953 //_ALLOC(b,sizeof(pBranch));
4954 b = Safe_calloc(1,sizeof(pBranch));
4955 b->pc = PCODE(t); // The link to the 'to' pCode.
4958 f->to = pic16_pBranchAppend(f->to,b);
4960 // Now do the same for the 'to' pCode.
4962 //_ALLOC(b,sizeof(pBranch));
4963 b = Safe_calloc(1,sizeof(pBranch));
4967 t->from = pic16_pBranchAppend(t->from,b);
4972 /*-----------------------------------------------------------------*/
4973 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4975 /*-----------------------------------------------------------------*/
4976 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4989 /*-----------------------------------------------------------------*/
4990 /* pCodeUnlink - Unlink the given pCode from its pCode chain. */
4991 /*-----------------------------------------------------------------*/
4992 static void pCodeUnlink(pCode *pc)
4997 if(!pc->prev || !pc->next) {
4998 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5002 /* first remove the pCode from the chain */
5003 pc->prev->next = pc->next;
5004 pc->next->prev = pc->prev;
5006 /* Now for the hard part... */
5008 /* Remove the branches */
5012 pc1 = pb1->pc; /* Get the pCode that branches to the
5013 * one we're unlinking */
5015 /* search for the link back to this pCode (the one we're
5017 if(pb2 = pBranchFind(pc1->to,pc)) {
5018 pb2->pc = pc->to->pc; // make the replacement
5020 /* if the pCode we're unlinking contains multiple 'to'
5021 * branches (e.g. this a skip instruction) then we need
5022 * to copy these extra branches to the chain. */
5024 pic16_pBranchAppend(pb2, pc->to->next);
5033 /*-----------------------------------------------------------------*/
5034 /*-----------------------------------------------------------------*/
5036 static void genericAnalyze(pCode *pc)
5046 // Go through the pCodes that are in pCode chain and link
5047 // them together through the pBranches. Note, the pCodes
5048 // are linked together as a contiguous stream like the
5049 // assembly source code lines. The linking here mimics this
5050 // except that comments are not linked in.
5052 pCode *npc = pc->next;
5054 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5055 pBranchLink(pc,npc);
5060 /* reached the end of the pcode chain without finding
5061 * an instruction we could link to. */
5065 fprintf(stderr,"analyze PC_FLOW\n");
5069 fprintf(stderr,,";A bad pCode is being used\n");
5075 /*-----------------------------------------------------------------*/
5076 /*-----------------------------------------------------------------*/
5077 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5081 if(pc->type == PC_LABEL) {
5082 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5085 if((pc->type == PC_OPCODE)
5086 || (pc->type == PC_ASMDIR)
5088 pbr = PCI(pc)->label;
5090 if(pbr->pc->type == PC_LABEL) {
5091 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5101 /*-----------------------------------------------------------------*/
5102 /*-----------------------------------------------------------------*/
5103 static int checkLabel(pCode *pc)
5107 if(pc && isPCI(pc)) {
5108 pbr = PCI(pc)->label;
5110 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5120 /*-----------------------------------------------------------------*/
5121 /* findLabelinpBlock - Search the pCode for a particular label */
5122 /*-----------------------------------------------------------------*/
5123 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5130 for(pc = pb->pcHead; pc; pc = pc->next)
5131 if(compareLabel(pc,pcop_label))
5137 /*-----------------------------------------------------------------*/
5138 /* findLabel - Search the pCode for a particular label */
5139 /*-----------------------------------------------------------------*/
5140 static pCode * findLabel(pCodeOpLabel *pcop_label)
5148 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5149 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5153 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5157 /*-----------------------------------------------------------------*/
5158 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5159 /* in the linked list */
5160 /*-----------------------------------------------------------------*/
5161 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5174 /*-----------------------------------------------------------------*/
5175 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5176 /* in the linked list */
5177 /*-----------------------------------------------------------------*/
5178 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5192 //#define PCODE_DEBUG
5193 /*-----------------------------------------------------------------*/
5194 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5195 /* in the linked list */
5196 /*-----------------------------------------------------------------*/
5197 pCode * pic16_findNextInstruction(pCode *pci)
5202 if((pc->type == PC_OPCODE)
5203 || (pc->type == PC_WILD)
5204 || (pc->type == PC_ASMDIR)
5209 fprintf(stderr,"pic16_findNextInstruction: ");
5210 printpCode(stderr, pc);
5215 //fprintf(stderr,"Couldn't find instruction\n");
5219 /*-----------------------------------------------------------------*/
5220 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5221 /* in the linked list */
5222 /*-----------------------------------------------------------------*/
5223 pCode * pic16_findPrevInstruction(pCode *pci)
5228 if((pc->type == PC_OPCODE)
5229 || (pc->type == PC_WILD)
5230 || (pc->type == PC_ASMDIR)
5236 fprintf(stderr,"pic16_findPrevInstruction: ");
5237 printpCode(stderr, pc);
5242 //fprintf(stderr,"Couldn't find instruction\n");
5249 /*-----------------------------------------------------------------*/
5250 /* findFunctionEnd - given a pCode find the end of the function */
5251 /* that contains it */
5252 /*-----------------------------------------------------------------*/
5253 static pCode * findFunctionEnd(pCode *pc)
5257 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5263 fprintf(stderr,"Couldn't find function end\n");
5268 /*-----------------------------------------------------------------*/
5269 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5270 /* instruction with which it is associated. */
5271 /*-----------------------------------------------------------------*/
5272 static void AnalyzeLabel(pCode *pc)
5281 static void AnalyzeGOTO(pCode *pc)
5284 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5288 static void AnalyzeSKIP(pCode *pc)
5291 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5292 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5296 static void AnalyzeRETURN(pCode *pc)
5299 // branch_link(pc,findFunctionEnd(pc->next));
5305 /*-----------------------------------------------------------------*/
5306 /*-----------------------------------------------------------------*/
5307 regs * pic16_getRegFromInstruction(pCode *pc)
5313 PCI(pc)->num_ops == 0 ||
5314 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5318 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5319 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5322 switch(PCI(pc)->pcop->type) {
5328 return PCOR(PCI(pc)->pcop)->r;
5330 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5334 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5335 return PCOR(PCI(pc)->pcop)->r;
5338 if(PCOI(PCI(pc)->pcop)->r)
5339 return (PCOI(PCI(pc)->pcop)->r);
5341 //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
5342 return pic16_dirregWithName(PCI(pc)->pcop->name);
5343 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5346 return PCOR(PCI(pc)->pcop)->r;
5349 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5350 return PCOR(PCI(pc)->pcop)->r;
5352 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5356 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5357 // genericPrint(stderr, pc);
5365 /*-------------------------------------------------------------------------------*/
5366 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5367 /*-------------------------------------------------------------------------------*/
5368 regs * pic16_getRegFromInstruction2(pCode *pc)
5374 PCI(pc)->num_ops == 0 ||
5375 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5380 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5381 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5385 * operands supported in MOVFF:
5392 switch(PCI(pc)->pcop->type) {
5398 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5400 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5404 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5405 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5410 // if(PCOI(PCI(pc)->pcop)->r)
5411 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5413 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5414 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5415 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5420 // return PCOR2(PCI(pc)->pcop)->r;
5423 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5424 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5428 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5431 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5432 //genericPrint(stderr, pc);
5440 /*-----------------------------------------------------------------*/
5441 /*-----------------------------------------------------------------*/
5443 static void AnalyzepBlock(pBlock *pb)
5450 /* Find all of the registers used in this pBlock
5451 * by looking at each instruction and examining it's
5454 for(pc = pb->pcHead; pc; pc = pc->next) {
5456 /* Is this an instruction with operands? */
5457 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5459 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5461 /* Loop through all of the registers declared so far in
5462 this block and see if we find this one there */
5464 regs *r = setFirstItem(pb->tregisters);
5467 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5468 PCOR(PCI(pc)->pcop)->r = r;
5471 r = setNextItem(pb->tregisters);
5475 /* register wasn't found */
5476 //r = Safe_calloc(1, sizeof(regs));
5477 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5478 //addSet(&pb->tregisters, r);
5479 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5480 //PCOR(PCI(pc)->pcop)->r = r;
5481 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5483 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5486 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5487 if(PCOR(PCI(pc)->pcop)->r) {
5488 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5489 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5491 if(PCI(pc)->pcop->name)
5492 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5494 fprintf(stderr,"ERROR: NULL register\n");
5503 /*-----------------------------------------------------------------*/
5505 /*-----------------------------------------------------------------*/
5506 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5508 static void InsertpFlow(pCode *pc, pCode **pflow)
5511 PCFL(*pflow)->end = pc;
5513 if(!pc || !pc->next)
5516 *pflow = pic16_newpCodeFlow();
5517 pic16_pCodeInsertAfter(pc, *pflow);
5520 /*-----------------------------------------------------------------*/
5521 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5522 /* the flow blocks. */
5524 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5525 * point the instruction flow changes.
5527 /*-----------------------------------------------------------------*/
5528 void pic16_BuildFlow(pBlock *pb)
5531 pCode *last_pci=NULL;
5538 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5539 /* Insert a pCodeFlow object at the beginning of a pBlock */
5541 InsertpFlow(pb->pcHead, &pflow);
5543 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5544 //pflow->next = pb->pcHead; /* Make the current head the next object */
5545 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5546 //pb->pcHead = pflow; /* Make the Flow object the head */
5549 for( pc = pic16_findNextInstruction(pb->pcHead);
5551 pc=pic16_findNextInstruction(pc)) {
5554 PCI(pc)->pcflow = PCFL(pflow);
5556 //fprintf(stderr," build: ");
5557 //pflow->print(stderr,pflow);
5559 if( PCI(pc)->isSkip) {
5561 /* The two instructions immediately following this one
5562 * mark the beginning of a new flow segment */
5564 while(pc && PCI(pc)->isSkip) {
5566 PCI(pc)->pcflow = PCFL(pflow);
5570 InsertpFlow(pc, &pflow);
5571 pc=pic16_findNextInstruction(pc->next);
5579 PCI(pc)->pcflow = PCFL(pflow);
5581 InsertpFlow(pc, &pflow);
5583 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5585 InsertpFlow(pc, &pflow);
5588 } else if (checkLabel(pc)) {
5590 /* This instruction marks the beginning of a
5591 * new flow segment */
5596 /* If the previous pCode is not a flow object, then
5597 * insert a new flow object. (This check prevents
5598 * two consecutive flow objects from being insert in
5599 * the case where a skip instruction preceeds an
5600 * instruction containing a label.) */
5602 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5603 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5605 PCI(pc)->pcflow = PCFL(pflow);
5612 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5614 PCFL(pflow)->end = pb->pcTail;
5617 /*-------------------------------------------------------------------*/
5618 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5619 /* the flow blocks. */
5621 * unBuildFlow removes pCodeFlow objects from a pCode chain
5623 /*-----------------------------------------------------------------*/
5624 static void unBuildFlow(pBlock *pb)
5639 if(PCI(pc)->pcflow) {
5640 //free(PCI(pc)->pcflow);
5641 PCI(pc)->pcflow = NULL;
5644 } else if(isPCFL(pc) )
5653 /*-----------------------------------------------------------------*/
5654 /*-----------------------------------------------------------------*/
5655 static void dumpCond(int cond)
5658 static char *pcc_str[] = {
5673 int ncond = sizeof(pcc_str) / sizeof(char *);
5676 fprintf(stderr, "0x%04X\n",cond);
5678 for(i=0,j=1; i<ncond; i++, j<<=1)
5680 fprintf(stderr, " %s\n",pcc_str[i]);
5686 /*-----------------------------------------------------------------*/
5687 /*-----------------------------------------------------------------*/
5688 static void FlowStats(pCodeFlow *pcflow)
5696 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5698 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5701 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5706 fprintf(stderr, " FlowStats inCond: ");
5707 dumpCond(pcflow->inCond);
5708 fprintf(stderr, " FlowStats outCond: ");
5709 dumpCond(pcflow->outCond);
5713 /*-----------------------------------------------------------------*
5714 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5715 * if it affects the banking bits.
5717 * return: -1 == Banking bits are unaffected by this pCode.
5719 * return: > 0 == Banking bits are affected.
5721 * If the banking bits are affected, then the returned value describes
5722 * which bits are affected and how they're affected. The lower half
5723 * of the integer maps to the bits that are affected, the upper half
5724 * to whether they're set or cleared.
5726 *-----------------------------------------------------------------*/
5728 static int isBankInstruction(pCode *pc)
5736 if( PCI(pc)->op == POC_MOVLB ||
5737 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5738 bank = PCOL(pc)->lit;
5745 /*-----------------------------------------------------------------*/
5746 /*-----------------------------------------------------------------*/
5747 static void FillFlow(pCodeFlow *pcflow)
5756 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5758 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5761 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5768 isBankInstruction(pc);
5770 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5774 fprintf(stderr, " FillFlow - Bad end of flow\n");
5776 fprintf(stderr, " FillFlow - Ending flow with\n ");
5777 pc->print(stderr,pc);
5780 fprintf(stderr, " FillFlow inCond: ");
5781 dumpCond(pcflow->inCond);
5782 fprintf(stderr, " FillFlow outCond: ");
5783 dumpCond(pcflow->outCond);
5787 /*-----------------------------------------------------------------*/
5788 /*-----------------------------------------------------------------*/
5789 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5791 pCodeFlowLink *fromLink, *toLink;
5793 if(!from || !to || !to->pcflow || !from->pcflow)
5796 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5797 toLink = pic16_newpCodeFlowLink(to->pcflow);
5799 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5800 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5804 /*-----------------------------------------------------------------*
5805 * void LinkFlow(pBlock *pb)
5807 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5808 * non-branching segments. In LinkFlow, we determine the execution
5809 * order of these segments. For example, if one of the segments ends
5810 * with a skip, then we know that there are two possible flow segments
5811 * to which control may be passed.
5812 *-----------------------------------------------------------------*/
5813 static void LinkFlow(pBlock *pb)
5819 //fprintf(stderr,"linkflow \n");
5821 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5823 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5826 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5828 //fprintf(stderr," link: ");
5829 //pcflow->print(stderr,pcflow);
5831 //FillFlow(PCFL(pcflow));
5833 pc = PCFL(pcflow)->end;
5835 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5836 if(isPCI_SKIP(pc)) {
5837 //fprintf(stderr, "ends with skip\n");
5838 //pc->print(stderr,pc);
5839 pct=pic16_findNextInstruction(pc->next);
5840 LinkFlow_pCode(PCI(pc),PCI(pct));
5841 pct=pic16_findNextInstruction(pct->next);
5842 LinkFlow_pCode(PCI(pc),PCI(pct));
5846 if(isPCI_BRANCH(pc)) {
5847 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5849 //fprintf(stderr, "ends with branch\n ");
5850 //pc->print(stderr,pc);
5852 if(!(pcol && isPCOLAB(pcol))) {
5853 if((PCI(pc)->op != POC_RETLW)
5854 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5856 /* continue if label is '$' which assembler knows how to parse */
5857 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5859 if(pic16_pcode_verbose) {
5860 pc->print(stderr,pc);
5861 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5867 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5868 LinkFlow_pCode(PCI(pc),PCI(pct));
5870 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5871 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5873 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5879 //fprintf(stderr, "ends with non-branching instruction:\n");
5880 //pc->print(stderr,pc);
5882 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5888 //fprintf(stderr, "ends with unknown\n");
5889 //pc->print(stderr,pc);
5893 //fprintf(stderr, "ends with nothing: ERROR\n");
5897 /*-----------------------------------------------------------------*/
5898 /*-----------------------------------------------------------------*/
5900 /*-----------------------------------------------------------------*/
5901 /*-----------------------------------------------------------------*/
5902 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5908 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5911 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5921 /*-----------------------------------------------------------------*/
5922 /* insertBankSwitch - inserts a bank switch statement in the */
5923 /* assembly listing */
5925 /* position == 0: insert before */
5926 /* position == 1: insert after pc */
5927 /* position == 2: 0 previous was a skip instruction */
5928 /*-----------------------------------------------------------------*/
5929 static void insertBankSwitch(int position, pCode *pc)
5937 /* emit BANKSEL [symbol] */
5939 reg = pic16_getRegFromInstruction(pc);
5941 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5943 // position = 0; // position is always before (sanity check!)
5946 fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5947 pc->print(stderr, pc);
5952 /* insert the bank switch after this pc instruction */
5953 pCode *pcnext = pic16_findNextInstruction(pc);
5954 pic16_pCodeInsertAfter(pc, new_pc);
5955 if(pcnext)pc = pcnext;
5959 /* insert the bank switch BEFORE this pc instruction */
5960 pic16_pCodeInsertAfter(pc->prev, new_pc);
5965 /* Move the label, if there is one */
5967 if(PCI(pc)->label) {
5968 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5969 // __FILE__, __LINE__, pc, new_pc);
5970 PCAD(new_pc)->pci.label = PCI(pc)->label;
5971 PCI(pc)->label = NULL;
5974 // fprintf(stderr, "BankSwitch has been inserted\n");
5978 /*-----------------------------------------------------------------*/
5979 /*int compareBankFlow - compare the banking requirements between */
5981 /*-----------------------------------------------------------------*/
5982 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5985 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5988 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5991 if(pcflow->firstBank == -1)
5995 if(pcflowLink->pcflow->firstBank == -1) {
5996 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
5997 pcflowLink->pcflow->to :
5998 pcflowLink->pcflow->from);
5999 return compareBankFlow(pcflow, pctl, toORfrom);
6003 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6006 pcflowLink->bank_conflict++;
6007 pcflowLink->pcflow->FromConflicts++;
6008 pcflow->ToConflicts++;
6011 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6014 pcflowLink->bank_conflict++;
6015 pcflowLink->pcflow->ToConflicts++;
6016 pcflow->FromConflicts++;
6020 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6021 pcflowLink->pcflow->pc.seq,
6022 pcflowLink->pcflow->FromConflicts,
6023 pcflowLink->pcflow->ToConflicts);
6030 /*-----------------------------------------------------------------*/
6031 /*-----------------------------------------------------------------*/
6032 static void DumpFlow(pBlock *pb)
6036 pCodeFlowLink *pcfl;
6039 fprintf(stderr,"Dump flow \n");
6040 pb->pcHead->print(stderr, pb->pcHead);
6042 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6043 pcflow->print(stderr,pcflow);
6045 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6047 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6049 if(!isPCFL(pcflow)) {
6050 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6053 fprintf(stderr,"dumping: ");
6054 pcflow->print(stderr,pcflow);
6055 FlowStats(PCFL(pcflow));
6057 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6059 pc = PCODE(pcfl->pcflow);
6061 fprintf(stderr, " from seq %d:\n",pc->seq);
6063 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6064 pc->print(stderr,pc);
6069 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6071 pc = PCODE(pcfl->pcflow);
6073 fprintf(stderr, " to seq %d:\n",pc->seq);
6075 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6076 pc->print(stderr,pc);
6085 /*-----------------------------------------------------------------*/
6086 /*-----------------------------------------------------------------*/
6087 static int OptimizepBlock(pBlock *pb)
6092 if(!pb || !peepOptimizing)
6095 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6097 for(pc = pb->pcHead; pc; pc = pc->next)
6098 matches += pic16_pCodePeepMatchRule(pc);
6101 pc = pic16_findNextInstruction(pb->pcHead);
6109 if(pic16_pCodePeepMatchRule(pc)) {
6114 pc = pic16_findNextInstruction(pcprev->next);
6116 pc = pic16_findNextInstruction(pb->pcHead);
6118 pc = pic16_findNextInstruction(pc->next);
6122 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6127 /*-----------------------------------------------------------------*/
6128 /*-----------------------------------------------------------------*/
6129 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6133 for(pc = pcs; pc; pc = pc->next) {
6135 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6137 (PCI(pc)->pcop->type == PO_LABEL) &&
6138 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6146 /*-----------------------------------------------------------------*/
6147 /*-----------------------------------------------------------------*/
6148 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6155 (PCI(pc)->pcop->type == PO_LABEL)) {
6157 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6159 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6161 free(pcol->pcop.name);
6163 /* If the key is negative, then we (probably) have a label to
6164 * a function and the name is already defined */
6167 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6171 //sprintf(buffer,"_%05d_DS_",pcl->key);
6173 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6175 pcol->pcop.name = Safe_strdup(s);
6176 pcol->key = pcl->key;
6177 //pc->print(stderr,pc);
6184 /*-----------------------------------------------------------------*/
6185 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6186 /* pCode chain if they're not used. */
6187 /*-----------------------------------------------------------------*/
6188 static void pBlockRemoveUnusedLabels(pBlock *pb)
6190 pCode *pc; pCodeLabel *pcl;
6195 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6197 pBranch *pbr = PCI(pc)->label;
6198 if(pbr && pbr->next) {
6199 pCode *pcd = pb->pcHead;
6201 // fprintf(stderr, "multiple labels\n");
6202 // pc->print(stderr,pc);
6207 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6208 //fprintf(stderr,"Used by:\n");
6209 //pcd->print(stderr,pcd);
6211 exchangeLabels(PCL(pbr->pc),pcd);
6220 for(pc = pb->pcHead; pc; pc = pc->next) {
6222 if(isPCL(pc)) // pc->type == PC_LABEL)
6224 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6225 pcl = PCL(PCI(pc)->label->pc);
6228 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6230 /* This pCode is a label, so search the pBlock to see if anyone
6233 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6235 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6236 /* Couldn't find an instruction that refers to this label
6237 * So, unlink the pCode label from it's pCode chain
6238 * and destroy the label */
6239 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6241 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6242 if(pc->type == PC_LABEL) {
6243 pic16_unlinkpCode(pc);
6244 pCodeLabelDestruct(pc);
6246 unlinkpCodeFromBranch(pc, PCODE(pcl));
6247 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6258 /*-----------------------------------------------------------------*/
6259 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6260 /* chain and put them into pBranches that are */
6261 /* associated with the appropriate pCode */
6263 /*-----------------------------------------------------------------*/
6264 void pic16_pBlockMergeLabels(pBlock *pb)
6267 pCode *pc, *pcnext=NULL;
6272 /* First, Try to remove any unused labels */
6273 //pBlockRemoveUnusedLabels(pb);
6275 /* Now loop through the pBlock and merge the labels with the opcodes */
6278 // for(pc = pb->pcHead; pc; pc = pc->next) {
6281 pCode *pcn = pc->next;
6283 if(pc->type == PC_LABEL) {
6285 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6286 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6288 if((pcnext = pic16_findNextInstruction(pc) )) {
6290 // pcnext->print(stderr, pcnext);
6292 // Unlink the pCode label from it's pCode chain
6293 pic16_unlinkpCode(pc);
6295 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6296 // And link it into the instruction's pBranch labels. (Note, since
6297 // it's possible to have multiple labels associated with one instruction
6298 // we must provide a means to accomodate the additional labels. Thus
6299 // the labels are placed into the singly-linked list "label" as
6300 // opposed to being a single member of the pCodeInstruction.)
6302 //_ALLOC(pbr,sizeof(pBranch));
6304 pbr = Safe_calloc(1,sizeof(pBranch));
6308 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6311 if(pic16_pcode_verbose)
6312 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6314 } else if(pc->type == PC_CSOURCE) {
6316 /* merge the source line symbolic info into the next instruction */
6317 if((pcnext = pic16_findNextInstruction(pc) )) {
6319 // Unlink the pCode label from it's pCode chain
6320 pic16_unlinkpCode(pc);
6321 PCI(pcnext)->cline = PCCS(pc);
6322 //fprintf(stderr, "merging CSRC\n");
6323 //genericPrint(stderr,pcnext);
6329 pBlockRemoveUnusedLabels(pb);
6333 /*-----------------------------------------------------------------*/
6334 /*-----------------------------------------------------------------*/
6335 static int OptimizepCode(char dbName)
6337 #define MAX_PASSES 4
6346 DFPRINTF((stderr," Optimizing pCode\n"));
6350 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6351 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6352 matches += OptimizepBlock(pb);
6355 while(matches && ++passes < MAX_PASSES);
6360 /*-----------------------------------------------------------------*/
6361 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6362 /*-----------------------------------------------------------------*/
6364 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6368 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
6370 if( !( (pcop->type == PO_LABEL) ||
6371 (pcop->type == PO_LITERAL) ||
6372 (pcop->type == PO_STR) ))
6373 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6374 PCOR(pcop)->r->wasUsed = 1;
6380 /*----------------------------------------------------------------------*
6381 * pic16_areRegsSame - check to see if the names of two registers match *
6382 *----------------------------------------------------------------------*/
6383 int pic16_areRegsSame(regs *r1, regs *r2)
6385 if(!strcmp(r1->name, r2->name))return 1;
6391 /*-----------------------------------------------------------------*/
6392 /*-----------------------------------------------------------------*/
6393 static void pic16_FixRegisterBanking(pBlock *pb)
6397 regs *reg, *prevreg;
6402 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6406 /* loop through all of the flow blocks with in one pblock */
6408 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6412 /* at this point, pc should point to a PC_FLOW object */
6413 /* for each flow block, determine the register banking
6416 if(isPCI(pc) && !PCI(pc)->is2MemOp) {
6417 reg = pic16_getRegFromInstruction(pc);
6420 fprintf(stderr, "reg = %p\n", reg);
6422 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6423 fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
6424 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
6425 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
6429 /* we can be 99% that within a pBlock, between two consequtive
6430 * refernces to the same register, the extra banksel is needless */
6432 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
6434 && (PCI(pc)->op != POC_CALL)
6436 && ( ((pic16_options.opt_banksel>0)
6437 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
6438 || (!pic16_options.opt_banksel)
6442 /* Examine the instruction before this one to make sure it is
6443 * not a skip type instruction */
6444 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6446 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6447 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6448 if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
6450 if(!pic16_options.no_banksel)
6451 insertBankSwitch(0, pc);
6453 // if(pcprev && isPCI_SKIP(pcprev))assert(0);
6465 if(pcprev && cur_bank) {
6467 int pos = 1; /* Assume that the bank switch instruction(s)
6468 * are inserted after this instruction */
6470 if((PCI(pcprev)->op == POC_RETLW) ||
6471 (PCI(pcprev)->op == POC_RETURN) ||
6472 (PCI(pcprev)->op == POC_RETFIE)) {
6474 /* oops, a RETURN - we need to switch banks *before* the RETURN */
6480 /* Brute force - make sure that we point to bank 0 at the
6481 * end of each flow block */
6483 // insertBankSwitch(pos, pcprev, 0);
6485 new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6486 pic16_pCodeInsertAfter(pcprev, new_pc);
6489 //fprintf(stderr, "Brute force switch\n");
6496 static void pBlockDestruct(pBlock *pb)
6507 /*-----------------------------------------------------------------*/
6508 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6509 /* name dbName and combine them */
6510 /* into one block */
6511 /*-----------------------------------------------------------------*/
6512 static void mergepBlocks(char dbName)
6515 pBlock *pb, *pbmerged = NULL,*pbn;
6517 pb = the_pFile->pbHead;
6519 //fprintf(stderr," merging blocks named %c\n",dbName);
6523 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6524 if( getpBlock_dbName(pb) == dbName) {
6526 //fprintf(stderr," merged block %c\n",dbName);
6531 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6532 /* pic16_addpCode2pBlock doesn't handle the tail: */
6533 pbmerged->pcTail = pb->pcTail;
6535 pb->prev->next = pbn;
6537 pbn->prev = pb->prev;
6542 //pic16_printpBlock(stderr, pbmerged);
6549 /*-----------------------------------------------------------------*/
6550 /* AnalyzeFlow - Examine the flow of the code and optimize */
6552 /* level 0 == minimal optimization */
6553 /* optimize registers that are used only by two instructions */
6554 /* level 1 == maximal optimization */
6555 /* optimize by looking at pairs of instructions that use the */
6557 /*-----------------------------------------------------------------*/
6559 static void AnalyzeFlow(int level)
6561 static int times_called=0;
6566 /* remove unused allocated registers before exiting */
6567 pic16_RemoveUnusedRegisters();
6573 /* if this is not the first time this function has been called,
6574 then clean up old flow information */
6575 if(times_called++) {
6576 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6579 pic16_RegsUnMapLiveRanges();
6584 /* Phase 2 - Flow Analysis - Register Banking
6586 * In this phase, the individual flow blocks are examined
6587 * and register banking is fixed.
6591 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6592 pic16_FixRegisterBanking(pb);
6595 /* Phase 2 - Flow Analysis
6597 * In this phase, the pCode is partition into pCodeFlow
6598 * blocks. The flow blocks mark the points where a continuous
6599 * stream of instructions changes flow (e.g. because of
6600 * a call or goto or whatever).
6603 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6604 pic16_BuildFlow(pb);
6607 /* Phase 2 - Flow Analysis - linking flow blocks
6609 * In this phase, the individual flow blocks are examined
6610 * to determine their order of excution.
6613 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6616 /* Phase 3 - Flow Analysis - Flow Tree
6618 * In this phase, the individual flow blocks are examined
6619 * to determine their order of execution.
6622 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6623 pic16_BuildFlowTree(pb);
6626 /* Phase x - Flow Analysis - Used Banks
6628 * In this phase, the individual flow blocks are examined
6629 * to determine the Register Banks they use
6633 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6638 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6639 pic16_pCodeRegMapLiveRanges(pb);
6641 pic16_RemoveUnusedRegisters();
6643 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6644 pic16_pCodeRegOptimizeRegUsage(level);
6652 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6657 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6659 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6660 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6661 pcflow = pcflow->next) {
6663 FillFlow(PCFL(pcflow));
6668 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6671 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6672 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6673 pcflow = pcflow->next) {
6675 FlowStats(PCFL(pcflow));
6681 /* VR -- no need to analyze banking in flow, but left here :
6682 * 1. because it may be used in the future for other purposes
6683 * 2. because if omitted we'll miss some optimization done here
6685 * Perhaps I should rename it to something else
6688 /*-----------------------------------------------------------------*/
6689 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6690 /* assigned to the registers. */
6692 /*-----------------------------------------------------------------*/
6694 void pic16_AnalyzeBanking(void)
6698 if(!pic16_picIsInitialized()) {
6699 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6700 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6701 fprintf(stderr,"support/scripts/inc2h.pl\n");
6702 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6704 /* I think it took a long long time to fix this bug! ;-) -- VR */
6710 /* Phase x - Flow Analysis - Used Banks
6712 * In this phase, the individual flow blocks are examined
6713 * to determine the Register Banks they use
6719 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6720 // BanksUsedFlow(pb);
6722 if(!the_pFile)return;
6724 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6725 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6726 pic16_FixRegisterBanking(pb);
6731 /*-----------------------------------------------------------------*/
6732 /* buildCallTree - Look at the flow and extract all of the calls. */
6733 /*-----------------------------------------------------------------*/
6734 static set *register_usage(pBlock *pb);
6736 static void buildCallTree(void )
6747 /* Now build the call tree.
6748 First we examine all of the pCodes for functions.
6749 Keep in mind that the function boundaries coincide
6750 with pBlock boundaries.
6752 The algorithm goes something like this:
6753 We have two nested loops. The outer loop iterates
6754 through all of the pBlocks/functions. The inner
6755 loop iterates through all of the pCodes for
6756 a given pBlock. When we begin iterating through
6757 a pBlock, the variable pc_fstart, pCode of the start
6758 of a function, is cleared. We then search for pCodes
6759 of type PC_FUNCTION. When one is encountered, we
6760 initialize pc_fstart to this and at the same time
6761 associate a new pBranch object that signifies a
6762 branch entry. If a return is found, then this signifies
6763 a function exit point. We'll link the pCodes of these
6764 returns to the matching pc_fstart.
6766 When we're done, a doubly linked list of pBranches
6767 will exist. The head of this list is stored in
6768 `the_pFile', which is the meta structure for all
6769 of the pCode. Look at the pic16_printCallTree function
6770 on how the pBranches are linked together.
6773 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6774 pCode *pc_fstart=NULL;
6775 for(pc = pb->pcHead; pc; pc = pc->next) {
6777 if (PCF(pc)->fname) {
6779 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6780 //fprintf(stderr," found main \n");
6781 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6785 pbr = Safe_calloc(1,sizeof(pBranch));
6786 pbr->pc = pc_fstart = pc;
6789 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6791 // Here's a better way of doing the same:
6792 addSet(&pb->function_entries, pc);
6795 // Found an exit point in a function, e.g. return
6796 // (Note, there may be more than one return per function)
6798 pBranchLink(PCF(pc_fstart), PCF(pc));
6800 addSet(&pb->function_exits, pc);
6802 } else if(isCALL(pc)) {
6803 addSet(&pb->function_calls,pc);
6810 /* This is not needed because currently all register used
6811 * by a function are stored in stack -- VR */
6813 /* Re-allocate the registers so that there are no collisions
6814 * between local variables when one function call another */
6817 // pic16_deallocateAllRegs();
6819 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6827 /*-----------------------------------------------------------------*/
6828 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6829 /* all of the logical connections. */
6831 /* Essentially what's done here is that the pCode flow is */
6833 /*-----------------------------------------------------------------*/
6835 void pic16_AnalyzepCode(char dbName)
6846 /* Phase 1 - Register allocation and peep hole optimization
6848 * The first part of the analysis is to determine the registers
6849 * that are used in the pCode. Once that is done, the peep rules
6850 * are applied to the code. We continue to loop until no more
6851 * peep rule optimizations are found (or until we exceed the
6852 * MAX_PASSES threshold).
6854 * When done, the required registers will be determined.
6860 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6861 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6863 /* First, merge the labels with the instructions */
6864 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6865 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6867 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6868 //fprintf(stderr," analyze and merging block %c\n",dbName);
6869 pic16_pBlockMergeLabels(pb);
6872 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6877 changes = OptimizepCode(dbName);
6880 } while(changes && (i++ < MAX_PASSES));
6885 /*-----------------------------------------------------------------*/
6886 /* ispCodeFunction - returns true if *pc is the pCode of a */
6888 /*-----------------------------------------------------------------*/
6889 static bool ispCodeFunction(pCode *pc)
6892 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6898 /*-----------------------------------------------------------------*/
6899 /* findFunction - Search for a function by name (given the name) */
6900 /* in the set of all functions that are in a pBlock */
6901 /* (note - I expect this to change because I'm planning to limit */
6902 /* pBlock's to just one function declaration */
6903 /*-----------------------------------------------------------------*/
6904 static pCode *findFunction(char *fname)
6911 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6913 pc = setFirstItem(pb->function_entries);
6916 if((pc->type == PC_FUNCTION) &&
6918 (strcmp(fname, PCF(pc)->fname)==0))
6921 pc = setNextItem(pb->function_entries);
6929 static void MarkUsedRegisters(set *regset)
6934 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6935 // fprintf(stderr, "marking register = %s\t", r1->name);
6936 r2 = pic16_regWithIdx(r1->rIdx);
6937 // fprintf(stderr, "to register = %s\n", r2->name);
6943 static void pBlockStats(FILE *of, pBlock *pb)
6949 if(!pic16_pcode_verbose)return;
6951 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6953 // for now just print the first element of each set
6954 pc = setFirstItem(pb->function_entries);
6956 fprintf(of,";entry: ");
6959 pc = setFirstItem(pb->function_exits);
6961 fprintf(of,";has an exit\n");
6965 pc = setFirstItem(pb->function_calls);
6967 fprintf(of,";functions called:\n");
6970 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6971 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
6973 pc = setNextItem(pb->function_calls);
6977 r = setFirstItem(pb->tregisters);
6979 int n = elementsInSet(pb->tregisters);
6981 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6984 fprintf(of,"; %s\n",r->name);
6985 r = setNextItem(pb->tregisters);
6990 /*-----------------------------------------------------------------*/
6991 /*-----------------------------------------------------------------*/
6993 static void sequencepCode(void)
6999 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7001 pb->seq = GpCodeSequenceNumber+1;
7003 for( pc = pb->pcHead; pc; pc = pc->next)
7004 pc->seq = ++GpCodeSequenceNumber;
7010 /*-----------------------------------------------------------------*/
7011 /*-----------------------------------------------------------------*/
7012 static set *register_usage(pBlock *pb)
7015 set *registers=NULL;
7016 set *registersInCallPath = NULL;
7018 /* check recursion */
7020 pc = setFirstItem(pb->function_entries);
7027 if(pc->type != PC_FUNCTION)
7028 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7030 pc = setFirstItem(pb->function_calls);
7031 for( ; pc; pc = setNextItem(pb->function_calls)) {
7033 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7034 char *dest = pic16_get_op_from_instruction(PCI(pc));
7036 pcn = findFunction(dest);
7038 registersInCallPath = register_usage(pcn->pb);
7040 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7045 pBlockStats(stderr,pb); // debug
7048 // Mark the registers in this block as used.
7050 MarkUsedRegisters(pb->tregisters);
7051 if(registersInCallPath) {
7052 /* registers were used in the functions this pBlock has called */
7053 /* so now, we need to see if these collide with the ones we are */
7056 regs *r1,*r2, *newreg;
7058 DFPRINTF((stderr,"comparing registers\n"));
7060 r1 = setFirstItem(registersInCallPath);
7063 r2 = setFirstItem(pb->tregisters);
7065 while(r2 && (r1->type != REG_STK)) {
7067 if(r2->rIdx == r1->rIdx) {
7068 newreg = pic16_findFreeReg(REG_GPR);
7072 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7076 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7077 r1->rIdx, newreg->rIdx));
7078 r2->rIdx = newreg->rIdx;
7079 //if(r2->name) free(r2->name);
7081 r2->name = Safe_strdup(newreg->name);
7085 newreg->wasUsed = 1;
7087 r2 = setNextItem(pb->tregisters);
7090 r1 = setNextItem(registersInCallPath);
7093 /* Collisions have been resolved. Now free the registers in the call path */
7094 r1 = setFirstItem(registersInCallPath);
7096 if(r1->type != REG_STK) {
7097 newreg = pic16_regWithIdx(r1->rIdx);
7100 r1 = setNextItem(registersInCallPath);
7104 // MarkUsedRegisters(pb->registers);
7106 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7109 DFPRINTF((stderr,"returning regs\n"));
7111 DFPRINTF((stderr,"not returning regs\n"));
7113 DFPRINTF((stderr,"pBlock after register optim.\n"));
7114 pBlockStats(stderr,pb); // debug
7120 /*-----------------------------------------------------------------*/
7121 /* pct2 - writes the call tree to a file */
7123 /*-----------------------------------------------------------------*/
7124 static void pct2(FILE *of,pBlock *pb,int indent)
7128 // set *registersInCallPath = NULL;
7134 return; //recursion ?
7136 pc = setFirstItem(pb->function_entries);
7143 for(i=0;i<indent;i++) // Indentation
7146 if(pc->type == PC_FUNCTION)
7147 fprintf(of,"%s\n",PCF(pc)->fname);
7152 pc = setFirstItem(pb->function_calls);
7153 for( ; pc; pc = setNextItem(pb->function_calls)) {
7155 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7156 char *dest = pic16_get_op_from_instruction(PCI(pc));
7158 pcn = findFunction(dest);
7160 pct2(of,pcn->pb,indent+1);
7162 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7170 /*-----------------------------------------------------------------*/
7171 /* pic16_printCallTree - writes the call tree to a file */
7173 /*-----------------------------------------------------------------*/
7175 void pic16_printCallTree(FILE *of)
7187 fprintf(of, "\npBlock statistics\n");
7188 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7193 fprintf(of,"Call Tree\n");
7194 pbr = the_pFile->functions;
7198 if(!ispCodeFunction(pc))
7199 fprintf(of,"bug in call tree");
7202 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7204 while(pc->next && !ispCodeFunction(pc->next)) {
7206 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7207 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7215 fprintf(of,"\n**************\n\na better call tree\n");
7216 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7221 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7222 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7228 /*-----------------------------------------------------------------*/
7230 /*-----------------------------------------------------------------*/
7232 static void InlineFunction(pBlock *pb)
7240 pc = setFirstItem(pb->function_calls);
7242 for( ; pc; pc = setNextItem(pb->function_calls)) {
7245 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7251 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7253 //fprintf(stderr,"Cool can inline:\n");
7254 //pcn->print(stderr,pcn);
7256 //fprintf(stderr,"recursive call Inline\n");
7257 InlineFunction(pcn->pb);
7258 //fprintf(stderr,"return from recursive call Inline\n");
7261 At this point, *pc points to a CALL mnemonic, and
7262 *pcn points to the function that is being called.
7264 To in-line this call, we need to remove the CALL
7265 and RETURN(s), and link the function pCode in with
7271 /* Remove the CALL */
7275 /* remove callee pBlock from the pBlock linked list */
7276 removepBlock(pcn->pb);
7284 /* Remove the Function pCode */
7285 pct = pic16_findNextInstruction(pcn->next);
7287 /* Link the function with the callee */
7288 pc->next = pcn->next;
7289 pcn->next->prev = pc;
7291 /* Convert the function name into a label */
7293 pbr = Safe_calloc(1,sizeof(pBranch));
7294 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7296 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7297 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7299 /* turn all of the return's except the last into goto's */
7300 /* check case for 2 instruction pBlocks */
7301 pce = pic16_findNextInstruction(pcn->next);
7303 pCode *pce_next = pic16_findNextInstruction(pce->next);
7305 if(pce_next == NULL) {
7306 /* found the last return */
7307 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7309 //fprintf(stderr,"found last return\n");
7310 //pce->print(stderr,pce);
7311 pce->prev->next = pc_call->next;
7312 pc_call->next->prev = pce->prev;
7313 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7323 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7329 /*-----------------------------------------------------------------*/
7331 /*-----------------------------------------------------------------*/
7333 void pic16_InlinepCode(void)
7342 if(!functionInlining)
7345 /* Loop through all of the function definitions and count the
7346 * number of times each one is called */
7347 //fprintf(stderr,"inlining %d\n",__LINE__);
7349 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7351 pc = setFirstItem(pb->function_calls);
7353 for( ; pc; pc = setNextItem(pb->function_calls)) {
7356 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7357 if(pcn && isPCF(pcn)) {
7358 PCF(pcn)->ncalled++;
7361 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7366 //fprintf(stderr,"inlining %d\n",__LINE__);
7368 /* Now, Loop through the function definitions again, but this
7369 * time inline those functions that have only been called once. */
7371 InlineFunction(the_pFile->pbHead);
7372 //fprintf(stderr,"inlining %d\n",__LINE__);
7374 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7379 char *pic_optype_names[]={
7380 "PO_NONE", // No operand e.g. NOP
7381 "PO_W", // The working register (as a destination)
7382 "PO_WREG", // The working register (as a file register)
7383 "PO_STATUS", // The 'STATUS' register
7384 "PO_BSR", // The 'BSR' register
7385 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7387 "PO_INDF0", // The Indirect register
7388 "PO_INTCON", // Interrupt Control register
7389 "PO_GPR_REGISTER", // A general purpose register
7390 "PO_GPR_BIT", // A bit of a general purpose register
7391 "PO_GPR_TEMP", // A general purpose temporary register
7392 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7393 "PO_PCL", // Program counter Low register
7394 "PO_PCLATH", // Program counter Latch high register
7395 "PO_PCLATU", // Program counter Latch upper register
7396 "PO_PRODL", // Product Register Low
7397 "PO_PRODH", // Product Register High
7398 "PO_LITERAL", // A constant
7399 "PO_REL_ADDR", // A relative address
7400 "PO_IMMEDIATE", // (8051 legacy)
7401 "PO_DIR", // Direct memory (8051 legacy)
7402 "PO_CRY", // bit memory (8051 legacy)
7403 "PO_BIT", // bit operand.
7404 "PO_STR", // (8051 legacy)
7406 "PO_WILD" // Wild card operand in peep optimizer
7410 char *dumpPicOptype(PIC_OPTYPE type)
7412 return (pic_optype_names[ type ]);