1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 static int mnemonics_initialized = 0;
118 static hTab *pic16MnemonicsHash = NULL;
119 static hTab *pic16pCodePeepCommandsHash = NULL;
121 static pFile *the_pFile = NULL;
122 static pBlock *pb_dead_pcodes = NULL;
124 /* Hardcoded flags to change the behavior of the PIC port */
125 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
126 static int functionInlining = 1; /* inline functions if nonzero */
127 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
129 int pic16_pcode_verbose = 0;
131 //static int GpCodeSequenceNumber = 1;
132 static int GpcFlowSeq = 1;
134 extern void pic16_RemoveUnusedRegisters(void);
135 extern void pic16_RegsUnMapLiveRanges(void);
136 extern void pic16_BuildFlowTree(pBlock *pb);
137 extern void pic16_pCodeRegOptimizeRegUsage(int level);
138 extern int pic16_picIsInitialized(void);
139 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
140 extern int mnem2key(char const *mnem);
142 /****************************************************************/
143 /* Forward declarations */
144 /****************************************************************/
146 void pic16_unlinkpCode(pCode *pc);
148 static void genericAnalyze(pCode *pc);
149 static void AnalyzeGOTO(pCode *pc);
150 static void AnalyzeSKIP(pCode *pc);
151 static void AnalyzeRETURN(pCode *pc);
154 static void genericDestruct(pCode *pc);
155 static void genericPrint(FILE *of,pCode *pc);
157 static void pCodePrintLabel(FILE *of, pCode *pc);
158 static void pCodePrintFunction(FILE *of, pCode *pc);
159 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
160 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
161 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
162 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
163 int pic16_pCodePeepMatchRule(pCode *pc);
164 static void pBlockStats(FILE *of, pBlock *pb);
165 static pBlock *newpBlock(void);
166 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
167 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
168 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
169 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
171 char *dumpPicOptype(PIC_OPTYPE type);
173 /****************************************************************/
174 /* PIC Instructions */
175 /****************************************************************/
177 pCodeInstruction pic16_pciADDWF = {
178 {PC_OPCODE, NULL, NULL, 0, NULL,
191 1,0, // dest, bit instruction
193 0, // literal operand
195 0, // fast call/return mode select bit
196 0, // second memory operand
197 0, // second literal operand
199 (PCC_W | PCC_REGISTER), // inCond
200 (PCC_REGISTER | PCC_Z), // outCond
204 pCodeInstruction pic16_pciADDFW = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
223 0, // second memory operand
224 0, // second literal operand
226 (PCC_W | PCC_REGISTER), // inCond
227 (PCC_W | PCC_Z), // outCond
231 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
232 {PC_OPCODE, NULL, NULL, 0, NULL,
245 1,0, // dest, bit instruction
247 0, // literal operand
249 0, // fast call/return mode select bit
250 0, // second memory operand
251 0, // second literal operand
253 (PCC_W | PCC_REGISTER | PCC_C), // inCond
254 (PCC_REGISTER | PCC_Z), // outCond
258 pCodeInstruction pic16_pciADDFWC = {
259 {PC_OPCODE, NULL, NULL, 0, NULL,
272 0,0, // dest, bit instruction
274 0, // literal operand
276 0, // fast call/return mode select bit
277 0, // second memory operand
278 0, // second literal operand
280 (PCC_W | PCC_REGISTER | PCC_C), // inCond
281 (PCC_W | PCC_Z), // outCond
285 pCodeInstruction pic16_pciADDLW = {
286 {PC_OPCODE, NULL, NULL, 0, NULL,
299 0,0, // dest, bit instruction
301 1, // literal operand
303 0, // fast call/return mode select bit
304 0, // second memory operand
305 0, // second literal operand
307 (PCC_W | PCC_LITERAL), // inCond
308 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
312 pCodeInstruction pic16_pciANDLW = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,0, // dest, bit instruction
328 1, // literal operand
330 0, // fast call/return mode select bit
331 0, // second memory operand
332 0, // second literal operand
334 (PCC_W | PCC_LITERAL), // inCond
335 (PCC_W | PCC_Z | PCC_N), // outCond
339 pCodeInstruction pic16_pciANDWF = {
340 {PC_OPCODE, NULL, NULL, 0, NULL,
353 1,0, // dest, bit instruction
355 0, // literal operand
357 0, // fast call/return mode select bit
358 0, // second memory operand
359 0, // second literal operand
361 (PCC_W | PCC_REGISTER), // inCond
362 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
366 pCodeInstruction pic16_pciANDFW = {
367 {PC_OPCODE, NULL, NULL, 0, NULL,
380 0,0, // dest, bit instruction
382 0, // literal operand
384 0, // fast call/return mode select bit
385 0, // second memory operand
386 0, // second literal operand
388 (PCC_W | PCC_REGISTER), // inCond
389 (PCC_W | PCC_Z) // outCond
392 pCodeInstruction pic16_pciBC = { // mdubuc - New
393 {PC_OPCODE, NULL, NULL, 0, NULL,
406 0,0, // dest, bit instruction
408 0, // literal operand
410 0, // fast call/return mode select bit
411 0, // second memory operand
412 0, // second literal operand
414 (PCC_REL_ADDR | PCC_C), // inCond
419 pCodeInstruction pic16_pciBCF = {
420 {PC_OPCODE, NULL, NULL, 0, NULL,
433 1,1, // dest, bit instruction
435 0, // literal operand
437 0, // fast call/return mode select bit
438 0, // second memory operand
439 0, // second literal operand
441 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
442 PCC_REGISTER, // outCond
446 pCodeInstruction pic16_pciBN = { // mdubuc - New
447 {PC_OPCODE, NULL, NULL, 0, NULL,
460 0,0, // dest, bit instruction
462 0, // literal operand
464 0, // fast call/return mode select bit
465 0, // second memory operand
466 0, // second literal operand
468 (PCC_REL_ADDR | PCC_N), // inCond
469 PCC_NONE , // outCond
473 pCodeInstruction pic16_pciBNC = { // mdubuc - New
474 {PC_OPCODE, NULL, NULL, 0, NULL,
487 0,0, // dest, bit instruction
489 0, // literal operand
491 0, // fast call/return mode select bit
492 0, // second memory operand
493 0, // second literal operand
495 (PCC_REL_ADDR | PCC_C), // inCond
496 PCC_NONE , // outCond
500 pCodeInstruction pic16_pciBNN = { // mdubuc - New
501 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 0, // fast call/return mode select bit
519 0, // second memory operand
520 0, // second literal operand
522 (PCC_REL_ADDR | PCC_N), // inCond
523 PCC_NONE , // outCond
527 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
528 {PC_OPCODE, NULL, NULL, 0, NULL,
541 0,0, // dest, bit instruction
543 0, // literal operand
545 0, // fast call/return mode select bit
546 0, // second memory operand
547 0, // second literal operand
549 (PCC_REL_ADDR | PCC_OV), // inCond
550 PCC_NONE , // outCond
554 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
555 {PC_OPCODE, NULL, NULL, 0, NULL,
568 0,0, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
574 0, // second literal operand
576 (PCC_REL_ADDR | PCC_Z), // inCond
577 PCC_NONE , // outCond
581 pCodeInstruction pic16_pciBOV = { // mdubuc - New
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 0,0, // dest, bit instruction
597 0, // literal operand
599 0, // fast call/return mode select bit
600 0, // second memory operand
601 0, // second literal operand
603 (PCC_REL_ADDR | PCC_OV), // inCond
604 PCC_NONE , // outCond
608 pCodeInstruction pic16_pciBRA = { // mdubuc - New
609 {PC_OPCODE, NULL, NULL, 0, NULL,
622 0,0, // dest, bit instruction
624 0, // literal operand
626 0, // fast call/return mode select bit
627 0, // second memory operand
628 0, // second literal operand
630 PCC_REL_ADDR, // inCond
631 PCC_NONE , // outCond
635 pCodeInstruction pic16_pciBSF = {
636 {PC_OPCODE, NULL, NULL, 0, NULL,
649 1,1, // dest, bit instruction
651 0, // literal operand
653 0, // fast call/return mode select bit
654 0, // second memory operand
655 0, // second literal operand
657 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
658 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
662 pCodeInstruction pic16_pciBTFSC = {
663 {PC_OPCODE, NULL, NULL, 0, NULL,
676 0,1, // dest, bit instruction
678 0, // literal operand
680 0, // fast call/return mode select bit
681 0, // second memory operand
682 0, // second literal operand
684 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
685 PCC_EXAMINE_PCOP, // outCond
689 pCodeInstruction pic16_pciBTFSS = {
690 {PC_OPCODE, NULL, NULL, 0, NULL,
703 0,1, // dest, bit instruction
705 0, // literal operand
707 0, // fast call/return mode select bit
708 0, // second memory operand
709 0, // second literal operand
711 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
712 PCC_EXAMINE_PCOP, // outCond
716 pCodeInstruction pic16_pciBTG = { // mdubuc - New
717 {PC_OPCODE, NULL, NULL, 0, NULL,
730 0,1, // dest, bit instruction
732 0, // literal operand
734 0, // fast call/return mode select bit
735 0, // second memory operand
736 0, // second literal operand
738 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
739 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
743 pCodeInstruction pic16_pciBZ = { // mdubuc - New
744 {PC_OPCODE, NULL, NULL, 0, NULL,
757 0,0, // dest, bit instruction
759 0, // literal operand
761 0, // fast call/return mode select bit
762 0, // second memory operand
763 0, // second literal operand
770 pCodeInstruction pic16_pciCALL = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
786 0, // literal operand
788 1, // fast call/return mode select bit
789 0, // second memory operand
790 0, // second literal operand
793 PCC_NONE , // outCond
797 pCodeInstruction pic16_pciCOMF = {
798 {PC_OPCODE, NULL, NULL, 0, NULL,
811 1,0, // dest, bit instruction
813 0, // literal operand
815 0, // fast call/return mode select bit
816 0, // second memory operand
817 0, // second literal operand
819 PCC_REGISTER, // inCond
820 PCC_REGISTER , // outCond
824 pCodeInstruction pic16_pciCOMFW = {
825 {PC_OPCODE, NULL, NULL, 0, NULL,
838 0,0, // dest, bit instruction
840 0, // literal operand
842 0, // fast call/return mode select bit
843 0, // second memory operand
844 0, // second literal operand
846 PCC_REGISTER, // inCond
851 pCodeInstruction pic16_pciCLRF = {
852 {PC_OPCODE, NULL, NULL, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
869 0, // fast call/return mode select bit
870 0, // second memory operand
871 0, // second literal operand
873 PCC_REGISTER, // inCond
874 PCC_REGISTER , // outCond
878 pCodeInstruction pic16_pciCLRWDT = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
894 0, // literal operand
896 0, // fast call/return mode select bit
897 0, // second memory operand
898 0, // second literal operand
901 PCC_NONE , // outCond
905 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
906 {PC_OPCODE, NULL, NULL, 0, NULL,
919 0,0, // dest, bit instruction
921 0, // literal operand
923 0, // fast call/return mode select bit
924 0, // second memory operand
925 0, // second literal operand
927 (PCC_W | PCC_REGISTER), // inCond
928 PCC_NONE , // outCond
932 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
933 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
954 (PCC_W | PCC_REGISTER), // inCond
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 1,0, // dest, bit instruction
975 0, // literal operand
977 0, // fast call/return mode select bit
978 0, // second memory operand
979 0, // second literal operand
981 (PCC_W | PCC_REGISTER), // inCond
982 PCC_NONE , // outCond
986 pCodeInstruction pic16_pciDAW = {
987 {PC_OPCODE, NULL, NULL, 0, NULL,
1000 0,0, // dest, bit instruction
1001 0,0, // branch, skip
1002 0, // literal operand
1003 0, // RAM access bit
1004 0, // fast call/return mode select bit
1005 0, // second memory operand
1006 0, // second literal operand
1009 (PCC_W | PCC_C), // outCond
1013 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1014 {PC_OPCODE, NULL, NULL, 0, NULL,
1020 NULL, // from branch
1027 1,0, // dest, bit instruction
1028 1,1, // branch, skip
1029 0, // literal operand
1030 1, // RAM access bit
1031 0, // fast call/return mode select bit
1032 0, // second memory operand
1033 0, // second literal operand
1035 PCC_REGISTER, // inCond
1036 PCC_REGISTER , // outCond
1040 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1041 {PC_OPCODE, NULL, NULL, 0, NULL,
1047 NULL, // from branch
1054 0,0, // dest, bit instruction
1055 1,1, // branch, skip
1056 0, // literal operand
1057 1, // RAM access bit
1058 0, // fast call/return mode select bit
1059 0, // second memory operand
1060 0, // second literal operand
1062 PCC_REGISTER, // inCond
1067 pCodeInstruction pic16_pciDECF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1084 1, // RAM access bit
1085 0, // fast call/return mode select bit
1086 0, // second memory operand
1087 0, // second literal operand
1089 PCC_REGISTER, // inCond
1090 PCC_REGISTER , // outCond
1094 pCodeInstruction pic16_pciDECFW = {
1095 {PC_OPCODE, NULL, NULL, 0, NULL,
1101 NULL, // from branch
1108 0,0, // dest, bit instruction
1109 0,0, // branch, skip
1110 0, // literal operand
1111 1, // RAM access bit
1112 0, // fast call/return mode select bit
1113 0, // second memory operand
1114 0, // second literal operand
1116 PCC_REGISTER, // inCond
1121 pCodeInstruction pic16_pciDECFSZ = {
1122 {PC_OPCODE, NULL, NULL, 0, NULL,
1128 NULL, // from branch
1135 1,0, // dest, bit instruction
1136 1,1, // branch, skip
1137 0, // literal operand
1138 1, // RAM access bit
1139 0, // fast call/return mode select bit
1140 0, // second memory operand
1141 0, // second literal operand
1143 PCC_REGISTER, // inCond
1144 PCC_REGISTER , // outCond
1148 pCodeInstruction pic16_pciDECFSZW = {
1149 {PC_OPCODE, NULL, NULL, 0, NULL,
1155 NULL, // from branch
1162 0,0, // dest, bit instruction
1163 1,1, // branch, skip
1164 0, // literal operand
1165 1, // RAM access bit
1166 0, // fast call/return mode select bit
1167 0, // second memory operand
1168 0, // second literal operand
1170 PCC_REGISTER, // inCond
1175 pCodeInstruction pic16_pciGOTO = {
1176 {PC_OPCODE, NULL, NULL, 0, NULL,
1182 NULL, // from branch
1189 0,0, // dest, bit instruction
1190 1,0, // branch, skip
1191 0, // literal operand
1192 0, // RAM access bit
1193 0, // fast call/return mode select bit
1194 0, // second memory operand
1195 0, // second literal operand
1197 PCC_REL_ADDR, // inCond
1198 PCC_NONE , // outCond
1202 pCodeInstruction pic16_pciINCF = {
1203 {PC_OPCODE, NULL, NULL, 0, NULL,
1209 NULL, // from branch
1216 1,0, // dest, bit instruction
1217 0,0, // branch, skip
1218 0, // literal operand
1219 1, // RAM access bit
1220 0, // fast call/return mode select bit
1221 0, // second memory operand
1222 0, // second literal operand
1224 PCC_REGISTER, // inCond
1225 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1229 pCodeInstruction pic16_pciINCFW = {
1230 {PC_OPCODE, NULL, NULL, 0, NULL,
1236 NULL, // from branch
1243 0,0, // dest, bit instruction
1244 0,0, // branch, skip
1245 0, // literal operand
1246 1, // RAM access bit
1247 0, // fast call/return mode select bit
1248 0, // second memory operand
1249 0, // second literal operand
1251 PCC_REGISTER, // inCond
1256 pCodeInstruction pic16_pciINCFSZ = {
1257 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 1,0, // dest, bit instruction
1271 1,1, // branch, skip
1272 0, // literal operand
1273 1, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1276 0, // second literal operand
1278 PCC_REGISTER, // inCond
1279 PCC_REGISTER , // outCond
1283 pCodeInstruction pic16_pciINCFSZW = {
1284 {PC_OPCODE, NULL, NULL, 0, NULL,
1290 NULL, // from branch
1297 0,0, // dest, bit instruction
1298 1,1, // branch, skip
1299 0, // literal operand
1300 1, // RAM access bit
1301 0, // fast call/return mode select bit
1302 0, // second memory operand
1303 0, // second literal operand
1305 PCC_REGISTER, // inCond
1310 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1311 {PC_OPCODE, NULL, NULL, 0, NULL,
1317 NULL, // from branch
1324 1,0, // dest, bit instruction
1325 1,1, // branch, skip
1326 0, // literal operand
1327 1, // RAM access bit
1328 0, // fast call/return mode select bit
1329 0, // second memory operand
1330 0, // second literal operand
1332 PCC_REGISTER, // inCond
1333 PCC_REGISTER , // outCond
1337 pCodeInstruction pic16_pciIORWF = {
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1344 NULL, // from branch
1351 1,0, // dest, bit instruction
1352 0,0, // branch, skip
1353 0, // literal operand
1354 1, // RAM access bit
1355 0, // fast call/return mode select bit
1356 0, // second memory operand
1357 0, // second literal operand
1359 (PCC_W | PCC_REGISTER), // inCond
1360 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1364 pCodeInstruction pic16_pciIORFW = {
1365 {PC_OPCODE, NULL, NULL, 0, NULL,
1371 NULL, // from branch
1378 0,0, // dest, bit instruction
1379 0,0, // branch, skip
1380 0, // literal operand
1381 1, // RAM access bit
1382 0, // fast call/return mode select bit
1383 0, // second memory operand
1384 0, // second literal operand
1386 (PCC_W | PCC_REGISTER), // inCond
1387 (PCC_W | PCC_Z | PCC_N), // outCond
1391 pCodeInstruction pic16_pciIORLW = {
1392 {PC_OPCODE, NULL, NULL, 0, NULL,
1398 NULL, // from branch
1405 0,0, // dest, bit instruction
1406 0,0, // branch, skip
1407 1, // literal operand
1408 0, // RAM access bit
1409 0, // fast call/return mode select bit
1410 0, // second memory operand
1411 0, // second literal operand
1413 (PCC_W | PCC_LITERAL), // inCond
1414 (PCC_W | PCC_Z | PCC_N), // outCond
1418 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1419 {PC_OPCODE, NULL, NULL, 0, NULL,
1425 NULL, // from branch
1432 0,0, // dest, bit instruction
1433 0,0, // branch, skip
1434 1, // literal operand
1435 0, // RAM access bit
1436 0, // fast call/return mode select bit
1437 0, // second memory operand
1438 1, // second literal operand
1440 (PCC_REGISTER | PCC_LITERAL),
1441 PCC_REGISTER, // outCond
1445 pCodeInstruction pic16_pciMOVF = {
1446 {PC_OPCODE, NULL, NULL, 0, NULL,
1452 NULL, // from branch
1459 1,0, // dest, bit instruction
1460 0,0, // branch, skip
1461 0, // literal operand
1462 1, // RAM access bit
1463 0, // fast call/return mode select bit
1464 0, // second memory operand
1465 0, // second literal operand
1467 PCC_REGISTER, // inCond
1468 (PCC_Z | PCC_N), // outCond
1472 pCodeInstruction pic16_pciMOVFW = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1479 NULL, // from branch
1486 0,0, // dest, bit instruction
1487 0,0, // branch, skip
1488 0, // literal operand
1489 1, // RAM access bit
1490 0, // fast call/return mode select bit
1491 0, // second memory operand
1492 0, // second literal operand
1494 PCC_REGISTER, // inCond
1495 (PCC_W | PCC_Z), // outCond
1499 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1500 {PC_OPCODE, NULL, NULL, 0, NULL,
1506 NULL, // from branch
1513 0,0, // dest, bit instruction
1514 0,0, // branch, skip
1515 0, // literal operand
1516 0, // RAM access bit
1517 0, // fast call/return mode select bit
1518 1, // second memory operand
1519 0, // second literal operand
1521 PCC_REGISTER, // inCond
1522 PCC_REGISTER, // outCond
1526 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1532 NULL, // from branch
1539 0,0, // dest, bit instruction
1540 0,0, // branch, skip
1541 1, // literal operand
1542 0, // RAM access bit
1543 0, // fast call/return mode select bit
1544 0, // second memory operand
1545 0, // second literal operand
1547 (PCC_NONE | PCC_LITERAL), // inCond
1548 PCC_REGISTER, // outCond - BSR
1552 pCodeInstruction pic16_pciMOVLW = {
1553 {PC_OPCODE, NULL, NULL, 0, NULL,
1558 NULL, // from branch
1565 0,0, // dest, bit instruction
1566 0,0, // branch, skip
1567 1, // literal operand
1568 0, // RAM access bit
1569 0, // fast call/return mode select bit
1570 0, // second memory operand
1571 0, // second literal operand
1573 (PCC_NONE | PCC_LITERAL), // inCond
1578 pCodeInstruction pic16_pciMOVWF = {
1579 {PC_OPCODE, NULL, NULL, 0, NULL,
1585 NULL, // from branch
1592 0,0, // dest, bit instruction
1593 0,0, // branch, skip
1594 0, // literal operand
1595 1, // RAM access bit
1596 0, // fast call/return mode select bit
1597 0, // second memory operand
1598 0, // second literal operand
1600 PCC_REGISTER, // inCond
1605 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1606 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 1, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 0, // second memory operand
1624 0, // second literal operand
1626 (PCC_W | PCC_LITERAL), // inCond
1627 PCC_REGISTER, // outCond - PROD
1631 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1637 NULL, // from branch
1644 0,0, // dest, bit instruction
1645 0,0, // branch, skip
1646 0, // literal operand
1647 1, // RAM access bit
1648 0, // fast call/return mode select bit
1649 0, // second memory operand
1650 0, // second literal operand
1652 (PCC_W | PCC_REGISTER), // inCond
1653 PCC_REGISTER, // outCond - PROD
1657 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1658 {PC_OPCODE, NULL, NULL, 0, NULL,
1663 NULL, // from branch
1670 0,0, // dest, bit instruction
1671 0,0, // branch, skip
1672 0, // literal operand
1673 1, // RAM access bit
1674 0, // fast call/return mode select bit
1675 0, // second memory operand
1676 0, // second literal operand
1678 PCC_REGISTER, // inCond
1679 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1683 pCodeInstruction pic16_pciNOP = {
1684 {PC_OPCODE, NULL, NULL, 0, NULL,
1689 NULL, // from branch
1696 0,0, // dest, bit instruction
1697 0,0, // branch, skip
1698 0, // literal operand
1699 0, // RAM access bit
1700 0, // fast call/return mode select bit
1701 0, // second memory operand
1702 0, // second literal operand
1705 PCC_NONE, // outCond
1709 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1710 {PC_OPCODE, NULL, NULL, 0, NULL,
1715 NULL, // from branch
1722 0,0, // dest, bit instruction
1723 0,0, // branch, skip
1724 0, // literal operand
1725 0, // RAM access bit
1726 0, // fast call/return mode select bit
1727 0, // second memory operand
1728 0, // second literal operand
1731 PCC_NONE , // outCond
1735 pCodeInstruction pic16_pciPUSH = {
1736 {PC_OPCODE, NULL, NULL, 0, NULL,
1741 NULL, // from branch
1748 0,0, // dest, bit instruction
1749 0,0, // branch, skip
1750 0, // literal operand
1751 0, // RAM access bit
1752 0, // fast call/return mode select bit
1753 0, // second memory operand
1754 0, // second literal operand
1757 PCC_NONE , // outCond
1761 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1762 {PC_OPCODE, NULL, NULL, 0, NULL,
1767 NULL, // from branch
1774 0,0, // dest, bit instruction
1775 0,0, // branch, skip
1776 0, // literal operand
1777 0, // RAM access bit
1778 0, // fast call/return mode select bit
1779 0, // second memory operand
1780 0, // second literal operand
1782 PCC_REL_ADDR, // inCond
1783 PCC_NONE , // outCond
1787 pCodeInstruction pic16_pciRETFIE = {
1788 {PC_OPCODE, NULL, NULL, 0, NULL,
1794 NULL, // from branch
1801 0,0, // dest, bit instruction
1802 1,0, // branch, skip
1803 0, // literal operand
1804 0, // RAM access bit
1805 1, // fast call/return mode select bit
1806 0, // second memory operand
1807 0, // second literal operand
1810 PCC_NONE, // outCond (not true... affects the GIE bit too)
1814 pCodeInstruction pic16_pciRETLW = {
1815 {PC_OPCODE, NULL, NULL, 0, NULL,
1821 NULL, // from branch
1828 0,0, // dest, bit instruction
1829 1,0, // branch, skip
1830 1, // literal operand
1831 0, // RAM access bit
1832 0, // fast call/return mode select bit
1833 0, // second memory operand
1834 0, // second literal operand
1836 PCC_LITERAL, // inCond
1841 pCodeInstruction pic16_pciRETURN = {
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 0,0, // dest, bit instruction
1856 1,0, // branch, skip
1857 0, // literal operand
1858 0, // RAM access bit
1859 1, // fast call/return mode select bit
1860 0, // second memory operand
1861 0, // second literal operand
1864 PCC_NONE, // outCond
1867 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1868 {PC_OPCODE, NULL, NULL, 0, NULL,
1874 NULL, // from branch
1881 1,0, // dest, bit instruction
1882 0,0, // branch, skip
1883 0, // literal operand
1884 1, // RAM access bit
1885 0, // fast call/return mode select bit
1886 0, // second memory operand
1887 0, // second literal operand
1889 (PCC_C | PCC_REGISTER), // inCond
1890 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1894 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1895 {PC_OPCODE, NULL, NULL, 0, NULL,
1901 NULL, // from branch
1908 0,0, // dest, bit instruction
1909 0,0, // branch, skip
1910 0, // literal operand
1911 1, // RAM access bit
1912 0, // fast call/return mode select bit
1913 0, // second memory operand
1914 0, // second literal operand
1916 (PCC_C | PCC_REGISTER), // inCond
1917 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1921 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1922 {PC_OPCODE, NULL, NULL, 0, NULL,
1928 NULL, // from branch
1935 1,0, // dest, bit instruction
1936 0,0, // branch, skip
1937 0, // literal operand
1938 1, // RAM access bit
1939 0, // fast call/return mode select bit
1940 0, // second memory operand
1941 0, // second literal operand
1943 PCC_REGISTER, // inCond
1944 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1947 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1948 {PC_OPCODE, NULL, NULL, 0, NULL,
1954 NULL, // from branch
1961 0,0, // dest, bit instruction
1962 0,0, // branch, skip
1963 0, // literal operand
1964 1, // RAM access bit
1965 0, // fast call/return mode select bit
1966 0, // second memory operand
1967 0, // second literal operand
1969 PCC_REGISTER, // inCond
1970 (PCC_W | PCC_Z | PCC_N), // outCond
1973 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1974 {PC_OPCODE, NULL, NULL, 0, NULL,
1980 NULL, // from branch
1987 1,0, // dest, bit instruction
1988 0,0, // branch, skip
1989 0, // literal operand
1990 1, // RAM access bit
1991 0, // fast call/return mode select bit
1992 0, // second memory operand
1993 0, // second literal operand
1995 (PCC_C | PCC_REGISTER), // inCond
1996 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1999 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2000 {PC_OPCODE, NULL, NULL, 0, NULL,
2006 NULL, // from branch
2013 0,0, // dest, bit instruction
2014 0,0, // branch, skip
2015 0, // literal operand
2016 1, // RAM access bit
2017 0, // fast call/return mode select bit
2018 0, // second memory operand
2019 0, // second literal operand
2021 (PCC_C | PCC_REGISTER), // inCond
2022 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2025 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2026 {PC_OPCODE, NULL, NULL, 0, NULL,
2032 NULL, // from branch
2039 1,0, // dest, bit instruction
2040 0,0, // branch, skip
2041 0, // literal operand
2042 1, // RAM access bit
2043 0, // fast call/return mode select bit
2044 0, // second memory operand
2045 0, // second literal operand
2047 PCC_REGISTER, // inCond
2048 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2052 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2053 {PC_OPCODE, NULL, NULL, 0, NULL,
2059 NULL, // from branch
2066 0,0, // dest, bit instruction
2067 0,0, // branch, skip
2068 0, // literal operand
2069 1, // RAM access bit
2070 0, // fast call/return mode select bit
2071 0, // second memory operand
2072 0, // second literal operand
2074 PCC_REGISTER, // inCond
2075 (PCC_W | PCC_Z | PCC_N), // outCond
2079 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2080 {PC_OPCODE, NULL, NULL, 0, NULL,
2086 NULL, // from branch
2093 0,0, // dest, bit instruction
2094 0,0, // branch, skip
2095 0, // literal operand
2096 1, // RAM access bit
2097 0, // fast call/return mode select bit
2098 0, // second memory operand
2099 0, // second literal operand
2101 PCC_REGISTER, // inCond
2102 PCC_REGISTER , // outCond
2106 pCodeInstruction pic16_pciSUBLW = {
2107 {PC_OPCODE, NULL, NULL, 0, NULL,
2113 NULL, // from branch
2120 0,0, // dest, bit instruction
2121 0,0, // branch, skip
2122 1, // literal operand
2123 0, // RAM access bit
2124 0, // fast call/return mode select bit
2125 0, // second memory operand
2126 0, // second literal operand
2128 (PCC_W | PCC_LITERAL), // inCond
2129 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2133 pCodeInstruction pic16_pciSUBFWB = {
2134 {PC_OPCODE, NULL, NULL, 0, NULL,
2140 NULL, // from branch
2147 1,0, // dest, bit instruction
2148 0,0, // branch, skip
2149 0, // literal operand
2150 1, // RAM access bit
2151 0, // fast call/return mode select bit
2152 0, // second memory operand
2153 0, // second literal operand
2155 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2156 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2160 pCodeInstruction pic16_pciSUBWF = {
2161 {PC_OPCODE, NULL, NULL, 0, NULL,
2167 NULL, // from branch
2174 1,0, // dest, bit instruction
2175 0,0, // branch, skip
2176 0, // literal operand
2177 1, // RAM access bit
2178 0, // fast call/return mode select bit
2179 0, // second memory operand
2180 0, // second literal operand
2182 (PCC_W | PCC_REGISTER), // inCond
2183 (PCC_REGISTER | PCC_Z), // outCond
2187 pCodeInstruction pic16_pciSUBFW = {
2188 {PC_OPCODE, NULL, NULL, 0, NULL,
2194 NULL, // from branch
2201 0,0, // dest, bit instruction
2202 0,0, // branch, skip
2203 0, // literal operand
2204 1, // RAM access bit
2205 0, // fast call/return mode select bit
2206 0, // second memory operand
2207 0, // second literal operand
2209 (PCC_W | PCC_REGISTER), // inCond
2210 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2214 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2215 {PC_OPCODE, NULL, NULL, 0, NULL,
2221 NULL, // from branch
2228 1,0, // dest, bit instruction
2229 0,0, // branch, skip
2230 0, // literal operand
2231 1, // RAM access bit
2232 0, // fast call/return mode select bit
2233 0, // second memory operand
2234 0, // second literal operand
2236 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2237 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2241 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2242 {PC_OPCODE, NULL, NULL, 0, NULL,
2248 NULL, // from branch
2255 0,0, // dest, bit instruction
2256 0,0, // branch, skip
2257 0, // literal operand
2258 1, // RAM access bit
2259 0, // fast call/return mode select bit
2260 0, // second memory operand
2261 0, // second literal operand
2263 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2264 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2268 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2269 {PC_OPCODE, NULL, NULL, 0, NULL,
2275 NULL, // from branch
2282 1,0, // dest, bit instruction
2283 0,0, // branch, skip
2284 0, // literal operand
2285 1, // RAM access bit
2286 0, // fast call/return mode select bit
2287 0, // second memory operand
2288 0, // second literal operand
2290 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2291 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2295 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2296 {PC_OPCODE, NULL, NULL, 0, NULL,
2302 NULL, // from branch
2309 0,0, // dest, bit instruction
2310 0,0, // branch, skip
2311 0, // literal operand
2312 1, // RAM access bit
2313 0, // fast call/return mode select bit
2314 0, // second memory operand
2315 0, // second literal operand
2317 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2318 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2322 pCodeInstruction pic16_pciSWAPF = {
2323 {PC_OPCODE, NULL, NULL, 0, NULL,
2329 NULL, // from branch
2336 1,0, // dest, bit instruction
2337 0,0, // branch, skip
2338 0, // literal operand
2339 1, // RAM access bit
2340 0, // fast call/return mode select bit
2341 0, // second memory operand
2342 0, // second literal operand
2344 (PCC_REGISTER), // inCond
2345 (PCC_REGISTER), // outCond
2349 pCodeInstruction pic16_pciSWAPFW = {
2350 {PC_OPCODE, NULL, NULL, 0, NULL,
2356 NULL, // from branch
2363 0,0, // dest, bit instruction
2364 0,0, // branch, skip
2365 0, // literal operand
2366 1, // RAM access bit
2367 0, // fast call/return mode select bit
2368 0, // second memory operand
2369 0, // second literal operand
2371 (PCC_REGISTER), // inCond
2376 pCodeInstruction pic16_pciTBLRD = { // patch 15
2377 {PC_OPCODE, NULL, NULL, 0, NULL,
2382 NULL, // from branch
2389 0,0, // dest, bit instruction
2390 0,0, // branch, skip
2391 0, // literal operand
2392 0, // RAM access bit
2393 0, // fast call/return mode select bit
2394 0, // second memory operand
2395 0, // second literal operand
2398 PCC_NONE , // outCond
2402 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2403 {PC_OPCODE, NULL, NULL, 0, NULL,
2408 NULL, // from branch
2415 0,0, // dest, bit instruction
2416 0,0, // branch, skip
2417 0, // literal operand
2418 0, // RAM access bit
2419 0, // fast call/return mode select bit
2420 0, // second memory operand
2421 0, // second literal operand
2424 PCC_NONE , // outCond
2428 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2429 {PC_OPCODE, NULL, NULL, 0, NULL,
2434 NULL, // from branch
2441 0,0, // dest, bit instruction
2442 0,0, // branch, skip
2443 0, // literal operand
2444 0, // RAM access bit
2445 0, // fast call/return mode select bit
2446 0, // second memory operand
2447 0, // second literal operand
2450 PCC_NONE , // outCond
2454 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2455 {PC_OPCODE, NULL, NULL, 0, NULL,
2460 NULL, // from branch
2467 0,0, // dest, bit instruction
2468 0,0, // branch, skip
2469 0, // literal operand
2470 0, // RAM access bit
2471 0, // fast call/return mode select bit
2472 0, // second memory operand
2473 0, // second literal operand
2476 PCC_NONE , // outCond
2480 pCodeInstruction pic16_pciTBLWT = { // patch 15
2481 {PC_OPCODE, NULL, NULL, 0, NULL,
2486 NULL, // from branch
2493 0,0, // dest, bit instruction
2494 0,0, // branch, skip
2495 0, // literal operand
2496 0, // RAM access bit
2497 0, // fast call/return mode select bit
2498 0, // second memory operand
2499 0, // second literal operand
2502 PCC_NONE , // outCond
2506 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2507 {PC_OPCODE, NULL, NULL, 0, NULL,
2512 NULL, // from branch
2519 0,0, // dest, bit instruction
2520 0,0, // branch, skip
2521 0, // literal operand
2522 0, // RAM access bit
2523 0, // fast call/return mode select bit
2524 0, // second memory operand
2525 0, // second literal operand
2528 PCC_NONE , // outCond
2532 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2533 {PC_OPCODE, NULL, NULL, 0, NULL,
2538 NULL, // from branch
2545 0,0, // dest, bit instruction
2546 0,0, // branch, skip
2547 0, // literal operand
2548 0, // RAM access bit
2549 0, // fast call/return mode select bit
2550 0, // second memory operand
2551 0, // second literal operand
2554 PCC_NONE , // outCond
2558 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2559 {PC_OPCODE, NULL, NULL, 0, NULL,
2564 NULL, // from branch
2571 0,0, // dest, bit instruction
2572 0,0, // branch, skip
2573 0, // literal operand
2574 0, // RAM access bit
2575 0, // fast call/return mode select bit
2576 0, // second memory operand
2577 0, // second literal operand
2580 PCC_NONE , // outCond
2584 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2585 {PC_OPCODE, NULL, NULL, 0, NULL,
2591 NULL, // from branch
2598 0,0, // dest, bit instruction
2599 1,1, // branch, skip
2600 0, // literal operand
2601 1, // RAM access bit
2602 0, // fast call/return mode select bit
2603 0, // second memory operand
2604 0, // second literal operand
2606 PCC_REGISTER, // inCond
2607 PCC_NONE, // outCond
2611 pCodeInstruction pic16_pciXORWF = {
2612 {PC_OPCODE, NULL, NULL, 0, NULL,
2618 NULL, // from branch
2625 1,0, // dest, bit instruction
2626 0,0, // branch, skip
2627 0, // literal operand
2628 1, // RAM access bit
2629 0, // fast call/return mode select bit
2630 0, // second memory operand
2631 0, // second literal operand
2633 (PCC_W | PCC_REGISTER), // inCond
2634 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2638 pCodeInstruction pic16_pciXORFW = {
2639 {PC_OPCODE, NULL, NULL, 0, NULL,
2645 NULL, // from branch
2652 0,0, // dest, bit instruction
2653 0,0, // branch, skip
2654 0, // literal operand
2655 1, // RAM access bit
2656 0, // fast call/return mode select bit
2657 0, // second memory operand
2658 0, // second literal operand
2660 (PCC_W | PCC_REGISTER), // inCond
2661 (PCC_W | PCC_Z | PCC_N), // outCond
2665 pCodeInstruction pic16_pciXORLW = {
2666 {PC_OPCODE, NULL, NULL, 0, NULL,
2672 NULL, // from branch
2679 0,0, // dest, bit instruction
2680 0,0, // branch, skip
2681 1, // literal operand
2682 1, // RAM access bit
2683 0, // fast call/return mode select bit
2684 0, // second memory operand
2685 0, // second literal operand
2687 (PCC_W | PCC_LITERAL), // inCond
2688 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2693 pCodeInstruction pic16_pciBANKSEL = {
2694 {PC_OPCODE, NULL, NULL, 0, NULL,
2699 NULL, // from branch
2706 0,0, // dest, bit instruction
2707 0,0, // branch, skip
2708 0, // literal operand
2709 0, // RAM access bit
2710 0, // fast call/return mode select bit
2711 0, // second memory operand
2712 0, // second literal operand
2715 PCC_NONE, // outCond
2720 #define MAX_PIC16MNEMONICS 100
2721 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2723 //#define USE_VSNPRINTF
2726 #ifdef USE_VSNPRINTF
2727 // Alas, vsnprintf is not ANSI standard, and does not exist
2728 // on Solaris (and probably other non-Gnu flavored Unixes).
2730 /*-----------------------------------------------------------------*/
2731 /* SAFE_snprintf - like snprintf except the string pointer is */
2732 /* after the string has been printed to. This is */
2733 /* useful for printing to string as though if it */
2734 /* were a stream. */
2735 /*-----------------------------------------------------------------*/
2736 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2744 va_start(val, format);
2746 vsnprintf(*str, *size, format, val);
2752 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2753 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2762 // This version is *not* safe, despite the name.
2764 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2768 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2773 va_start(val, format);
2775 vsprintf(buffer, format, val);
2778 len = strlen(buffer);
2780 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2781 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2784 strcpy(*str, buffer);
2790 #endif // USE_VSNPRINTF
2793 extern void pic16_initStack(int base_address, int size);
2794 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2795 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2796 extern void pic16_init_pic(char *);
2798 void pic16_pCodeInitRegisters(void)
2800 static int initialized=0;
2807 // pic16_initStack(0xfff, 8);
2808 pic16_init_pic(port->processor);
2810 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2811 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2812 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2813 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2814 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2815 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2816 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2818 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2819 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2820 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2822 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2823 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2824 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2825 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2827 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2828 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2829 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2830 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2831 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2832 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2834 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2835 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2836 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2837 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2838 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2840 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2841 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2842 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2843 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2844 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2846 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2847 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2848 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2849 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2850 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2852 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2853 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2856 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2857 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2858 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2859 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2862 pic16_pc_status.rIdx = IDX_STATUS;
2863 pic16_pc_intcon.rIdx = IDX_INTCON;
2864 pic16_pc_pcl.rIdx = IDX_PCL;
2865 pic16_pc_pclath.rIdx = IDX_PCLATH;
2866 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2867 pic16_pc_wreg.rIdx = IDX_WREG;
2868 pic16_pc_bsr.rIdx = IDX_BSR;
2870 pic16_pc_tosl.rIdx = IDX_TOSL;
2871 pic16_pc_tosh.rIdx = IDX_TOSH;
2872 pic16_pc_tosu.rIdx = IDX_TOSU;
2874 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2875 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2876 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2877 pic16_pc_tablat.rIdx = IDX_TABLAT;
2879 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2880 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2881 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2882 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2883 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2884 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2885 pic16_pc_indf0.rIdx = IDX_INDF0;
2886 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2887 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2888 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2889 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2890 pic16_pc_indf1.rIdx = IDX_INDF1;
2891 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2892 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2893 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2894 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2895 pic16_pc_indf2.rIdx = IDX_INDF2;
2896 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2897 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2898 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2899 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2900 pic16_pc_prodl.rIdx = IDX_PRODL;
2901 pic16_pc_prodh.rIdx = IDX_PRODH;
2903 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2904 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2905 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2907 pic16_pc_kzero.rIdx = IDX_KZ;
2908 pic16_pc_wsave.rIdx = IDX_WSAVE;
2909 pic16_pc_ssave.rIdx = IDX_SSAVE;
2911 pic16_pc_eecon1.rIdx = IDX_EECON1;
2912 pic16_pc_eecon2.rIdx = IDX_EECON2;
2913 pic16_pc_eedata.rIdx = IDX_EEDATA;
2914 pic16_pc_eeadr.rIdx = IDX_EEADR;
2917 /* probably should put this in a separate initialization routine */
2918 pb_dead_pcodes = newpBlock();
2923 /*-----------------------------------------------------------------*/
2924 /* mnem2key - convert a pic mnemonic into a hash key */
2925 /* (BTW - this spreads the mnemonics quite well) */
2927 /*-----------------------------------------------------------------*/
2929 int mnem2key(char const *mnem)
2938 key += toupper(*mnem++) +1;
2942 return (key & 0x1f);
2947 void pic16initMnemonics(void)
2952 pCodeInstruction *pci;
2954 if(mnemonics_initialized)
2957 // NULL out the array before making the assignments
2958 // since we check the array contents below this initialization.
2960 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2961 pic16Mnemonics[i] = NULL;
2964 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2965 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2966 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2967 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2968 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2969 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2970 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2971 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2972 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2973 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2974 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2975 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2976 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2977 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2978 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2979 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2980 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2981 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2982 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2983 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2984 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2985 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2986 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2987 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2988 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2989 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2990 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2991 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2992 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2993 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2994 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2995 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2996 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2997 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2998 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2999 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3000 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3001 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3002 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3003 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3004 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3005 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3006 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3007 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3008 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3009 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3010 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3011 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3012 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3013 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3014 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3015 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3016 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3017 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3018 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3019 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3020 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3021 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3022 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3023 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3024 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3025 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3026 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3027 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3028 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3029 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3030 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3031 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3032 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3033 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3034 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3035 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3036 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3037 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3038 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3039 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3040 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3041 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3042 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3043 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3044 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3045 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3046 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3047 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3048 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3049 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3050 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3051 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3052 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3053 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3054 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3055 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3056 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3058 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3059 if(pic16Mnemonics[i])
3060 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3061 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3064 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3065 pci = hTabNextItem(pic16MnemonicsHash, &key);
3068 mnemonics_initialized = 1;
3071 int pic16_getpCodePeepCommand(char *cmd);
3073 int pic16_getpCode(char *mnem,unsigned dest)
3076 pCodeInstruction *pci;
3077 int key = mnem2key(mnem);
3079 if(!mnemonics_initialized)
3080 pic16initMnemonics();
3082 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3086 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3087 if((pci->num_ops <= 1)
3088 || (pci->isModReg == dest)
3090 || (pci->num_ops <= 2 && pci->isAccess)
3091 || (pci->num_ops <= 2 && pci->isFastCall)
3092 || (pci->num_ops <= 2 && pci->is2MemOp)
3093 || (pci->num_ops <= 2 && pci->is2LitOp) )
3097 pci = hTabNextItemWK (pic16MnemonicsHash);
3104 /*-----------------------------------------------------------------*
3105 * pic16initpCodePeepCommands
3107 *-----------------------------------------------------------------*/
3108 void pic16initpCodePeepCommands(void)
3116 hTabAddItem(&pic16pCodePeepCommandsHash,
3117 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3119 } while (peepCommands[i].cmd);
3121 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3124 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3125 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3130 /*-----------------------------------------------------------------
3133 *-----------------------------------------------------------------*/
3135 int pic16_getpCodePeepCommand(char *cmd)
3139 int key = mnem2key(cmd);
3142 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3145 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3146 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3150 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3157 static char getpBlock_dbName(pBlock *pb)
3163 return pb->cmemmap->dbName;
3167 void pic16_pBlockConvert2ISR(pBlock *pb)
3171 if(pb->cmemmap)pb->cmemmap = NULL;
3175 if(pic16_pcode_verbose)
3176 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3179 void pic16_pBlockConvert2Absolute(pBlock *pb)
3182 if(pb->cmemmap)pb->cmemmap = NULL;
3186 if(pic16_pcode_verbose)
3187 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3190 /*-----------------------------------------------------------------*/
3191 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3192 /* instances to the front of the doubly linked */
3193 /* list of pBlocks */
3194 /*-----------------------------------------------------------------*/
3196 void pic16_movepBlock2Head(char dbName)
3201 /* this can happen in sources without code,
3202 * only variable definitions */
3203 if(!the_pFile)return;
3205 pb = the_pFile->pbHead;
3209 if(getpBlock_dbName(pb) == dbName) {
3210 pBlock *pbn = pb->next;
3211 pb->next = the_pFile->pbHead;
3212 the_pFile->pbHead->prev = pb;
3213 the_pFile->pbHead = pb;
3216 pb->prev->next = pbn;
3218 // If the pBlock that we just moved was the last
3219 // one in the link of all of the pBlocks, then we
3220 // need to point the tail to the block just before
3221 // the one we moved.
3222 // Note: if pb->next is NULL, then pb must have
3223 // been the last pBlock in the chain.
3226 pbn->prev = pb->prev;
3228 the_pFile->pbTail = pb->prev;
3239 void pic16_copypCode(FILE *of, char dbName)
3243 if(!of || !the_pFile)
3246 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3247 if(getpBlock_dbName(pb) == dbName) {
3248 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3250 pic16_printpBlock(of,pb);
3255 void pic16_pcode_test(void)
3258 DFPRINTF((stderr,"pcode is alive!\n"));
3268 /* create the file name */
3269 strcpy(buffer,dstFileName);
3270 strcat(buffer,".p");
3272 if( !(pFile = fopen(buffer, "w" ))) {
3273 werror(E_FILE_OPEN_ERR,buffer);
3277 fprintf(pFile,"pcode dump\n\n");
3279 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3280 fprintf(pFile,"\n\tNew pBlock\n\n");
3282 fprintf(pFile,"%s",pb->cmemmap->sname);
3284 fprintf(pFile,"internal pblock");
3286 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3287 pic16_printpBlock(pFile,pb);
3291 /*-----------------------------------------------------------------*/
3292 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3293 /* ister, RegCond will return the bit being referenced. */
3295 /* fixme - why not just OR in the pcop bit field */
3296 /*-----------------------------------------------------------------*/
3298 static int RegCond(pCodeOp *pcop)
3304 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3305 switch(PCORB(pcop)->bit) {
3319 /*-----------------------------------------------------------------*/
3320 /* pic16_newpCode - create and return a newly initialized pCode */
3322 /* fixme - rename this */
3324 /* The purpose of this routine is to create a new Instruction */
3325 /* pCode. This is called by gen.c while the assembly code is being */
3329 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3330 /* (note that the op is analogous to but not the */
3331 /* same thing as the opcode of the instruction.) */
3332 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3335 /* a pointer to the new malloc'd pCode is returned. */
3339 /*-----------------------------------------------------------------*/
3340 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3342 pCodeInstruction *pci ;
3344 if(!mnemonics_initialized)
3345 pic16initMnemonics();
3347 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3349 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3350 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3353 if(pci->inCond & PCC_EXAMINE_PCOP)
3354 pci->inCond |= RegCond(pcop);
3356 if(pci->outCond & PCC_EXAMINE_PCOP)
3357 pci->outCond |= RegCond(pcop);
3359 pci->pc.prev = pci->pc.next = NULL;
3360 return (pCode *)pci;
3363 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3369 /*-----------------------------------------------------------------*/
3370 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3372 /* Wild pcodes are used during the peep hole optimizer to serve */
3373 /* as place holders for any instruction. When a snippet of code is */
3374 /* compared to a peep hole rule, the wild card opcode will match */
3375 /* any instruction. However, the optional operand and label are */
3376 /* additional qualifiers that must also be matched before the */
3377 /* line (of assembly code) is declared matched. Note that the */
3378 /* operand may be wild too. */
3380 /* Note, a wild instruction is specified just like a wild var: */
3381 /* %4 ; A wild instruction, */
3382 /* See the peeph.def file for additional examples */
3384 /*-----------------------------------------------------------------*/
3386 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3391 pcw = Safe_calloc(1,sizeof(pCodeWild));
3393 pcw->pci.pc.type = PC_WILD;
3394 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3395 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3396 pcw->pci.pc.pb = NULL;
3398 // pcw->pci.pc.analyze = genericAnalyze;
3399 pcw->pci.pc.destruct = genericDestruct;
3400 pcw->pci.pc.print = genericPrint;
3402 pcw->id = pCodeID; // this is the 'n' in %n
3403 pcw->operand = optional_operand;
3404 pcw->label = optional_label;
3406 pcw->mustBeBitSkipInst = 0;
3407 pcw->mustNotBeBitSkipInst = 0;
3408 pcw->invertBitSkipInst = 0;
3410 return ( (pCode *)pcw);
3414 /*-----------------------------------------------------------------*/
3415 /* newPcodeInlineP - create a new pCode from a char string */
3416 /*-----------------------------------------------------------------*/
3419 pCode *pic16_newpCodeInlineP(char *cP)
3424 pcc = Safe_calloc(1,sizeof(pCodeComment));
3426 pcc->pc.type = PC_INLINE;
3427 pcc->pc.prev = pcc->pc.next = NULL;
3428 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3431 // pcc->pc.analyze = genericAnalyze;
3432 pcc->pc.destruct = genericDestruct;
3433 pcc->pc.print = genericPrint;
3436 pcc->comment = Safe_strdup(cP);
3438 pcc->comment = NULL;
3440 return ( (pCode *)pcc);
3444 /*-----------------------------------------------------------------*/
3445 /* newPcodeCharP - create a new pCode from a char string */
3446 /*-----------------------------------------------------------------*/
3448 pCode *pic16_newpCodeCharP(char *cP)
3453 pcc = Safe_calloc(1,sizeof(pCodeComment));
3455 pcc->pc.type = PC_COMMENT;
3456 pcc->pc.prev = pcc->pc.next = NULL;
3457 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3460 // pcc->pc.analyze = genericAnalyze;
3461 pcc->pc.destruct = genericDestruct;
3462 pcc->pc.print = genericPrint;
3465 pcc->comment = Safe_strdup(cP);
3467 pcc->comment = NULL;
3469 return ( (pCode *)pcc);
3473 /*-----------------------------------------------------------------*/
3474 /* pic16_newpCodeFunction - */
3475 /*-----------------------------------------------------------------*/
3478 pCode *pic16_newpCodeFunction(char *mod,char *f)
3482 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3484 pcf->pc.type = PC_FUNCTION;
3485 pcf->pc.prev = pcf->pc.next = NULL;
3486 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3489 // pcf->pc.analyze = genericAnalyze;
3490 pcf->pc.destruct = genericDestruct;
3491 pcf->pc.print = pCodePrintFunction;
3497 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3498 strcpy(pcf->modname,mod);
3500 pcf->modname = NULL;
3503 pcf->fname = Safe_calloc(1,strlen(f)+1);
3504 strcpy(pcf->fname,f);
3508 pcf->stackusage = 0;
3510 return ( (pCode *)pcf);
3513 /*-----------------------------------------------------------------*/
3514 /* pic16_newpCodeFlow */
3515 /*-----------------------------------------------------------------*/
3516 static void destructpCodeFlow(pCode *pc)
3518 if(!pc || !isPCFL(pc))
3525 pic16_unlinkpCode(pc);
3527 deleteSet(&PCFL(pc)->registers);
3528 deleteSet(&PCFL(pc)->from);
3529 deleteSet(&PCFL(pc)->to);
3531 /* Instead of deleting the memory used by this pCode, mark
3532 * the object as bad so that if there's a pointer to this pCode
3533 * dangling around somewhere then (hopefully) when the type is
3534 * checked we'll catch it.
3538 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3544 pCode *pic16_newpCodeFlow(void )
3548 //_ALLOC(pcflow,sizeof(pCodeFlow));
3549 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3551 pcflow->pc.type = PC_FLOW;
3552 pcflow->pc.prev = pcflow->pc.next = NULL;
3553 pcflow->pc.pb = NULL;
3555 // pcflow->pc.analyze = genericAnalyze;
3556 pcflow->pc.destruct = destructpCodeFlow;
3557 pcflow->pc.print = genericPrint;
3559 pcflow->pc.seq = GpcFlowSeq++;
3561 pcflow->from = pcflow->to = NULL;
3563 pcflow->inCond = PCC_NONE;
3564 pcflow->outCond = PCC_NONE;
3566 pcflow->firstBank = -1;
3567 pcflow->lastBank = -1;
3569 pcflow->FromConflicts = 0;
3570 pcflow->ToConflicts = 0;
3574 pcflow->registers = newSet();
3576 return ( (pCode *)pcflow);
3580 /*-----------------------------------------------------------------*/
3581 /*-----------------------------------------------------------------*/
3582 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3584 pCodeFlowLink *pcflowLink;
3586 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3588 pcflowLink->pcflow = pcflow;
3589 pcflowLink->bank_conflict = 0;
3594 /*-----------------------------------------------------------------*/
3595 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3596 /*-----------------------------------------------------------------*/
3598 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3603 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3605 pccs->pc.type = PC_CSOURCE;
3606 pccs->pc.prev = pccs->pc.next = NULL;
3609 pccs->pc.destruct = genericDestruct;
3610 pccs->pc.print = genericPrint;
3612 pccs->line_number = ln;
3614 pccs->line = Safe_strdup(l);
3619 pccs->file_name = Safe_strdup(f);
3621 pccs->file_name = NULL;
3623 return ( (pCode *)pccs);
3628 /*******************************************************************/
3629 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3630 /* added by VR 6-Jun-2003 */
3631 /*******************************************************************/
3633 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3640 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3641 pcad->pci.pc.type = PC_ASMDIR;
3642 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3643 pcad->pci.pc.pb = NULL;
3645 pcad->pci.pc.destruct = genericDestruct;
3646 pcad->pci.pc.print = genericPrint;
3648 if(asdir && *asdir) {
3650 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3652 pcad->directive = Safe_strdup( asdir );
3655 va_start(ap, argfmt);
3657 memset(buffer, 0, sizeof(buffer));
3658 if(argfmt && *argfmt)
3659 vsprintf(buffer, argfmt, ap);
3663 while(isspace(*lbp))lbp++;
3666 pcad->arg = Safe_strdup( lbp );
3668 return ((pCode *)pcad);
3671 /*-----------------------------------------------------------------*/
3672 /* pCodeLabelDestruct - free memory used by a label. */
3673 /*-----------------------------------------------------------------*/
3674 static void pCodeLabelDestruct(pCode *pc)
3680 if((pc->type == PC_LABEL) && PCL(pc)->label)
3681 free(PCL(pc)->label);
3683 /* Instead of deleting the memory used by this pCode, mark
3684 * the object as bad so that if there's a pointer to this pCode
3685 * dangling around somewhere then (hopefully) when the type is
3686 * checked we'll catch it.
3690 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3696 pCode *pic16_newpCodeLabel(char *name, int key)
3702 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3704 pcl->pc.type = PC_LABEL;
3705 pcl->pc.prev = pcl->pc.next = NULL;
3706 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3709 // pcl->pc.analyze = genericAnalyze;
3710 pcl->pc.destruct = pCodeLabelDestruct;
3711 pcl->pc.print = pCodePrintLabel;
3718 sprintf(s,"_%05d_DS_",key);
3723 pcl->label = Safe_strdup(s);
3725 // if(pic16_pcode_verbose)
3726 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3729 return ( (pCode *)pcl);
3733 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3735 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3739 return ( (pCode *)pcl );
3743 /*-----------------------------------------------------------------*/
3744 /* newpBlock - create and return a pointer to a new pBlock */
3745 /*-----------------------------------------------------------------*/
3746 static pBlock *newpBlock(void)
3751 PpB = Safe_calloc(1,sizeof(pBlock) );
3752 PpB->next = PpB->prev = NULL;
3754 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3755 PpB->tregisters = NULL;
3757 PpB->FlowTree = NULL;
3763 /*-----------------------------------------------------------------*/
3764 /* pic16_newpCodeChain - create a new chain of pCodes */
3765 /*-----------------------------------------------------------------*
3767 * This function will create a new pBlock and the pointer to the
3768 * pCode that is passed in will be the first pCode in the block.
3769 *-----------------------------------------------------------------*/
3772 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3775 pBlock *pB = newpBlock();
3777 pB->pcHead = pB->pcTail = pc;
3784 /*-----------------------------------------------------------------*/
3785 /* pic16_newpCodeOpLabel - Create a new label given the key */
3786 /* Note, a negative key means that the label is part of wild card */
3787 /* (and hence a wild card label) used in the pCodePeep */
3788 /* optimizations). */
3789 /*-----------------------------------------------------------------*/
3791 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3794 static int label_key=-1;
3798 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3799 pcop->type = PO_LABEL;
3804 sprintf(s=buffer,"_%05d_DS_",key);
3806 s = name, key = label_key--;
3809 pcop->name = Safe_strdup(s);
3811 ((pCodeOpLabel *)pcop)->key = key;
3813 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3817 /*-----------------------------------------------------------------*/
3818 /*-----------------------------------------------------------------*/
3819 pCodeOp *pic16_newpCodeOpLit(int lit)
3825 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3826 pcop->type = PO_LITERAL;
3830 sprintf(s,"0x%02x",lit);
3832 pcop->name = Safe_strdup(s);
3835 ((pCodeOpLit *)pcop)->lit = lit;
3840 /*-----------------------------------------------------------------*/
3841 /*-----------------------------------------------------------------*/
3842 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3844 char *s = buffer, tbuf[256], *tb=tbuf;
3848 tb = pic16_get_op(arg2, NULL, 0);
3849 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3850 pcop->type = PO_LITERAL;
3854 sprintf(s,"0x%02x, %s",lit, tb);
3856 pcop->name = Safe_strdup(s);
3859 ((pCodeOpLit2 *)pcop)->lit = lit;
3860 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3865 /*-----------------------------------------------------------------*/
3866 /*-----------------------------------------------------------------*/
3867 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3871 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3872 pcop->type = PO_IMMEDIATE;
3874 regs *r = pic16_dirregWithName(name);
3875 pcop->name = Safe_strdup(name);
3879 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3880 PCOI(pcop)->rIdx = r->rIdx;
3882 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3883 PCOI(pcop)->rIdx = -1;
3885 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3890 PCOI(pcop)->index = index;
3891 PCOI(pcop)->offset = offset;
3892 PCOI(pcop)->_const = code_space;
3897 /*-----------------------------------------------------------------*/
3898 /*-----------------------------------------------------------------*/
3899 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3905 if(!pcwb || !subtype) {
3906 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3910 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3911 pcop->type = PO_WILD;
3912 sprintf(s,"%%%d",id);
3913 pcop->name = Safe_strdup(s);
3915 PCOW(pcop)->id = id;
3916 PCOW(pcop)->pcwb = pcwb;
3917 PCOW(pcop)->subtype = subtype;
3918 PCOW(pcop)->matched = NULL;
3920 PCOW(pcop)->pcop2 = NULL;
3925 /*-----------------------------------------------------------------*/
3926 /*-----------------------------------------------------------------*/
3927 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3933 if(!pcwb || !subtype || !subtype2) {
3934 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3938 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3939 pcop->type = PO_WILD;
3940 sprintf(s,"%%%d",id);
3941 pcop->name = Safe_strdup(s);
3943 PCOW(pcop)->id = id;
3944 PCOW(pcop)->pcwb = pcwb;
3945 PCOW(pcop)->subtype = subtype;
3946 PCOW(pcop)->matched = NULL;
3948 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3950 if(!subtype2->name) {
3951 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3952 PCOW2(pcop)->pcop.type = PO_WILD;
3953 sprintf(s, "%%%d", id2);
3954 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3955 PCOW2(pcop)->id = id2;
3956 PCOW2(pcop)->subtype = subtype2;
3958 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3959 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3961 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
3963 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3964 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3973 /*-----------------------------------------------------------------*/
3974 /*-----------------------------------------------------------------*/
3975 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
3979 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3980 pcop->type = PO_GPR_BIT;
3982 pcop->name = Safe_strdup(s);
3986 PCORB(pcop)->bit = bit;
3987 PCORB(pcop)->inBitSpace = inBitSpace;
3988 PCORB(pcop)->subtype = subt;
3990 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3991 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
3992 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
3993 // PCOR(pcop)->rIdx = 0;
3998 /*-----------------------------------------------------------------*
3999 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4001 * If rIdx >=0 then a specific register from the set of registers
4002 * will be selected. If rIdx <0, then a new register will be searched
4004 *-----------------------------------------------------------------*/
4006 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4010 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4015 PCOR(pcop)->rIdx = rIdx;
4016 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4018 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4021 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4023 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4024 __FUNCTION__, __LINE__);
4029 pcop->type = PCOR(pcop)->r->pc_type;
4034 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4039 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4040 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4041 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4042 pcop->type = PCOR(pcop)->r->pc_type;
4043 pcop->name = PCOR(pcop)->r->name;
4045 // if(pic16_pcode_verbose) {
4046 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4047 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4053 /*-----------------------------------------------------------------*/
4054 /*-----------------------------------------------------------------*/
4056 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4063 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4067 pcop = pic16_newpCodeOpLit(-1);
4071 pcop = pic16_newpCodeOpLabel(NULL,-1);
4074 pcop = pic16_newpCodeOpReg(-1);
4077 case PO_GPR_REGISTER:
4079 pcop = pic16_newpCodeOpRegFromStr(name);
4081 pcop = pic16_newpCodeOpReg(-1);
4085 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4088 pcop->name = Safe_strdup(name);
4096 #define DB_ITEMS_PER_LINE 8
4098 typedef struct DBdata
4105 static int DBd_init = -1;
4107 /*-----------------------------------------------------------------*/
4108 /* Initialiase "DB" data buffer */
4109 /*-----------------------------------------------------------------*/
4110 void pic16_initDB(void)
4116 /*-----------------------------------------------------------------*/
4117 /* Flush pending "DB" data to a pBlock */
4119 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4120 /*-----------------------------------------------------------------*/
4121 void pic16_flushDB(char ptype, void *p)
4125 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4128 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4131 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4135 DBd.buffer[0] = '\0';
4140 /*-----------------------------------------------------------------*/
4141 /* Add "DB" directives to a pBlock */
4142 /*-----------------------------------------------------------------*/
4143 void pic16_emitDB(char c, char ptype, void *p)
4148 // we need to initialize
4151 DBd.buffer[0] = '\0';
4154 l = strlen(DBd.buffer);
4155 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4157 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4160 if (DBd.count>= DB_ITEMS_PER_LINE)
4161 pic16_flushDB(ptype, p);
4164 void pic16_emitDS(char *s, char ptype, void *p)
4169 // we need to initialize
4172 DBd.buffer[0] = '\0';
4175 l = strlen(DBd.buffer);
4176 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4178 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4180 DBd.count++; //=strlen(s);
4182 pic16_flushDB(ptype, p);
4186 /*-----------------------------------------------------------------*/
4187 /*-----------------------------------------------------------------*/
4188 void pic16_pCodeConstString(char *name, char *value)
4192 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4197 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4199 pic16_addpBlock(pb);
4201 sprintf(buffer,"; %s = %s",name,value);
4203 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4204 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4207 pic16_emitDB(*value, 'p', (void *)pb);
4209 pic16_flushDB('p', (void *)pb);
4212 /*-----------------------------------------------------------------*/
4213 /*-----------------------------------------------------------------*/
4215 static void pCodeReadCodeTable(void)
4219 fprintf(stderr, " %s\n",__FUNCTION__);
4221 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4223 pic16_addpBlock(pb);
4225 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4226 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4227 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4228 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4230 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4231 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4232 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4233 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4238 /*-----------------------------------------------------------------*/
4239 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4240 /*-----------------------------------------------------------------*/
4241 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4248 /* If this is the first pcode to be added to a block that
4249 * was initialized with a NULL pcode, then go ahead and
4250 * make this pcode the head and tail */
4251 pb->pcHead = pb->pcTail = pc;
4254 pb->pcTail->next = pc;
4256 pc->prev = pb->pcTail;
4263 /*-----------------------------------------------------------------*/
4264 /* pic16_addpBlock - place a pBlock into the pFile */
4265 /*-----------------------------------------------------------------*/
4266 void pic16_addpBlock(pBlock *pb)
4268 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4271 /* First time called, we'll pass through here. */
4272 //_ALLOC(the_pFile,sizeof(pFile));
4273 the_pFile = Safe_calloc(1,sizeof(pFile));
4274 the_pFile->pbHead = the_pFile->pbTail = pb;
4275 the_pFile->functions = NULL;
4279 the_pFile->pbTail->next = pb;
4280 pb->prev = the_pFile->pbTail;
4282 the_pFile->pbTail = pb;
4285 /*-----------------------------------------------------------------*/
4286 /* removepBlock - remove a pBlock from the pFile */
4287 /*-----------------------------------------------------------------*/
4288 static void removepBlock(pBlock *pb)
4296 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4298 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4301 if(pbs == the_pFile->pbHead)
4302 the_pFile->pbHead = pbs->next;
4304 if (pbs == the_pFile->pbTail)
4305 the_pFile->pbTail = pbs->prev;
4308 pbs->next->prev = pbs->prev;
4311 pbs->prev->next = pbs->next;
4318 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4322 /*-----------------------------------------------------------------*/
4323 /* printpCode - write the contents of a pCode to a file */
4324 /*-----------------------------------------------------------------*/
4325 static void printpCode(FILE *of, pCode *pc)
4336 fprintf(of,"warning - unable to print pCode\n");
4339 /*-----------------------------------------------------------------*/
4340 /* pic16_printpBlock - write the contents of a pBlock to a file */
4341 /*-----------------------------------------------------------------*/
4342 void pic16_printpBlock(FILE *of, pBlock *pb)
4350 for(pc = pb->pcHead; pc; pc = pc->next) {
4351 if(isPCF(pc) && PCF(pc)->fname) {
4352 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4353 if(pb->dbName == 'A') {
4355 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4356 if(!strcmp(ab->name, PCF(pc)->fname)) {
4357 fprintf(of, "\t0X%06X", ab->address);
4368 /*-----------------------------------------------------------------*/
4370 /* pCode processing */
4374 /*-----------------------------------------------------------------*/
4376 void pic16_unlinkpCode(pCode *pc)
4382 fprintf(stderr,"Unlinking: ");
4383 printpCode(stderr, pc);
4386 pc->prev->next = pc->next;
4388 pc->next->prev = pc->prev;
4390 pc->prev = pc->next = NULL;
4394 /*-----------------------------------------------------------------*/
4395 /*-----------------------------------------------------------------*/
4397 static void genericDestruct(pCode *pc)
4400 pic16_unlinkpCode(pc);
4403 /* For instructions, tell the register (if there's one used)
4404 * that it's no longer needed */
4405 regs *reg = pic16_getRegFromInstruction(pc);
4407 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4409 if(PCI(pc)->is2MemOp) {
4410 reg = pic16_getRegFromInstruction2(pc);
4412 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4416 /* Instead of deleting the memory used by this pCode, mark
4417 * the object as bad so that if there's a pointer to this pCode
4418 * dangling around somewhere then (hopefully) when the type is
4419 * checked we'll catch it.
4423 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4429 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4430 /*-----------------------------------------------------------------*/
4431 /*-----------------------------------------------------------------*/
4432 /* modifiers for constant immediate */
4433 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4435 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4440 int use_buffer = 1; // copy the string to the passed buffer pointer
4445 use_buffer = 0; // Don't bother copying the string to the buffer.
4449 switch(pcop->type) {
4457 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4460 return PCOR(pcop)->r->name;
4463 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4465 SAFE_snprintf(&buffer,&size,"%s",r->name);
4472 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4473 if(PCOI(pcop)->index) {
4474 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4475 immdmod[ PCOI(pcop)->offset ],
4479 SAFE_snprintf(&s,&size,"%s(%s)",
4480 immdmod[ PCOI(pcop)->offset ],
4484 if(PCOI(pcop)->index) {
4485 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4490 SAFE_snprintf(&s,&size, "%s(%s)",
4497 case PO_GPR_REGISTER:
4500 // size = sizeof(buffer);
4501 if( PCOR(pcop)->instance) {
4502 SAFE_snprintf(&s,&size,"(%s + %d)",
4504 PCOR(pcop)->instance );
4506 SAFE_snprintf(&s,&size,"%s",pcop->name);
4513 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4522 return "NO operand1";
4525 /*-----------------------------------------------------------------*/
4526 /* pic16_get_op2 - variant to support two memory operand commands */
4527 /*-----------------------------------------------------------------*/
4528 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4533 int use_buffer = 1; // copy the string to the passed buffer pointer
4538 use_buffer = 0; // Don't bother copying the string to the buffer.
4542 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",
4543 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4544 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4548 switch(PCOR2(pcop)->pcop2->type) {
4556 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4559 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4562 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4565 SAFE_snprintf(&buffer,&size,"%s",r->name);
4576 if(PCOI(pcop)->_const) {
4577 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4578 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4581 8 * PCOI(pcop)->offset );
4583 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4585 if( PCOI(pcop)->index) {
4586 SAFE_snprintf(&s,&size,"(%s + %d)",
4588 PCOI(pcop)->index );
4590 if(PCOI(pcop)->offset)
4591 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4593 SAFE_snprintf(&s,&size,"%s",pcop->name);
4600 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4601 SAFE_snprintf(&s,&size,"(%s + %d)",
4602 PCOR(PCOR2(pcop)->pcop2)->r->name,
4603 PCOR(PCOR2(pcop)->pcop2)->instance );
4605 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4610 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4612 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4615 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4620 return "NO operand2";
4623 /*-----------------------------------------------------------------*/
4624 /*-----------------------------------------------------------------*/
4625 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4629 return pic16_get_op(pcc->pcop,NULL,0);
4631 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4632 * return ("ERROR Null: "__FUNCTION__);
4634 return ("ERROR Null: pic16_get_op_from_instruction");
4638 /*-----------------------------------------------------------------*/
4639 /*-----------------------------------------------------------------*/
4640 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4643 fprintf(of,"pcodeopprint- not implemented\n");
4646 /*-----------------------------------------------------------------*/
4647 /* pic16_pCode2str - convert a pCode instruction to string */
4648 /*-----------------------------------------------------------------*/
4649 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4655 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4656 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4657 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4665 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4667 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4669 if(PCI(pc)->is2MemOp) {
4670 SAFE_snprintf(&s,&size, "%s, %s",
4671 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4672 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4676 if(PCI(pc)->is2LitOp) {
4677 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4681 if(PCI(pc)->isBitInst) {
4682 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4683 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4684 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4685 PCI(pc)->pcop->name ,
4686 PCI(pc)->pcop->name );
4688 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4689 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4690 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4691 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4693 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4694 //PCI(pc)->pcop->t.bit );
4697 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4698 if( PCI(pc)->num_ops == 3)
4699 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4701 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4704 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4706 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4707 if(PCI(pc)->num_ops == 3)
4708 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4710 r = pic16_getRegFromInstruction(pc);
4711 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4712 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4714 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4723 /* assuming that comment ends with a \n */
4724 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4728 /* assuming that inline code ends with a \n */
4729 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4733 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4736 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4739 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4742 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4745 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4746 SAFE_snprintf(&s,&size,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4747 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4750 if(PCAD(pc)->directive) {
4751 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4754 /* special case to handle inline labels without a tab */
4755 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4760 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4767 /*-----------------------------------------------------------------*/
4768 /* genericPrint - the contents of a pCode to a file */
4769 /*-----------------------------------------------------------------*/
4770 static void genericPrint(FILE *of, pCode *pc)
4778 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4782 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4786 // If the opcode has a label, print that first
4788 pBranch *pbl = PCI(pc)->label;
4789 while(pbl && pbl->pc) {
4790 if(pbl->pc->type == PC_LABEL)
4791 pCodePrintLabel(of, pbl->pc);
4797 genericPrint(of,PCODE(PCI(pc)->cline));
4802 pic16_pCode2str(str, 256, pc);
4804 fprintf(of,"%s",str);
4806 if(pic16_debug_verbose) {
4807 fprintf(of, "\t;key=%03x",pc->seq);
4809 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4816 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4817 if(PCW(pc)->pci.label)
4818 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4820 if(PCW(pc)->operand) {
4821 fprintf(of,";\toperand ");
4822 pCodeOpPrint(of,PCW(pc)->operand );
4827 if(pic16_debug_verbose) {
4828 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4829 if(PCFL(pc)->ancestor)
4830 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4837 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4838 fprintf(of,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4839 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4845 pBranch *pbl = PCAD(pc)->pci.label;
4846 while(pbl && pbl->pc) {
4847 if(pbl->pc->type == PC_LABEL)
4848 pCodePrintLabel(of, pbl->pc);
4852 if(PCAD(pc)->directive) {
4853 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4856 /* special case to handle inline labels without tab */
4857 fprintf(of, "%s\n", PCAD(pc)->arg);
4863 fprintf(of,"unknown pCode type %d\n",pc->type);
4868 /*-----------------------------------------------------------------*/
4869 /* pCodePrintFunction - prints function begin/end */
4870 /*-----------------------------------------------------------------*/
4872 static void pCodePrintFunction(FILE *of, pCode *pc)
4879 if( ((pCodeFunction *)pc)->modname)
4880 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4883 if(!PCF(pc)->absblock) {
4884 if(PCF(pc)->fname) {
4885 pBranch *exits = PCF(pc)->to;
4888 fprintf(of,"%s:", PCF(pc)->fname);
4890 if(pic16_pcode_verbose)
4891 fprintf(of, "\t;Function start");
4897 exits = exits->next;
4901 if(pic16_pcode_verbose)
4902 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4905 if((PCF(pc)->from &&
4906 PCF(pc)->from->pc->type == PC_FUNCTION &&
4907 PCF(PCF(pc)->from->pc)->fname) ) {
4909 if(pic16_pcode_verbose)
4910 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4912 if(pic16_pcode_verbose)
4913 fprintf(of,"; exit point [can't find entry point]\n");
4919 /*-----------------------------------------------------------------*/
4920 /* pCodePrintLabel - prints label */
4921 /*-----------------------------------------------------------------*/
4923 static void pCodePrintLabel(FILE *of, pCode *pc)
4930 fprintf(of,"%s:\n",PCL(pc)->label);
4931 else if (PCL(pc)->key >=0)
4932 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4934 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4937 /*-----------------------------------------------------------------*/
4938 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4939 /* remove it if it is found. */
4940 /*-----------------------------------------------------------------*/
4941 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4948 if(pcl->type == PC_OPCODE)
4949 b = PCI(pcl)->label;
4951 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4956 //fprintf (stderr, "%s \n",__FUNCTION__);
4957 //pcl->print(stderr,pcl);
4958 //pc->print(stderr,pc);
4961 //fprintf (stderr, "found label\n");
4962 //pc->print(stderr, pc);
4966 bprev->next = b->next; /* Not first pCode in chain */
4970 PCI(pcl)->label = b->next; /* First pCode in chain */
4973 return; /* A label can't occur more than once */
4981 /*-----------------------------------------------------------------*/
4982 /*-----------------------------------------------------------------*/
4983 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5002 /*-----------------------------------------------------------------*/
5003 /* pBranchLink - given two pcodes, this function will link them */
5004 /* together through their pBranches */
5005 /*-----------------------------------------------------------------*/
5006 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5010 // Declare a new branch object for the 'from' pCode.
5012 //_ALLOC(b,sizeof(pBranch));
5013 b = Safe_calloc(1,sizeof(pBranch));
5014 b->pc = PCODE(t); // The link to the 'to' pCode.
5017 f->to = pic16_pBranchAppend(f->to,b);
5019 // Now do the same for the 'to' pCode.
5021 //_ALLOC(b,sizeof(pBranch));
5022 b = Safe_calloc(1,sizeof(pBranch));
5026 t->from = pic16_pBranchAppend(t->from,b);
5031 /*-----------------------------------------------------------------*/
5032 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5034 /*-----------------------------------------------------------------*/
5035 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5048 /*-----------------------------------------------------------------*/
5049 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5050 /*-----------------------------------------------------------------*/
5051 void pic16_pCodeUnlink(pCode *pc)
5056 if(!pc->prev || !pc->next) {
5057 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5061 /* first remove the pCode from the chain */
5062 pc->prev->next = pc->next;
5063 pc->next->prev = pc->prev;
5065 /* Now for the hard part... */
5067 /* Remove the branches */
5069 pb1 = PCI(pc)->from;
5071 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5072 * one we're unlinking */
5074 /* search for the link back to this pCode (the one we're
5076 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5077 pb2->pc = PCI(pc)->to->pc; // make the replacement
5079 /* if the pCode we're unlinking contains multiple 'to'
5080 * branches (e.g. this a skip instruction) then we need
5081 * to copy these extra branches to the chain. */
5082 if(PCI(pc)->to->next)
5083 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5092 /*-----------------------------------------------------------------*/
5093 /*-----------------------------------------------------------------*/
5095 static void genericAnalyze(pCode *pc)
5105 // Go through the pCodes that are in pCode chain and link
5106 // them together through the pBranches. Note, the pCodes
5107 // are linked together as a contiguous stream like the
5108 // assembly source code lines. The linking here mimics this
5109 // except that comments are not linked in.
5111 pCode *npc = pc->next;
5113 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5114 pBranchLink(pc,npc);
5119 /* reached the end of the pcode chain without finding
5120 * an instruction we could link to. */
5124 fprintf(stderr,"analyze PC_FLOW\n");
5128 fprintf(stderr,,";A bad pCode is being used\n");
5134 /*-----------------------------------------------------------------*/
5135 /*-----------------------------------------------------------------*/
5136 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5140 if(pc->type == PC_LABEL) {
5141 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5144 if((pc->type == PC_OPCODE)
5145 || (pc->type == PC_ASMDIR)
5147 pbr = PCI(pc)->label;
5149 if(pbr->pc->type == PC_LABEL) {
5150 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5160 /*-----------------------------------------------------------------*/
5161 /*-----------------------------------------------------------------*/
5162 static int checkLabel(pCode *pc)
5166 if(pc && isPCI(pc)) {
5167 pbr = PCI(pc)->label;
5169 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5179 /*-----------------------------------------------------------------*/
5180 /* findLabelinpBlock - Search the pCode for a particular label */
5181 /*-----------------------------------------------------------------*/
5182 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5189 for(pc = pb->pcHead; pc; pc = pc->next)
5190 if(compareLabel(pc,pcop_label))
5196 /*-----------------------------------------------------------------*/
5197 /* findLabel - Search the pCode for a particular label */
5198 /*-----------------------------------------------------------------*/
5199 static pCode * findLabel(pCodeOpLabel *pcop_label)
5207 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5208 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5212 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5216 /*-----------------------------------------------------------------*/
5217 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5218 /* in the linked list */
5219 /*-----------------------------------------------------------------*/
5220 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5233 /*-----------------------------------------------------------------*/
5234 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5235 /* in the linked list */
5236 /*-----------------------------------------------------------------*/
5237 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5251 //#define PCODE_DEBUG
5252 /*-----------------------------------------------------------------*/
5253 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5254 /* in the linked list */
5255 /*-----------------------------------------------------------------*/
5256 pCode * pic16_findNextInstruction(pCode *pci)
5261 if((pc->type == PC_OPCODE)
5262 || (pc->type == PC_WILD)
5263 || (pc->type == PC_ASMDIR)
5268 fprintf(stderr,"pic16_findNextInstruction: ");
5269 printpCode(stderr, pc);
5274 //fprintf(stderr,"Couldn't find instruction\n");
5278 /*-----------------------------------------------------------------*/
5279 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5280 /* in the linked list */
5281 /*-----------------------------------------------------------------*/
5282 pCode * pic16_findPrevInstruction(pCode *pci)
5288 if((pc->type == PC_OPCODE)
5289 || (pc->type == PC_WILD)
5290 || (pc->type == PC_ASMDIR)
5296 fprintf(stderr,"pic16_findPrevInstruction: ");
5297 printpCode(stderr, pc);
5302 //fprintf(stderr,"Couldn't find instruction\n");
5309 /*-----------------------------------------------------------------*/
5310 /* findFunctionEnd - given a pCode find the end of the function */
5311 /* that contains it */
5312 /*-----------------------------------------------------------------*/
5313 static pCode * findFunctionEnd(pCode *pc)
5317 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5323 fprintf(stderr,"Couldn't find function end\n");
5328 /*-----------------------------------------------------------------*/
5329 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5330 /* instruction with which it is associated. */
5331 /*-----------------------------------------------------------------*/
5332 static void AnalyzeLabel(pCode *pc)
5335 pic16_pCodeUnlink(pc);
5341 static void AnalyzeGOTO(pCode *pc)
5344 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5348 static void AnalyzeSKIP(pCode *pc)
5351 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5352 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5356 static void AnalyzeRETURN(pCode *pc)
5359 // branch_link(pc,findFunctionEnd(pc->next));
5365 /*-----------------------------------------------------------------*/
5366 /*-----------------------------------------------------------------*/
5367 regs * pic16_getRegFromInstruction(pCode *pc)
5373 PCI(pc)->num_ops == 0 ||
5374 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5378 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5379 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5382 switch(PCI(pc)->pcop->type) {
5388 return PCOR(PCI(pc)->pcop)->r;
5392 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5393 return PCOR(PCI(pc)->pcop)->r;
5396 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5398 if(PCOI(PCI(pc)->pcop)->r)
5399 return (PCOI(PCI(pc)->pcop)->r);
5404 return PCOR(PCI(pc)->pcop)->r;
5406 case PO_GPR_REGISTER:
5408 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5409 return PCOR(PCI(pc)->pcop)->r;
5412 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5416 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5417 // genericPrint(stderr, pc);
5425 /*-------------------------------------------------------------------------------*/
5426 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5427 /*-------------------------------------------------------------------------------*/
5428 regs * pic16_getRegFromInstruction2(pCode *pc)
5434 PCI(pc)->num_ops == 0 ||
5435 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5440 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5441 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5445 * operands supported in MOVFF:
5452 switch(PCI(pc)->pcop->type) {
5458 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5460 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5464 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5465 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5469 // if(PCOI(PCI(pc)->pcop)->r)
5470 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5472 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5473 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5476 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5477 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5484 // return PCOR2(PCI(pc)->pcop)->r;
5486 case PO_GPR_REGISTER:
5488 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5489 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5493 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5496 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5497 //genericPrint(stderr, pc);
5505 /*-----------------------------------------------------------------*/
5506 /*-----------------------------------------------------------------*/
5508 static void AnalyzepBlock(pBlock *pb)
5515 /* Find all of the registers used in this pBlock
5516 * by looking at each instruction and examining it's
5519 for(pc = pb->pcHead; pc; pc = pc->next) {
5521 /* Is this an instruction with operands? */
5522 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5524 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5526 /* Loop through all of the registers declared so far in
5527 this block and see if we find this one there */
5529 regs *r = setFirstItem(pb->tregisters);
5532 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5533 PCOR(PCI(pc)->pcop)->r = r;
5536 r = setNextItem(pb->tregisters);
5540 /* register wasn't found */
5541 //r = Safe_calloc(1, sizeof(regs));
5542 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5543 //addSet(&pb->tregisters, r);
5544 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5545 //PCOR(PCI(pc)->pcop)->r = r;
5546 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5548 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5551 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5552 if(PCOR(PCI(pc)->pcop)->r) {
5553 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5554 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5556 if(PCI(pc)->pcop->name)
5557 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5559 fprintf(stderr,"ERROR: NULL register\n");
5568 /*-----------------------------------------------------------------*/
5570 /*-----------------------------------------------------------------*/
5571 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5573 static void InsertpFlow(pCode *pc, pCode **pflow)
5576 PCFL(*pflow)->end = pc;
5578 if(!pc || !pc->next)
5581 *pflow = pic16_newpCodeFlow();
5582 pic16_pCodeInsertAfter(pc, *pflow);
5585 /*-----------------------------------------------------------------*/
5586 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5587 /* the flow blocks. */
5589 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5590 * point the instruction flow changes.
5592 /*-----------------------------------------------------------------*/
5593 void pic16_BuildFlow(pBlock *pb)
5596 pCode *last_pci=NULL;
5603 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5604 /* Insert a pCodeFlow object at the beginning of a pBlock */
5606 InsertpFlow(pb->pcHead, &pflow);
5608 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5609 //pflow->next = pb->pcHead; /* Make the current head the next object */
5610 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5611 //pb->pcHead = pflow; /* Make the Flow object the head */
5614 for( pc = pic16_findNextInstruction(pb->pcHead);
5616 pc=pic16_findNextInstruction(pc)) {
5619 PCI(pc)->pcflow = PCFL(pflow);
5621 //fprintf(stderr," build: ");
5622 //pflow->print(stderr,pflow);
5624 if( PCI(pc)->isSkip) {
5626 /* The two instructions immediately following this one
5627 * mark the beginning of a new flow segment */
5629 while(pc && PCI(pc)->isSkip) {
5631 PCI(pc)->pcflow = PCFL(pflow);
5635 InsertpFlow(pc, &pflow);
5636 pc=pic16_findNextInstruction(pc->next);
5644 PCI(pc)->pcflow = PCFL(pflow);
5646 InsertpFlow(pc, &pflow);
5648 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5650 InsertpFlow(pc, &pflow);
5653 } else if (checkLabel(pc)) {
5655 /* This instruction marks the beginning of a
5656 * new flow segment */
5661 /* If the previous pCode is not a flow object, then
5662 * insert a new flow object. (This check prevents
5663 * two consecutive flow objects from being insert in
5664 * the case where a skip instruction preceeds an
5665 * instruction containing a label.) */
5667 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5668 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5670 PCI(pc)->pcflow = PCFL(pflow);
5677 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5679 PCFL(pflow)->end = pb->pcTail;
5682 /*-------------------------------------------------------------------*/
5683 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5684 /* the flow blocks. */
5686 * unBuildFlow removes pCodeFlow objects from a pCode chain
5688 /*-----------------------------------------------------------------*/
5689 static void unBuildFlow(pBlock *pb)
5704 if(PCI(pc)->pcflow) {
5705 //free(PCI(pc)->pcflow);
5706 PCI(pc)->pcflow = NULL;
5709 } else if(isPCFL(pc) )
5718 /*-----------------------------------------------------------------*/
5719 /*-----------------------------------------------------------------*/
5720 static void dumpCond(int cond)
5723 static char *pcc_str[] = {
5737 int ncond = sizeof(pcc_str) / sizeof(char *);
5740 fprintf(stderr, "0x%04X\n",cond);
5742 for(i=0,j=1; i<ncond; i++, j<<=1)
5744 fprintf(stderr, " %s\n",pcc_str[i]);
5750 /*-----------------------------------------------------------------*/
5751 /*-----------------------------------------------------------------*/
5752 static void FlowStats(pCodeFlow *pcflow)
5760 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5762 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5765 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5770 fprintf(stderr, " FlowStats inCond: ");
5771 dumpCond(pcflow->inCond);
5772 fprintf(stderr, " FlowStats outCond: ");
5773 dumpCond(pcflow->outCond);
5777 /*-----------------------------------------------------------------*
5778 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5779 * if it affects the banking bits.
5781 * return: -1 == Banking bits are unaffected by this pCode.
5783 * return: > 0 == Banking bits are affected.
5785 * If the banking bits are affected, then the returned value describes
5786 * which bits are affected and how they're affected. The lower half
5787 * of the integer maps to the bits that are affected, the upper half
5788 * to whether they're set or cleared.
5790 *-----------------------------------------------------------------*/
5792 static int isBankInstruction(pCode *pc)
5800 if( PCI(pc)->op == POC_MOVLB ||
5801 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5802 bank = PCOL(pc)->lit;
5809 /*-----------------------------------------------------------------*/
5810 /*-----------------------------------------------------------------*/
5811 static void FillFlow(pCodeFlow *pcflow)
5820 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5822 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5825 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5832 isBankInstruction(pc);
5834 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5838 fprintf(stderr, " FillFlow - Bad end of flow\n");
5840 fprintf(stderr, " FillFlow - Ending flow with\n ");
5841 pc->print(stderr,pc);
5844 fprintf(stderr, " FillFlow inCond: ");
5845 dumpCond(pcflow->inCond);
5846 fprintf(stderr, " FillFlow outCond: ");
5847 dumpCond(pcflow->outCond);
5851 /*-----------------------------------------------------------------*/
5852 /*-----------------------------------------------------------------*/
5853 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5855 pCodeFlowLink *fromLink, *toLink;
5857 if(!from || !to || !to->pcflow || !from->pcflow)
5860 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5861 toLink = pic16_newpCodeFlowLink(to->pcflow);
5863 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5864 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5868 /*-----------------------------------------------------------------*
5869 * void LinkFlow(pBlock *pb)
5871 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5872 * non-branching segments. In LinkFlow, we determine the execution
5873 * order of these segments. For example, if one of the segments ends
5874 * with a skip, then we know that there are two possible flow segments
5875 * to which control may be passed.
5876 *-----------------------------------------------------------------*/
5877 static void LinkFlow(pBlock *pb)
5883 //fprintf(stderr,"linkflow \n");
5885 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5887 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5890 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5892 //fprintf(stderr," link: ");
5893 //pcflow->print(stderr,pcflow);
5895 //FillFlow(PCFL(pcflow));
5897 pc = PCFL(pcflow)->end;
5899 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5900 if(isPCI_SKIP(pc)) {
5901 //fprintf(stderr, "ends with skip\n");
5902 //pc->print(stderr,pc);
5903 pct=pic16_findNextInstruction(pc->next);
5904 LinkFlow_pCode(PCI(pc),PCI(pct));
5905 pct=pic16_findNextInstruction(pct->next);
5906 LinkFlow_pCode(PCI(pc),PCI(pct));
5910 if(isPCI_BRANCH(pc)) {
5911 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5913 //fprintf(stderr, "ends with branch\n ");
5914 //pc->print(stderr,pc);
5916 if(!(pcol && isPCOLAB(pcol))) {
5917 if((PCI(pc)->op != POC_RETLW)
5918 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5920 /* continue if label is '$' which assembler knows how to parse */
5921 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5923 if(pic16_pcode_verbose) {
5924 pc->print(stderr,pc);
5925 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5931 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5932 LinkFlow_pCode(PCI(pc),PCI(pct));
5934 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5935 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5937 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5943 //fprintf(stderr, "ends with non-branching instruction:\n");
5944 //pc->print(stderr,pc);
5946 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5952 //fprintf(stderr, "ends with unknown\n");
5953 //pc->print(stderr,pc);
5957 //fprintf(stderr, "ends with nothing: ERROR\n");
5961 /*-----------------------------------------------------------------*/
5962 /*-----------------------------------------------------------------*/
5964 /*-----------------------------------------------------------------*/
5965 /*-----------------------------------------------------------------*/
5966 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5972 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5975 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5985 /*-----------------------------------------------------------------*/
5986 /* insertBankSwitch - inserts a bank switch statement in the */
5987 /* assembly listing */
5989 /* position == 0: insert before */
5990 /* position == 1: insert after pc */
5991 /* position == 2: like 0 but previous was a skip instruction */
5992 /*-----------------------------------------------------------------*/
5993 pCodeOp *pic16_popGetLabel(unsigned int key);
5994 extern int pic16_labelOffset;
5996 static void insertBankSwitch(int position, pCode *pc)
6003 /* emit BANKSEL [symbol] */
6006 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6008 // position = 0; // position is always before (sanity check!)
6011 fprintf(stderr, "%s:%d: inserting bank switch\n", __FUNCTION__, __LINE__);
6012 pc->print(stderr, pc);
6017 /* insert the bank switch after this pc instruction */
6018 pCode *pcnext = pic16_findNextInstruction(pc);
6020 pic16_pCodeInsertAfter(pc, new_pc);
6021 if(pcnext)pc = pcnext;
6025 /* insert the bank switch BEFORE this pc instruction */
6026 pic16_pCodeInsertAfter(pc->prev, new_pc);
6031 pCode *pcnext, *pcprev, *npci;
6033 /* just like 0, but previous was a skip instruction,
6034 * so some care should be taken */
6036 pic16_labelOffset += 10000;
6037 tlbl = newiTempLabel(NULL);
6039 /* invert skip instruction */
6040 pcprev = pic16_findPrevInstruction(pc->prev);
6041 ipci = PCI(pcprev)->inverted_op;
6042 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6045 PCI(npci)->from = PCI(pcprev)->from;
6046 PCI(npci)->to = PCI(pcprev)->to;
6047 PCI(npci)->label = PCI(pcprev)->label;
6048 PCI(npci)->pcflow = PCI(pcprev)->pcflow;
6049 PCI(npci)->cline = PCI(pcprev)->cline;
6052 // memmove(PCI(pcprev), PCI(npci), sizeof(pCode) + sizeof(PIC_OPCODE) + sizeof(char const * const));
6055 pic16_pCodeInsertAfter(pcprev->prev, npci);
6056 /* unlink the pCode */
6057 pcprev->prev->next = pcprev->next;
6058 pcprev->next->prev = pcprev->prev;
6061 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6062 pic16_pCodeInsertAfter(pc->prev, pcnext);
6063 pic16_pCodeInsertAfter(pc->prev, new_pc);
6065 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6066 pic16_pCodeInsertAfter(pc, pcnext);
6071 /* Move the label, if there is one */
6072 if(PCI(pc)->label) {
6073 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6074 // __FILE__, __LINE__, pc, new_pc);
6075 PCAD(new_pc)->pci.label = PCI(pc)->label;
6076 PCI(pc)->label = NULL;
6081 /*-----------------------------------------------------------------*/
6082 /*int compareBankFlow - compare the banking requirements between */
6084 /*-----------------------------------------------------------------*/
6085 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6088 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6091 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6094 if(pcflow->firstBank == -1)
6098 if(pcflowLink->pcflow->firstBank == -1) {
6099 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6100 pcflowLink->pcflow->to :
6101 pcflowLink->pcflow->from);
6102 return compareBankFlow(pcflow, pctl, toORfrom);
6106 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6109 pcflowLink->bank_conflict++;
6110 pcflowLink->pcflow->FromConflicts++;
6111 pcflow->ToConflicts++;
6114 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6117 pcflowLink->bank_conflict++;
6118 pcflowLink->pcflow->ToConflicts++;
6119 pcflow->FromConflicts++;
6123 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6124 pcflowLink->pcflow->pc.seq,
6125 pcflowLink->pcflow->FromConflicts,
6126 pcflowLink->pcflow->ToConflicts);
6133 /*-----------------------------------------------------------------*/
6134 /*-----------------------------------------------------------------*/
6135 static void DumpFlow(pBlock *pb)
6139 pCodeFlowLink *pcfl;
6142 fprintf(stderr,"Dump flow \n");
6143 pb->pcHead->print(stderr, pb->pcHead);
6145 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6146 pcflow->print(stderr,pcflow);
6148 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6150 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6152 if(!isPCFL(pcflow)) {
6153 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6156 fprintf(stderr,"dumping: ");
6157 pcflow->print(stderr,pcflow);
6158 FlowStats(PCFL(pcflow));
6160 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6162 pc = PCODE(pcfl->pcflow);
6164 fprintf(stderr, " from seq %d:\n",pc->seq);
6166 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6167 pc->print(stderr,pc);
6172 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6174 pc = PCODE(pcfl->pcflow);
6176 fprintf(stderr, " to seq %d:\n",pc->seq);
6178 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6179 pc->print(stderr,pc);
6188 /*-----------------------------------------------------------------*/
6189 /*-----------------------------------------------------------------*/
6190 static int OptimizepBlock(pBlock *pb)
6195 if(!pb || !peepOptimizing)
6198 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6200 for(pc = pb->pcHead; pc; pc = pc->next)
6201 matches += pic16_pCodePeepMatchRule(pc);
6204 pc = pic16_findNextInstruction(pb->pcHead);
6212 if(pic16_pCodePeepMatchRule(pc)) {
6217 pc = pic16_findNextInstruction(pcprev->next);
6219 pc = pic16_findNextInstruction(pb->pcHead);
6221 pc = pic16_findNextInstruction(pc->next);
6225 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6230 /*-----------------------------------------------------------------*/
6231 /*-----------------------------------------------------------------*/
6232 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6236 for(pc = pcs; pc; pc = pc->next) {
6238 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6240 (PCI(pc)->pcop->type == PO_LABEL) &&
6241 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6249 /*-----------------------------------------------------------------*/
6250 /*-----------------------------------------------------------------*/
6251 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6258 (PCI(pc)->pcop->type == PO_LABEL)) {
6260 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6262 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6264 free(pcol->pcop.name);
6266 /* If the key is negative, then we (probably) have a label to
6267 * a function and the name is already defined */
6270 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6274 //sprintf(buffer,"_%05d_DS_",pcl->key);
6276 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6278 pcol->pcop.name = Safe_strdup(s);
6279 pcol->key = pcl->key;
6280 //pc->print(stderr,pc);
6287 /*-----------------------------------------------------------------*/
6288 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6289 /* pCode chain if they're not used. */
6290 /*-----------------------------------------------------------------*/
6291 static void pBlockRemoveUnusedLabels(pBlock *pb)
6293 pCode *pc; pCodeLabel *pcl;
6298 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6300 pBranch *pbr = PCI(pc)->label;
6301 if(pbr && pbr->next) {
6302 pCode *pcd = pb->pcHead;
6304 // fprintf(stderr, "multiple labels\n");
6305 // pc->print(stderr,pc);
6310 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6311 //fprintf(stderr,"Used by:\n");
6312 //pcd->print(stderr,pcd);
6314 exchangeLabels(PCL(pbr->pc),pcd);
6323 for(pc = pb->pcHead; pc; pc = pc->next) {
6325 if(isPCL(pc)) // pc->type == PC_LABEL)
6327 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6328 pcl = PCL(PCI(pc)->label->pc);
6331 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6333 /* This pCode is a label, so search the pBlock to see if anyone
6336 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6338 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6339 /* Couldn't find an instruction that refers to this label
6340 * So, unlink the pCode label from it's pCode chain
6341 * and destroy the label */
6342 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6344 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6345 if(pc->type == PC_LABEL) {
6346 pic16_unlinkpCode(pc);
6347 pCodeLabelDestruct(pc);
6349 unlinkpCodeFromBranch(pc, PCODE(pcl));
6350 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6361 /*-----------------------------------------------------------------*/
6362 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6363 /* chain and put them into pBranches that are */
6364 /* associated with the appropriate pCode */
6366 /*-----------------------------------------------------------------*/
6367 void pic16_pBlockMergeLabels(pBlock *pb)
6370 pCode *pc, *pcnext=NULL;
6375 /* First, Try to remove any unused labels */
6376 //pBlockRemoveUnusedLabels(pb);
6378 /* Now loop through the pBlock and merge the labels with the opcodes */
6381 // for(pc = pb->pcHead; pc; pc = pc->next) {
6384 pCode *pcn = pc->next;
6386 if(pc->type == PC_LABEL) {
6388 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6389 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6391 if((pcnext = pic16_findNextInstruction(pc) )) {
6393 // pcnext->print(stderr, pcnext);
6395 // Unlink the pCode label from it's pCode chain
6396 pic16_unlinkpCode(pc);
6398 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6399 // And link it into the instruction's pBranch labels. (Note, since
6400 // it's possible to have multiple labels associated with one instruction
6401 // we must provide a means to accomodate the additional labels. Thus
6402 // the labels are placed into the singly-linked list "label" as
6403 // opposed to being a single member of the pCodeInstruction.)
6405 //_ALLOC(pbr,sizeof(pBranch));
6407 pbr = Safe_calloc(1,sizeof(pBranch));
6411 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6414 if(pic16_pcode_verbose)
6415 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6417 } else if(pc->type == PC_CSOURCE) {
6419 /* merge the source line symbolic info into the next instruction */
6420 if((pcnext = pic16_findNextInstruction(pc) )) {
6422 // Unlink the pCode label from it's pCode chain
6423 pic16_unlinkpCode(pc);
6424 PCI(pcnext)->cline = PCCS(pc);
6425 //fprintf(stderr, "merging CSRC\n");
6426 //genericPrint(stderr,pcnext);
6432 pBlockRemoveUnusedLabels(pb);
6436 /*-----------------------------------------------------------------*/
6437 /*-----------------------------------------------------------------*/
6438 static int OptimizepCode(char dbName)
6440 #define MAX_PASSES 4
6449 DFPRINTF((stderr," Optimizing pCode\n"));
6453 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6454 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6455 matches += OptimizepBlock(pb);
6458 while(matches && ++passes < MAX_PASSES);
6465 const char *pic16_pCodeOpType(pCodeOp *pcop);
6466 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6469 /*-----------------------------------------------------------------*/
6470 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6471 /*-----------------------------------------------------------------*/
6473 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6477 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6478 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6480 if( !( (pcop->type == PO_LABEL) ||
6481 (pcop->type == PO_LITERAL) ||
6482 (pcop->type == PO_STR) ))
6483 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6484 PCOR(pcop)->r->wasUsed = 1;
6490 /*----------------------------------------------------------------------*
6491 * pic16_areRegsSame - check to see if the names of two registers match *
6492 *----------------------------------------------------------------------*/
6493 int pic16_areRegsSame(regs *r1, regs *r2)
6495 if(!strcmp(r1->name, r2->name))return 1;
6501 /*-----------------------------------------------------------------*/
6502 /*-----------------------------------------------------------------*/
6503 static void pic16_FixRegisterBanking(pBlock *pb)
6507 regs *reg, *prevreg;
6513 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6516 /* loop through all of the flow blocks with in one pblock */
6518 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6522 /* at this point, pc should point to a PC_FLOW object */
6523 /* for each flow block, determine the register banking
6526 if(!isPCI(pc))goto loop;
6528 if(PCI(pc)->is2MemOp)goto loop;
6530 reg = pic16_getRegFromInstruction(pc);
6533 pc->print(stderr, pc);
6534 fprintf(stderr, "reg = %p\n", reg);
6537 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6538 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6539 reg->address,reg->isBitField, reg->isFixed);
6543 /* now make some tests to make sure that instruction needs bank switch */
6545 /* if no register exists, and if not a bit opcode goto loop */
6547 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6550 if(isPCI_SKIP(pc)) {
6551 // fprintf(stderr, "instruction is SKIP instruction\n");
6553 if(reg && isACCESS_BANK(reg))goto loop;
6555 if(!isBankInstruction(pc))goto loop;
6557 if(isPCI_LIT(pc))goto loop;
6559 if(PCI(pc)->op == POC_CALL)goto loop;
6561 /* Examine the instruction before this one to make sure it is
6562 * not a skip type instruction */
6563 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6565 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6566 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6568 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6571 insertBankSwitch(flag, pc);
6574 // fprintf(stderr, "BANK SWITCH inserted\n");
6583 static void pBlockDestruct(pBlock *pb)
6594 /*-----------------------------------------------------------------*/
6595 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6596 /* name dbName and combine them */
6597 /* into one block */
6598 /*-----------------------------------------------------------------*/
6599 static void mergepBlocks(char dbName)
6602 pBlock *pb, *pbmerged = NULL,*pbn;
6604 pb = the_pFile->pbHead;
6606 //fprintf(stderr," merging blocks named %c\n",dbName);
6610 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6611 if( getpBlock_dbName(pb) == dbName) {
6613 //fprintf(stderr," merged block %c\n",dbName);
6618 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6619 /* pic16_addpCode2pBlock doesn't handle the tail: */
6620 pbmerged->pcTail = pb->pcTail;
6622 pb->prev->next = pbn;
6624 pbn->prev = pb->prev;
6629 //pic16_printpBlock(stderr, pbmerged);
6636 /*-----------------------------------------------------------------*/
6637 /* AnalyzeFlow - Examine the flow of the code and optimize */
6639 /* level 0 == minimal optimization */
6640 /* optimize registers that are used only by two instructions */
6641 /* level 1 == maximal optimization */
6642 /* optimize by looking at pairs of instructions that use the */
6644 /*-----------------------------------------------------------------*/
6646 static void AnalyzeFlow(int level)
6648 static int times_called=0;
6653 /* remove unused allocated registers before exiting */
6654 pic16_RemoveUnusedRegisters();
6660 /* if this is not the first time this function has been called,
6661 then clean up old flow information */
6662 if(times_called++) {
6663 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6666 pic16_RegsUnMapLiveRanges();
6671 /* Phase 2 - Flow Analysis - Register Banking
6673 * In this phase, the individual flow blocks are examined
6674 * and register banking is fixed.
6678 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6679 pic16_FixRegisterBanking(pb);
6682 /* Phase 2 - Flow Analysis
6684 * In this phase, the pCode is partition into pCodeFlow
6685 * blocks. The flow blocks mark the points where a continuous
6686 * stream of instructions changes flow (e.g. because of
6687 * a call or goto or whatever).
6690 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6691 pic16_BuildFlow(pb);
6694 /* Phase 2 - Flow Analysis - linking flow blocks
6696 * In this phase, the individual flow blocks are examined
6697 * to determine their order of excution.
6700 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6703 /* Phase 3 - Flow Analysis - Flow Tree
6705 * In this phase, the individual flow blocks are examined
6706 * to determine their order of execution.
6709 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6710 pic16_BuildFlowTree(pb);
6713 /* Phase x - Flow Analysis - Used Banks
6715 * In this phase, the individual flow blocks are examined
6716 * to determine the Register Banks they use
6720 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6725 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6726 pic16_pCodeRegMapLiveRanges(pb);
6728 pic16_RemoveUnusedRegisters();
6730 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6731 pic16_pCodeRegOptimizeRegUsage(level);
6739 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6744 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6746 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6747 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6748 pcflow = pcflow->next) {
6750 FillFlow(PCFL(pcflow));
6755 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6758 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6759 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6760 pcflow = pcflow->next) {
6762 FlowStats(PCFL(pcflow));
6768 /* VR -- no need to analyze banking in flow, but left here :
6769 * 1. because it may be used in the future for other purposes
6770 * 2. because if omitted we'll miss some optimization done here
6772 * Perhaps I should rename it to something else
6775 /*-----------------------------------------------------------------*/
6776 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6777 /* assigned to the registers. */
6779 /*-----------------------------------------------------------------*/
6781 void pic16_AnalyzeBanking(void)
6786 /* Phase x - Flow Analysis - Used Banks
6788 * In this phase, the individual flow blocks are examined
6789 * to determine the Register Banks they use
6795 if(!the_pFile)return;
6797 if(!pic16_options.no_banksel) {
6798 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6799 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6800 pic16_FixRegisterBanking(pb);
6806 /*-----------------------------------------------------------------*/
6807 /* buildCallTree - Look at the flow and extract all of the calls. */
6808 /*-----------------------------------------------------------------*/
6809 static set *register_usage(pBlock *pb);
6811 static void buildCallTree(void )
6823 /* Now build the call tree.
6824 First we examine all of the pCodes for functions.
6825 Keep in mind that the function boundaries coincide
6826 with pBlock boundaries.
6828 The algorithm goes something like this:
6829 We have two nested loops. The outer loop iterates
6830 through all of the pBlocks/functions. The inner
6831 loop iterates through all of the pCodes for
6832 a given pBlock. When we begin iterating through
6833 a pBlock, the variable pc_fstart, pCode of the start
6834 of a function, is cleared. We then search for pCodes
6835 of type PC_FUNCTION. When one is encountered, we
6836 initialize pc_fstart to this and at the same time
6837 associate a new pBranch object that signifies a
6838 branch entry. If a return is found, then this signifies
6839 a function exit point. We'll link the pCodes of these
6840 returns to the matching pc_fstart.
6842 When we're done, a doubly linked list of pBranches
6843 will exist. The head of this list is stored in
6844 `the_pFile', which is the meta structure for all
6845 of the pCode. Look at the pic16_printCallTree function
6846 on how the pBranches are linked together.
6849 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6850 pCode *pc_fstart=NULL;
6851 for(pc = pb->pcHead; pc; pc = pc->next) {
6853 if(isPCI(pc) && pc_fstart) {
6854 if(PCI(pc)->is2MemOp) {
6855 r = pic16_getRegFromInstruction2(pc);
6856 if(r && !strcmp(r->name, "POSTDEC1"))
6857 PCF(pc_fstart)->stackusage++;
6859 r = pic16_getRegFromInstruction(pc);
6860 if(r && !strcmp(r->name, "PREINC1"))
6861 PCF(pc_fstart)->stackusage--;
6866 if (PCF(pc)->fname) {
6868 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6869 //fprintf(stderr," found main \n");
6870 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6874 pbr = Safe_calloc(1,sizeof(pBranch));
6875 pbr->pc = pc_fstart = pc;
6878 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6880 // Here's a better way of doing the same:
6881 addSet(&pb->function_entries, pc);
6884 // Found an exit point in a function, e.g. return
6885 // (Note, there may be more than one return per function)
6887 pBranchLink(PCF(pc_fstart), PCF(pc));
6889 addSet(&pb->function_exits, pc);
6891 } else if(isCALL(pc)) {
6892 addSet(&pb->function_calls,pc);
6899 /* This is not needed because currently all register used
6900 * by a function are stored in stack -- VR */
6902 /* Re-allocate the registers so that there are no collisions
6903 * between local variables when one function call another */
6906 // pic16_deallocateAllRegs();
6908 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6916 /*-----------------------------------------------------------------*/
6917 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6918 /* all of the logical connections. */
6920 /* Essentially what's done here is that the pCode flow is */
6922 /*-----------------------------------------------------------------*/
6924 void pic16_AnalyzepCode(char dbName)
6935 /* Phase 1 - Register allocation and peep hole optimization
6937 * The first part of the analysis is to determine the registers
6938 * that are used in the pCode. Once that is done, the peep rules
6939 * are applied to the code. We continue to loop until no more
6940 * peep rule optimizations are found (or until we exceed the
6941 * MAX_PASSES threshold).
6943 * When done, the required registers will be determined.
6949 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6950 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6952 /* First, merge the labels with the instructions */
6953 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6954 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6956 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6957 //fprintf(stderr," analyze and merging block %c\n",dbName);
6958 pic16_pBlockMergeLabels(pb);
6961 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6966 changes = OptimizepCode(dbName);
6969 } while(changes && (i++ < MAX_PASSES));
6974 /*-----------------------------------------------------------------*/
6975 /* ispCodeFunction - returns true if *pc is the pCode of a */
6977 /*-----------------------------------------------------------------*/
6978 static bool ispCodeFunction(pCode *pc)
6981 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6987 /*-----------------------------------------------------------------*/
6988 /* findFunction - Search for a function by name (given the name) */
6989 /* in the set of all functions that are in a pBlock */
6990 /* (note - I expect this to change because I'm planning to limit */
6991 /* pBlock's to just one function declaration */
6992 /*-----------------------------------------------------------------*/
6993 static pCode *findFunction(char *fname)
7000 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7002 pc = setFirstItem(pb->function_entries);
7005 if((pc->type == PC_FUNCTION) &&
7007 (strcmp(fname, PCF(pc)->fname)==0))
7010 pc = setNextItem(pb->function_entries);
7018 static void MarkUsedRegisters(set *regset)
7023 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7024 // fprintf(stderr, "marking register = %s\t", r1->name);
7025 r2 = pic16_regWithIdx(r1->rIdx);
7026 // fprintf(stderr, "to register = %s\n", r2->name);
7032 static void pBlockStats(FILE *of, pBlock *pb)
7038 if(!pic16_pcode_verbose)return;
7040 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7042 // for now just print the first element of each set
7043 pc = setFirstItem(pb->function_entries);
7045 fprintf(of,";entry: ");
7048 pc = setFirstItem(pb->function_exits);
7050 fprintf(of,";has an exit\n");
7054 pc = setFirstItem(pb->function_calls);
7056 fprintf(of,";functions called:\n");
7059 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7060 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7062 pc = setNextItem(pb->function_calls);
7066 r = setFirstItem(pb->tregisters);
7068 int n = elementsInSet(pb->tregisters);
7070 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7073 fprintf(of,"; %s\n",r->name);
7074 r = setNextItem(pb->tregisters);
7078 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7081 /*-----------------------------------------------------------------*/
7082 /*-----------------------------------------------------------------*/
7084 static void sequencepCode(void)
7090 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7092 pb->seq = GpCodeSequenceNumber+1;
7094 for( pc = pb->pcHead; pc; pc = pc->next)
7095 pc->seq = ++GpCodeSequenceNumber;
7101 /*-----------------------------------------------------------------*/
7102 /*-----------------------------------------------------------------*/
7103 static set *register_usage(pBlock *pb)
7106 set *registers=NULL;
7107 set *registersInCallPath = NULL;
7109 /* check recursion */
7111 pc = setFirstItem(pb->function_entries);
7118 if(pc->type != PC_FUNCTION)
7119 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7121 pc = setFirstItem(pb->function_calls);
7122 for( ; pc; pc = setNextItem(pb->function_calls)) {
7124 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7125 char *dest = pic16_get_op_from_instruction(PCI(pc));
7127 pcn = findFunction(dest);
7129 registersInCallPath = register_usage(pcn->pb);
7131 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7136 pBlockStats(stderr,pb); // debug
7139 // Mark the registers in this block as used.
7141 MarkUsedRegisters(pb->tregisters);
7142 if(registersInCallPath) {
7143 /* registers were used in the functions this pBlock has called */
7144 /* so now, we need to see if these collide with the ones we are */
7147 regs *r1,*r2, *newreg;
7149 DFPRINTF((stderr,"comparing registers\n"));
7151 r1 = setFirstItem(registersInCallPath);
7154 r2 = setFirstItem(pb->tregisters);
7156 while(r2 && (r1->type != REG_STK)) {
7158 if(r2->rIdx == r1->rIdx) {
7159 newreg = pic16_findFreeReg(REG_GPR);
7163 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7167 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7168 r1->rIdx, newreg->rIdx));
7169 r2->rIdx = newreg->rIdx;
7170 //if(r2->name) free(r2->name);
7172 r2->name = Safe_strdup(newreg->name);
7176 newreg->wasUsed = 1;
7178 r2 = setNextItem(pb->tregisters);
7181 r1 = setNextItem(registersInCallPath);
7184 /* Collisions have been resolved. Now free the registers in the call path */
7185 r1 = setFirstItem(registersInCallPath);
7187 if(r1->type != REG_STK) {
7188 newreg = pic16_regWithIdx(r1->rIdx);
7191 r1 = setNextItem(registersInCallPath);
7195 // MarkUsedRegisters(pb->registers);
7197 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7200 DFPRINTF((stderr,"returning regs\n"));
7202 DFPRINTF((stderr,"not returning regs\n"));
7204 DFPRINTF((stderr,"pBlock after register optim.\n"));
7205 pBlockStats(stderr,pb); // debug
7211 /*-----------------------------------------------------------------*/
7212 /* pct2 - writes the call tree to a file */
7214 /*-----------------------------------------------------------------*/
7215 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7219 // set *registersInCallPath = NULL;
7225 fprintf(of, "recursive function\n");
7226 return; //recursion ?
7229 pc = setFirstItem(pb->function_entries);
7236 for(i=0;i<indent;i++) // Indentation
7240 if(pc->type == PC_FUNCTION) {
7241 usedstack += PCF(pc)->stackusage;
7242 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7243 } else return; // ???
7246 pc = setFirstItem(pb->function_calls);
7247 for( ; pc; pc = setNextItem(pb->function_calls)) {
7249 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7250 char *dest = pic16_get_op_from_instruction(PCI(pc));
7252 pcn = findFunction(dest);
7254 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7256 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7264 /*-----------------------------------------------------------------*/
7265 /* pic16_printCallTree - writes the call tree to a file */
7267 /*-----------------------------------------------------------------*/
7269 void pic16_printCallTree(FILE *of)
7281 fprintf(of, "\npBlock statistics\n");
7282 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7286 fprintf(of,"Call Tree\n");
7287 pbr = the_pFile->functions;
7291 if(!ispCodeFunction(pc))
7292 fprintf(of,"bug in call tree");
7295 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7297 while(pc->next && !ispCodeFunction(pc->next)) {
7299 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7300 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7308 fprintf(of,"\n**************\n\na better call tree\n");
7309 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7314 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7315 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7321 /*-----------------------------------------------------------------*/
7323 /*-----------------------------------------------------------------*/
7325 static void InlineFunction(pBlock *pb)
7333 pc = setFirstItem(pb->function_calls);
7335 for( ; pc; pc = setNextItem(pb->function_calls)) {
7338 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7344 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7346 //fprintf(stderr,"Cool can inline:\n");
7347 //pcn->print(stderr,pcn);
7349 //fprintf(stderr,"recursive call Inline\n");
7350 InlineFunction(pcn->pb);
7351 //fprintf(stderr,"return from recursive call Inline\n");
7354 At this point, *pc points to a CALL mnemonic, and
7355 *pcn points to the function that is being called.
7357 To in-line this call, we need to remove the CALL
7358 and RETURN(s), and link the function pCode in with
7364 /* Remove the CALL */
7368 /* remove callee pBlock from the pBlock linked list */
7369 removepBlock(pcn->pb);
7377 /* Remove the Function pCode */
7378 pct = pic16_findNextInstruction(pcn->next);
7380 /* Link the function with the callee */
7381 pc->next = pcn->next;
7382 pcn->next->prev = pc;
7384 /* Convert the function name into a label */
7386 pbr = Safe_calloc(1,sizeof(pBranch));
7387 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7389 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7390 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7392 /* turn all of the return's except the last into goto's */
7393 /* check case for 2 instruction pBlocks */
7394 pce = pic16_findNextInstruction(pcn->next);
7396 pCode *pce_next = pic16_findNextInstruction(pce->next);
7398 if(pce_next == NULL) {
7399 /* found the last return */
7400 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7402 //fprintf(stderr,"found last return\n");
7403 //pce->print(stderr,pce);
7404 pce->prev->next = pc_call->next;
7405 pc_call->next->prev = pce->prev;
7406 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7416 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7422 /*-----------------------------------------------------------------*/
7424 /*-----------------------------------------------------------------*/
7426 void pic16_InlinepCode(void)
7435 if(!functionInlining)
7438 /* Loop through all of the function definitions and count the
7439 * number of times each one is called */
7440 //fprintf(stderr,"inlining %d\n",__LINE__);
7442 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7444 pc = setFirstItem(pb->function_calls);
7446 for( ; pc; pc = setNextItem(pb->function_calls)) {
7449 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7450 if(pcn && isPCF(pcn)) {
7451 PCF(pcn)->ncalled++;
7454 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7459 //fprintf(stderr,"inlining %d\n",__LINE__);
7461 /* Now, Loop through the function definitions again, but this
7462 * time inline those functions that have only been called once. */
7464 InlineFunction(the_pFile->pbHead);
7465 //fprintf(stderr,"inlining %d\n",__LINE__);
7467 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7472 char *pic_optype_names[]={
7473 "PO_NONE", // No operand e.g. NOP
7474 "PO_W", // The working register (as a destination)
7475 "PO_WREG", // The working register (as a file register)
7476 "PO_STATUS", // The 'STATUS' register
7477 "PO_BSR", // The 'BSR' register
7478 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7480 "PO_INDF0", // The Indirect register
7481 "PO_INTCON", // Interrupt Control register
7482 "PO_GPR_REGISTER", // A general purpose register
7483 "PO_GPR_BIT", // A bit of a general purpose register
7484 "PO_GPR_TEMP", // A general purpose temporary register
7485 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7486 "PO_PCL", // Program counter Low register
7487 "PO_PCLATH", // Program counter Latch high register
7488 "PO_PCLATU", // Program counter Latch upper register
7489 "PO_PRODL", // Product Register Low
7490 "PO_PRODH", // Product Register High
7491 "PO_LITERAL", // A constant
7492 "PO_REL_ADDR", // A relative address
7493 "PO_IMMEDIATE", // (8051 legacy)
7494 "PO_DIR", // Direct memory (8051 legacy)
7495 "PO_CRY", // bit memory (8051 legacy)
7496 "PO_BIT", // bit operand.
7497 "PO_STR", // (8051 legacy)
7499 "PO_WILD" // Wild card operand in peep optimizer
7503 char *dumpPicOptype(PIC_OPTYPE type)
7505 return (pic_optype_names[ type ]);