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 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
116 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
119 static int mnemonics_initialized = 0;
122 static hTab *pic16MnemonicsHash = NULL;
123 static hTab *pic16pCodePeepCommandsHash = NULL;
125 static pFile *the_pFile = NULL;
126 static pBlock *pb_dead_pcodes = NULL;
128 /* Hardcoded flags to change the behavior of the PIC port */
129 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
130 static int functionInlining = 1; /* inline functions if nonzero */
131 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
133 int pic16_pcode_verbose = 0;
135 //static int GpCodeSequenceNumber = 1;
136 static int GpcFlowSeq = 1;
138 extern void pic16_RemoveUnusedRegisters(void);
139 extern void pic16_RegsUnMapLiveRanges(void);
140 extern void pic16_BuildFlowTree(pBlock *pb);
141 extern void pic16_pCodeRegOptimizeRegUsage(int level);
142 extern int pic16_picIsInitialized(void);
143 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
144 extern int mnem2key(char const *mnem);
146 /****************************************************************/
147 /* Forward declarations */
148 /****************************************************************/
150 void pic16_unlinkpCode(pCode *pc);
152 static void genericAnalyze(pCode *pc);
153 static void AnalyzeGOTO(pCode *pc);
154 static void AnalyzeSKIP(pCode *pc);
155 static void AnalyzeRETURN(pCode *pc);
158 static void genericDestruct(pCode *pc);
159 static void genericPrint(FILE *of,pCode *pc);
161 static void pCodePrintLabel(FILE *of, pCode *pc);
162 static void pCodePrintFunction(FILE *of, pCode *pc);
163 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
164 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
165 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
166 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
167 int pic16_pCodePeepMatchRule(pCode *pc);
168 static void pBlockStats(FILE *of, pBlock *pb);
169 static pBlock *newpBlock(void);
170 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
171 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
172 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
173 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
175 char *dumpPicOptype(PIC_OPTYPE type);
177 /****************************************************************/
178 /* PIC Instructions */
179 /****************************************************************/
181 pCodeInstruction pic16_pciADDWF = {
182 {PC_OPCODE, NULL, NULL, 0, NULL,
195 1,0, // dest, bit instruction
197 0, // literal operand
199 0, // fast call/return mode select bit
200 0, // second memory operand
201 0, // second literal operand
203 (PCC_W | PCC_REGISTER), // inCond
204 (PCC_REGISTER | PCC_Z), // outCond
208 pCodeInstruction pic16_pciADDFW = {
209 {PC_OPCODE, NULL, NULL, 0, NULL,
222 0,0, // dest, bit instruction
224 0, // literal operand
226 0, // fast call/return mode select bit
227 0, // second memory operand
228 0, // second literal operand
230 (PCC_W | PCC_REGISTER), // inCond
231 (PCC_W | PCC_Z), // outCond
235 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
236 {PC_OPCODE, NULL, NULL, 0, NULL,
249 1,0, // dest, bit instruction
251 0, // literal operand
253 0, // fast call/return mode select bit
254 0, // second memory operand
255 0, // second literal operand
257 (PCC_W | PCC_REGISTER | PCC_C), // inCond
258 (PCC_REGISTER | PCC_Z), // outCond
262 pCodeInstruction pic16_pciADDFWC = {
263 {PC_OPCODE, NULL, NULL, 0, NULL,
276 0,0, // dest, bit instruction
278 0, // literal operand
280 0, // fast call/return mode select bit
281 0, // second memory operand
282 0, // second literal operand
284 (PCC_W | PCC_REGISTER | PCC_C), // inCond
285 (PCC_W | PCC_Z), // outCond
289 pCodeInstruction pic16_pciADDLW = {
290 {PC_OPCODE, NULL, NULL, 0, NULL,
303 0,0, // dest, bit instruction
305 1, // literal operand
307 0, // fast call/return mode select bit
308 0, // second memory operand
309 0, // second literal operand
311 (PCC_W | PCC_LITERAL), // inCond
312 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
316 pCodeInstruction pic16_pciANDLW = {
317 {PC_OPCODE, NULL, NULL, 0, NULL,
330 0,0, // dest, bit instruction
332 1, // literal operand
334 0, // fast call/return mode select bit
335 0, // second memory operand
336 0, // second literal operand
338 (PCC_W | PCC_LITERAL), // inCond
339 (PCC_W | PCC_Z | PCC_N), // outCond
343 pCodeInstruction pic16_pciANDWF = {
344 {PC_OPCODE, NULL, NULL, 0, NULL,
357 1,0, // dest, bit instruction
359 0, // literal operand
361 0, // fast call/return mode select bit
362 0, // second memory operand
363 0, // second literal operand
365 (PCC_W | PCC_REGISTER), // inCond
366 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
370 pCodeInstruction pic16_pciANDFW = {
371 {PC_OPCODE, NULL, NULL, 0, NULL,
384 0,0, // dest, bit instruction
386 0, // literal operand
388 0, // fast call/return mode select bit
389 0, // second memory operand
390 0, // second literal operand
392 (PCC_W | PCC_REGISTER), // inCond
393 (PCC_W | PCC_Z) // outCond
396 pCodeInstruction pic16_pciBC = { // mdubuc - New
397 {PC_OPCODE, NULL, NULL, 0, NULL,
410 0,0, // dest, bit instruction
412 0, // literal operand
414 0, // fast call/return mode select bit
415 0, // second memory operand
416 0, // second literal operand
418 (PCC_REL_ADDR | PCC_C), // inCond
423 pCodeInstruction pic16_pciBCF = {
424 {PC_OPCODE, NULL, NULL, 0, NULL,
437 1,1, // dest, bit instruction
439 0, // literal operand
441 0, // fast call/return mode select bit
442 0, // second memory operand
443 0, // second literal operand
445 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
446 PCC_REGISTER, // outCond
450 pCodeInstruction pic16_pciBN = { // mdubuc - New
451 {PC_OPCODE, NULL, NULL, 0, NULL,
464 0,0, // dest, bit instruction
466 0, // literal operand
468 0, // fast call/return mode select bit
469 0, // second memory operand
470 0, // second literal operand
472 (PCC_REL_ADDR | PCC_N), // inCond
473 PCC_NONE , // outCond
477 pCodeInstruction pic16_pciBNC = { // mdubuc - New
478 {PC_OPCODE, NULL, NULL, 0, NULL,
491 0,0, // dest, bit instruction
493 0, // literal operand
495 0, // fast call/return mode select bit
496 0, // second memory operand
497 0, // second literal operand
499 (PCC_REL_ADDR | PCC_C), // inCond
500 PCC_NONE , // outCond
504 pCodeInstruction pic16_pciBNN = { // mdubuc - New
505 {PC_OPCODE, NULL, NULL, 0, NULL,
518 0,0, // dest, bit instruction
520 0, // literal operand
522 0, // fast call/return mode select bit
523 0, // second memory operand
524 0, // second literal operand
526 (PCC_REL_ADDR | PCC_N), // inCond
527 PCC_NONE , // outCond
531 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
532 {PC_OPCODE, NULL, NULL, 0, NULL,
545 0,0, // dest, bit instruction
547 0, // literal operand
549 0, // fast call/return mode select bit
550 0, // second memory operand
551 0, // second literal operand
553 (PCC_REL_ADDR | PCC_OV), // inCond
554 PCC_NONE , // outCond
558 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
559 {PC_OPCODE, NULL, NULL, 0, NULL,
572 0,0, // dest, bit instruction
574 0, // literal operand
576 0, // fast call/return mode select bit
577 0, // second memory operand
578 0, // second literal operand
580 (PCC_REL_ADDR | PCC_Z), // inCond
581 PCC_NONE , // outCond
585 pCodeInstruction pic16_pciBOV = { // mdubuc - New
586 {PC_OPCODE, NULL, NULL, 0, NULL,
599 0,0, // dest, bit instruction
601 0, // literal operand
603 0, // fast call/return mode select bit
604 0, // second memory operand
605 0, // second literal operand
607 (PCC_REL_ADDR | PCC_OV), // inCond
608 PCC_NONE , // outCond
612 pCodeInstruction pic16_pciBRA = { // mdubuc - New
613 {PC_OPCODE, NULL, NULL, 0, NULL,
626 0,0, // dest, bit instruction
628 0, // literal operand
630 0, // fast call/return mode select bit
631 0, // second memory operand
632 0, // second literal operand
634 PCC_REL_ADDR, // inCond
635 PCC_NONE , // outCond
639 pCodeInstruction pic16_pciBSF = {
640 {PC_OPCODE, NULL, NULL, 0, NULL,
653 1,1, // dest, bit instruction
655 0, // literal operand
657 0, // fast call/return mode select bit
658 0, // second memory operand
659 0, // second literal operand
661 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
662 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
666 pCodeInstruction pic16_pciBTFSC = {
667 {PC_OPCODE, NULL, NULL, 0, NULL,
680 0,1, // dest, bit instruction
682 0, // literal operand
684 0, // fast call/return mode select bit
685 0, // second memory operand
686 0, // second literal operand
688 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
689 PCC_EXAMINE_PCOP, // outCond
693 pCodeInstruction pic16_pciBTFSS = {
694 {PC_OPCODE, NULL, NULL, 0, NULL,
707 0,1, // dest, bit instruction
709 0, // literal operand
711 0, // fast call/return mode select bit
712 0, // second memory operand
713 0, // second literal operand
715 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
716 PCC_EXAMINE_PCOP, // outCond
720 pCodeInstruction pic16_pciBTG = { // mdubuc - New
721 {PC_OPCODE, NULL, NULL, 0, NULL,
734 0,1, // dest, bit instruction
736 0, // literal operand
738 0, // fast call/return mode select bit
739 0, // second memory operand
740 0, // second literal operand
742 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
743 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
747 pCodeInstruction pic16_pciBZ = { // mdubuc - New
748 {PC_OPCODE, NULL, NULL, 0, NULL,
761 0,0, // dest, bit instruction
763 0, // literal operand
765 0, // fast call/return mode select bit
766 0, // second memory operand
767 0, // second literal operand
774 pCodeInstruction pic16_pciCALL = {
775 {PC_OPCODE, NULL, NULL, 0, NULL,
788 0,0, // dest, bit instruction
790 0, // literal operand
792 1, // fast call/return mode select bit
793 0, // second memory operand
794 0, // second literal operand
797 PCC_NONE , // outCond
801 pCodeInstruction pic16_pciCOMF = {
802 {PC_OPCODE, NULL, NULL, 0, NULL,
815 1,0, // dest, bit instruction
817 0, // literal operand
819 0, // fast call/return mode select bit
820 0, // second memory operand
821 0, // second literal operand
823 PCC_REGISTER, // inCond
824 PCC_REGISTER , // outCond
828 pCodeInstruction pic16_pciCOMFW = {
829 {PC_OPCODE, NULL, NULL, 0, NULL,
842 0,0, // dest, bit instruction
844 0, // literal operand
846 0, // fast call/return mode select bit
847 0, // second memory operand
848 0, // second literal operand
850 PCC_REGISTER, // inCond
855 pCodeInstruction pic16_pciCLRF = {
856 {PC_OPCODE, NULL, NULL, 0, NULL,
869 0,0, // dest, bit instruction
871 0, // literal operand
873 0, // fast call/return mode select bit
874 0, // second memory operand
875 0, // second literal operand
877 PCC_REGISTER, // inCond
878 PCC_REGISTER , // outCond
882 pCodeInstruction pic16_pciCLRWDT = {
883 {PC_OPCODE, NULL, NULL, 0, NULL,
896 0,0, // dest, bit instruction
898 0, // literal operand
900 0, // fast call/return mode select bit
901 0, // second memory operand
902 0, // second literal operand
905 PCC_NONE , // outCond
909 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
910 {PC_OPCODE, NULL, NULL, 0, NULL,
923 0,0, // dest, bit instruction
925 0, // literal operand
927 0, // fast call/return mode select bit
928 0, // second memory operand
929 0, // second literal operand
931 (PCC_W | PCC_REGISTER), // inCond
932 PCC_NONE , // outCond
936 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
937 {PC_OPCODE, NULL, NULL, 0, NULL,
950 0,0, // dest, bit instruction
952 0, // literal operand
954 0, // fast call/return mode select bit
955 0, // second memory operand
956 0, // second literal operand
958 (PCC_W | PCC_REGISTER), // inCond
959 PCC_NONE , // outCond
963 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
964 {PC_OPCODE, NULL, NULL, 0, NULL,
977 1,0, // dest, bit instruction
979 0, // literal operand
981 0, // fast call/return mode select bit
982 0, // second memory operand
983 0, // second literal operand
985 (PCC_W | PCC_REGISTER), // inCond
986 PCC_NONE , // outCond
990 pCodeInstruction pic16_pciDAW = {
991 {PC_OPCODE, NULL, NULL, 0, NULL,
1004 0,0, // dest, bit instruction
1005 0,0, // branch, skip
1006 0, // literal operand
1007 0, // RAM access bit
1008 0, // fast call/return mode select bit
1009 0, // second memory operand
1010 0, // second literal operand
1013 (PCC_W | PCC_C), // outCond
1017 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1018 {PC_OPCODE, NULL, NULL, 0, NULL,
1024 NULL, // from branch
1031 1,0, // dest, bit instruction
1032 1,1, // branch, skip
1033 0, // literal operand
1034 1, // RAM access bit
1035 0, // fast call/return mode select bit
1036 0, // second memory operand
1037 0, // second literal operand
1039 PCC_REGISTER, // inCond
1040 PCC_REGISTER , // outCond
1044 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1045 {PC_OPCODE, NULL, NULL, 0, NULL,
1051 NULL, // from branch
1058 0,0, // dest, bit instruction
1059 1,1, // branch, skip
1060 0, // literal operand
1061 1, // RAM access bit
1062 0, // fast call/return mode select bit
1063 0, // second memory operand
1064 0, // second literal operand
1066 PCC_REGISTER, // inCond
1071 pCodeInstruction pic16_pciDECF = {
1072 {PC_OPCODE, NULL, NULL, 0, NULL,
1078 NULL, // from branch
1085 1,0, // dest, bit instruction
1086 0,0, // branch, skip
1087 0, // literal operand
1088 1, // RAM access bit
1089 0, // fast call/return mode select bit
1090 0, // second memory operand
1091 0, // second literal operand
1093 PCC_REGISTER, // inCond
1094 PCC_REGISTER , // outCond
1098 pCodeInstruction pic16_pciDECFW = {
1099 {PC_OPCODE, NULL, NULL, 0, NULL,
1105 NULL, // from branch
1112 0,0, // dest, bit instruction
1113 0,0, // branch, skip
1114 0, // literal operand
1115 1, // RAM access bit
1116 0, // fast call/return mode select bit
1117 0, // second memory operand
1118 0, // second literal operand
1120 PCC_REGISTER, // inCond
1125 pCodeInstruction pic16_pciDECFSZ = {
1126 {PC_OPCODE, NULL, NULL, 0, NULL,
1132 NULL, // from branch
1139 1,0, // dest, bit instruction
1140 1,1, // branch, skip
1141 0, // literal operand
1142 1, // RAM access bit
1143 0, // fast call/return mode select bit
1144 0, // second memory operand
1145 0, // second literal operand
1147 PCC_REGISTER, // inCond
1148 PCC_REGISTER , // outCond
1152 pCodeInstruction pic16_pciDECFSZW = {
1153 {PC_OPCODE, NULL, NULL, 0, NULL,
1159 NULL, // from branch
1166 0,0, // dest, bit instruction
1167 1,1, // branch, skip
1168 0, // literal operand
1169 1, // RAM access bit
1170 0, // fast call/return mode select bit
1171 0, // second memory operand
1172 0, // second literal operand
1174 PCC_REGISTER, // inCond
1179 pCodeInstruction pic16_pciGOTO = {
1180 {PC_OPCODE, NULL, NULL, 0, NULL,
1186 NULL, // from branch
1193 0,0, // dest, bit instruction
1194 1,0, // branch, skip
1195 0, // literal operand
1196 0, // RAM access bit
1197 0, // fast call/return mode select bit
1198 0, // second memory operand
1199 0, // second literal operand
1201 PCC_REL_ADDR, // inCond
1202 PCC_NONE , // outCond
1206 pCodeInstruction pic16_pciINCF = {
1207 {PC_OPCODE, NULL, NULL, 0, NULL,
1213 NULL, // from branch
1220 1,0, // dest, bit instruction
1221 0,0, // branch, skip
1222 0, // literal operand
1223 1, // RAM access bit
1224 0, // fast call/return mode select bit
1225 0, // second memory operand
1226 0, // second literal operand
1228 PCC_REGISTER, // inCond
1229 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1233 pCodeInstruction pic16_pciINCFW = {
1234 {PC_OPCODE, NULL, NULL, 0, NULL,
1240 NULL, // from branch
1247 0,0, // dest, bit instruction
1248 0,0, // branch, skip
1249 0, // literal operand
1250 1, // RAM access bit
1251 0, // fast call/return mode select bit
1252 0, // second memory operand
1253 0, // second literal operand
1255 PCC_REGISTER, // inCond
1260 pCodeInstruction pic16_pciINCFSZ = {
1261 {PC_OPCODE, NULL, NULL, 0, NULL,
1267 NULL, // from branch
1274 1,0, // dest, bit instruction
1275 1,1, // branch, skip
1276 0, // literal operand
1277 1, // RAM access bit
1278 0, // fast call/return mode select bit
1279 0, // second memory operand
1280 0, // second literal operand
1282 PCC_REGISTER, // inCond
1283 PCC_REGISTER , // outCond
1287 pCodeInstruction pic16_pciINCFSZW = {
1288 {PC_OPCODE, NULL, NULL, 0, NULL,
1294 NULL, // from branch
1301 0,0, // dest, bit instruction
1302 1,1, // branch, skip
1303 0, // literal operand
1304 1, // RAM access bit
1305 0, // fast call/return mode select bit
1306 0, // second memory operand
1307 0, // second literal operand
1309 PCC_REGISTER, // inCond
1314 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1315 {PC_OPCODE, NULL, NULL, 0, NULL,
1321 NULL, // from branch
1328 1,0, // dest, bit instruction
1329 1,1, // branch, skip
1330 0, // literal operand
1331 1, // RAM access bit
1332 0, // fast call/return mode select bit
1333 0, // second memory operand
1334 0, // second literal operand
1336 PCC_REGISTER, // inCond
1337 PCC_REGISTER , // outCond
1341 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1342 {PC_OPCODE, NULL, NULL, 0, NULL,
1348 NULL, // from branch
1355 0,0, // dest, bit instruction
1356 1,1, // branch, skip
1357 0, // literal operand
1358 1, // RAM access bit
1359 0, // fast call/return mode select bit
1360 0, // second memory operand
1361 0, // second literal operand
1363 PCC_REGISTER, // inCond
1368 pCodeInstruction pic16_pciIORWF = {
1369 {PC_OPCODE, NULL, NULL, 0, NULL,
1375 NULL, // from branch
1382 1,0, // dest, bit instruction
1383 0,0, // branch, skip
1384 0, // literal operand
1385 1, // RAM access bit
1386 0, // fast call/return mode select bit
1387 0, // second memory operand
1388 0, // second literal operand
1390 (PCC_W | PCC_REGISTER), // inCond
1391 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1395 pCodeInstruction pic16_pciIORFW = {
1396 {PC_OPCODE, NULL, NULL, 0, NULL,
1402 NULL, // from branch
1409 0,0, // dest, bit instruction
1410 0,0, // branch, skip
1411 0, // literal operand
1412 1, // RAM access bit
1413 0, // fast call/return mode select bit
1414 0, // second memory operand
1415 0, // second literal operand
1417 (PCC_W | PCC_REGISTER), // inCond
1418 (PCC_W | PCC_Z | PCC_N), // outCond
1422 pCodeInstruction pic16_pciIORLW = {
1423 {PC_OPCODE, NULL, NULL, 0, NULL,
1429 NULL, // from branch
1436 0,0, // dest, bit instruction
1437 0,0, // branch, skip
1438 1, // literal operand
1439 0, // RAM access bit
1440 0, // fast call/return mode select bit
1441 0, // second memory operand
1442 0, // second literal operand
1444 (PCC_W | PCC_LITERAL), // inCond
1445 (PCC_W | PCC_Z | PCC_N), // outCond
1449 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1450 {PC_OPCODE, NULL, NULL, 0, NULL,
1456 NULL, // from branch
1463 0,0, // dest, bit instruction
1464 0,0, // branch, skip
1465 1, // literal operand
1466 0, // RAM access bit
1467 0, // fast call/return mode select bit
1468 0, // second memory operand
1469 1, // second literal operand
1471 (PCC_REGISTER | PCC_LITERAL),
1472 PCC_REGISTER, // outCond
1476 pCodeInstruction pic16_pciMOVF = {
1477 {PC_OPCODE, NULL, NULL, 0, NULL,
1483 NULL, // from branch
1490 1,0, // dest, bit instruction
1491 0,0, // branch, skip
1492 0, // literal operand
1493 1, // RAM access bit
1494 0, // fast call/return mode select bit
1495 0, // second memory operand
1496 0, // second literal operand
1498 PCC_REGISTER, // inCond
1499 (PCC_Z | PCC_N), // outCond
1503 pCodeInstruction pic16_pciMOVFW = {
1504 {PC_OPCODE, NULL, NULL, 0, NULL,
1510 NULL, // from branch
1517 0,0, // dest, bit instruction
1518 0,0, // branch, skip
1519 0, // literal operand
1520 1, // RAM access bit
1521 0, // fast call/return mode select bit
1522 0, // second memory operand
1523 0, // second literal operand
1525 PCC_REGISTER, // inCond
1526 (PCC_W | PCC_Z), // outCond
1530 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1531 {PC_OPCODE, NULL, NULL, 0, NULL,
1537 NULL, // from branch
1544 0,0, // dest, bit instruction
1545 0,0, // branch, skip
1546 0, // literal operand
1547 0, // RAM access bit
1548 0, // fast call/return mode select bit
1549 1, // second memory operand
1550 0, // second literal operand
1552 PCC_REGISTER, // inCond
1553 PCC_REGISTER, // outCond
1557 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1558 {PC_OPCODE, NULL, NULL, 0, NULL,
1563 NULL, // from branch
1570 0,0, // dest, bit instruction
1571 0,0, // branch, skip
1572 1, // literal operand
1573 0, // RAM access bit
1574 0, // fast call/return mode select bit
1575 0, // second memory operand
1576 0, // second literal operand
1578 (PCC_NONE | PCC_LITERAL), // inCond
1579 PCC_REGISTER, // outCond - BSR
1583 pCodeInstruction pic16_pciMOVLW = {
1584 {PC_OPCODE, NULL, NULL, 0, NULL,
1589 NULL, // from branch
1596 0,0, // dest, bit instruction
1597 0,0, // branch, skip
1598 1, // literal operand
1599 0, // RAM access bit
1600 0, // fast call/return mode select bit
1601 0, // second memory operand
1602 0, // second literal operand
1604 (PCC_NONE | PCC_LITERAL), // inCond
1609 pCodeInstruction pic16_pciMOVWF = {
1610 {PC_OPCODE, NULL, NULL, 0, NULL,
1616 NULL, // from branch
1623 0,0, // dest, bit instruction
1624 0,0, // branch, skip
1625 0, // literal operand
1626 1, // RAM access bit
1627 0, // fast call/return mode select bit
1628 0, // second memory operand
1629 0, // second literal operand
1631 PCC_REGISTER, // inCond
1636 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1637 {PC_OPCODE, NULL, NULL, 0, NULL,
1642 NULL, // from branch
1649 0,0, // dest, bit instruction
1650 0,0, // branch, skip
1651 1, // literal operand
1652 0, // RAM access bit
1653 0, // fast call/return mode select bit
1654 0, // second memory operand
1655 0, // second literal operand
1657 (PCC_W | PCC_LITERAL), // inCond
1658 PCC_REGISTER, // outCond - PROD
1662 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1663 {PC_OPCODE, NULL, NULL, 0, NULL,
1668 NULL, // from branch
1675 0,0, // dest, bit instruction
1676 0,0, // branch, skip
1677 0, // literal operand
1678 1, // RAM access bit
1679 0, // fast call/return mode select bit
1680 0, // second memory operand
1681 0, // second literal operand
1683 (PCC_W | PCC_REGISTER), // inCond
1684 PCC_REGISTER, // outCond - PROD
1688 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1689 {PC_OPCODE, NULL, NULL, 0, NULL,
1694 NULL, // from branch
1701 0,0, // dest, bit instruction
1702 0,0, // branch, skip
1703 0, // literal operand
1704 1, // RAM access bit
1705 0, // fast call/return mode select bit
1706 0, // second memory operand
1707 0, // second literal operand
1709 PCC_REGISTER, // inCond
1710 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1714 pCodeInstruction pic16_pciNOP = {
1715 {PC_OPCODE, NULL, NULL, 0, NULL,
1720 NULL, // from branch
1727 0,0, // dest, bit instruction
1728 0,0, // branch, skip
1729 0, // literal operand
1730 0, // RAM access bit
1731 0, // fast call/return mode select bit
1732 0, // second memory operand
1733 0, // second literal operand
1736 PCC_NONE, // outCond
1740 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1741 {PC_OPCODE, NULL, NULL, 0, NULL,
1746 NULL, // from branch
1753 0,0, // dest, bit instruction
1754 0,0, // branch, skip
1755 0, // literal operand
1756 0, // RAM access bit
1757 0, // fast call/return mode select bit
1758 0, // second memory operand
1759 0, // second literal operand
1762 PCC_NONE , // outCond
1766 pCodeInstruction pic16_pciPUSH = {
1767 {PC_OPCODE, NULL, NULL, 0, NULL,
1772 NULL, // from branch
1779 0,0, // dest, bit instruction
1780 0,0, // branch, skip
1781 0, // literal operand
1782 0, // RAM access bit
1783 0, // fast call/return mode select bit
1784 0, // second memory operand
1785 0, // second literal operand
1788 PCC_NONE , // outCond
1792 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1793 {PC_OPCODE, NULL, NULL, 0, NULL,
1798 NULL, // from branch
1805 0,0, // dest, bit instruction
1806 0,0, // branch, skip
1807 0, // literal operand
1808 0, // RAM access bit
1809 0, // fast call/return mode select bit
1810 0, // second memory operand
1811 0, // second literal operand
1813 PCC_REL_ADDR, // inCond
1814 PCC_NONE , // outCond
1818 pCodeInstruction pic16_pciRETFIE = {
1819 {PC_OPCODE, NULL, NULL, 0, NULL,
1825 NULL, // from branch
1832 0,0, // dest, bit instruction
1833 1,0, // branch, skip
1834 0, // literal operand
1835 0, // RAM access bit
1836 1, // fast call/return mode select bit
1837 0, // second memory operand
1838 0, // second literal operand
1841 PCC_NONE, // outCond (not true... affects the GIE bit too)
1845 pCodeInstruction pic16_pciRETLW = {
1846 {PC_OPCODE, NULL, NULL, 0, NULL,
1852 NULL, // from branch
1859 0,0, // dest, bit instruction
1860 1,0, // branch, skip
1861 1, // literal operand
1862 0, // RAM access bit
1863 0, // fast call/return mode select bit
1864 0, // second memory operand
1865 0, // second literal operand
1867 PCC_LITERAL, // inCond
1872 pCodeInstruction pic16_pciRETURN = {
1873 {PC_OPCODE, NULL, NULL, 0, NULL,
1879 NULL, // from branch
1886 0,0, // dest, bit instruction
1887 1,0, // branch, skip
1888 0, // literal operand
1889 0, // RAM access bit
1890 1, // fast call/return mode select bit
1891 0, // second memory operand
1892 0, // second literal operand
1895 PCC_NONE, // outCond
1898 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1899 {PC_OPCODE, NULL, NULL, 0, NULL,
1905 NULL, // from branch
1912 1,0, // dest, bit instruction
1913 0,0, // branch, skip
1914 0, // literal operand
1915 1, // RAM access bit
1916 0, // fast call/return mode select bit
1917 0, // second memory operand
1918 0, // second literal operand
1920 (PCC_C | PCC_REGISTER), // inCond
1921 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1925 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1926 {PC_OPCODE, NULL, NULL, 0, NULL,
1932 NULL, // from branch
1939 0,0, // dest, bit instruction
1940 0,0, // branch, skip
1941 0, // literal operand
1942 1, // RAM access bit
1943 0, // fast call/return mode select bit
1944 0, // second memory operand
1945 0, // second literal operand
1947 (PCC_C | PCC_REGISTER), // inCond
1948 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1952 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1953 {PC_OPCODE, NULL, NULL, 0, NULL,
1959 NULL, // from branch
1966 1,0, // dest, bit instruction
1967 0,0, // branch, skip
1968 0, // literal operand
1969 1, // RAM access bit
1970 0, // fast call/return mode select bit
1971 0, // second memory operand
1972 0, // second literal operand
1974 PCC_REGISTER, // inCond
1975 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1978 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1979 {PC_OPCODE, NULL, NULL, 0, NULL,
1985 NULL, // from branch
1992 0,0, // dest, bit instruction
1993 0,0, // branch, skip
1994 0, // literal operand
1995 1, // RAM access bit
1996 0, // fast call/return mode select bit
1997 0, // second memory operand
1998 0, // second literal operand
2000 PCC_REGISTER, // inCond
2001 (PCC_W | PCC_Z | PCC_N), // outCond
2004 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2005 {PC_OPCODE, NULL, NULL, 0, NULL,
2011 NULL, // from branch
2018 1,0, // dest, bit instruction
2019 0,0, // branch, skip
2020 0, // literal operand
2021 1, // RAM access bit
2022 0, // fast call/return mode select bit
2023 0, // second memory operand
2024 0, // second literal operand
2026 (PCC_C | PCC_REGISTER), // inCond
2027 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2030 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2031 {PC_OPCODE, NULL, NULL, 0, NULL,
2037 NULL, // from branch
2044 0,0, // dest, bit instruction
2045 0,0, // branch, skip
2046 0, // literal operand
2047 1, // RAM access bit
2048 0, // fast call/return mode select bit
2049 0, // second memory operand
2050 0, // second literal operand
2052 (PCC_C | PCC_REGISTER), // inCond
2053 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2056 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2057 {PC_OPCODE, NULL, NULL, 0, NULL,
2063 NULL, // from branch
2070 1,0, // dest, bit instruction
2071 0,0, // branch, skip
2072 0, // literal operand
2073 1, // RAM access bit
2074 0, // fast call/return mode select bit
2075 0, // second memory operand
2076 0, // second literal operand
2078 PCC_REGISTER, // inCond
2079 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2083 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2084 {PC_OPCODE, NULL, NULL, 0, NULL,
2090 NULL, // from branch
2097 0,0, // dest, bit instruction
2098 0,0, // branch, skip
2099 0, // literal operand
2100 1, // RAM access bit
2101 0, // fast call/return mode select bit
2102 0, // second memory operand
2103 0, // second literal operand
2105 PCC_REGISTER, // inCond
2106 (PCC_W | PCC_Z | PCC_N), // outCond
2110 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2111 {PC_OPCODE, NULL, NULL, 0, NULL,
2117 NULL, // from branch
2124 0,0, // dest, bit instruction
2125 0,0, // branch, skip
2126 0, // literal operand
2127 1, // RAM access bit
2128 0, // fast call/return mode select bit
2129 0, // second memory operand
2130 0, // second literal operand
2132 PCC_REGISTER, // inCond
2133 PCC_REGISTER , // outCond
2137 pCodeInstruction pic16_pciSUBLW = {
2138 {PC_OPCODE, NULL, NULL, 0, NULL,
2144 NULL, // from branch
2151 0,0, // dest, bit instruction
2152 0,0, // branch, skip
2153 1, // literal operand
2154 0, // RAM access bit
2155 0, // fast call/return mode select bit
2156 0, // second memory operand
2157 0, // second literal operand
2159 (PCC_W | PCC_LITERAL), // inCond
2160 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2164 pCodeInstruction pic16_pciSUBFWB = {
2165 {PC_OPCODE, NULL, NULL, 0, NULL,
2171 NULL, // from branch
2178 1,0, // dest, bit instruction
2179 0,0, // branch, skip
2180 0, // literal operand
2181 1, // RAM access bit
2182 0, // fast call/return mode select bit
2183 0, // second memory operand
2184 0, // second literal operand
2186 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2187 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2191 pCodeInstruction pic16_pciSUBWF = {
2192 {PC_OPCODE, NULL, NULL, 0, NULL,
2198 NULL, // from branch
2205 1,0, // dest, bit instruction
2206 0,0, // branch, skip
2207 0, // literal operand
2208 1, // RAM access bit
2209 0, // fast call/return mode select bit
2210 0, // second memory operand
2211 0, // second literal operand
2213 (PCC_W | PCC_REGISTER), // inCond
2214 (PCC_REGISTER | PCC_Z), // outCond
2218 pCodeInstruction pic16_pciSUBFW = {
2219 {PC_OPCODE, NULL, NULL, 0, NULL,
2225 NULL, // from branch
2232 0,0, // dest, bit instruction
2233 0,0, // branch, skip
2234 0, // literal operand
2235 1, // RAM access bit
2236 0, // fast call/return mode select bit
2237 0, // second memory operand
2238 0, // second literal operand
2240 (PCC_W | PCC_REGISTER), // inCond
2241 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2245 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2246 {PC_OPCODE, NULL, NULL, 0, NULL,
2252 NULL, // from branch
2259 1,0, // dest, bit instruction
2260 0,0, // branch, skip
2261 0, // literal operand
2262 1, // RAM access bit
2263 0, // fast call/return mode select bit
2264 0, // second memory operand
2265 0, // second literal operand
2267 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2268 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2272 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2273 {PC_OPCODE, NULL, NULL, 0, NULL,
2279 NULL, // from branch
2286 0,0, // dest, bit instruction
2287 0,0, // branch, skip
2288 0, // literal operand
2289 1, // RAM access bit
2290 0, // fast call/return mode select bit
2291 0, // second memory operand
2292 0, // second literal operand
2294 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2295 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2299 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2300 {PC_OPCODE, NULL, NULL, 0, NULL,
2306 NULL, // from branch
2313 1,0, // dest, bit instruction
2314 0,0, // branch, skip
2315 0, // literal operand
2316 1, // RAM access bit
2317 0, // fast call/return mode select bit
2318 0, // second memory operand
2319 0, // second literal operand
2321 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2322 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2326 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2327 {PC_OPCODE, NULL, NULL, 0, NULL,
2333 NULL, // from branch
2340 0,0, // dest, bit instruction
2341 0,0, // branch, skip
2342 0, // literal operand
2343 1, // RAM access bit
2344 0, // fast call/return mode select bit
2345 0, // second memory operand
2346 0, // second literal operand
2348 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2349 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2353 pCodeInstruction pic16_pciSWAPF = {
2354 {PC_OPCODE, NULL, NULL, 0, NULL,
2360 NULL, // from branch
2367 1,0, // dest, bit instruction
2368 0,0, // branch, skip
2369 0, // literal operand
2370 1, // RAM access bit
2371 0, // fast call/return mode select bit
2372 0, // second memory operand
2373 0, // second literal operand
2375 (PCC_REGISTER), // inCond
2376 (PCC_REGISTER), // outCond
2380 pCodeInstruction pic16_pciSWAPFW = {
2381 {PC_OPCODE, NULL, NULL, 0, NULL,
2387 NULL, // from branch
2394 0,0, // dest, bit instruction
2395 0,0, // branch, skip
2396 0, // literal operand
2397 1, // RAM access bit
2398 0, // fast call/return mode select bit
2399 0, // second memory operand
2400 0, // second literal operand
2402 (PCC_REGISTER), // inCond
2407 pCodeInstruction pic16_pciTBLRD = { // patch 15
2408 {PC_OPCODE, NULL, NULL, 0, NULL,
2413 NULL, // from branch
2420 0,0, // dest, bit instruction
2421 0,0, // branch, skip
2422 0, // literal operand
2423 0, // RAM access bit
2424 0, // fast call/return mode select bit
2425 0, // second memory operand
2426 0, // second literal operand
2429 PCC_NONE , // outCond
2433 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2434 {PC_OPCODE, NULL, NULL, 0, NULL,
2439 NULL, // from branch
2446 0,0, // dest, bit instruction
2447 0,0, // branch, skip
2448 0, // literal operand
2449 0, // RAM access bit
2450 0, // fast call/return mode select bit
2451 0, // second memory operand
2452 0, // second literal operand
2455 PCC_NONE , // outCond
2459 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2460 {PC_OPCODE, NULL, NULL, 0, NULL,
2465 NULL, // from branch
2472 0,0, // dest, bit instruction
2473 0,0, // branch, skip
2474 0, // literal operand
2475 0, // RAM access bit
2476 0, // fast call/return mode select bit
2477 0, // second memory operand
2478 0, // second literal operand
2481 PCC_NONE , // outCond
2485 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2486 {PC_OPCODE, NULL, NULL, 0, NULL,
2491 NULL, // from branch
2498 0,0, // dest, bit instruction
2499 0,0, // branch, skip
2500 0, // literal operand
2501 0, // RAM access bit
2502 0, // fast call/return mode select bit
2503 0, // second memory operand
2504 0, // second literal operand
2507 PCC_NONE , // outCond
2511 pCodeInstruction pic16_pciTBLWT = { // patch 15
2512 {PC_OPCODE, NULL, NULL, 0, NULL,
2517 NULL, // from branch
2524 0,0, // dest, bit instruction
2525 0,0, // branch, skip
2526 0, // literal operand
2527 0, // RAM access bit
2528 0, // fast call/return mode select bit
2529 0, // second memory operand
2530 0, // second literal operand
2533 PCC_NONE , // outCond
2537 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2538 {PC_OPCODE, NULL, NULL, 0, NULL,
2543 NULL, // from branch
2550 0,0, // dest, bit instruction
2551 0,0, // branch, skip
2552 0, // literal operand
2553 0, // RAM access bit
2554 0, // fast call/return mode select bit
2555 0, // second memory operand
2556 0, // second literal operand
2559 PCC_NONE , // outCond
2563 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2564 {PC_OPCODE, NULL, NULL, 0, NULL,
2569 NULL, // from branch
2576 0,0, // dest, bit instruction
2577 0,0, // branch, skip
2578 0, // literal operand
2579 0, // RAM access bit
2580 0, // fast call/return mode select bit
2581 0, // second memory operand
2582 0, // second literal operand
2585 PCC_NONE , // outCond
2589 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2590 {PC_OPCODE, NULL, NULL, 0, NULL,
2595 NULL, // from branch
2602 0,0, // dest, bit instruction
2603 0,0, // branch, skip
2604 0, // literal operand
2605 0, // RAM access bit
2606 0, // fast call/return mode select bit
2607 0, // second memory operand
2608 0, // second literal operand
2611 PCC_NONE , // outCond
2615 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2616 {PC_OPCODE, NULL, NULL, 0, NULL,
2622 NULL, // from branch
2629 0,0, // dest, bit instruction
2630 1,1, // branch, skip
2631 0, // literal operand
2632 1, // RAM access bit
2633 0, // fast call/return mode select bit
2634 0, // second memory operand
2635 0, // second literal operand
2637 PCC_REGISTER, // inCond
2638 PCC_NONE, // outCond
2642 pCodeInstruction pic16_pciXORWF = {
2643 {PC_OPCODE, NULL, NULL, 0, NULL,
2649 NULL, // from branch
2656 1,0, // dest, bit instruction
2657 0,0, // branch, skip
2658 0, // literal operand
2659 1, // RAM access bit
2660 0, // fast call/return mode select bit
2661 0, // second memory operand
2662 0, // second literal operand
2664 (PCC_W | PCC_REGISTER), // inCond
2665 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2669 pCodeInstruction pic16_pciXORFW = {
2670 {PC_OPCODE, NULL, NULL, 0, NULL,
2676 NULL, // from branch
2683 0,0, // dest, bit instruction
2684 0,0, // branch, skip
2685 0, // literal operand
2686 1, // RAM access bit
2687 0, // fast call/return mode select bit
2688 0, // second memory operand
2689 0, // second literal operand
2691 (PCC_W | PCC_REGISTER), // inCond
2692 (PCC_W | PCC_Z | PCC_N), // outCond
2696 pCodeInstruction pic16_pciXORLW = {
2697 {PC_OPCODE, NULL, NULL, 0, NULL,
2703 NULL, // from branch
2710 0,0, // dest, bit instruction
2711 0,0, // branch, skip
2712 1, // literal operand
2713 1, // RAM access bit
2714 0, // fast call/return mode select bit
2715 0, // second memory operand
2716 0, // second literal operand
2718 (PCC_W | PCC_LITERAL), // inCond
2719 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2724 pCodeInstruction pic16_pciBANKSEL = {
2725 {PC_OPCODE, NULL, NULL, 0, NULL,
2730 NULL, // from branch
2737 0,0, // dest, bit instruction
2738 0,0, // branch, skip
2739 0, // literal operand
2740 0, // RAM access bit
2741 0, // fast call/return mode select bit
2742 0, // second memory operand
2743 0, // second literal operand
2746 PCC_NONE, // outCond
2751 #define MAX_PIC16MNEMONICS 100
2752 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2754 //#define USE_VSNPRINTF
2757 #ifdef USE_VSNPRINTF
2758 // Alas, vsnprintf is not ANSI standard, and does not exist
2759 // on Solaris (and probably other non-Gnu flavored Unixes).
2761 /*-----------------------------------------------------------------*/
2762 /* SAFE_snprintf - like snprintf except the string pointer is */
2763 /* after the string has been printed to. This is */
2764 /* useful for printing to string as though if it */
2765 /* were a stream. */
2766 /*-----------------------------------------------------------------*/
2767 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2775 va_start(val, format);
2777 vsnprintf(*str, *size, format, val);
2783 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2784 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2793 // This version is *not* safe, despite the name.
2795 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2799 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2804 va_start(val, format);
2806 vsprintf(buffer, format, val);
2809 len = strlen(buffer);
2811 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2812 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2815 strcpy(*str, buffer);
2821 #endif // USE_VSNPRINTF
2824 extern set *externs;
2825 extern void pic16_initStack(int base_address, int size);
2826 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2827 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2828 extern void pic16_init_pic(char *);
2830 void pic16_pCodeInitRegisters(void)
2832 static int initialized=0;
2839 // pic16_initStack(0xfff, 8);
2840 pic16_init_pic(port->processor);
2842 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2843 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2844 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2845 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2846 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2847 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2848 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2850 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2851 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2852 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2854 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2855 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2856 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2857 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2859 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2860 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2861 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2862 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2863 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2864 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2866 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2867 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2868 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2869 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2870 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2872 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2873 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2874 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2875 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2876 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2878 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2879 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2880 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2881 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2882 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2884 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2885 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2888 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2889 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2890 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2891 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2894 pic16_pc_status.rIdx = IDX_STATUS;
2895 pic16_pc_intcon.rIdx = IDX_INTCON;
2896 pic16_pc_pcl.rIdx = IDX_PCL;
2897 pic16_pc_pclath.rIdx = IDX_PCLATH;
2898 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2899 pic16_pc_wreg.rIdx = IDX_WREG;
2900 pic16_pc_bsr.rIdx = IDX_BSR;
2902 pic16_pc_tosl.rIdx = IDX_TOSL;
2903 pic16_pc_tosh.rIdx = IDX_TOSH;
2904 pic16_pc_tosu.rIdx = IDX_TOSU;
2906 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2907 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2908 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2909 pic16_pc_tablat.rIdx = IDX_TABLAT;
2911 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2912 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2913 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2914 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2915 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2916 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2917 pic16_pc_indf0.rIdx = IDX_INDF0;
2918 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2919 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2920 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2921 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2922 pic16_pc_indf1.rIdx = IDX_INDF1;
2923 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2924 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2925 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2926 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2927 pic16_pc_indf2.rIdx = IDX_INDF2;
2928 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2929 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2930 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2931 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2932 pic16_pc_prodl.rIdx = IDX_PRODL;
2933 pic16_pc_prodh.rIdx = IDX_PRODH;
2935 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2936 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2937 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2939 pic16_pc_kzero.rIdx = IDX_KZ;
2940 pic16_pc_wsave.rIdx = IDX_WSAVE;
2941 pic16_pc_ssave.rIdx = IDX_SSAVE;
2943 pic16_pc_eecon1.rIdx = IDX_EECON1;
2944 pic16_pc_eecon2.rIdx = IDX_EECON2;
2945 pic16_pc_eedata.rIdx = IDX_EEDATA;
2946 pic16_pc_eeadr.rIdx = IDX_EEADR;
2949 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
2950 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
2952 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
2953 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
2955 /* probably should put this in a separate initialization routine */
2956 pb_dead_pcodes = newpBlock();
2961 /*-----------------------------------------------------------------*/
2962 /* mnem2key - convert a pic mnemonic into a hash key */
2963 /* (BTW - this spreads the mnemonics quite well) */
2965 /*-----------------------------------------------------------------*/
2967 int mnem2key(char const *mnem)
2976 key += toupper(*mnem++) +1;
2980 return (key & 0x1f);
2985 void pic16initMnemonics(void)
2990 pCodeInstruction *pci;
2992 if(mnemonics_initialized)
2995 // NULL out the array before making the assignments
2996 // since we check the array contents below this initialization.
2998 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2999 pic16Mnemonics[i] = NULL;
3002 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3003 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3004 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3005 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3006 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3007 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3008 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3009 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3010 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3011 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3012 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3013 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3014 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3015 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3016 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3017 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3018 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3019 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3020 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3021 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3022 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3023 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3024 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3025 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3026 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3027 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3028 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3029 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3030 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3031 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3032 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3033 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3034 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3035 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3036 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3037 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3038 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3039 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3040 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3041 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3042 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3043 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3044 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3045 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3046 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3047 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3048 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3049 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3050 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3051 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3052 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3053 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3054 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3055 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3056 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3057 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3058 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3059 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3060 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3061 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3062 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3063 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3064 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3065 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3066 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3067 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3068 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3069 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3070 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3071 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3072 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3073 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3074 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3075 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3076 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3077 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3078 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3079 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3080 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3081 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3082 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3083 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3084 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3085 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3086 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3087 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3088 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3089 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3090 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3091 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3092 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3093 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3094 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3095 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3097 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3098 if(pic16Mnemonics[i])
3099 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3100 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3103 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3104 pci = hTabNextItem(pic16MnemonicsHash, &key);
3107 mnemonics_initialized = 1;
3110 int pic16_getpCodePeepCommand(char *cmd);
3112 int pic16_getpCode(char *mnem,unsigned dest)
3115 pCodeInstruction *pci;
3116 int key = mnem2key(mnem);
3118 if(!mnemonics_initialized)
3119 pic16initMnemonics();
3121 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3125 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3126 if((pci->num_ops <= 1)
3127 || (pci->isModReg == dest)
3129 || (pci->num_ops <= 2 && pci->isAccess)
3130 || (pci->num_ops <= 2 && pci->isFastCall)
3131 || (pci->num_ops <= 2 && pci->is2MemOp)
3132 || (pci->num_ops <= 2 && pci->is2LitOp) )
3136 pci = hTabNextItemWK (pic16MnemonicsHash);
3143 /*-----------------------------------------------------------------*
3144 * pic16initpCodePeepCommands
3146 *-----------------------------------------------------------------*/
3147 void pic16initpCodePeepCommands(void)
3155 hTabAddItem(&pic16pCodePeepCommandsHash,
3156 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3158 } while (peepCommands[i].cmd);
3160 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3163 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3164 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3169 /*-----------------------------------------------------------------
3172 *-----------------------------------------------------------------*/
3174 int pic16_getpCodePeepCommand(char *cmd)
3178 int key = mnem2key(cmd);
3181 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3184 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3185 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3189 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3196 static char getpBlock_dbName(pBlock *pb)
3202 return pb->cmemmap->dbName;
3206 void pic16_pBlockConvert2ISR(pBlock *pb)
3210 if(pb->cmemmap)pb->cmemmap = NULL;
3214 if(pic16_pcode_verbose)
3215 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3218 void pic16_pBlockConvert2Absolute(pBlock *pb)
3221 if(pb->cmemmap)pb->cmemmap = NULL;
3225 if(pic16_pcode_verbose)
3226 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3229 /*-----------------------------------------------------------------*/
3230 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3231 /* instances to the front of the doubly linked */
3232 /* list of pBlocks */
3233 /*-----------------------------------------------------------------*/
3235 void pic16_movepBlock2Head(char dbName)
3240 /* this can happen in sources without code,
3241 * only variable definitions */
3242 if(!the_pFile)return;
3244 pb = the_pFile->pbHead;
3248 if(getpBlock_dbName(pb) == dbName) {
3249 pBlock *pbn = pb->next;
3250 pb->next = the_pFile->pbHead;
3251 the_pFile->pbHead->prev = pb;
3252 the_pFile->pbHead = pb;
3255 pb->prev->next = pbn;
3257 // If the pBlock that we just moved was the last
3258 // one in the link of all of the pBlocks, then we
3259 // need to point the tail to the block just before
3260 // the one we moved.
3261 // Note: if pb->next is NULL, then pb must have
3262 // been the last pBlock in the chain.
3265 pbn->prev = pb->prev;
3267 the_pFile->pbTail = pb->prev;
3278 void pic16_copypCode(FILE *of, char dbName)
3282 if(!of || !the_pFile)
3285 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3286 if(getpBlock_dbName(pb) == dbName) {
3287 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3289 pic16_printpBlock(of,pb);
3294 void pic16_pcode_test(void)
3297 DFPRINTF((stderr,"pcode is alive!\n"));
3307 /* create the file name */
3308 strcpy(buffer,dstFileName);
3309 strcat(buffer,".p");
3311 if( !(pFile = fopen(buffer, "w" ))) {
3312 werror(E_FILE_OPEN_ERR,buffer);
3316 fprintf(pFile,"pcode dump\n\n");
3318 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3319 fprintf(pFile,"\n\tNew pBlock\n\n");
3321 fprintf(pFile,"%s",pb->cmemmap->sname);
3323 fprintf(pFile,"internal pblock");
3325 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3326 pic16_printpBlock(pFile,pb);
3330 /*-----------------------------------------------------------------*/
3331 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3332 /* ister, RegCond will return the bit being referenced. */
3334 /* fixme - why not just OR in the pcop bit field */
3335 /*-----------------------------------------------------------------*/
3337 static int RegCond(pCodeOp *pcop)
3343 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3344 switch(PCORB(pcop)->bit) {
3358 /*-----------------------------------------------------------------*/
3359 /* pic16_newpCode - create and return a newly initialized pCode */
3361 /* fixme - rename this */
3363 /* The purpose of this routine is to create a new Instruction */
3364 /* pCode. This is called by gen.c while the assembly code is being */
3368 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3369 /* (note that the op is analogous to but not the */
3370 /* same thing as the opcode of the instruction.) */
3371 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3374 /* a pointer to the new malloc'd pCode is returned. */
3378 /*-----------------------------------------------------------------*/
3379 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3381 pCodeInstruction *pci ;
3383 if(!mnemonics_initialized)
3384 pic16initMnemonics();
3386 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3388 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3389 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3392 if(pci->inCond & PCC_EXAMINE_PCOP)
3393 pci->inCond |= RegCond(pcop);
3395 if(pci->outCond & PCC_EXAMINE_PCOP)
3396 pci->outCond |= RegCond(pcop);
3398 pci->pc.prev = pci->pc.next = NULL;
3399 return (pCode *)pci;
3402 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3408 /*-----------------------------------------------------------------*/
3409 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3411 /* Wild pcodes are used during the peep hole optimizer to serve */
3412 /* as place holders for any instruction. When a snippet of code is */
3413 /* compared to a peep hole rule, the wild card opcode will match */
3414 /* any instruction. However, the optional operand and label are */
3415 /* additional qualifiers that must also be matched before the */
3416 /* line (of assembly code) is declared matched. Note that the */
3417 /* operand may be wild too. */
3419 /* Note, a wild instruction is specified just like a wild var: */
3420 /* %4 ; A wild instruction, */
3421 /* See the peeph.def file for additional examples */
3423 /*-----------------------------------------------------------------*/
3425 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3430 pcw = Safe_calloc(1,sizeof(pCodeWild));
3432 pcw->pci.pc.type = PC_WILD;
3433 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3434 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3435 pcw->pci.pc.pb = NULL;
3437 // pcw->pci.pc.analyze = genericAnalyze;
3438 pcw->pci.pc.destruct = genericDestruct;
3439 pcw->pci.pc.print = genericPrint;
3441 pcw->id = pCodeID; // this is the 'n' in %n
3442 pcw->operand = optional_operand;
3443 pcw->label = optional_label;
3445 pcw->mustBeBitSkipInst = 0;
3446 pcw->mustNotBeBitSkipInst = 0;
3447 pcw->invertBitSkipInst = 0;
3449 return ( (pCode *)pcw);
3453 /*-----------------------------------------------------------------*/
3454 /* newPcodeInlineP - create a new pCode from a char string */
3455 /*-----------------------------------------------------------------*/
3458 pCode *pic16_newpCodeInlineP(char *cP)
3463 pcc = Safe_calloc(1,sizeof(pCodeComment));
3465 pcc->pc.type = PC_INLINE;
3466 pcc->pc.prev = pcc->pc.next = NULL;
3467 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3470 // pcc->pc.analyze = genericAnalyze;
3471 pcc->pc.destruct = genericDestruct;
3472 pcc->pc.print = genericPrint;
3475 pcc->comment = Safe_strdup(cP);
3477 pcc->comment = NULL;
3479 return ( (pCode *)pcc);
3483 /*-----------------------------------------------------------------*/
3484 /* newPcodeCharP - create a new pCode from a char string */
3485 /*-----------------------------------------------------------------*/
3487 pCode *pic16_newpCodeCharP(char *cP)
3492 pcc = Safe_calloc(1,sizeof(pCodeComment));
3494 pcc->pc.type = PC_COMMENT;
3495 pcc->pc.prev = pcc->pc.next = NULL;
3496 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3499 // pcc->pc.analyze = genericAnalyze;
3500 pcc->pc.destruct = genericDestruct;
3501 pcc->pc.print = genericPrint;
3504 pcc->comment = Safe_strdup(cP);
3506 pcc->comment = NULL;
3508 return ( (pCode *)pcc);
3512 /*-----------------------------------------------------------------*/
3513 /* pic16_newpCodeFunction - */
3514 /*-----------------------------------------------------------------*/
3517 pCode *pic16_newpCodeFunction(char *mod,char *f)
3521 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3523 pcf->pc.type = PC_FUNCTION;
3524 pcf->pc.prev = pcf->pc.next = NULL;
3525 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3528 // pcf->pc.analyze = genericAnalyze;
3529 pcf->pc.destruct = genericDestruct;
3530 pcf->pc.print = pCodePrintFunction;
3536 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3537 strcpy(pcf->modname,mod);
3539 pcf->modname = NULL;
3542 pcf->fname = Safe_calloc(1,strlen(f)+1);
3543 strcpy(pcf->fname,f);
3547 pcf->stackusage = 0;
3549 return ( (pCode *)pcf);
3552 /*-----------------------------------------------------------------*/
3553 /* pic16_newpCodeFlow */
3554 /*-----------------------------------------------------------------*/
3555 static void destructpCodeFlow(pCode *pc)
3557 if(!pc || !isPCFL(pc))
3564 pic16_unlinkpCode(pc);
3566 deleteSet(&PCFL(pc)->registers);
3567 deleteSet(&PCFL(pc)->from);
3568 deleteSet(&PCFL(pc)->to);
3570 /* Instead of deleting the memory used by this pCode, mark
3571 * the object as bad so that if there's a pointer to this pCode
3572 * dangling around somewhere then (hopefully) when the type is
3573 * checked we'll catch it.
3577 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3583 pCode *pic16_newpCodeFlow(void )
3587 //_ALLOC(pcflow,sizeof(pCodeFlow));
3588 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3590 pcflow->pc.type = PC_FLOW;
3591 pcflow->pc.prev = pcflow->pc.next = NULL;
3592 pcflow->pc.pb = NULL;
3594 // pcflow->pc.analyze = genericAnalyze;
3595 pcflow->pc.destruct = destructpCodeFlow;
3596 pcflow->pc.print = genericPrint;
3598 pcflow->pc.seq = GpcFlowSeq++;
3600 pcflow->from = pcflow->to = NULL;
3602 pcflow->inCond = PCC_NONE;
3603 pcflow->outCond = PCC_NONE;
3605 pcflow->firstBank = -1;
3606 pcflow->lastBank = -1;
3608 pcflow->FromConflicts = 0;
3609 pcflow->ToConflicts = 0;
3613 pcflow->registers = newSet();
3615 return ( (pCode *)pcflow);
3619 /*-----------------------------------------------------------------*/
3620 /*-----------------------------------------------------------------*/
3621 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3623 pCodeFlowLink *pcflowLink;
3625 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3627 pcflowLink->pcflow = pcflow;
3628 pcflowLink->bank_conflict = 0;
3633 /*-----------------------------------------------------------------*/
3634 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3635 /*-----------------------------------------------------------------*/
3637 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3642 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3644 pccs->pc.type = PC_CSOURCE;
3645 pccs->pc.prev = pccs->pc.next = NULL;
3648 pccs->pc.destruct = genericDestruct;
3649 pccs->pc.print = genericPrint;
3651 pccs->line_number = ln;
3653 pccs->line = Safe_strdup(l);
3658 pccs->file_name = Safe_strdup(f);
3660 pccs->file_name = NULL;
3662 return ( (pCode *)pccs);
3667 /*******************************************************************/
3668 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3669 /* added by VR 6-Jun-2003 */
3670 /*******************************************************************/
3672 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3679 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3680 pcad->pci.pc.type = PC_ASMDIR;
3681 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3682 pcad->pci.pc.pb = NULL;
3684 pcad->pci.pc.destruct = genericDestruct;
3685 pcad->pci.pc.print = genericPrint;
3687 if(asdir && *asdir) {
3689 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3691 pcad->directive = Safe_strdup( asdir );
3694 va_start(ap, argfmt);
3696 memset(buffer, 0, sizeof(buffer));
3697 if(argfmt && *argfmt)
3698 vsprintf(buffer, argfmt, ap);
3702 while(isspace(*lbp))lbp++;
3705 pcad->arg = Safe_strdup( lbp );
3707 return ((pCode *)pcad);
3710 /*-----------------------------------------------------------------*/
3711 /* pCodeLabelDestruct - free memory used by a label. */
3712 /*-----------------------------------------------------------------*/
3713 static void pCodeLabelDestruct(pCode *pc)
3719 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3720 // free(PCL(pc)->label);
3722 /* Instead of deleting the memory used by this pCode, mark
3723 * the object as bad so that if there's a pointer to this pCode
3724 * dangling around somewhere then (hopefully) when the type is
3725 * checked we'll catch it.
3729 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3735 pCode *pic16_newpCodeLabel(char *name, int key)
3741 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3743 pcl->pc.type = PC_LABEL;
3744 pcl->pc.prev = pcl->pc.next = NULL;
3745 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3748 // pcl->pc.analyze = genericAnalyze;
3749 pcl->pc.destruct = pCodeLabelDestruct;
3750 pcl->pc.print = pCodePrintLabel;
3757 sprintf(s,"_%05d_DS_",key);
3762 pcl->label = Safe_strdup(s);
3764 // if(pic16_pcode_verbose)
3765 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3768 return ( (pCode *)pcl);
3772 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3774 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3778 return ( (pCode *)pcl );
3782 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3789 /*-----------------------------------------------------------------*/
3790 /* newpBlock - create and return a pointer to a new pBlock */
3791 /*-----------------------------------------------------------------*/
3792 static pBlock *newpBlock(void)
3797 PpB = Safe_calloc(1,sizeof(pBlock) );
3798 PpB->next = PpB->prev = NULL;
3800 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3801 PpB->tregisters = NULL;
3803 PpB->FlowTree = NULL;
3809 /*-----------------------------------------------------------------*/
3810 /* pic16_newpCodeChain - create a new chain of pCodes */
3811 /*-----------------------------------------------------------------*
3813 * This function will create a new pBlock and the pointer to the
3814 * pCode that is passed in will be the first pCode in the block.
3815 *-----------------------------------------------------------------*/
3818 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3821 pBlock *pB = newpBlock();
3823 pB->pcHead = pB->pcTail = pc;
3832 /*-----------------------------------------------------------------*/
3833 /* pic16_newpCodeOpLabel - Create a new label given the key */
3834 /* Note, a negative key means that the label is part of wild card */
3835 /* (and hence a wild card label) used in the pCodePeep */
3836 /* optimizations). */
3837 /*-----------------------------------------------------------------*/
3839 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3842 static int label_key=-1;
3846 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3847 pcop->type = PO_LABEL;
3852 sprintf(s=buffer,"_%05d_DS_",key);
3854 s = name, key = label_key--;
3857 pcop->name = Safe_strdup(s);
3859 ((pCodeOpLabel *)pcop)->key = key;
3861 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3865 /*-----------------------------------------------------------------*/
3866 /*-----------------------------------------------------------------*/
3867 pCodeOp *pic16_newpCodeOpLit(int lit)
3873 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3874 pcop->type = PO_LITERAL;
3878 sprintf(s,"0x%02hhx",(char)(lit));
3880 // sprintf(s, "%i", lit);
3883 pcop->name = Safe_strdup(s);
3885 ((pCodeOpLit *)pcop)->lit = lit;
3890 /*-----------------------------------------------------------------*/
3891 /*-----------------------------------------------------------------*/
3892 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3894 char *s = buffer, tbuf[256], *tb=tbuf;
3898 tb = pic16_get_op(arg2, NULL, 0);
3899 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3900 pcop->type = PO_LITERAL;
3904 sprintf(s,"0x%02x, %s",lit, tb);
3906 pcop->name = Safe_strdup(s);
3909 ((pCodeOpLit2 *)pcop)->lit = lit;
3910 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3915 /*-----------------------------------------------------------------*/
3916 /*-----------------------------------------------------------------*/
3917 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3921 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3922 pcop->type = PO_IMMEDIATE;
3924 regs *r = pic16_dirregWithName(name);
3925 pcop->name = Safe_strdup(name);
3929 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3930 PCOI(pcop)->rIdx = r->rIdx;
3932 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3933 PCOI(pcop)->rIdx = -1;
3935 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3940 PCOI(pcop)->index = index;
3941 PCOI(pcop)->offset = offset;
3942 PCOI(pcop)->_const = code_space;
3947 /*-----------------------------------------------------------------*/
3948 /*-----------------------------------------------------------------*/
3949 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3955 if(!pcwb || !subtype) {
3956 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3960 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3961 pcop->type = PO_WILD;
3962 sprintf(s,"%%%d",id);
3963 pcop->name = Safe_strdup(s);
3965 PCOW(pcop)->id = id;
3966 PCOW(pcop)->pcwb = pcwb;
3967 PCOW(pcop)->subtype = subtype;
3968 PCOW(pcop)->matched = NULL;
3970 PCOW(pcop)->pcop2 = NULL;
3975 /*-----------------------------------------------------------------*/
3976 /*-----------------------------------------------------------------*/
3977 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3983 if(!pcwb || !subtype || !subtype2) {
3984 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3988 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3989 pcop->type = PO_WILD;
3990 sprintf(s,"%%%d",id);
3991 pcop->name = Safe_strdup(s);
3993 PCOW(pcop)->id = id;
3994 PCOW(pcop)->pcwb = pcwb;
3995 PCOW(pcop)->subtype = subtype;
3996 PCOW(pcop)->matched = NULL;
3998 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4000 if(!subtype2->name) {
4001 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4002 PCOW2(pcop)->pcop.type = PO_WILD;
4003 sprintf(s, "%%%d", id2);
4004 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4005 PCOW2(pcop)->id = id2;
4006 PCOW2(pcop)->subtype = subtype2;
4008 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4009 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4011 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4013 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4014 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4023 /*-----------------------------------------------------------------*/
4024 /*-----------------------------------------------------------------*/
4025 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4029 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4030 pcop->type = PO_GPR_BIT;
4032 pcop->name = Safe_strdup(s);
4036 PCORB(pcop)->bit = bit;
4037 PCORB(pcop)->inBitSpace = inBitSpace;
4038 PCORB(pcop)->subtype = subt;
4040 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4041 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4042 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4043 // PCOR(pcop)->rIdx = 0;
4048 /*-----------------------------------------------------------------*
4049 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4051 * If rIdx >=0 then a specific register from the set of registers
4052 * will be selected. If rIdx <0, then a new register will be searched
4054 *-----------------------------------------------------------------*/
4056 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4060 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4065 PCOR(pcop)->rIdx = rIdx;
4066 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4068 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4071 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4073 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4074 __FUNCTION__, __LINE__);
4079 pcop->type = PCOR(pcop)->r->pc_type;
4084 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4089 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4090 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4091 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4092 pcop->type = PCOR(pcop)->r->pc_type;
4093 pcop->name = PCOR(pcop)->r->name;
4095 // if(pic16_pcode_verbose) {
4096 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4097 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4103 /*-----------------------------------------------------------------*/
4104 /*-----------------------------------------------------------------*/
4105 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4109 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4112 pcop->key = Safe_strdup( key );
4114 return (PCOP(pcop));
4118 /*-----------------------------------------------------------------*/
4119 /*-----------------------------------------------------------------*/
4121 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4128 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4132 pcop = pic16_newpCodeOpLit(-1);
4136 pcop = pic16_newpCodeOpLabel(NULL,-1);
4139 pcop = pic16_newpCodeOpReg(-1);
4142 case PO_GPR_REGISTER:
4144 pcop = pic16_newpCodeOpRegFromStr(name);
4146 pcop = pic16_newpCodeOpReg(-1);
4150 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4153 pcop->name = Safe_strdup(name);
4161 #define DB_ITEMS_PER_LINE 8
4163 typedef struct DBdata
4170 static int DBd_init = -1;
4172 /*-----------------------------------------------------------------*/
4173 /* Initialiase "DB" data buffer */
4174 /*-----------------------------------------------------------------*/
4175 void pic16_initDB(void)
4181 /*-----------------------------------------------------------------*/
4182 /* Flush pending "DB" data to a pBlock */
4184 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4185 /*-----------------------------------------------------------------*/
4186 void pic16_flushDB(char ptype, void *p)
4190 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4193 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4196 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4200 DBd.buffer[0] = '\0';
4205 /*-----------------------------------------------------------------*/
4206 /* Add "DB" directives to a pBlock */
4207 /*-----------------------------------------------------------------*/
4208 void pic16_emitDB(char c, char ptype, void *p)
4213 // we need to initialize
4216 DBd.buffer[0] = '\0';
4219 l = strlen(DBd.buffer);
4220 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4222 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4225 if (DBd.count>= DB_ITEMS_PER_LINE)
4226 pic16_flushDB(ptype, p);
4229 void pic16_emitDS(char *s, char ptype, void *p)
4234 // we need to initialize
4237 DBd.buffer[0] = '\0';
4240 l = strlen(DBd.buffer);
4241 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4243 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4245 DBd.count++; //=strlen(s);
4247 pic16_flushDB(ptype, p);
4251 /*-----------------------------------------------------------------*/
4252 /*-----------------------------------------------------------------*/
4253 void pic16_pCodeConstString(char *name, char *value)
4257 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4262 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4264 pic16_addpBlock(pb);
4266 sprintf(buffer,"; %s = %s",name,value);
4268 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4269 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4272 pic16_emitDB(*value, 'p', (void *)pb);
4274 pic16_flushDB('p', (void *)pb);
4277 /*-----------------------------------------------------------------*/
4278 /*-----------------------------------------------------------------*/
4280 static void pCodeReadCodeTable(void)
4284 fprintf(stderr, " %s\n",__FUNCTION__);
4286 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4288 pic16_addpBlock(pb);
4290 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4291 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4292 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4293 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4295 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4296 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4297 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4298 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4303 /*-----------------------------------------------------------------*/
4304 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4305 /*-----------------------------------------------------------------*/
4306 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4313 /* If this is the first pcode to be added to a block that
4314 * was initialized with a NULL pcode, then go ahead and
4315 * make this pcode the head and tail */
4316 pb->pcHead = pb->pcTail = pc;
4319 pb->pcTail->next = pc;
4321 pc->prev = pb->pcTail;
4328 /*-----------------------------------------------------------------*/
4329 /* pic16_addpBlock - place a pBlock into the pFile */
4330 /*-----------------------------------------------------------------*/
4331 void pic16_addpBlock(pBlock *pb)
4333 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4336 /* First time called, we'll pass through here. */
4337 //_ALLOC(the_pFile,sizeof(pFile));
4338 the_pFile = Safe_calloc(1,sizeof(pFile));
4339 the_pFile->pbHead = the_pFile->pbTail = pb;
4340 the_pFile->functions = NULL;
4344 the_pFile->pbTail->next = pb;
4345 pb->prev = the_pFile->pbTail;
4347 the_pFile->pbTail = pb;
4350 /*-----------------------------------------------------------------*/
4351 /* removepBlock - remove a pBlock from the pFile */
4352 /*-----------------------------------------------------------------*/
4353 static void removepBlock(pBlock *pb)
4361 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4363 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4366 if(pbs == the_pFile->pbHead)
4367 the_pFile->pbHead = pbs->next;
4369 if (pbs == the_pFile->pbTail)
4370 the_pFile->pbTail = pbs->prev;
4373 pbs->next->prev = pbs->prev;
4376 pbs->prev->next = pbs->next;
4383 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4387 /*-----------------------------------------------------------------*/
4388 /* printpCode - write the contents of a pCode to a file */
4389 /*-----------------------------------------------------------------*/
4390 static void printpCode(FILE *of, pCode *pc)
4401 fprintf(of,"warning - unable to print pCode\n");
4404 /*-----------------------------------------------------------------*/
4405 /* pic16_printpBlock - write the contents of a pBlock to a file */
4406 /*-----------------------------------------------------------------*/
4407 void pic16_printpBlock(FILE *of, pBlock *pb)
4415 for(pc = pb->pcHead; pc; pc = pc->next) {
4416 if(isPCF(pc) && PCF(pc)->fname) {
4417 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4418 if(pb->dbName == 'A') {
4420 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4421 if(!strcmp(ab->name, PCF(pc)->fname)) {
4422 fprintf(of, "\t0X%06X", ab->address);
4433 /*-----------------------------------------------------------------*/
4435 /* pCode processing */
4439 /*-----------------------------------------------------------------*/
4441 void pic16_unlinkpCode(pCode *pc)
4447 fprintf(stderr,"Unlinking: ");
4448 printpCode(stderr, pc);
4451 pc->prev->next = pc->next;
4453 pc->next->prev = pc->prev;
4455 pc->prev = pc->next = NULL;
4459 /*-----------------------------------------------------------------*/
4460 /*-----------------------------------------------------------------*/
4462 static void genericDestruct(pCode *pc)
4465 pic16_unlinkpCode(pc);
4468 /* For instructions, tell the register (if there's one used)
4469 * that it's no longer needed */
4470 regs *reg = pic16_getRegFromInstruction(pc);
4472 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4474 if(PCI(pc)->is2MemOp) {
4475 reg = pic16_getRegFromInstruction2(pc);
4477 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4481 /* Instead of deleting the memory used by this pCode, mark
4482 * the object as bad so that if there's a pointer to this pCode
4483 * dangling around somewhere then (hopefully) when the type is
4484 * checked we'll catch it.
4488 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4494 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4495 /*-----------------------------------------------------------------*/
4496 /*-----------------------------------------------------------------*/
4497 /* modifiers for constant immediate */
4498 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4500 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4505 int use_buffer = 1; // copy the string to the passed buffer pointer
4510 use_buffer = 0; // Don't bother copying the string to the buffer.
4514 switch(pcop->type) {
4522 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4525 return PCOR(pcop)->r->name;
4528 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4530 SAFE_snprintf(&buffer,&size,"%s",r->name);
4537 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4538 if(PCOI(pcop)->index) {
4539 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4540 immdmod[ PCOI(pcop)->offset ],
4544 SAFE_snprintf(&s,&size,"%s(%s)",
4545 immdmod[ PCOI(pcop)->offset ],
4549 if(PCOI(pcop)->index) {
4550 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4555 SAFE_snprintf(&s,&size, "%s(%s)",
4562 case PO_GPR_REGISTER:
4565 // size = sizeof(buffer);
4566 if( PCOR(pcop)->instance) {
4567 SAFE_snprintf(&s,&size,"(%s + %d)",
4569 PCOR(pcop)->instance );
4571 SAFE_snprintf(&s,&size,"%s",pcop->name);
4578 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4587 return "NO operand1";
4590 /*-----------------------------------------------------------------*/
4591 /* pic16_get_op2 - variant to support two memory operand commands */
4592 /*-----------------------------------------------------------------*/
4593 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4598 int use_buffer = 1; // copy the string to the passed buffer pointer
4603 use_buffer = 0; // Don't bother copying the string to the buffer.
4607 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",
4608 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4609 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4613 switch(PCOR2(pcop)->pcop2->type) {
4621 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4624 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4627 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4630 SAFE_snprintf(&buffer,&size,"%s",r->name);
4641 if(PCOI(pcop)->_const) {
4642 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4643 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4646 8 * PCOI(pcop)->offset );
4648 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4650 if( PCOI(pcop)->index) {
4651 SAFE_snprintf(&s,&size,"(%s + %d)",
4653 PCOI(pcop)->index );
4655 if(PCOI(pcop)->offset)
4656 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4658 SAFE_snprintf(&s,&size,"%s",pcop->name);
4665 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4666 SAFE_snprintf(&s,&size,"(%s + %d)",
4667 PCOR(PCOR2(pcop)->pcop2)->r->name,
4668 PCOR(PCOR2(pcop)->pcop2)->instance );
4670 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4675 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4677 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4680 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4685 return "NO operand2";
4688 /*-----------------------------------------------------------------*/
4689 /*-----------------------------------------------------------------*/
4690 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4694 return pic16_get_op(pcc->pcop,NULL,0);
4696 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4697 * return ("ERROR Null: "__FUNCTION__);
4699 return ("ERROR Null: pic16_get_op_from_instruction");
4703 /*-----------------------------------------------------------------*/
4704 /*-----------------------------------------------------------------*/
4705 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4708 fprintf(of,"pcodeopprint- not implemented\n");
4711 /*-----------------------------------------------------------------*/
4712 /* pic16_pCode2str - convert a pCode instruction to string */
4713 /*-----------------------------------------------------------------*/
4714 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4720 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4721 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4722 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4730 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4732 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4734 if(PCI(pc)->is2MemOp) {
4735 SAFE_snprintf(&s,&size, "%s, %s",
4736 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4737 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4741 if(PCI(pc)->is2LitOp) {
4742 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4746 if(PCI(pc)->isBitInst) {
4747 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4748 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4749 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4750 PCI(pc)->pcop->name ,
4751 PCI(pc)->pcop->name );
4753 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4754 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4755 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4756 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4758 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4759 //PCI(pc)->pcop->t.bit );
4762 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4763 if( PCI(pc)->num_ops == 3)
4764 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4766 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4769 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4771 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4772 if(PCI(pc)->num_ops == 3)
4773 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4775 r = pic16_getRegFromInstruction(pc);
4776 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4777 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4779 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4788 /* assuming that comment ends with a \n */
4789 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4793 /* assuming that inline code ends with a \n */
4794 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4798 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4801 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4804 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4807 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4810 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4811 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4812 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4815 if(PCAD(pc)->directive) {
4816 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4819 /* special case to handle inline labels without a tab */
4820 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4825 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4829 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4837 /*-----------------------------------------------------------------*/
4838 /* genericPrint - the contents of a pCode to a file */
4839 /*-----------------------------------------------------------------*/
4840 static void genericPrint(FILE *of, pCode *pc)
4848 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4852 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4856 // If the opcode has a label, print that first
4858 pBranch *pbl = PCI(pc)->label;
4859 while(pbl && pbl->pc) {
4860 if(pbl->pc->type == PC_LABEL)
4861 pCodePrintLabel(of, pbl->pc);
4867 genericPrint(of,PCODE(PCI(pc)->cline));
4872 pic16_pCode2str(str, 256, pc);
4874 fprintf(of,"%s",str);
4876 if(pic16_debug_verbose) {
4877 fprintf(of, "\t;key=%03x",pc->seq);
4879 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4886 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4887 if(PCW(pc)->pci.label)
4888 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4890 if(PCW(pc)->operand) {
4891 fprintf(of,";\toperand ");
4892 pCodeOpPrint(of,PCW(pc)->operand );
4897 if(pic16_debug_verbose) {
4898 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4899 if(PCFL(pc)->ancestor)
4900 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4907 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4908 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4909 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4915 pBranch *pbl = PCAD(pc)->pci.label;
4916 while(pbl && pbl->pc) {
4917 if(pbl->pc->type == PC_LABEL)
4918 pCodePrintLabel(of, pbl->pc);
4922 if(PCAD(pc)->directive) {
4923 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4926 /* special case to handle inline labels without tab */
4927 fprintf(of, "%s\n", PCAD(pc)->arg);
4933 fprintf(of,"unknown pCode type %d\n",pc->type);
4938 /*-----------------------------------------------------------------*/
4939 /* pCodePrintFunction - prints function begin/end */
4940 /*-----------------------------------------------------------------*/
4942 static void pCodePrintFunction(FILE *of, pCode *pc)
4949 if( ((pCodeFunction *)pc)->modname)
4950 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4953 if(!PCF(pc)->absblock) {
4954 if(PCF(pc)->fname) {
4955 pBranch *exits = PCF(pc)->to;
4958 fprintf(of,"%s:", PCF(pc)->fname);
4960 if(pic16_pcode_verbose)
4961 fprintf(of, "\t;Function start");
4967 exits = exits->next;
4971 if(pic16_pcode_verbose)
4972 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4975 if((PCF(pc)->from &&
4976 PCF(pc)->from->pc->type == PC_FUNCTION &&
4977 PCF(PCF(pc)->from->pc)->fname) ) {
4979 if(pic16_pcode_verbose)
4980 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4982 if(pic16_pcode_verbose)
4983 fprintf(of,"; exit point [can't find entry point]\n");
4989 /*-----------------------------------------------------------------*/
4990 /* pCodePrintLabel - prints label */
4991 /*-----------------------------------------------------------------*/
4993 static void pCodePrintLabel(FILE *of, pCode *pc)
5000 fprintf(of,"%s:\n",PCL(pc)->label);
5001 else if (PCL(pc)->key >=0)
5002 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5004 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5007 /*-----------------------------------------------------------------*/
5008 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5009 /* remove it if it is found. */
5010 /*-----------------------------------------------------------------*/
5011 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5018 if(pcl->type == PC_OPCODE)
5019 b = PCI(pcl)->label;
5021 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5026 //fprintf (stderr, "%s \n",__FUNCTION__);
5027 //pcl->print(stderr,pcl);
5028 //pc->print(stderr,pc);
5031 //fprintf (stderr, "found label\n");
5032 //pc->print(stderr, pc);
5036 bprev->next = b->next; /* Not first pCode in chain */
5040 PCI(pcl)->label = b->next; /* First pCode in chain */
5043 return; /* A label can't occur more than once */
5051 /*-----------------------------------------------------------------*/
5052 /*-----------------------------------------------------------------*/
5053 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5072 /*-----------------------------------------------------------------*/
5073 /* pBranchLink - given two pcodes, this function will link them */
5074 /* together through their pBranches */
5075 /*-----------------------------------------------------------------*/
5076 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5080 // Declare a new branch object for the 'from' pCode.
5082 //_ALLOC(b,sizeof(pBranch));
5083 b = Safe_calloc(1,sizeof(pBranch));
5084 b->pc = PCODE(t); // The link to the 'to' pCode.
5087 f->to = pic16_pBranchAppend(f->to,b);
5089 // Now do the same for the 'to' pCode.
5091 //_ALLOC(b,sizeof(pBranch));
5092 b = Safe_calloc(1,sizeof(pBranch));
5096 t->from = pic16_pBranchAppend(t->from,b);
5101 /*-----------------------------------------------------------------*/
5102 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5104 /*-----------------------------------------------------------------*/
5105 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5118 /*-----------------------------------------------------------------*/
5119 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5120 /*-----------------------------------------------------------------*/
5121 void pic16_pCodeUnlink(pCode *pc)
5126 if(!pc->prev || !pc->next) {
5127 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5131 /* first remove the pCode from the chain */
5132 pc->prev->next = pc->next;
5133 pc->next->prev = pc->prev;
5135 /* Now for the hard part... */
5137 /* Remove the branches */
5139 pb1 = PCI(pc)->from;
5141 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5142 * one we're unlinking */
5144 /* search for the link back to this pCode (the one we're
5146 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5147 pb2->pc = PCI(pc)->to->pc; // make the replacement
5149 /* if the pCode we're unlinking contains multiple 'to'
5150 * branches (e.g. this a skip instruction) then we need
5151 * to copy these extra branches to the chain. */
5152 if(PCI(pc)->to->next)
5153 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5162 /*-----------------------------------------------------------------*/
5163 /*-----------------------------------------------------------------*/
5165 static void genericAnalyze(pCode *pc)
5175 // Go through the pCodes that are in pCode chain and link
5176 // them together through the pBranches. Note, the pCodes
5177 // are linked together as a contiguous stream like the
5178 // assembly source code lines. The linking here mimics this
5179 // except that comments are not linked in.
5181 pCode *npc = pc->next;
5183 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5184 pBranchLink(pc,npc);
5189 /* reached the end of the pcode chain without finding
5190 * an instruction we could link to. */
5194 fprintf(stderr,"analyze PC_FLOW\n");
5198 fprintf(stderr,,";A bad pCode is being used\n");
5204 /*-----------------------------------------------------------------*/
5205 /*-----------------------------------------------------------------*/
5206 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5210 if(pc->type == PC_LABEL) {
5211 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5214 if((pc->type == PC_OPCODE)
5215 || (pc->type == PC_ASMDIR)
5217 pbr = PCI(pc)->label;
5219 if(pbr->pc->type == PC_LABEL) {
5220 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5230 /*-----------------------------------------------------------------*/
5231 /*-----------------------------------------------------------------*/
5232 static int checkLabel(pCode *pc)
5236 if(pc && isPCI(pc)) {
5237 pbr = PCI(pc)->label;
5239 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5249 /*-----------------------------------------------------------------*/
5250 /* findLabelinpBlock - Search the pCode for a particular label */
5251 /*-----------------------------------------------------------------*/
5252 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5259 for(pc = pb->pcHead; pc; pc = pc->next)
5260 if(compareLabel(pc,pcop_label))
5266 /*-----------------------------------------------------------------*/
5267 /* findLabel - Search the pCode for a particular label */
5268 /*-----------------------------------------------------------------*/
5269 static pCode * findLabel(pCodeOpLabel *pcop_label)
5277 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5278 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5282 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5286 /*-----------------------------------------------------------------*/
5287 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5288 /* in the linked list */
5289 /*-----------------------------------------------------------------*/
5290 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5303 /*-----------------------------------------------------------------*/
5304 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5305 /* in the linked list */
5306 /*-----------------------------------------------------------------*/
5307 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5321 //#define PCODE_DEBUG
5322 /*-----------------------------------------------------------------*/
5323 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5324 /* in the linked list */
5325 /*-----------------------------------------------------------------*/
5326 pCode * pic16_findNextInstruction(pCode *pci)
5331 if((pc->type == PC_OPCODE)
5332 || (pc->type == PC_WILD)
5333 || (pc->type == PC_ASMDIR)
5338 fprintf(stderr,"pic16_findNextInstruction: ");
5339 printpCode(stderr, pc);
5344 //fprintf(stderr,"Couldn't find instruction\n");
5348 /*-----------------------------------------------------------------*/
5349 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5350 /* in the linked list */
5351 /*-----------------------------------------------------------------*/
5352 pCode * pic16_findPrevInstruction(pCode *pci)
5358 if((pc->type == PC_OPCODE)
5359 || (pc->type == PC_WILD)
5360 || (pc->type == PC_ASMDIR)
5366 fprintf(stderr,"pic16_findPrevInstruction: ");
5367 printpCode(stderr, pc);
5372 //fprintf(stderr,"Couldn't find instruction\n");
5379 /*-----------------------------------------------------------------*/
5380 /* findFunctionEnd - given a pCode find the end of the function */
5381 /* that contains it */
5382 /*-----------------------------------------------------------------*/
5383 static pCode * findFunctionEnd(pCode *pc)
5387 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5393 fprintf(stderr,"Couldn't find function end\n");
5398 /*-----------------------------------------------------------------*/
5399 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5400 /* instruction with which it is associated. */
5401 /*-----------------------------------------------------------------*/
5402 static void AnalyzeLabel(pCode *pc)
5405 pic16_pCodeUnlink(pc);
5411 static void AnalyzeGOTO(pCode *pc)
5414 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5418 static void AnalyzeSKIP(pCode *pc)
5421 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5422 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5426 static void AnalyzeRETURN(pCode *pc)
5429 // branch_link(pc,findFunctionEnd(pc->next));
5435 /*-----------------------------------------------------------------*/
5436 /*-----------------------------------------------------------------*/
5437 regs * pic16_getRegFromInstruction(pCode *pc)
5443 PCI(pc)->num_ops == 0 ||
5444 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5448 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5449 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5452 switch(PCI(pc)->pcop->type) {
5458 return PCOR(PCI(pc)->pcop)->r;
5462 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5463 return PCOR(PCI(pc)->pcop)->r;
5466 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5468 if(PCOI(PCI(pc)->pcop)->r)
5469 return (PCOI(PCI(pc)->pcop)->r);
5474 return PCOR(PCI(pc)->pcop)->r;
5476 case PO_GPR_REGISTER:
5478 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5479 return PCOR(PCI(pc)->pcop)->r;
5482 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5486 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5487 // genericPrint(stderr, pc);
5495 /*-------------------------------------------------------------------------------*/
5496 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5497 /*-------------------------------------------------------------------------------*/
5498 regs * pic16_getRegFromInstruction2(pCode *pc)
5504 PCI(pc)->num_ops == 0 ||
5505 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5510 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5511 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5515 * operands supported in MOVFF:
5522 switch(PCI(pc)->pcop->type) {
5528 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5530 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5534 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5535 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5539 // if(PCOI(PCI(pc)->pcop)->r)
5540 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5542 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5543 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5546 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5547 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5554 // return PCOR2(PCI(pc)->pcop)->r;
5556 case PO_GPR_REGISTER:
5558 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5559 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5563 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5566 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5567 //genericPrint(stderr, pc);
5575 /*-----------------------------------------------------------------*/
5576 /*-----------------------------------------------------------------*/
5578 static void AnalyzepBlock(pBlock *pb)
5585 /* Find all of the registers used in this pBlock
5586 * by looking at each instruction and examining it's
5589 for(pc = pb->pcHead; pc; pc = pc->next) {
5591 /* Is this an instruction with operands? */
5592 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5594 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5596 /* Loop through all of the registers declared so far in
5597 this block and see if we find this one there */
5599 regs *r = setFirstItem(pb->tregisters);
5602 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5603 PCOR(PCI(pc)->pcop)->r = r;
5606 r = setNextItem(pb->tregisters);
5610 /* register wasn't found */
5611 //r = Safe_calloc(1, sizeof(regs));
5612 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5613 //addSet(&pb->tregisters, r);
5614 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5615 //PCOR(PCI(pc)->pcop)->r = r;
5616 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5618 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5621 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5622 if(PCOR(PCI(pc)->pcop)->r) {
5623 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5624 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5626 if(PCI(pc)->pcop->name)
5627 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5629 fprintf(stderr,"ERROR: NULL register\n");
5638 /*-----------------------------------------------------------------*/
5640 /*-----------------------------------------------------------------*/
5641 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5643 static void InsertpFlow(pCode *pc, pCode **pflow)
5646 PCFL(*pflow)->end = pc;
5648 if(!pc || !pc->next)
5651 *pflow = pic16_newpCodeFlow();
5652 pic16_pCodeInsertAfter(pc, *pflow);
5655 /*-----------------------------------------------------------------*/
5656 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5657 /* the flow blocks. */
5659 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5660 * point the instruction flow changes.
5662 /*-----------------------------------------------------------------*/
5663 void pic16_BuildFlow(pBlock *pb)
5666 pCode *last_pci=NULL;
5673 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5674 /* Insert a pCodeFlow object at the beginning of a pBlock */
5676 InsertpFlow(pb->pcHead, &pflow);
5678 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5679 //pflow->next = pb->pcHead; /* Make the current head the next object */
5680 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5681 //pb->pcHead = pflow; /* Make the Flow object the head */
5684 for( pc = pic16_findNextInstruction(pb->pcHead);
5686 pc=pic16_findNextInstruction(pc)) {
5689 PCI(pc)->pcflow = PCFL(pflow);
5691 //fprintf(stderr," build: ");
5692 //pflow->print(stderr,pflow);
5694 if( PCI(pc)->isSkip) {
5696 /* The two instructions immediately following this one
5697 * mark the beginning of a new flow segment */
5699 while(pc && PCI(pc)->isSkip) {
5701 PCI(pc)->pcflow = PCFL(pflow);
5705 InsertpFlow(pc, &pflow);
5706 pc=pic16_findNextInstruction(pc->next);
5714 PCI(pc)->pcflow = PCFL(pflow);
5716 InsertpFlow(pc, &pflow);
5718 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5720 InsertpFlow(pc, &pflow);
5723 } else if (checkLabel(pc)) {
5725 /* This instruction marks the beginning of a
5726 * new flow segment */
5731 /* If the previous pCode is not a flow object, then
5732 * insert a new flow object. (This check prevents
5733 * two consecutive flow objects from being insert in
5734 * the case where a skip instruction preceeds an
5735 * instruction containing a label.) */
5737 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5738 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5740 PCI(pc)->pcflow = PCFL(pflow);
5747 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5749 PCFL(pflow)->end = pb->pcTail;
5752 /*-------------------------------------------------------------------*/
5753 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5754 /* the flow blocks. */
5756 * unBuildFlow removes pCodeFlow objects from a pCode chain
5758 /*-----------------------------------------------------------------*/
5759 static void unBuildFlow(pBlock *pb)
5774 if(PCI(pc)->pcflow) {
5775 //free(PCI(pc)->pcflow);
5776 PCI(pc)->pcflow = NULL;
5779 } else if(isPCFL(pc) )
5788 /*-----------------------------------------------------------------*/
5789 /*-----------------------------------------------------------------*/
5790 static void dumpCond(int cond)
5793 static char *pcc_str[] = {
5807 int ncond = sizeof(pcc_str) / sizeof(char *);
5810 fprintf(stderr, "0x%04X\n",cond);
5812 for(i=0,j=1; i<ncond; i++, j<<=1)
5814 fprintf(stderr, " %s\n",pcc_str[i]);
5820 /*-----------------------------------------------------------------*/
5821 /*-----------------------------------------------------------------*/
5822 static void FlowStats(pCodeFlow *pcflow)
5830 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5832 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5835 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5840 fprintf(stderr, " FlowStats inCond: ");
5841 dumpCond(pcflow->inCond);
5842 fprintf(stderr, " FlowStats outCond: ");
5843 dumpCond(pcflow->outCond);
5847 /*-----------------------------------------------------------------*
5848 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5849 * if it affects the banking bits.
5851 * return: -1 == Banking bits are unaffected by this pCode.
5853 * return: > 0 == Banking bits are affected.
5855 * If the banking bits are affected, then the returned value describes
5856 * which bits are affected and how they're affected. The lower half
5857 * of the integer maps to the bits that are affected, the upper half
5858 * to whether they're set or cleared.
5860 *-----------------------------------------------------------------*/
5862 static int isBankInstruction(pCode *pc)
5870 if( PCI(pc)->op == POC_MOVLB ||
5871 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5872 bank = PCOL(pc)->lit;
5879 /*-----------------------------------------------------------------*/
5880 /*-----------------------------------------------------------------*/
5881 static void FillFlow(pCodeFlow *pcflow)
5890 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5892 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5895 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5902 isBankInstruction(pc);
5904 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5908 fprintf(stderr, " FillFlow - Bad end of flow\n");
5910 fprintf(stderr, " FillFlow - Ending flow with\n ");
5911 pc->print(stderr,pc);
5914 fprintf(stderr, " FillFlow inCond: ");
5915 dumpCond(pcflow->inCond);
5916 fprintf(stderr, " FillFlow outCond: ");
5917 dumpCond(pcflow->outCond);
5921 /*-----------------------------------------------------------------*/
5922 /*-----------------------------------------------------------------*/
5923 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5925 pCodeFlowLink *fromLink, *toLink;
5927 if(!from || !to || !to->pcflow || !from->pcflow)
5930 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5931 toLink = pic16_newpCodeFlowLink(to->pcflow);
5933 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5934 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5938 /*-----------------------------------------------------------------*
5939 * void LinkFlow(pBlock *pb)
5941 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5942 * non-branching segments. In LinkFlow, we determine the execution
5943 * order of these segments. For example, if one of the segments ends
5944 * with a skip, then we know that there are two possible flow segments
5945 * to which control may be passed.
5946 *-----------------------------------------------------------------*/
5947 static void LinkFlow(pBlock *pb)
5953 //fprintf(stderr,"linkflow \n");
5955 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5957 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5960 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5962 //fprintf(stderr," link: ");
5963 //pcflow->print(stderr,pcflow);
5965 //FillFlow(PCFL(pcflow));
5967 pc = PCFL(pcflow)->end;
5969 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5970 if(isPCI_SKIP(pc)) {
5971 //fprintf(stderr, "ends with skip\n");
5972 //pc->print(stderr,pc);
5973 pct=pic16_findNextInstruction(pc->next);
5974 LinkFlow_pCode(PCI(pc),PCI(pct));
5975 pct=pic16_findNextInstruction(pct->next);
5976 LinkFlow_pCode(PCI(pc),PCI(pct));
5980 if(isPCI_BRANCH(pc)) {
5981 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5983 //fprintf(stderr, "ends with branch\n ");
5984 //pc->print(stderr,pc);
5986 if(!(pcol && isPCOLAB(pcol))) {
5987 if((PCI(pc)->op != POC_RETLW)
5988 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5990 /* continue if label is '$' which assembler knows how to parse */
5991 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5993 if(pic16_pcode_verbose) {
5994 pc->print(stderr,pc);
5995 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6001 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6002 LinkFlow_pCode(PCI(pc),PCI(pct));
6004 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6005 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6007 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6013 //fprintf(stderr, "ends with non-branching instruction:\n");
6014 //pc->print(stderr,pc);
6016 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6022 //fprintf(stderr, "ends with unknown\n");
6023 //pc->print(stderr,pc);
6027 //fprintf(stderr, "ends with nothing: ERROR\n");
6031 /*-----------------------------------------------------------------*/
6032 /*-----------------------------------------------------------------*/
6034 /*-----------------------------------------------------------------*/
6035 /*-----------------------------------------------------------------*/
6036 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6042 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6045 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6055 /*-----------------------------------------------------------------*/
6056 /* insertBankSwitch - inserts a bank switch statement in the */
6057 /* assembly listing */
6059 /* position == 0: insert before */
6060 /* position == 1: insert after pc */
6061 /* position == 2: like 0 but previous was a skip instruction */
6062 /*-----------------------------------------------------------------*/
6063 pCodeOp *pic16_popGetLabel(unsigned int key);
6064 extern int pic16_labelOffset;
6066 static void insertBankSwitch(unsigned char position, pCode *pc)
6073 /* emit BANKSEL [symbol] */
6076 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6078 // position = 0; // position is always before (sanity check!)
6081 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6082 pc->print(stderr, pc);
6087 /* insert the bank switch after this pc instruction */
6088 pCode *pcnext = pic16_findNextInstruction(pc);
6090 pic16_pCodeInsertAfter(pc, new_pc);
6091 if(pcnext)pc = pcnext;
6095 /* insert the bank switch BEFORE this pc instruction */
6096 pic16_pCodeInsertAfter(pc->prev, new_pc);
6101 pCode *pcnext, *pcprev, *npci, *ppc;
6103 int ofs1=0, ofs2=0, len=0;
6105 /* just like 0, but previous was a skip instruction,
6106 * so some care should be taken */
6108 pic16_labelOffset += 10000;
6109 tlbl = newiTempLabel(NULL);
6111 /* invert skip instruction */
6112 pcprev = pic16_findPrevInstruction(pc->prev);
6113 ipci = PCI(pcprev)->inverted_op;
6114 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6116 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6118 /* copy info from old pCode */
6119 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6120 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6121 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6122 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6123 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6124 PCI(npci)->op = PCI(pcprev)->inverted_op;
6126 /* unlink old pCode */
6128 ppc->next = pcprev->next;
6129 pcprev->next->prev = ppc;
6130 pic16_pCodeInsertAfter(ppc, npci);
6132 /* extra instructions to handle invertion */
6133 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6134 pic16_pCodeInsertAfter(npci, pcnext);
6135 pic16_pCodeInsertAfter(pc->prev, new_pc);
6137 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6138 pic16_pCodeInsertAfter(pc, pcnext);
6143 /* Move the label, if there is one */
6144 if(PCI(pc)->label) {
6145 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6146 // __FILE__, __LINE__, pc, new_pc);
6147 PCAD(new_pc)->pci.label = PCI(pc)->label;
6148 PCI(pc)->label = NULL;
6153 /*-----------------------------------------------------------------*/
6154 /*int compareBankFlow - compare the banking requirements between */
6156 /*-----------------------------------------------------------------*/
6157 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6160 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6163 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6166 if(pcflow->firstBank == -1)
6170 if(pcflowLink->pcflow->firstBank == -1) {
6171 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6172 pcflowLink->pcflow->to :
6173 pcflowLink->pcflow->from);
6174 return compareBankFlow(pcflow, pctl, toORfrom);
6178 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6181 pcflowLink->bank_conflict++;
6182 pcflowLink->pcflow->FromConflicts++;
6183 pcflow->ToConflicts++;
6186 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6189 pcflowLink->bank_conflict++;
6190 pcflowLink->pcflow->ToConflicts++;
6191 pcflow->FromConflicts++;
6195 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6196 pcflowLink->pcflow->pc.seq,
6197 pcflowLink->pcflow->FromConflicts,
6198 pcflowLink->pcflow->ToConflicts);
6205 /*-----------------------------------------------------------------*/
6206 /*-----------------------------------------------------------------*/
6207 static void DumpFlow(pBlock *pb)
6211 pCodeFlowLink *pcfl;
6214 fprintf(stderr,"Dump flow \n");
6215 pb->pcHead->print(stderr, pb->pcHead);
6217 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6218 pcflow->print(stderr,pcflow);
6220 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6222 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6224 if(!isPCFL(pcflow)) {
6225 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6228 fprintf(stderr,"dumping: ");
6229 pcflow->print(stderr,pcflow);
6230 FlowStats(PCFL(pcflow));
6232 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6234 pc = PCODE(pcfl->pcflow);
6236 fprintf(stderr, " from seq %d:\n",pc->seq);
6238 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6239 pc->print(stderr,pc);
6244 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6246 pc = PCODE(pcfl->pcflow);
6248 fprintf(stderr, " to seq %d:\n",pc->seq);
6250 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6251 pc->print(stderr,pc);
6260 /*-----------------------------------------------------------------*/
6261 /*-----------------------------------------------------------------*/
6262 static int OptimizepBlock(pBlock *pb)
6267 if(!pb || !peepOptimizing)
6270 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6272 for(pc = pb->pcHead; pc; pc = pc->next)
6273 matches += pic16_pCodePeepMatchRule(pc);
6276 pc = pic16_findNextInstruction(pb->pcHead);
6284 if(pic16_pCodePeepMatchRule(pc)) {
6289 pc = pic16_findNextInstruction(pcprev->next);
6291 pc = pic16_findNextInstruction(pb->pcHead);
6293 pc = pic16_findNextInstruction(pc->next);
6297 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6302 /*-----------------------------------------------------------------*/
6303 /*-----------------------------------------------------------------*/
6304 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6308 for(pc = pcs; pc; pc = pc->next) {
6310 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6312 (PCI(pc)->pcop->type == PO_LABEL) &&
6313 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6321 /*-----------------------------------------------------------------*/
6322 /*-----------------------------------------------------------------*/
6323 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6330 (PCI(pc)->pcop->type == PO_LABEL)) {
6332 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6334 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6335 // if(pcol->pcop.name)
6336 // free(pcol->pcop.name);
6338 /* If the key is negative, then we (probably) have a label to
6339 * a function and the name is already defined */
6342 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6346 //sprintf(buffer,"_%05d_DS_",pcl->key);
6348 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6350 pcol->pcop.name = Safe_strdup(s);
6351 pcol->key = pcl->key;
6352 //pc->print(stderr,pc);
6359 /*-----------------------------------------------------------------*/
6360 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6361 /* pCode chain if they're not used. */
6362 /*-----------------------------------------------------------------*/
6363 static void pBlockRemoveUnusedLabels(pBlock *pb)
6365 pCode *pc; pCodeLabel *pcl;
6370 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6372 pBranch *pbr = PCI(pc)->label;
6373 if(pbr && pbr->next) {
6374 pCode *pcd = pb->pcHead;
6376 // fprintf(stderr, "multiple labels\n");
6377 // pc->print(stderr,pc);
6382 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6383 //fprintf(stderr,"Used by:\n");
6384 //pcd->print(stderr,pcd);
6386 exchangeLabels(PCL(pbr->pc),pcd);
6395 for(pc = pb->pcHead; pc; pc = pc->next) {
6397 if(isPCL(pc)) // pc->type == PC_LABEL)
6399 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6400 pcl = PCL(PCI(pc)->label->pc);
6403 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6405 /* This pCode is a label, so search the pBlock to see if anyone
6408 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6410 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6411 /* Couldn't find an instruction that refers to this label
6412 * So, unlink the pCode label from it's pCode chain
6413 * and destroy the label */
6414 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6416 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6417 if(pc->type == PC_LABEL) {
6418 pic16_unlinkpCode(pc);
6419 pCodeLabelDestruct(pc);
6421 unlinkpCodeFromBranch(pc, PCODE(pcl));
6422 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6433 /*-----------------------------------------------------------------*/
6434 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6435 /* chain and put them into pBranches that are */
6436 /* associated with the appropriate pCode */
6438 /*-----------------------------------------------------------------*/
6439 void pic16_pBlockMergeLabels(pBlock *pb)
6442 pCode *pc, *pcnext=NULL;
6447 /* First, Try to remove any unused labels */
6448 //pBlockRemoveUnusedLabels(pb);
6450 /* Now loop through the pBlock and merge the labels with the opcodes */
6453 // for(pc = pb->pcHead; pc; pc = pc->next) {
6456 pCode *pcn = pc->next;
6458 if(pc->type == PC_LABEL) {
6460 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6461 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6463 if((pcnext = pic16_findNextInstruction(pc) )) {
6465 // pcnext->print(stderr, pcnext);
6467 // Unlink the pCode label from it's pCode chain
6468 pic16_unlinkpCode(pc);
6470 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6471 // And link it into the instruction's pBranch labels. (Note, since
6472 // it's possible to have multiple labels associated with one instruction
6473 // we must provide a means to accomodate the additional labels. Thus
6474 // the labels are placed into the singly-linked list "label" as
6475 // opposed to being a single member of the pCodeInstruction.)
6477 //_ALLOC(pbr,sizeof(pBranch));
6479 pbr = Safe_calloc(1,sizeof(pBranch));
6483 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6486 if(pic16_pcode_verbose)
6487 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6489 } else if(pc->type == PC_CSOURCE) {
6491 /* merge the source line symbolic info into the next instruction */
6492 if((pcnext = pic16_findNextInstruction(pc) )) {
6494 // Unlink the pCode label from it's pCode chain
6495 pic16_unlinkpCode(pc);
6496 PCI(pcnext)->cline = PCCS(pc);
6497 //fprintf(stderr, "merging CSRC\n");
6498 //genericPrint(stderr,pcnext);
6504 pBlockRemoveUnusedLabels(pb);
6508 /*-----------------------------------------------------------------*/
6509 /*-----------------------------------------------------------------*/
6510 static int OptimizepCode(char dbName)
6512 #define MAX_PASSES 4
6521 DFPRINTF((stderr," Optimizing pCode\n"));
6525 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6526 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6527 matches += OptimizepBlock(pb);
6530 while(matches && ++passes < MAX_PASSES);
6537 const char *pic16_pCodeOpType(pCodeOp *pcop);
6538 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6541 /*-----------------------------------------------------------------*/
6542 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6543 /*-----------------------------------------------------------------*/
6545 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6549 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6550 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6552 if( !( (pcop->type == PO_LABEL) ||
6553 (pcop->type == PO_LITERAL) ||
6554 (pcop->type == PO_STR) ))
6555 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6556 PCOR(pcop)->r->wasUsed = 1;
6562 /*----------------------------------------------------------------------*
6563 * pic16_areRegsSame - check to see if the names of two registers match *
6564 *----------------------------------------------------------------------*/
6565 int pic16_areRegsSame(regs *r1, regs *r2)
6567 if(!strcmp(r1->name, r2->name))return 1;
6573 /*-----------------------------------------------------------------*/
6574 /*-----------------------------------------------------------------*/
6575 static void pic16_FixRegisterBanking(pBlock *pb)
6579 regs *reg, *prevreg;
6580 unsigned char flag=0;
6585 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6588 /* loop through all of the flow blocks with in one pblock */
6590 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6594 /* at this point, pc should point to a PC_FLOW object */
6595 /* for each flow block, determine the register banking
6598 if(!isPCI(pc))goto loop;
6600 if(PCI(pc)->is2MemOp)goto loop;
6602 reg = pic16_getRegFromInstruction(pc);
6605 pc->print(stderr, pc);
6606 fprintf(stderr, "reg = %p\n", reg);
6609 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6610 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6611 reg->address,reg->isBitField, reg->isFixed);
6615 /* now make some tests to make sure that instruction needs bank switch */
6617 /* if no register exists, and if not a bit opcode goto loop */
6619 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6622 if(isPCI_SKIP(pc)) {
6623 // fprintf(stderr, "instruction is SKIP instruction\n");
6625 if(reg && isACCESS_BANK(reg))goto loop;
6627 if(!isBankInstruction(pc))goto loop;
6629 if(isPCI_LIT(pc))goto loop;
6631 if(PCI(pc)->op == POC_CALL)goto loop;
6633 /* Examine the instruction before this one to make sure it is
6634 * not a skip type instruction */
6635 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6637 flag = 0; /* add before this instruction */
6639 /* if previous instruction is a skip one, then set flag
6640 * to 2 and call insertBankSwitch */
6641 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6644 insertBankSwitch(flag, pc);
6647 // fprintf(stderr, "BANK SWITCH inserted\n");
6656 static void pBlockDestruct(pBlock *pb)
6667 /*-----------------------------------------------------------------*/
6668 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6669 /* name dbName and combine them */
6670 /* into one block */
6671 /*-----------------------------------------------------------------*/
6672 static void mergepBlocks(char dbName)
6675 pBlock *pb, *pbmerged = NULL,*pbn;
6677 pb = the_pFile->pbHead;
6679 //fprintf(stderr," merging blocks named %c\n",dbName);
6683 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6684 if( getpBlock_dbName(pb) == dbName) {
6686 //fprintf(stderr," merged block %c\n",dbName);
6691 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6692 /* pic16_addpCode2pBlock doesn't handle the tail: */
6693 pbmerged->pcTail = pb->pcTail;
6695 pb->prev->next = pbn;
6697 pbn->prev = pb->prev;
6702 //pic16_printpBlock(stderr, pbmerged);
6709 /*-----------------------------------------------------------------*/
6710 /* AnalyzeFlow - Examine the flow of the code and optimize */
6712 /* level 0 == minimal optimization */
6713 /* optimize registers that are used only by two instructions */
6714 /* level 1 == maximal optimization */
6715 /* optimize by looking at pairs of instructions that use the */
6717 /*-----------------------------------------------------------------*/
6719 static void AnalyzeFlow(int level)
6721 static int times_called=0;
6726 /* remove unused allocated registers before exiting */
6727 pic16_RemoveUnusedRegisters();
6733 /* if this is not the first time this function has been called,
6734 then clean up old flow information */
6735 if(times_called++) {
6736 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6739 pic16_RegsUnMapLiveRanges();
6744 /* Phase 2 - Flow Analysis - Register Banking
6746 * In this phase, the individual flow blocks are examined
6747 * and register banking is fixed.
6751 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6752 pic16_FixRegisterBanking(pb);
6755 /* Phase 2 - Flow Analysis
6757 * In this phase, the pCode is partition into pCodeFlow
6758 * blocks. The flow blocks mark the points where a continuous
6759 * stream of instructions changes flow (e.g. because of
6760 * a call or goto or whatever).
6763 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6764 pic16_BuildFlow(pb);
6767 /* Phase 2 - Flow Analysis - linking flow blocks
6769 * In this phase, the individual flow blocks are examined
6770 * to determine their order of excution.
6773 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6776 /* Phase 3 - Flow Analysis - Flow Tree
6778 * In this phase, the individual flow blocks are examined
6779 * to determine their order of execution.
6782 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6783 pic16_BuildFlowTree(pb);
6786 /* Phase x - Flow Analysis - Used Banks
6788 * In this phase, the individual flow blocks are examined
6789 * to determine the Register Banks they use
6793 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6798 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6799 pic16_pCodeRegMapLiveRanges(pb);
6801 pic16_RemoveUnusedRegisters();
6803 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6804 pic16_pCodeRegOptimizeRegUsage(level);
6812 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6817 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6819 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6820 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6821 pcflow = pcflow->next) {
6823 FillFlow(PCFL(pcflow));
6828 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6831 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6832 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6833 pcflow = pcflow->next) {
6835 FlowStats(PCFL(pcflow));
6841 /* VR -- no need to analyze banking in flow, but left here :
6842 * 1. because it may be used in the future for other purposes
6843 * 2. because if omitted we'll miss some optimization done here
6845 * Perhaps I should rename it to something else
6848 /*-----------------------------------------------------------------*/
6849 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6850 /* assigned to the registers. */
6852 /*-----------------------------------------------------------------*/
6854 void pic16_AnalyzeBanking(void)
6859 /* Phase x - Flow Analysis - Used Banks
6861 * In this phase, the individual flow blocks are examined
6862 * to determine the Register Banks they use
6868 if(!the_pFile)return;
6870 if(!pic16_options.no_banksel) {
6871 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6872 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6873 pic16_FixRegisterBanking(pb);
6879 /*-----------------------------------------------------------------*/
6880 /* buildCallTree - Look at the flow and extract all of the calls. */
6881 /*-----------------------------------------------------------------*/
6882 static set *register_usage(pBlock *pb);
6884 static void buildCallTree(void )
6896 /* Now build the call tree.
6897 First we examine all of the pCodes for functions.
6898 Keep in mind that the function boundaries coincide
6899 with pBlock boundaries.
6901 The algorithm goes something like this:
6902 We have two nested loops. The outer loop iterates
6903 through all of the pBlocks/functions. The inner
6904 loop iterates through all of the pCodes for
6905 a given pBlock. When we begin iterating through
6906 a pBlock, the variable pc_fstart, pCode of the start
6907 of a function, is cleared. We then search for pCodes
6908 of type PC_FUNCTION. When one is encountered, we
6909 initialize pc_fstart to this and at the same time
6910 associate a new pBranch object that signifies a
6911 branch entry. If a return is found, then this signifies
6912 a function exit point. We'll link the pCodes of these
6913 returns to the matching pc_fstart.
6915 When we're done, a doubly linked list of pBranches
6916 will exist. The head of this list is stored in
6917 `the_pFile', which is the meta structure for all
6918 of the pCode. Look at the pic16_printCallTree function
6919 on how the pBranches are linked together.
6922 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6923 pCode *pc_fstart=NULL;
6924 for(pc = pb->pcHead; pc; pc = pc->next) {
6926 if(isPCI(pc) && pc_fstart) {
6927 if(PCI(pc)->is2MemOp) {
6928 r = pic16_getRegFromInstruction2(pc);
6929 if(r && !strcmp(r->name, "POSTDEC1"))
6930 PCF(pc_fstart)->stackusage++;
6932 r = pic16_getRegFromInstruction(pc);
6933 if(r && !strcmp(r->name, "PREINC1"))
6934 PCF(pc_fstart)->stackusage--;
6939 if (PCF(pc)->fname) {
6941 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6942 //fprintf(stderr," found main \n");
6943 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6947 pbr = Safe_calloc(1,sizeof(pBranch));
6948 pbr->pc = pc_fstart = pc;
6951 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6953 // Here's a better way of doing the same:
6954 addSet(&pb->function_entries, pc);
6957 // Found an exit point in a function, e.g. return
6958 // (Note, there may be more than one return per function)
6960 pBranchLink(PCF(pc_fstart), PCF(pc));
6962 addSet(&pb->function_exits, pc);
6964 } else if(isCALL(pc)) {
6965 addSet(&pb->function_calls,pc);
6972 /* This is not needed because currently all register used
6973 * by a function are stored in stack -- VR */
6975 /* Re-allocate the registers so that there are no collisions
6976 * between local variables when one function call another */
6979 // pic16_deallocateAllRegs();
6981 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6989 /*-----------------------------------------------------------------*/
6990 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6991 /* all of the logical connections. */
6993 /* Essentially what's done here is that the pCode flow is */
6995 /*-----------------------------------------------------------------*/
6997 void pic16_AnalyzepCode(char dbName)
7008 /* Phase 1 - Register allocation and peep hole optimization
7010 * The first part of the analysis is to determine the registers
7011 * that are used in the pCode. Once that is done, the peep rules
7012 * are applied to the code. We continue to loop until no more
7013 * peep rule optimizations are found (or until we exceed the
7014 * MAX_PASSES threshold).
7016 * When done, the required registers will be determined.
7022 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7023 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7025 /* First, merge the labels with the instructions */
7026 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7027 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7029 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7030 //fprintf(stderr," analyze and merging block %c\n",dbName);
7031 pic16_pBlockMergeLabels(pb);
7034 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7039 changes = OptimizepCode(dbName);
7042 } while(changes && (i++ < MAX_PASSES));
7047 /*-----------------------------------------------------------------*/
7048 /* ispCodeFunction - returns true if *pc is the pCode of a */
7050 /*-----------------------------------------------------------------*/
7051 static bool ispCodeFunction(pCode *pc)
7054 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7060 /*-----------------------------------------------------------------*/
7061 /* findFunction - Search for a function by name (given the name) */
7062 /* in the set of all functions that are in a pBlock */
7063 /* (note - I expect this to change because I'm planning to limit */
7064 /* pBlock's to just one function declaration */
7065 /*-----------------------------------------------------------------*/
7066 static pCode *findFunction(char *fname)
7073 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7075 pc = setFirstItem(pb->function_entries);
7078 if((pc->type == PC_FUNCTION) &&
7080 (strcmp(fname, PCF(pc)->fname)==0))
7083 pc = setNextItem(pb->function_entries);
7091 static void MarkUsedRegisters(set *regset)
7096 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7097 // fprintf(stderr, "marking register = %s\t", r1->name);
7098 r2 = pic16_regWithIdx(r1->rIdx);
7099 // fprintf(stderr, "to register = %s\n", r2->name);
7105 static void pBlockStats(FILE *of, pBlock *pb)
7111 if(!pic16_pcode_verbose)return;
7113 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7115 // for now just print the first element of each set
7116 pc = setFirstItem(pb->function_entries);
7118 fprintf(of,";entry: ");
7121 pc = setFirstItem(pb->function_exits);
7123 fprintf(of,";has an exit\n");
7127 pc = setFirstItem(pb->function_calls);
7129 fprintf(of,";functions called:\n");
7132 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7133 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7135 pc = setNextItem(pb->function_calls);
7139 r = setFirstItem(pb->tregisters);
7141 int n = elementsInSet(pb->tregisters);
7143 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7146 fprintf(of,"; %s\n",r->name);
7147 r = setNextItem(pb->tregisters);
7151 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7154 /*-----------------------------------------------------------------*/
7155 /*-----------------------------------------------------------------*/
7157 static void sequencepCode(void)
7163 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7165 pb->seq = GpCodeSequenceNumber+1;
7167 for( pc = pb->pcHead; pc; pc = pc->next)
7168 pc->seq = ++GpCodeSequenceNumber;
7174 /*-----------------------------------------------------------------*/
7175 /*-----------------------------------------------------------------*/
7176 static set *register_usage(pBlock *pb)
7179 set *registers=NULL;
7180 set *registersInCallPath = NULL;
7182 /* check recursion */
7184 pc = setFirstItem(pb->function_entries);
7191 if(pc->type != PC_FUNCTION)
7192 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7194 pc = setFirstItem(pb->function_calls);
7195 for( ; pc; pc = setNextItem(pb->function_calls)) {
7197 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7198 char *dest = pic16_get_op_from_instruction(PCI(pc));
7200 pcn = findFunction(dest);
7202 registersInCallPath = register_usage(pcn->pb);
7204 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7209 pBlockStats(stderr,pb); // debug
7212 // Mark the registers in this block as used.
7214 MarkUsedRegisters(pb->tregisters);
7215 if(registersInCallPath) {
7216 /* registers were used in the functions this pBlock has called */
7217 /* so now, we need to see if these collide with the ones we are */
7220 regs *r1,*r2, *newreg;
7222 DFPRINTF((stderr,"comparing registers\n"));
7224 r1 = setFirstItem(registersInCallPath);
7227 r2 = setFirstItem(pb->tregisters);
7229 while(r2 && (r1->type != REG_STK)) {
7231 if(r2->rIdx == r1->rIdx) {
7232 newreg = pic16_findFreeReg(REG_GPR);
7236 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7240 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7241 r1->rIdx, newreg->rIdx));
7242 r2->rIdx = newreg->rIdx;
7243 //if(r2->name) free(r2->name);
7245 r2->name = Safe_strdup(newreg->name);
7249 newreg->wasUsed = 1;
7251 r2 = setNextItem(pb->tregisters);
7254 r1 = setNextItem(registersInCallPath);
7257 /* Collisions have been resolved. Now free the registers in the call path */
7258 r1 = setFirstItem(registersInCallPath);
7260 if(r1->type != REG_STK) {
7261 newreg = pic16_regWithIdx(r1->rIdx);
7264 r1 = setNextItem(registersInCallPath);
7268 // MarkUsedRegisters(pb->registers);
7270 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7273 DFPRINTF((stderr,"returning regs\n"));
7275 DFPRINTF((stderr,"not returning regs\n"));
7277 DFPRINTF((stderr,"pBlock after register optim.\n"));
7278 pBlockStats(stderr,pb); // debug
7284 /*-----------------------------------------------------------------*/
7285 /* pct2 - writes the call tree to a file */
7287 /*-----------------------------------------------------------------*/
7288 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7292 // set *registersInCallPath = NULL;
7298 fprintf(of, "recursive function\n");
7299 return; //recursion ?
7302 pc = setFirstItem(pb->function_entries);
7309 for(i=0;i<indent;i++) // Indentation
7313 if(pc->type == PC_FUNCTION) {
7314 usedstack += PCF(pc)->stackusage;
7315 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7316 } else return; // ???
7319 pc = setFirstItem(pb->function_calls);
7320 for( ; pc; pc = setNextItem(pb->function_calls)) {
7322 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7323 char *dest = pic16_get_op_from_instruction(PCI(pc));
7325 pcn = findFunction(dest);
7327 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7329 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7337 /*-----------------------------------------------------------------*/
7338 /* pic16_printCallTree - writes the call tree to a file */
7340 /*-----------------------------------------------------------------*/
7342 void pic16_printCallTree(FILE *of)
7354 fprintf(of, "\npBlock statistics\n");
7355 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7359 fprintf(of,"Call Tree\n");
7360 pbr = the_pFile->functions;
7364 if(!ispCodeFunction(pc))
7365 fprintf(of,"bug in call tree");
7368 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7370 while(pc->next && !ispCodeFunction(pc->next)) {
7372 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7373 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7381 fprintf(of,"\n**************\n\na better call tree\n");
7382 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7387 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7388 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7394 /*-----------------------------------------------------------------*/
7396 /*-----------------------------------------------------------------*/
7398 static void InlineFunction(pBlock *pb)
7406 pc = setFirstItem(pb->function_calls);
7408 for( ; pc; pc = setNextItem(pb->function_calls)) {
7411 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7417 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7419 //fprintf(stderr,"Cool can inline:\n");
7420 //pcn->print(stderr,pcn);
7422 //fprintf(stderr,"recursive call Inline\n");
7423 InlineFunction(pcn->pb);
7424 //fprintf(stderr,"return from recursive call Inline\n");
7427 At this point, *pc points to a CALL mnemonic, and
7428 *pcn points to the function that is being called.
7430 To in-line this call, we need to remove the CALL
7431 and RETURN(s), and link the function pCode in with
7437 /* Remove the CALL */
7441 /* remove callee pBlock from the pBlock linked list */
7442 removepBlock(pcn->pb);
7450 /* Remove the Function pCode */
7451 pct = pic16_findNextInstruction(pcn->next);
7453 /* Link the function with the callee */
7454 pc->next = pcn->next;
7455 pcn->next->prev = pc;
7457 /* Convert the function name into a label */
7459 pbr = Safe_calloc(1,sizeof(pBranch));
7460 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7462 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7463 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7465 /* turn all of the return's except the last into goto's */
7466 /* check case for 2 instruction pBlocks */
7467 pce = pic16_findNextInstruction(pcn->next);
7469 pCode *pce_next = pic16_findNextInstruction(pce->next);
7471 if(pce_next == NULL) {
7472 /* found the last return */
7473 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7475 //fprintf(stderr,"found last return\n");
7476 //pce->print(stderr,pce);
7477 pce->prev->next = pc_call->next;
7478 pc_call->next->prev = pce->prev;
7479 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7489 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7495 /*-----------------------------------------------------------------*/
7497 /*-----------------------------------------------------------------*/
7499 void pic16_InlinepCode(void)
7508 if(!functionInlining)
7511 /* Loop through all of the function definitions and count the
7512 * number of times each one is called */
7513 //fprintf(stderr,"inlining %d\n",__LINE__);
7515 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7517 pc = setFirstItem(pb->function_calls);
7519 for( ; pc; pc = setNextItem(pb->function_calls)) {
7522 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7523 if(pcn && isPCF(pcn)) {
7524 PCF(pcn)->ncalled++;
7527 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7532 //fprintf(stderr,"inlining %d\n",__LINE__);
7534 /* Now, Loop through the function definitions again, but this
7535 * time inline those functions that have only been called once. */
7537 InlineFunction(the_pFile->pbHead);
7538 //fprintf(stderr,"inlining %d\n",__LINE__);
7540 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7545 char *pic_optype_names[]={
7546 "PO_NONE", // No operand e.g. NOP
7547 "PO_W", // The working register (as a destination)
7548 "PO_WREG", // The working register (as a file register)
7549 "PO_STATUS", // The 'STATUS' register
7550 "PO_BSR", // The 'BSR' register
7551 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7553 "PO_INDF0", // The Indirect register
7554 "PO_INTCON", // Interrupt Control register
7555 "PO_GPR_REGISTER", // A general purpose register
7556 "PO_GPR_BIT", // A bit of a general purpose register
7557 "PO_GPR_TEMP", // A general purpose temporary register
7558 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7559 "PO_PCL", // Program counter Low register
7560 "PO_PCLATH", // Program counter Latch high register
7561 "PO_PCLATU", // Program counter Latch upper register
7562 "PO_PRODL", // Product Register Low
7563 "PO_PRODH", // Product Register High
7564 "PO_LITERAL", // A constant
7565 "PO_REL_ADDR", // A relative address
7566 "PO_IMMEDIATE", // (8051 legacy)
7567 "PO_DIR", // Direct memory (8051 legacy)
7568 "PO_CRY", // bit memory (8051 legacy)
7569 "PO_BIT", // bit operand.
7570 "PO_STR", // (8051 legacy)
7572 "PO_WILD" // Wild card operand in peep optimizer
7576 char *dumpPicOptype(PIC_OPTYPE type)
7578 return (pic_optype_names[ type ]);