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 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4422 if(!strcmp(ab->name, PCF(pc)->fname)) {
4423 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4424 fprintf(of, "\t0X%06X", ab->address);
4435 /*-----------------------------------------------------------------*/
4437 /* pCode processing */
4441 /*-----------------------------------------------------------------*/
4443 void pic16_unlinkpCode(pCode *pc)
4449 fprintf(stderr,"Unlinking: ");
4450 printpCode(stderr, pc);
4453 pc->prev->next = pc->next;
4455 pc->next->prev = pc->prev;
4457 pc->prev = pc->next = NULL;
4461 /*-----------------------------------------------------------------*/
4462 /*-----------------------------------------------------------------*/
4464 static void genericDestruct(pCode *pc)
4467 pic16_unlinkpCode(pc);
4470 /* For instructions, tell the register (if there's one used)
4471 * that it's no longer needed */
4472 regs *reg = pic16_getRegFromInstruction(pc);
4474 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4476 if(PCI(pc)->is2MemOp) {
4477 reg = pic16_getRegFromInstruction2(pc);
4479 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4483 /* Instead of deleting the memory used by this pCode, mark
4484 * the object as bad so that if there's a pointer to this pCode
4485 * dangling around somewhere then (hopefully) when the type is
4486 * checked we'll catch it.
4490 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4496 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4497 /*-----------------------------------------------------------------*/
4498 /*-----------------------------------------------------------------*/
4499 /* modifiers for constant immediate */
4500 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4502 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4507 int use_buffer = 1; // copy the string to the passed buffer pointer
4512 use_buffer = 0; // Don't bother copying the string to the buffer.
4516 switch(pcop->type) {
4524 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4527 return PCOR(pcop)->r->name;
4530 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4532 SAFE_snprintf(&buffer,&size,"%s",r->name);
4539 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4540 if(PCOI(pcop)->index) {
4541 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4542 immdmod[ PCOI(pcop)->offset ],
4546 SAFE_snprintf(&s,&size,"%s(%s)",
4547 immdmod[ PCOI(pcop)->offset ],
4551 if(PCOI(pcop)->index) {
4552 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4557 SAFE_snprintf(&s,&size, "%s(%s)",
4564 case PO_GPR_REGISTER:
4567 // size = sizeof(buffer);
4568 if( PCOR(pcop)->instance) {
4569 SAFE_snprintf(&s,&size,"(%s + %d)",
4571 PCOR(pcop)->instance );
4573 SAFE_snprintf(&s,&size,"%s",pcop->name);
4580 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4589 return "NO operand1";
4592 /*-----------------------------------------------------------------*/
4593 /* pic16_get_op2 - variant to support two memory operand commands */
4594 /*-----------------------------------------------------------------*/
4595 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4600 int use_buffer = 1; // copy the string to the passed buffer pointer
4605 use_buffer = 0; // Don't bother copying the string to the buffer.
4609 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",
4610 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4611 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4615 switch(PCOR2(pcop)->pcop2->type) {
4623 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4626 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4629 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4632 SAFE_snprintf(&buffer,&size,"%s",r->name);
4643 if(PCOI(pcop)->_const) {
4644 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4645 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4648 8 * PCOI(pcop)->offset );
4650 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4652 if( PCOI(pcop)->index) {
4653 SAFE_snprintf(&s,&size,"(%s + %d)",
4655 PCOI(pcop)->index );
4657 if(PCOI(pcop)->offset)
4658 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4660 SAFE_snprintf(&s,&size,"%s",pcop->name);
4667 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4668 SAFE_snprintf(&s,&size,"(%s + %d)",
4669 PCOR(PCOR2(pcop)->pcop2)->r->name,
4670 PCOR(PCOR2(pcop)->pcop2)->instance );
4672 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4677 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4679 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4682 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4687 return "NO operand2";
4690 /*-----------------------------------------------------------------*/
4691 /*-----------------------------------------------------------------*/
4692 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4696 return pic16_get_op(pcc->pcop,NULL,0);
4698 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4699 * return ("ERROR Null: "__FUNCTION__);
4701 return ("ERROR Null: pic16_get_op_from_instruction");
4705 /*-----------------------------------------------------------------*/
4706 /*-----------------------------------------------------------------*/
4707 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4710 fprintf(of,"pcodeopprint- not implemented\n");
4713 /*-----------------------------------------------------------------*/
4714 /* pic16_pCode2str - convert a pCode instruction to string */
4715 /*-----------------------------------------------------------------*/
4716 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4722 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4723 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4724 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4732 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4734 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4736 if(PCI(pc)->is2MemOp) {
4737 SAFE_snprintf(&s,&size, "%s, %s",
4738 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4739 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4743 if(PCI(pc)->is2LitOp) {
4744 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4748 if(PCI(pc)->isBitInst) {
4749 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4750 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4751 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4752 PCI(pc)->pcop->name ,
4753 PCI(pc)->pcop->name );
4755 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4756 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4757 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4758 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4760 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4761 //PCI(pc)->pcop->t.bit );
4764 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4765 if( PCI(pc)->num_ops == 3)
4766 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4768 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4771 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4773 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4774 if(PCI(pc)->num_ops == 3)
4775 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4777 r = pic16_getRegFromInstruction(pc);
4778 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4779 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4781 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4790 /* assuming that comment ends with a \n */
4791 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4795 /* assuming that inline code ends with a \n */
4796 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4800 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4803 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4806 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4809 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4812 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4813 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4814 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4817 if(PCAD(pc)->directive) {
4818 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4821 /* special case to handle inline labels without a tab */
4822 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4827 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4831 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4839 /*-----------------------------------------------------------------*/
4840 /* genericPrint - the contents of a pCode to a file */
4841 /*-----------------------------------------------------------------*/
4842 static void genericPrint(FILE *of, pCode *pc)
4850 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4854 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4858 // If the opcode has a label, print that first
4860 pBranch *pbl = PCI(pc)->label;
4861 while(pbl && pbl->pc) {
4862 if(pbl->pc->type == PC_LABEL)
4863 pCodePrintLabel(of, pbl->pc);
4869 genericPrint(of,PCODE(PCI(pc)->cline));
4874 pic16_pCode2str(str, 256, pc);
4876 fprintf(of,"%s",str);
4878 if(pic16_debug_verbose) {
4879 fprintf(of, "\t;key=%03x",pc->seq);
4881 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4888 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4889 if(PCW(pc)->pci.label)
4890 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4892 if(PCW(pc)->operand) {
4893 fprintf(of,";\toperand ");
4894 pCodeOpPrint(of,PCW(pc)->operand );
4899 if(pic16_debug_verbose) {
4900 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4901 if(PCFL(pc)->ancestor)
4902 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4909 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4910 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4911 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4917 pBranch *pbl = PCAD(pc)->pci.label;
4918 while(pbl && pbl->pc) {
4919 if(pbl->pc->type == PC_LABEL)
4920 pCodePrintLabel(of, pbl->pc);
4924 if(PCAD(pc)->directive) {
4925 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4928 /* special case to handle inline labels without tab */
4929 fprintf(of, "%s\n", PCAD(pc)->arg);
4935 fprintf(of,"unknown pCode type %d\n",pc->type);
4940 /*-----------------------------------------------------------------*/
4941 /* pCodePrintFunction - prints function begin/end */
4942 /*-----------------------------------------------------------------*/
4944 static void pCodePrintFunction(FILE *of, pCode *pc)
4951 if( ((pCodeFunction *)pc)->modname)
4952 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4955 if(!PCF(pc)->absblock) {
4956 if(PCF(pc)->fname) {
4957 pBranch *exits = PCF(pc)->to;
4960 fprintf(of,"%s:", PCF(pc)->fname);
4962 if(pic16_pcode_verbose)
4963 fprintf(of, "\t;Function start");
4969 exits = exits->next;
4973 if(pic16_pcode_verbose)
4974 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4977 if((PCF(pc)->from &&
4978 PCF(pc)->from->pc->type == PC_FUNCTION &&
4979 PCF(PCF(pc)->from->pc)->fname) ) {
4981 if(pic16_pcode_verbose)
4982 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4984 if(pic16_pcode_verbose)
4985 fprintf(of,"; exit point [can't find entry point]\n");
4991 /*-----------------------------------------------------------------*/
4992 /* pCodePrintLabel - prints label */
4993 /*-----------------------------------------------------------------*/
4995 static void pCodePrintLabel(FILE *of, pCode *pc)
5002 fprintf(of,"%s:\n",PCL(pc)->label);
5003 else if (PCL(pc)->key >=0)
5004 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5006 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5009 /*-----------------------------------------------------------------*/
5010 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5011 /* remove it if it is found. */
5012 /*-----------------------------------------------------------------*/
5013 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5020 if(pcl->type == PC_OPCODE)
5021 b = PCI(pcl)->label;
5023 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5028 //fprintf (stderr, "%s \n",__FUNCTION__);
5029 //pcl->print(stderr,pcl);
5030 //pc->print(stderr,pc);
5033 //fprintf (stderr, "found label\n");
5034 //pc->print(stderr, pc);
5038 bprev->next = b->next; /* Not first pCode in chain */
5042 PCI(pcl)->label = b->next; /* First pCode in chain */
5045 return; /* A label can't occur more than once */
5053 /*-----------------------------------------------------------------*/
5054 /*-----------------------------------------------------------------*/
5055 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5074 /*-----------------------------------------------------------------*/
5075 /* pBranchLink - given two pcodes, this function will link them */
5076 /* together through their pBranches */
5077 /*-----------------------------------------------------------------*/
5078 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5082 // Declare a new branch object for the 'from' pCode.
5084 //_ALLOC(b,sizeof(pBranch));
5085 b = Safe_calloc(1,sizeof(pBranch));
5086 b->pc = PCODE(t); // The link to the 'to' pCode.
5089 f->to = pic16_pBranchAppend(f->to,b);
5091 // Now do the same for the 'to' pCode.
5093 //_ALLOC(b,sizeof(pBranch));
5094 b = Safe_calloc(1,sizeof(pBranch));
5098 t->from = pic16_pBranchAppend(t->from,b);
5103 /*-----------------------------------------------------------------*/
5104 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5106 /*-----------------------------------------------------------------*/
5107 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5120 /*-----------------------------------------------------------------*/
5121 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5122 /*-----------------------------------------------------------------*/
5123 void pic16_pCodeUnlink(pCode *pc)
5128 if(!pc->prev || !pc->next) {
5129 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5133 /* first remove the pCode from the chain */
5134 pc->prev->next = pc->next;
5135 pc->next->prev = pc->prev;
5137 /* Now for the hard part... */
5139 /* Remove the branches */
5141 pb1 = PCI(pc)->from;
5143 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5144 * one we're unlinking */
5146 /* search for the link back to this pCode (the one we're
5148 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5149 pb2->pc = PCI(pc)->to->pc; // make the replacement
5151 /* if the pCode we're unlinking contains multiple 'to'
5152 * branches (e.g. this a skip instruction) then we need
5153 * to copy these extra branches to the chain. */
5154 if(PCI(pc)->to->next)
5155 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5164 /*-----------------------------------------------------------------*/
5165 /*-----------------------------------------------------------------*/
5167 static void genericAnalyze(pCode *pc)
5177 // Go through the pCodes that are in pCode chain and link
5178 // them together through the pBranches. Note, the pCodes
5179 // are linked together as a contiguous stream like the
5180 // assembly source code lines. The linking here mimics this
5181 // except that comments are not linked in.
5183 pCode *npc = pc->next;
5185 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5186 pBranchLink(pc,npc);
5191 /* reached the end of the pcode chain without finding
5192 * an instruction we could link to. */
5196 fprintf(stderr,"analyze PC_FLOW\n");
5200 fprintf(stderr,,";A bad pCode is being used\n");
5206 /*-----------------------------------------------------------------*/
5207 /*-----------------------------------------------------------------*/
5208 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5212 if(pc->type == PC_LABEL) {
5213 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5216 if((pc->type == PC_OPCODE)
5217 || (pc->type == PC_ASMDIR)
5219 pbr = PCI(pc)->label;
5221 if(pbr->pc->type == PC_LABEL) {
5222 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5232 /*-----------------------------------------------------------------*/
5233 /*-----------------------------------------------------------------*/
5234 static int checkLabel(pCode *pc)
5238 if(pc && isPCI(pc)) {
5239 pbr = PCI(pc)->label;
5241 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5251 /*-----------------------------------------------------------------*/
5252 /* findLabelinpBlock - Search the pCode for a particular label */
5253 /*-----------------------------------------------------------------*/
5254 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5261 for(pc = pb->pcHead; pc; pc = pc->next)
5262 if(compareLabel(pc,pcop_label))
5268 /*-----------------------------------------------------------------*/
5269 /* findLabel - Search the pCode for a particular label */
5270 /*-----------------------------------------------------------------*/
5271 static pCode * findLabel(pCodeOpLabel *pcop_label)
5279 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5280 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5284 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5288 /*-----------------------------------------------------------------*/
5289 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5290 /* in the linked list */
5291 /*-----------------------------------------------------------------*/
5292 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5305 /*-----------------------------------------------------------------*/
5306 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5307 /* in the linked list */
5308 /*-----------------------------------------------------------------*/
5309 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5323 //#define PCODE_DEBUG
5324 /*-----------------------------------------------------------------*/
5325 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5326 /* in the linked list */
5327 /*-----------------------------------------------------------------*/
5328 pCode * pic16_findNextInstruction(pCode *pci)
5333 if((pc->type == PC_OPCODE)
5334 || (pc->type == PC_WILD)
5335 || (pc->type == PC_ASMDIR)
5340 fprintf(stderr,"pic16_findNextInstruction: ");
5341 printpCode(stderr, pc);
5346 //fprintf(stderr,"Couldn't find instruction\n");
5350 /*-----------------------------------------------------------------*/
5351 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5352 /* in the linked list */
5353 /*-----------------------------------------------------------------*/
5354 pCode * pic16_findPrevInstruction(pCode *pci)
5360 if((pc->type == PC_OPCODE)
5361 || (pc->type == PC_WILD)
5362 || (pc->type == PC_ASMDIR)
5368 fprintf(stderr,"pic16_findPrevInstruction: ");
5369 printpCode(stderr, pc);
5374 //fprintf(stderr,"Couldn't find instruction\n");
5381 /*-----------------------------------------------------------------*/
5382 /* findFunctionEnd - given a pCode find the end of the function */
5383 /* that contains it */
5384 /*-----------------------------------------------------------------*/
5385 static pCode * findFunctionEnd(pCode *pc)
5389 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5395 fprintf(stderr,"Couldn't find function end\n");
5400 /*-----------------------------------------------------------------*/
5401 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5402 /* instruction with which it is associated. */
5403 /*-----------------------------------------------------------------*/
5404 static void AnalyzeLabel(pCode *pc)
5407 pic16_pCodeUnlink(pc);
5413 static void AnalyzeGOTO(pCode *pc)
5416 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5420 static void AnalyzeSKIP(pCode *pc)
5423 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5424 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5428 static void AnalyzeRETURN(pCode *pc)
5431 // branch_link(pc,findFunctionEnd(pc->next));
5437 /*-----------------------------------------------------------------*/
5438 /*-----------------------------------------------------------------*/
5439 regs * pic16_getRegFromInstruction(pCode *pc)
5445 PCI(pc)->num_ops == 0 ||
5446 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5450 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5451 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5454 switch(PCI(pc)->pcop->type) {
5460 return PCOR(PCI(pc)->pcop)->r;
5464 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5465 return PCOR(PCI(pc)->pcop)->r;
5468 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5470 if(PCOI(PCI(pc)->pcop)->r)
5471 return (PCOI(PCI(pc)->pcop)->r);
5476 return PCOR(PCI(pc)->pcop)->r;
5478 case PO_GPR_REGISTER:
5480 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5481 return PCOR(PCI(pc)->pcop)->r;
5484 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5488 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5489 // genericPrint(stderr, pc);
5497 /*-------------------------------------------------------------------------------*/
5498 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5499 /*-------------------------------------------------------------------------------*/
5500 regs * pic16_getRegFromInstruction2(pCode *pc)
5506 PCI(pc)->num_ops == 0 ||
5507 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5512 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5513 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5517 * operands supported in MOVFF:
5524 switch(PCI(pc)->pcop->type) {
5530 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5532 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5536 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5537 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5541 // if(PCOI(PCI(pc)->pcop)->r)
5542 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5544 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5545 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5548 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5549 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5556 // return PCOR2(PCI(pc)->pcop)->r;
5558 case PO_GPR_REGISTER:
5560 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5561 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5565 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5568 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5569 //genericPrint(stderr, pc);
5577 /*-----------------------------------------------------------------*/
5578 /*-----------------------------------------------------------------*/
5580 static void AnalyzepBlock(pBlock *pb)
5587 /* Find all of the registers used in this pBlock
5588 * by looking at each instruction and examining it's
5591 for(pc = pb->pcHead; pc; pc = pc->next) {
5593 /* Is this an instruction with operands? */
5594 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5596 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5598 /* Loop through all of the registers declared so far in
5599 this block and see if we find this one there */
5601 regs *r = setFirstItem(pb->tregisters);
5604 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5605 PCOR(PCI(pc)->pcop)->r = r;
5608 r = setNextItem(pb->tregisters);
5612 /* register wasn't found */
5613 //r = Safe_calloc(1, sizeof(regs));
5614 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5615 //addSet(&pb->tregisters, r);
5616 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5617 //PCOR(PCI(pc)->pcop)->r = r;
5618 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5620 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5623 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5624 if(PCOR(PCI(pc)->pcop)->r) {
5625 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5626 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5628 if(PCI(pc)->pcop->name)
5629 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5631 fprintf(stderr,"ERROR: NULL register\n");
5640 /*-----------------------------------------------------------------*/
5642 /*-----------------------------------------------------------------*/
5643 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5645 static void InsertpFlow(pCode *pc, pCode **pflow)
5648 PCFL(*pflow)->end = pc;
5650 if(!pc || !pc->next)
5653 *pflow = pic16_newpCodeFlow();
5654 pic16_pCodeInsertAfter(pc, *pflow);
5657 /*-----------------------------------------------------------------*/
5658 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5659 /* the flow blocks. */
5661 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5662 * point the instruction flow changes.
5664 /*-----------------------------------------------------------------*/
5665 void pic16_BuildFlow(pBlock *pb)
5668 pCode *last_pci=NULL;
5675 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5676 /* Insert a pCodeFlow object at the beginning of a pBlock */
5678 InsertpFlow(pb->pcHead, &pflow);
5680 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5681 //pflow->next = pb->pcHead; /* Make the current head the next object */
5682 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5683 //pb->pcHead = pflow; /* Make the Flow object the head */
5686 for( pc = pic16_findNextInstruction(pb->pcHead);
5688 pc=pic16_findNextInstruction(pc)) {
5691 PCI(pc)->pcflow = PCFL(pflow);
5693 //fprintf(stderr," build: ");
5694 //pflow->print(stderr,pflow);
5696 if( PCI(pc)->isSkip) {
5698 /* The two instructions immediately following this one
5699 * mark the beginning of a new flow segment */
5701 while(pc && PCI(pc)->isSkip) {
5703 PCI(pc)->pcflow = PCFL(pflow);
5707 InsertpFlow(pc, &pflow);
5708 pc=pic16_findNextInstruction(pc->next);
5716 PCI(pc)->pcflow = PCFL(pflow);
5718 InsertpFlow(pc, &pflow);
5720 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5722 InsertpFlow(pc, &pflow);
5725 } else if (checkLabel(pc)) {
5727 /* This instruction marks the beginning of a
5728 * new flow segment */
5733 /* If the previous pCode is not a flow object, then
5734 * insert a new flow object. (This check prevents
5735 * two consecutive flow objects from being insert in
5736 * the case where a skip instruction preceeds an
5737 * instruction containing a label.) */
5739 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5740 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5742 PCI(pc)->pcflow = PCFL(pflow);
5749 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5751 PCFL(pflow)->end = pb->pcTail;
5754 /*-------------------------------------------------------------------*/
5755 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5756 /* the flow blocks. */
5758 * unBuildFlow removes pCodeFlow objects from a pCode chain
5760 /*-----------------------------------------------------------------*/
5761 static void unBuildFlow(pBlock *pb)
5776 if(PCI(pc)->pcflow) {
5777 //free(PCI(pc)->pcflow);
5778 PCI(pc)->pcflow = NULL;
5781 } else if(isPCFL(pc) )
5790 /*-----------------------------------------------------------------*/
5791 /*-----------------------------------------------------------------*/
5792 static void dumpCond(int cond)
5795 static char *pcc_str[] = {
5809 int ncond = sizeof(pcc_str) / sizeof(char *);
5812 fprintf(stderr, "0x%04X\n",cond);
5814 for(i=0,j=1; i<ncond; i++, j<<=1)
5816 fprintf(stderr, " %s\n",pcc_str[i]);
5822 /*-----------------------------------------------------------------*/
5823 /*-----------------------------------------------------------------*/
5824 static void FlowStats(pCodeFlow *pcflow)
5832 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5834 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5837 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5842 fprintf(stderr, " FlowStats inCond: ");
5843 dumpCond(pcflow->inCond);
5844 fprintf(stderr, " FlowStats outCond: ");
5845 dumpCond(pcflow->outCond);
5849 /*-----------------------------------------------------------------*
5850 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5851 * if it affects the banking bits.
5853 * return: -1 == Banking bits are unaffected by this pCode.
5855 * return: > 0 == Banking bits are affected.
5857 * If the banking bits are affected, then the returned value describes
5858 * which bits are affected and how they're affected. The lower half
5859 * of the integer maps to the bits that are affected, the upper half
5860 * to whether they're set or cleared.
5862 *-----------------------------------------------------------------*/
5864 static int isBankInstruction(pCode *pc)
5872 if( PCI(pc)->op == POC_MOVLB ||
5873 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5874 bank = PCOL(pc)->lit;
5881 /*-----------------------------------------------------------------*/
5882 /*-----------------------------------------------------------------*/
5883 static void FillFlow(pCodeFlow *pcflow)
5892 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5894 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5897 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5904 isBankInstruction(pc);
5906 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5910 fprintf(stderr, " FillFlow - Bad end of flow\n");
5912 fprintf(stderr, " FillFlow - Ending flow with\n ");
5913 pc->print(stderr,pc);
5916 fprintf(stderr, " FillFlow inCond: ");
5917 dumpCond(pcflow->inCond);
5918 fprintf(stderr, " FillFlow outCond: ");
5919 dumpCond(pcflow->outCond);
5923 /*-----------------------------------------------------------------*/
5924 /*-----------------------------------------------------------------*/
5925 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5927 pCodeFlowLink *fromLink, *toLink;
5929 if(!from || !to || !to->pcflow || !from->pcflow)
5932 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5933 toLink = pic16_newpCodeFlowLink(to->pcflow);
5935 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5936 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5940 /*-----------------------------------------------------------------*
5941 * void LinkFlow(pBlock *pb)
5943 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5944 * non-branching segments. In LinkFlow, we determine the execution
5945 * order of these segments. For example, if one of the segments ends
5946 * with a skip, then we know that there are two possible flow segments
5947 * to which control may be passed.
5948 *-----------------------------------------------------------------*/
5949 static void LinkFlow(pBlock *pb)
5955 //fprintf(stderr,"linkflow \n");
5957 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5959 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5962 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5964 //fprintf(stderr," link: ");
5965 //pcflow->print(stderr,pcflow);
5967 //FillFlow(PCFL(pcflow));
5969 pc = PCFL(pcflow)->end;
5971 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5972 if(isPCI_SKIP(pc)) {
5973 //fprintf(stderr, "ends with skip\n");
5974 //pc->print(stderr,pc);
5975 pct=pic16_findNextInstruction(pc->next);
5976 LinkFlow_pCode(PCI(pc),PCI(pct));
5977 pct=pic16_findNextInstruction(pct->next);
5978 LinkFlow_pCode(PCI(pc),PCI(pct));
5982 if(isPCI_BRANCH(pc)) {
5983 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5985 //fprintf(stderr, "ends with branch\n ");
5986 //pc->print(stderr,pc);
5988 if(!(pcol && isPCOLAB(pcol))) {
5989 if((PCI(pc)->op != POC_RETLW)
5990 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5992 /* continue if label is '$' which assembler knows how to parse */
5993 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5995 if(pic16_pcode_verbose) {
5996 pc->print(stderr,pc);
5997 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6003 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6004 LinkFlow_pCode(PCI(pc),PCI(pct));
6006 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6007 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6009 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6015 //fprintf(stderr, "ends with non-branching instruction:\n");
6016 //pc->print(stderr,pc);
6018 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6024 //fprintf(stderr, "ends with unknown\n");
6025 //pc->print(stderr,pc);
6029 //fprintf(stderr, "ends with nothing: ERROR\n");
6033 /*-----------------------------------------------------------------*/
6034 /*-----------------------------------------------------------------*/
6036 /*-----------------------------------------------------------------*/
6037 /*-----------------------------------------------------------------*/
6038 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6044 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6047 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6057 /*-----------------------------------------------------------------*/
6058 /* insertBankSwitch - inserts a bank switch statement in the */
6059 /* assembly listing */
6061 /* position == 0: insert before */
6062 /* position == 1: insert after pc */
6063 /* position == 2: like 0 but previous was a skip instruction */
6064 /*-----------------------------------------------------------------*/
6065 pCodeOp *pic16_popGetLabel(unsigned int key);
6066 extern int pic16_labelOffset;
6068 static void insertBankSwitch(unsigned char position, pCode *pc)
6075 /* emit BANKSEL [symbol] */
6078 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6080 // position = 0; // position is always before (sanity check!)
6083 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6084 pc->print(stderr, pc);
6089 /* insert the bank switch after this pc instruction */
6090 pCode *pcnext = pic16_findNextInstruction(pc);
6092 pic16_pCodeInsertAfter(pc, new_pc);
6093 if(pcnext)pc = pcnext;
6097 /* insert the bank switch BEFORE this pc instruction */
6098 pic16_pCodeInsertAfter(pc->prev, new_pc);
6103 pCode *pcnext, *pcprev, *npci, *ppc;
6105 int ofs1=0, ofs2=0, len=0;
6107 /* just like 0, but previous was a skip instruction,
6108 * so some care should be taken */
6110 pic16_labelOffset += 10000;
6111 tlbl = newiTempLabel(NULL);
6113 /* invert skip instruction */
6114 pcprev = pic16_findPrevInstruction(pc->prev);
6115 ipci = PCI(pcprev)->inverted_op;
6116 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6118 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6120 /* copy info from old pCode */
6121 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6122 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6123 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6124 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6125 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6126 PCI(npci)->op = PCI(pcprev)->inverted_op;
6128 /* unlink old pCode */
6130 ppc->next = pcprev->next;
6131 pcprev->next->prev = ppc;
6132 pic16_pCodeInsertAfter(ppc, npci);
6134 /* extra instructions to handle invertion */
6135 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6136 pic16_pCodeInsertAfter(npci, pcnext);
6137 pic16_pCodeInsertAfter(pc->prev, new_pc);
6139 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6140 pic16_pCodeInsertAfter(pc, pcnext);
6145 /* Move the label, if there is one */
6146 if(PCI(pc)->label) {
6147 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6148 // __FILE__, __LINE__, pc, new_pc);
6149 PCAD(new_pc)->pci.label = PCI(pc)->label;
6150 PCI(pc)->label = NULL;
6155 /*-----------------------------------------------------------------*/
6156 /*int compareBankFlow - compare the banking requirements between */
6158 /*-----------------------------------------------------------------*/
6159 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6162 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6165 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6168 if(pcflow->firstBank == -1)
6172 if(pcflowLink->pcflow->firstBank == -1) {
6173 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6174 pcflowLink->pcflow->to :
6175 pcflowLink->pcflow->from);
6176 return compareBankFlow(pcflow, pctl, toORfrom);
6180 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6183 pcflowLink->bank_conflict++;
6184 pcflowLink->pcflow->FromConflicts++;
6185 pcflow->ToConflicts++;
6188 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6191 pcflowLink->bank_conflict++;
6192 pcflowLink->pcflow->ToConflicts++;
6193 pcflow->FromConflicts++;
6197 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6198 pcflowLink->pcflow->pc.seq,
6199 pcflowLink->pcflow->FromConflicts,
6200 pcflowLink->pcflow->ToConflicts);
6207 /*-----------------------------------------------------------------*/
6208 /*-----------------------------------------------------------------*/
6209 static void DumpFlow(pBlock *pb)
6213 pCodeFlowLink *pcfl;
6216 fprintf(stderr,"Dump flow \n");
6217 pb->pcHead->print(stderr, pb->pcHead);
6219 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6220 pcflow->print(stderr,pcflow);
6222 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6224 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6226 if(!isPCFL(pcflow)) {
6227 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6230 fprintf(stderr,"dumping: ");
6231 pcflow->print(stderr,pcflow);
6232 FlowStats(PCFL(pcflow));
6234 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6236 pc = PCODE(pcfl->pcflow);
6238 fprintf(stderr, " from seq %d:\n",pc->seq);
6240 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6241 pc->print(stderr,pc);
6246 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6248 pc = PCODE(pcfl->pcflow);
6250 fprintf(stderr, " to seq %d:\n",pc->seq);
6252 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6253 pc->print(stderr,pc);
6262 /*-----------------------------------------------------------------*/
6263 /*-----------------------------------------------------------------*/
6264 static int OptimizepBlock(pBlock *pb)
6269 if(!pb || !peepOptimizing)
6272 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6274 for(pc = pb->pcHead; pc; pc = pc->next)
6275 matches += pic16_pCodePeepMatchRule(pc);
6278 pc = pic16_findNextInstruction(pb->pcHead);
6286 if(pic16_pCodePeepMatchRule(pc)) {
6291 pc = pic16_findNextInstruction(pcprev->next);
6293 pc = pic16_findNextInstruction(pb->pcHead);
6295 pc = pic16_findNextInstruction(pc->next);
6299 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6304 /*-----------------------------------------------------------------*/
6305 /*-----------------------------------------------------------------*/
6306 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6310 for(pc = pcs; pc; pc = pc->next) {
6312 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6314 (PCI(pc)->pcop->type == PO_LABEL) &&
6315 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6323 /*-----------------------------------------------------------------*/
6324 /*-----------------------------------------------------------------*/
6325 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6332 (PCI(pc)->pcop->type == PO_LABEL)) {
6334 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6336 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6337 // if(pcol->pcop.name)
6338 // free(pcol->pcop.name);
6340 /* If the key is negative, then we (probably) have a label to
6341 * a function and the name is already defined */
6344 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6348 //sprintf(buffer,"_%05d_DS_",pcl->key);
6350 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6352 pcol->pcop.name = Safe_strdup(s);
6353 pcol->key = pcl->key;
6354 //pc->print(stderr,pc);
6361 /*-----------------------------------------------------------------*/
6362 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6363 /* pCode chain if they're not used. */
6364 /*-----------------------------------------------------------------*/
6365 static void pBlockRemoveUnusedLabels(pBlock *pb)
6367 pCode *pc; pCodeLabel *pcl;
6372 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6374 pBranch *pbr = PCI(pc)->label;
6375 if(pbr && pbr->next) {
6376 pCode *pcd = pb->pcHead;
6378 // fprintf(stderr, "multiple labels\n");
6379 // pc->print(stderr,pc);
6384 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6385 //fprintf(stderr,"Used by:\n");
6386 //pcd->print(stderr,pcd);
6388 exchangeLabels(PCL(pbr->pc),pcd);
6397 for(pc = pb->pcHead; pc; pc = pc->next) {
6399 if(isPCL(pc)) // pc->type == PC_LABEL)
6401 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6402 pcl = PCL(PCI(pc)->label->pc);
6405 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6407 /* This pCode is a label, so search the pBlock to see if anyone
6410 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6412 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6413 /* Couldn't find an instruction that refers to this label
6414 * So, unlink the pCode label from it's pCode chain
6415 * and destroy the label */
6416 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6418 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6419 if(pc->type == PC_LABEL) {
6420 pic16_unlinkpCode(pc);
6421 pCodeLabelDestruct(pc);
6423 unlinkpCodeFromBranch(pc, PCODE(pcl));
6424 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6435 /*-----------------------------------------------------------------*/
6436 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6437 /* chain and put them into pBranches that are */
6438 /* associated with the appropriate pCode */
6440 /*-----------------------------------------------------------------*/
6441 void pic16_pBlockMergeLabels(pBlock *pb)
6444 pCode *pc, *pcnext=NULL;
6449 /* First, Try to remove any unused labels */
6450 //pBlockRemoveUnusedLabels(pb);
6452 /* Now loop through the pBlock and merge the labels with the opcodes */
6455 // for(pc = pb->pcHead; pc; pc = pc->next) {
6458 pCode *pcn = pc->next;
6460 if(pc->type == PC_LABEL) {
6462 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6463 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6465 if((pcnext = pic16_findNextInstruction(pc) )) {
6467 // pcnext->print(stderr, pcnext);
6469 // Unlink the pCode label from it's pCode chain
6470 pic16_unlinkpCode(pc);
6472 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6473 // And link it into the instruction's pBranch labels. (Note, since
6474 // it's possible to have multiple labels associated with one instruction
6475 // we must provide a means to accomodate the additional labels. Thus
6476 // the labels are placed into the singly-linked list "label" as
6477 // opposed to being a single member of the pCodeInstruction.)
6479 //_ALLOC(pbr,sizeof(pBranch));
6481 pbr = Safe_calloc(1,sizeof(pBranch));
6485 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6488 if(pic16_pcode_verbose)
6489 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6491 } else if(pc->type == PC_CSOURCE) {
6493 /* merge the source line symbolic info into the next instruction */
6494 if((pcnext = pic16_findNextInstruction(pc) )) {
6496 // Unlink the pCode label from it's pCode chain
6497 pic16_unlinkpCode(pc);
6498 PCI(pcnext)->cline = PCCS(pc);
6499 //fprintf(stderr, "merging CSRC\n");
6500 //genericPrint(stderr,pcnext);
6506 pBlockRemoveUnusedLabels(pb);
6510 /*-----------------------------------------------------------------*/
6511 /*-----------------------------------------------------------------*/
6512 static int OptimizepCode(char dbName)
6514 #define MAX_PASSES 4
6523 DFPRINTF((stderr," Optimizing pCode\n"));
6527 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6528 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6529 matches += OptimizepBlock(pb);
6532 while(matches && ++passes < MAX_PASSES);
6539 const char *pic16_pCodeOpType(pCodeOp *pcop);
6540 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6543 /*-----------------------------------------------------------------*/
6544 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6545 /*-----------------------------------------------------------------*/
6547 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6551 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6552 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6554 if( !( (pcop->type == PO_LABEL) ||
6555 (pcop->type == PO_LITERAL) ||
6556 (pcop->type == PO_STR) ))
6557 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6558 PCOR(pcop)->r->wasUsed = 1;
6564 /*----------------------------------------------------------------------*
6565 * pic16_areRegsSame - check to see if the names of two registers match *
6566 *----------------------------------------------------------------------*/
6567 int pic16_areRegsSame(regs *r1, regs *r2)
6569 if(!strcmp(r1->name, r2->name))return 1;
6575 /*-----------------------------------------------------------------*/
6576 /*-----------------------------------------------------------------*/
6577 static void pic16_FixRegisterBanking(pBlock *pb)
6581 regs *reg, *prevreg;
6582 unsigned char flag=0;
6587 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6590 /* loop through all of the flow blocks with in one pblock */
6592 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6596 /* at this point, pc should point to a PC_FLOW object */
6597 /* for each flow block, determine the register banking
6600 if(!isPCI(pc))goto loop;
6602 if(PCI(pc)->is2MemOp)goto loop;
6604 reg = pic16_getRegFromInstruction(pc);
6607 pc->print(stderr, pc);
6608 fprintf(stderr, "reg = %p\n", reg);
6611 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6612 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6613 reg->address,reg->isBitField, reg->isFixed);
6617 /* now make some tests to make sure that instruction needs bank switch */
6619 /* if no register exists, and if not a bit opcode goto loop */
6621 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6624 if(isPCI_SKIP(pc)) {
6625 // fprintf(stderr, "instruction is SKIP instruction\n");
6627 if(reg && isACCESS_BANK(reg))goto loop;
6629 if(!isBankInstruction(pc))goto loop;
6631 if(isPCI_LIT(pc))goto loop;
6633 if(PCI(pc)->op == POC_CALL)goto loop;
6635 /* Examine the instruction before this one to make sure it is
6636 * not a skip type instruction */
6637 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6639 flag = 0; /* add before this instruction */
6641 /* if previous instruction is a skip one, then set flag
6642 * to 2 and call insertBankSwitch */
6643 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6646 insertBankSwitch(flag, pc);
6649 // fprintf(stderr, "BANK SWITCH inserted\n");
6658 static void pBlockDestruct(pBlock *pb)
6669 /*-----------------------------------------------------------------*/
6670 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6671 /* name dbName and combine them */
6672 /* into one block */
6673 /*-----------------------------------------------------------------*/
6674 static void mergepBlocks(char dbName)
6677 pBlock *pb, *pbmerged = NULL,*pbn;
6679 pb = the_pFile->pbHead;
6681 //fprintf(stderr," merging blocks named %c\n",dbName);
6685 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6686 if( getpBlock_dbName(pb) == dbName) {
6688 //fprintf(stderr," merged block %c\n",dbName);
6693 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6694 /* pic16_addpCode2pBlock doesn't handle the tail: */
6695 pbmerged->pcTail = pb->pcTail;
6697 pb->prev->next = pbn;
6699 pbn->prev = pb->prev;
6704 //pic16_printpBlock(stderr, pbmerged);
6711 /*-----------------------------------------------------------------*/
6712 /* AnalyzeFlow - Examine the flow of the code and optimize */
6714 /* level 0 == minimal optimization */
6715 /* optimize registers that are used only by two instructions */
6716 /* level 1 == maximal optimization */
6717 /* optimize by looking at pairs of instructions that use the */
6719 /*-----------------------------------------------------------------*/
6721 static void AnalyzeFlow(int level)
6723 static int times_called=0;
6728 /* remove unused allocated registers before exiting */
6729 pic16_RemoveUnusedRegisters();
6735 /* if this is not the first time this function has been called,
6736 then clean up old flow information */
6737 if(times_called++) {
6738 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6741 pic16_RegsUnMapLiveRanges();
6746 /* Phase 2 - Flow Analysis - Register Banking
6748 * In this phase, the individual flow blocks are examined
6749 * and register banking is fixed.
6753 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6754 pic16_FixRegisterBanking(pb);
6757 /* Phase 2 - Flow Analysis
6759 * In this phase, the pCode is partition into pCodeFlow
6760 * blocks. The flow blocks mark the points where a continuous
6761 * stream of instructions changes flow (e.g. because of
6762 * a call or goto or whatever).
6765 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6766 pic16_BuildFlow(pb);
6769 /* Phase 2 - Flow Analysis - linking flow blocks
6771 * In this phase, the individual flow blocks are examined
6772 * to determine their order of excution.
6775 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6778 /* Phase 3 - Flow Analysis - Flow Tree
6780 * In this phase, the individual flow blocks are examined
6781 * to determine their order of execution.
6784 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6785 pic16_BuildFlowTree(pb);
6788 /* Phase x - Flow Analysis - Used Banks
6790 * In this phase, the individual flow blocks are examined
6791 * to determine the Register Banks they use
6795 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6800 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6801 pic16_pCodeRegMapLiveRanges(pb);
6803 pic16_RemoveUnusedRegisters();
6805 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6806 pic16_pCodeRegOptimizeRegUsage(level);
6814 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6819 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6821 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6822 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6823 pcflow = pcflow->next) {
6825 FillFlow(PCFL(pcflow));
6830 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6833 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6834 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6835 pcflow = pcflow->next) {
6837 FlowStats(PCFL(pcflow));
6843 /* VR -- no need to analyze banking in flow, but left here :
6844 * 1. because it may be used in the future for other purposes
6845 * 2. because if omitted we'll miss some optimization done here
6847 * Perhaps I should rename it to something else
6850 /*-----------------------------------------------------------------*/
6851 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6852 /* assigned to the registers. */
6854 /*-----------------------------------------------------------------*/
6856 void pic16_AnalyzeBanking(void)
6861 /* Phase x - Flow Analysis - Used Banks
6863 * In this phase, the individual flow blocks are examined
6864 * to determine the Register Banks they use
6870 if(!the_pFile)return;
6872 if(!pic16_options.no_banksel) {
6873 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6874 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6875 pic16_FixRegisterBanking(pb);
6881 /*-----------------------------------------------------------------*/
6882 /* buildCallTree - Look at the flow and extract all of the calls. */
6883 /*-----------------------------------------------------------------*/
6884 static set *register_usage(pBlock *pb);
6886 static void buildCallTree(void )
6898 /* Now build the call tree.
6899 First we examine all of the pCodes for functions.
6900 Keep in mind that the function boundaries coincide
6901 with pBlock boundaries.
6903 The algorithm goes something like this:
6904 We have two nested loops. The outer loop iterates
6905 through all of the pBlocks/functions. The inner
6906 loop iterates through all of the pCodes for
6907 a given pBlock. When we begin iterating through
6908 a pBlock, the variable pc_fstart, pCode of the start
6909 of a function, is cleared. We then search for pCodes
6910 of type PC_FUNCTION. When one is encountered, we
6911 initialize pc_fstart to this and at the same time
6912 associate a new pBranch object that signifies a
6913 branch entry. If a return is found, then this signifies
6914 a function exit point. We'll link the pCodes of these
6915 returns to the matching pc_fstart.
6917 When we're done, a doubly linked list of pBranches
6918 will exist. The head of this list is stored in
6919 `the_pFile', which is the meta structure for all
6920 of the pCode. Look at the pic16_printCallTree function
6921 on how the pBranches are linked together.
6924 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6925 pCode *pc_fstart=NULL;
6926 for(pc = pb->pcHead; pc; pc = pc->next) {
6928 if(isPCI(pc) && pc_fstart) {
6929 if(PCI(pc)->is2MemOp) {
6930 r = pic16_getRegFromInstruction2(pc);
6931 if(r && !strcmp(r->name, "POSTDEC1"))
6932 PCF(pc_fstart)->stackusage++;
6934 r = pic16_getRegFromInstruction(pc);
6935 if(r && !strcmp(r->name, "PREINC1"))
6936 PCF(pc_fstart)->stackusage--;
6941 if (PCF(pc)->fname) {
6943 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6944 //fprintf(stderr," found main \n");
6945 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6949 pbr = Safe_calloc(1,sizeof(pBranch));
6950 pbr->pc = pc_fstart = pc;
6953 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6955 // Here's a better way of doing the same:
6956 addSet(&pb->function_entries, pc);
6959 // Found an exit point in a function, e.g. return
6960 // (Note, there may be more than one return per function)
6962 pBranchLink(PCF(pc_fstart), PCF(pc));
6964 addSet(&pb->function_exits, pc);
6966 } else if(isCALL(pc)) {
6967 addSet(&pb->function_calls,pc);
6974 /* This is not needed because currently all register used
6975 * by a function are stored in stack -- VR */
6977 /* Re-allocate the registers so that there are no collisions
6978 * between local variables when one function call another */
6981 // pic16_deallocateAllRegs();
6983 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6991 /*-----------------------------------------------------------------*/
6992 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6993 /* all of the logical connections. */
6995 /* Essentially what's done here is that the pCode flow is */
6997 /*-----------------------------------------------------------------*/
6999 void pic16_AnalyzepCode(char dbName)
7010 /* Phase 1 - Register allocation and peep hole optimization
7012 * The first part of the analysis is to determine the registers
7013 * that are used in the pCode. Once that is done, the peep rules
7014 * are applied to the code. We continue to loop until no more
7015 * peep rule optimizations are found (or until we exceed the
7016 * MAX_PASSES threshold).
7018 * When done, the required registers will be determined.
7024 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7025 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7027 /* First, merge the labels with the instructions */
7028 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7029 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7031 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7032 //fprintf(stderr," analyze and merging block %c\n",dbName);
7033 pic16_pBlockMergeLabels(pb);
7036 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7041 changes = OptimizepCode(dbName);
7044 } while(changes && (i++ < MAX_PASSES));
7049 /*-----------------------------------------------------------------*/
7050 /* ispCodeFunction - returns true if *pc is the pCode of a */
7052 /*-----------------------------------------------------------------*/
7053 static bool ispCodeFunction(pCode *pc)
7056 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7062 /*-----------------------------------------------------------------*/
7063 /* findFunction - Search for a function by name (given the name) */
7064 /* in the set of all functions that are in a pBlock */
7065 /* (note - I expect this to change because I'm planning to limit */
7066 /* pBlock's to just one function declaration */
7067 /*-----------------------------------------------------------------*/
7068 static pCode *findFunction(char *fname)
7075 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7077 pc = setFirstItem(pb->function_entries);
7080 if((pc->type == PC_FUNCTION) &&
7082 (strcmp(fname, PCF(pc)->fname)==0))
7085 pc = setNextItem(pb->function_entries);
7093 static void MarkUsedRegisters(set *regset)
7098 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7099 // fprintf(stderr, "marking register = %s\t", r1->name);
7100 r2 = pic16_regWithIdx(r1->rIdx);
7101 // fprintf(stderr, "to register = %s\n", r2->name);
7107 static void pBlockStats(FILE *of, pBlock *pb)
7113 if(!pic16_pcode_verbose)return;
7115 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7117 // for now just print the first element of each set
7118 pc = setFirstItem(pb->function_entries);
7120 fprintf(of,";entry: ");
7123 pc = setFirstItem(pb->function_exits);
7125 fprintf(of,";has an exit\n");
7129 pc = setFirstItem(pb->function_calls);
7131 fprintf(of,";functions called:\n");
7134 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7135 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7137 pc = setNextItem(pb->function_calls);
7141 r = setFirstItem(pb->tregisters);
7143 int n = elementsInSet(pb->tregisters);
7145 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7148 fprintf(of,"; %s\n",r->name);
7149 r = setNextItem(pb->tregisters);
7153 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7156 /*-----------------------------------------------------------------*/
7157 /*-----------------------------------------------------------------*/
7159 static void sequencepCode(void)
7165 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7167 pb->seq = GpCodeSequenceNumber+1;
7169 for( pc = pb->pcHead; pc; pc = pc->next)
7170 pc->seq = ++GpCodeSequenceNumber;
7176 /*-----------------------------------------------------------------*/
7177 /*-----------------------------------------------------------------*/
7178 static set *register_usage(pBlock *pb)
7181 set *registers=NULL;
7182 set *registersInCallPath = NULL;
7184 /* check recursion */
7186 pc = setFirstItem(pb->function_entries);
7193 if(pc->type != PC_FUNCTION)
7194 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7196 pc = setFirstItem(pb->function_calls);
7197 for( ; pc; pc = setNextItem(pb->function_calls)) {
7199 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7200 char *dest = pic16_get_op_from_instruction(PCI(pc));
7202 pcn = findFunction(dest);
7204 registersInCallPath = register_usage(pcn->pb);
7206 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7211 pBlockStats(stderr,pb); // debug
7214 // Mark the registers in this block as used.
7216 MarkUsedRegisters(pb->tregisters);
7217 if(registersInCallPath) {
7218 /* registers were used in the functions this pBlock has called */
7219 /* so now, we need to see if these collide with the ones we are */
7222 regs *r1,*r2, *newreg;
7224 DFPRINTF((stderr,"comparing registers\n"));
7226 r1 = setFirstItem(registersInCallPath);
7229 r2 = setFirstItem(pb->tregisters);
7231 while(r2 && (r1->type != REG_STK)) {
7233 if(r2->rIdx == r1->rIdx) {
7234 newreg = pic16_findFreeReg(REG_GPR);
7238 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7242 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7243 r1->rIdx, newreg->rIdx));
7244 r2->rIdx = newreg->rIdx;
7245 //if(r2->name) free(r2->name);
7247 r2->name = Safe_strdup(newreg->name);
7251 newreg->wasUsed = 1;
7253 r2 = setNextItem(pb->tregisters);
7256 r1 = setNextItem(registersInCallPath);
7259 /* Collisions have been resolved. Now free the registers in the call path */
7260 r1 = setFirstItem(registersInCallPath);
7262 if(r1->type != REG_STK) {
7263 newreg = pic16_regWithIdx(r1->rIdx);
7266 r1 = setNextItem(registersInCallPath);
7270 // MarkUsedRegisters(pb->registers);
7272 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7275 DFPRINTF((stderr,"returning regs\n"));
7277 DFPRINTF((stderr,"not returning regs\n"));
7279 DFPRINTF((stderr,"pBlock after register optim.\n"));
7280 pBlockStats(stderr,pb); // debug
7286 /*-----------------------------------------------------------------*/
7287 /* pct2 - writes the call tree to a file */
7289 /*-----------------------------------------------------------------*/
7290 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7294 // set *registersInCallPath = NULL;
7300 fprintf(of, "recursive function\n");
7301 return; //recursion ?
7304 pc = setFirstItem(pb->function_entries);
7311 for(i=0;i<indent;i++) // Indentation
7315 if(pc->type == PC_FUNCTION) {
7316 usedstack += PCF(pc)->stackusage;
7317 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7318 } else return; // ???
7321 pc = setFirstItem(pb->function_calls);
7322 for( ; pc; pc = setNextItem(pb->function_calls)) {
7324 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7325 char *dest = pic16_get_op_from_instruction(PCI(pc));
7327 pcn = findFunction(dest);
7329 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7331 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7339 /*-----------------------------------------------------------------*/
7340 /* pic16_printCallTree - writes the call tree to a file */
7342 /*-----------------------------------------------------------------*/
7344 void pic16_printCallTree(FILE *of)
7356 fprintf(of, "\npBlock statistics\n");
7357 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7361 fprintf(of,"Call Tree\n");
7362 pbr = the_pFile->functions;
7366 if(!ispCodeFunction(pc))
7367 fprintf(of,"bug in call tree");
7370 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7372 while(pc->next && !ispCodeFunction(pc->next)) {
7374 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7375 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7383 fprintf(of,"\n**************\n\na better call tree\n");
7384 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7389 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7390 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7396 /*-----------------------------------------------------------------*/
7398 /*-----------------------------------------------------------------*/
7400 static void InlineFunction(pBlock *pb)
7408 pc = setFirstItem(pb->function_calls);
7410 for( ; pc; pc = setNextItem(pb->function_calls)) {
7413 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7419 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7421 //fprintf(stderr,"Cool can inline:\n");
7422 //pcn->print(stderr,pcn);
7424 //fprintf(stderr,"recursive call Inline\n");
7425 InlineFunction(pcn->pb);
7426 //fprintf(stderr,"return from recursive call Inline\n");
7429 At this point, *pc points to a CALL mnemonic, and
7430 *pcn points to the function that is being called.
7432 To in-line this call, we need to remove the CALL
7433 and RETURN(s), and link the function pCode in with
7439 /* Remove the CALL */
7443 /* remove callee pBlock from the pBlock linked list */
7444 removepBlock(pcn->pb);
7452 /* Remove the Function pCode */
7453 pct = pic16_findNextInstruction(pcn->next);
7455 /* Link the function with the callee */
7456 pc->next = pcn->next;
7457 pcn->next->prev = pc;
7459 /* Convert the function name into a label */
7461 pbr = Safe_calloc(1,sizeof(pBranch));
7462 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7464 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7465 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7467 /* turn all of the return's except the last into goto's */
7468 /* check case for 2 instruction pBlocks */
7469 pce = pic16_findNextInstruction(pcn->next);
7471 pCode *pce_next = pic16_findNextInstruction(pce->next);
7473 if(pce_next == NULL) {
7474 /* found the last return */
7475 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7477 //fprintf(stderr,"found last return\n");
7478 //pce->print(stderr,pce);
7479 pce->prev->next = pc_call->next;
7480 pc_call->next->prev = pce->prev;
7481 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7491 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7497 /*-----------------------------------------------------------------*/
7499 /*-----------------------------------------------------------------*/
7501 void pic16_InlinepCode(void)
7510 if(!functionInlining)
7513 /* Loop through all of the function definitions and count the
7514 * number of times each one is called */
7515 //fprintf(stderr,"inlining %d\n",__LINE__);
7517 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7519 pc = setFirstItem(pb->function_calls);
7521 for( ; pc; pc = setNextItem(pb->function_calls)) {
7524 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7525 if(pcn && isPCF(pcn)) {
7526 PCF(pcn)->ncalled++;
7529 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7534 //fprintf(stderr,"inlining %d\n",__LINE__);
7536 /* Now, Loop through the function definitions again, but this
7537 * time inline those functions that have only been called once. */
7539 InlineFunction(the_pFile->pbHead);
7540 //fprintf(stderr,"inlining %d\n",__LINE__);
7542 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7547 char *pic_optype_names[]={
7548 "PO_NONE", // No operand e.g. NOP
7549 "PO_W", // The working register (as a destination)
7550 "PO_WREG", // The working register (as a file register)
7551 "PO_STATUS", // The 'STATUS' register
7552 "PO_BSR", // The 'BSR' register
7553 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7555 "PO_INDF0", // The Indirect register
7556 "PO_INTCON", // Interrupt Control register
7557 "PO_GPR_REGISTER", // A general purpose register
7558 "PO_GPR_BIT", // A bit of a general purpose register
7559 "PO_GPR_TEMP", // A general purpose temporary register
7560 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7561 "PO_PCL", // Program counter Low register
7562 "PO_PCLATH", // Program counter Latch high register
7563 "PO_PCLATU", // Program counter Latch upper register
7564 "PO_PRODL", // Product Register Low
7565 "PO_PRODH", // Product Register High
7566 "PO_LITERAL", // A constant
7567 "PO_REL_ADDR", // A relative address
7568 "PO_IMMEDIATE", // (8051 legacy)
7569 "PO_DIR", // Direct memory (8051 legacy)
7570 "PO_CRY", // bit memory (8051 legacy)
7571 "PO_BIT", // bit operand.
7572 "PO_STR", // (8051 legacy)
7574 "PO_WILD" // Wild card operand in peep optimizer
7578 char *dumpPicOptype(PIC_OPTYPE type)
7580 return (pic_optype_names[ type ]);