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; // patch 15
2875 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH; // patch 15
2876 pic16_pc_tblptru.rIdx = IDX_TBLPTRU; // patch 15
2877 pic16_pc_tablat.rIdx = IDX_TABLAT; // patch 15
2879 // pic16_pc_fsr0.rIdx = IDX_FSR0;
2880 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2881 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2882 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2883 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2884 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2885 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2886 pic16_pc_indf0.rIdx = IDX_INDF0;
2887 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2888 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2889 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2890 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2891 pic16_pc_indf1.rIdx = IDX_INDF1;
2892 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2893 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2894 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2895 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2896 pic16_pc_indf2.rIdx = IDX_INDF2;
2897 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2898 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2899 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2900 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2901 pic16_pc_prodl.rIdx = IDX_PRODL;
2902 pic16_pc_prodh.rIdx = IDX_PRODH;
2904 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2905 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2906 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2908 pic16_pc_kzero.rIdx = IDX_KZ;
2909 pic16_pc_wsave.rIdx = IDX_WSAVE;
2910 pic16_pc_ssave.rIdx = IDX_SSAVE;
2912 pic16_pc_eecon1.rIdx = IDX_EECON1;
2913 pic16_pc_eecon2.rIdx = IDX_EECON2;
2914 pic16_pc_eedata.rIdx = IDX_EEDATA;
2915 pic16_pc_eeadr.rIdx = IDX_EEADR;
2918 /* probably should put this in a separate initialization routine */
2919 pb_dead_pcodes = newpBlock();
2924 /*-----------------------------------------------------------------*/
2925 /* mnem2key - convert a pic mnemonic into a hash key */
2926 /* (BTW - this spreads the mnemonics quite well) */
2928 /*-----------------------------------------------------------------*/
2930 int mnem2key(char const *mnem)
2939 key += toupper(*mnem++) +1;
2943 return (key & 0x1f);
2948 void pic16initMnemonics(void)
2953 pCodeInstruction *pci;
2955 if(mnemonics_initialized)
2958 // NULL out the array before making the assignments
2959 // since we check the array contents below this initialization.
2961 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2962 pic16Mnemonics[i] = NULL;
2965 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2966 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2967 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2968 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2969 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2970 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2971 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2972 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2973 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2974 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2975 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2976 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2977 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2978 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2979 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2980 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2981 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2982 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2983 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2984 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2985 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2986 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2987 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2988 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2989 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2990 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2991 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2992 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2993 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2994 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2995 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2996 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2997 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2998 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2999 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3000 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3001 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3002 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3003 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3004 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3005 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3006 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3007 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3008 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3009 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3010 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3011 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3012 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3013 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3014 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3015 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3016 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3017 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3018 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3019 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3020 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3021 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3022 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3023 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3024 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3025 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3026 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3027 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3028 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3029 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3030 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3031 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3032 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3033 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3034 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3035 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3036 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3037 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3038 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3039 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3040 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3041 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3042 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3043 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3044 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3045 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3046 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3047 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3048 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3049 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3050 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3051 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3052 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3053 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3054 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3055 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3056 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3057 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3059 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3060 if(pic16Mnemonics[i])
3061 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3062 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3065 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3066 pci = hTabNextItem(pic16MnemonicsHash, &key);
3069 mnemonics_initialized = 1;
3072 int pic16_getpCodePeepCommand(char *cmd);
3074 int pic16_getpCode(char *mnem,unsigned dest)
3077 pCodeInstruction *pci;
3078 int key = mnem2key(mnem);
3080 if(!mnemonics_initialized)
3081 pic16initMnemonics();
3083 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3087 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3088 if((pci->num_ops <= 1)
3089 || (pci->isModReg == dest)
3091 || (pci->num_ops <= 2 && pci->isAccess)
3092 || (pci->num_ops <= 2 && pci->isFastCall)
3093 || (pci->num_ops <= 2 && pci->is2MemOp)
3094 || (pci->num_ops <= 2 && pci->is2LitOp) )
3098 pci = hTabNextItemWK (pic16MnemonicsHash);
3105 /*-----------------------------------------------------------------*
3106 * pic16initpCodePeepCommands
3108 *-----------------------------------------------------------------*/
3109 void pic16initpCodePeepCommands(void)
3117 hTabAddItem(&pic16pCodePeepCommandsHash,
3118 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3120 } while (peepCommands[i].cmd);
3122 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3125 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3126 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3131 /*-----------------------------------------------------------------
3134 *-----------------------------------------------------------------*/
3136 int pic16_getpCodePeepCommand(char *cmd)
3140 int key = mnem2key(cmd);
3143 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3146 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3147 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3151 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3158 static char getpBlock_dbName(pBlock *pb)
3164 return pb->cmemmap->dbName;
3168 void pic16_pBlockConvert2ISR(pBlock *pb)
3172 if(pb->cmemmap)pb->cmemmap = NULL;
3176 if(pic16_pcode_verbose)
3177 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3180 void pic16_pBlockConvert2Absolute(pBlock *pb)
3183 if(pb->cmemmap)pb->cmemmap = NULL;
3187 if(pic16_pcode_verbose)
3188 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3191 /*-----------------------------------------------------------------*/
3192 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3193 /* instances to the front of the doubly linked */
3194 /* list of pBlocks */
3195 /*-----------------------------------------------------------------*/
3197 void pic16_movepBlock2Head(char dbName)
3202 /* this can happen in sources without code,
3203 * only variable definitions */
3204 if(!the_pFile)return;
3206 pb = the_pFile->pbHead;
3210 if(getpBlock_dbName(pb) == dbName) {
3211 pBlock *pbn = pb->next;
3212 pb->next = the_pFile->pbHead;
3213 the_pFile->pbHead->prev = pb;
3214 the_pFile->pbHead = pb;
3217 pb->prev->next = pbn;
3219 // If the pBlock that we just moved was the last
3220 // one in the link of all of the pBlocks, then we
3221 // need to point the tail to the block just before
3222 // the one we moved.
3223 // Note: if pb->next is NULL, then pb must have
3224 // been the last pBlock in the chain.
3227 pbn->prev = pb->prev;
3229 the_pFile->pbTail = pb->prev;
3240 void pic16_copypCode(FILE *of, char dbName)
3244 if(!of || !the_pFile)
3247 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3248 if(getpBlock_dbName(pb) == dbName) {
3249 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3251 pic16_printpBlock(of,pb);
3256 void pic16_pcode_test(void)
3259 DFPRINTF((stderr,"pcode is alive!\n"));
3269 /* create the file name */
3270 strcpy(buffer,dstFileName);
3271 strcat(buffer,".p");
3273 if( !(pFile = fopen(buffer, "w" ))) {
3274 werror(E_FILE_OPEN_ERR,buffer);
3278 fprintf(pFile,"pcode dump\n\n");
3280 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3281 fprintf(pFile,"\n\tNew pBlock\n\n");
3283 fprintf(pFile,"%s",pb->cmemmap->sname);
3285 fprintf(pFile,"internal pblock");
3287 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3288 pic16_printpBlock(pFile,pb);
3292 /*-----------------------------------------------------------------*/
3293 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3294 /* ister, RegCond will return the bit being referenced. */
3296 /* fixme - why not just OR in the pcop bit field */
3297 /*-----------------------------------------------------------------*/
3299 static int RegCond(pCodeOp *pcop)
3305 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3306 switch(PCORB(pcop)->bit) {
3320 /*-----------------------------------------------------------------*/
3321 /* pic16_newpCode - create and return a newly initialized pCode */
3323 /* fixme - rename this */
3325 /* The purpose of this routine is to create a new Instruction */
3326 /* pCode. This is called by gen.c while the assembly code is being */
3330 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3331 /* (note that the op is analogous to but not the */
3332 /* same thing as the opcode of the instruction.) */
3333 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3336 /* a pointer to the new malloc'd pCode is returned. */
3340 /*-----------------------------------------------------------------*/
3341 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3343 pCodeInstruction *pci ;
3345 if(!mnemonics_initialized)
3346 pic16initMnemonics();
3348 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3350 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3351 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3354 if(pci->inCond & PCC_EXAMINE_PCOP)
3355 pci->inCond |= RegCond(pcop);
3357 if(pci->outCond & PCC_EXAMINE_PCOP)
3358 pci->outCond |= RegCond(pcop);
3360 pci->pc.prev = pci->pc.next = NULL;
3361 return (pCode *)pci;
3364 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3370 /*-----------------------------------------------------------------*/
3371 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3373 /* Wild pcodes are used during the peep hole optimizer to serve */
3374 /* as place holders for any instruction. When a snippet of code is */
3375 /* compared to a peep hole rule, the wild card opcode will match */
3376 /* any instruction. However, the optional operand and label are */
3377 /* additional qualifiers that must also be matched before the */
3378 /* line (of assembly code) is declared matched. Note that the */
3379 /* operand may be wild too. */
3381 /* Note, a wild instruction is specified just like a wild var: */
3382 /* %4 ; A wild instruction, */
3383 /* See the peeph.def file for additional examples */
3385 /*-----------------------------------------------------------------*/
3387 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3392 pcw = Safe_calloc(1,sizeof(pCodeWild));
3394 pcw->pci.pc.type = PC_WILD;
3395 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3396 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3397 pcw->pci.pc.pb = NULL;
3399 // pcw->pci.pc.analyze = genericAnalyze;
3400 pcw->pci.pc.destruct = genericDestruct;
3401 pcw->pci.pc.print = genericPrint;
3403 pcw->id = pCodeID; // this is the 'n' in %n
3404 pcw->operand = optional_operand;
3405 pcw->label = optional_label;
3407 pcw->mustBeBitSkipInst = 0;
3408 pcw->mustNotBeBitSkipInst = 0;
3409 pcw->invertBitSkipInst = 0;
3411 return ( (pCode *)pcw);
3415 /*-----------------------------------------------------------------*/
3416 /* newPcodeInlineP - create a new pCode from a char string */
3417 /*-----------------------------------------------------------------*/
3420 pCode *pic16_newpCodeInlineP(char *cP)
3425 pcc = Safe_calloc(1,sizeof(pCodeComment));
3427 pcc->pc.type = PC_INLINE;
3428 pcc->pc.prev = pcc->pc.next = NULL;
3429 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3432 // pcc->pc.analyze = genericAnalyze;
3433 pcc->pc.destruct = genericDestruct;
3434 pcc->pc.print = genericPrint;
3437 pcc->comment = Safe_strdup(cP);
3439 pcc->comment = NULL;
3441 return ( (pCode *)pcc);
3445 /*-----------------------------------------------------------------*/
3446 /* newPcodeCharP - create a new pCode from a char string */
3447 /*-----------------------------------------------------------------*/
3449 pCode *pic16_newpCodeCharP(char *cP)
3454 pcc = Safe_calloc(1,sizeof(pCodeComment));
3456 pcc->pc.type = PC_COMMENT;
3457 pcc->pc.prev = pcc->pc.next = NULL;
3458 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3461 // pcc->pc.analyze = genericAnalyze;
3462 pcc->pc.destruct = genericDestruct;
3463 pcc->pc.print = genericPrint;
3466 pcc->comment = Safe_strdup(cP);
3468 pcc->comment = NULL;
3470 return ( (pCode *)pcc);
3474 /*-----------------------------------------------------------------*/
3475 /* pic16_newpCodeFunction - */
3476 /*-----------------------------------------------------------------*/
3479 pCode *pic16_newpCodeFunction(char *mod,char *f)
3483 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3485 pcf->pc.type = PC_FUNCTION;
3486 pcf->pc.prev = pcf->pc.next = NULL;
3487 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3490 // pcf->pc.analyze = genericAnalyze;
3491 pcf->pc.destruct = genericDestruct;
3492 pcf->pc.print = pCodePrintFunction;
3498 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3499 strcpy(pcf->modname,mod);
3501 pcf->modname = NULL;
3504 pcf->fname = Safe_calloc(1,strlen(f)+1);
3505 strcpy(pcf->fname,f);
3509 pcf->stackusage = 0;
3511 return ( (pCode *)pcf);
3514 /*-----------------------------------------------------------------*/
3515 /* pic16_newpCodeFlow */
3516 /*-----------------------------------------------------------------*/
3517 static void destructpCodeFlow(pCode *pc)
3519 if(!pc || !isPCFL(pc))
3526 pic16_unlinkpCode(pc);
3528 deleteSet(&PCFL(pc)->registers);
3529 deleteSet(&PCFL(pc)->from);
3530 deleteSet(&PCFL(pc)->to);
3535 pCode *pic16_newpCodeFlow(void )
3539 //_ALLOC(pcflow,sizeof(pCodeFlow));
3540 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3542 pcflow->pc.type = PC_FLOW;
3543 pcflow->pc.prev = pcflow->pc.next = NULL;
3544 pcflow->pc.pb = NULL;
3546 // pcflow->pc.analyze = genericAnalyze;
3547 pcflow->pc.destruct = destructpCodeFlow;
3548 pcflow->pc.print = genericPrint;
3550 pcflow->pc.seq = GpcFlowSeq++;
3552 pcflow->from = pcflow->to = NULL;
3554 pcflow->inCond = PCC_NONE;
3555 pcflow->outCond = PCC_NONE;
3557 pcflow->firstBank = -1;
3558 pcflow->lastBank = -1;
3560 pcflow->FromConflicts = 0;
3561 pcflow->ToConflicts = 0;
3565 pcflow->registers = newSet();
3567 return ( (pCode *)pcflow);
3571 /*-----------------------------------------------------------------*/
3572 /*-----------------------------------------------------------------*/
3573 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3575 pCodeFlowLink *pcflowLink;
3577 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3579 pcflowLink->pcflow = pcflow;
3580 pcflowLink->bank_conflict = 0;
3585 /*-----------------------------------------------------------------*/
3586 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3587 /*-----------------------------------------------------------------*/
3589 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3594 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3596 pccs->pc.type = PC_CSOURCE;
3597 pccs->pc.prev = pccs->pc.next = NULL;
3600 pccs->pc.destruct = genericDestruct;
3601 pccs->pc.print = genericPrint;
3603 pccs->line_number = ln;
3605 pccs->line = Safe_strdup(l);
3610 pccs->file_name = Safe_strdup(f);
3612 pccs->file_name = NULL;
3614 return ( (pCode *)pccs);
3619 /*******************************************************************/
3620 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3621 /* added by VR 6-Jun-2003 */
3622 /*******************************************************************/
3624 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3631 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3632 pcad->pci.pc.type = PC_ASMDIR;
3633 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3634 pcad->pci.pc.pb = NULL;
3636 pcad->pci.pc.destruct = genericDestruct;
3637 pcad->pci.pc.print = genericPrint;
3639 if(asdir && *asdir) {
3641 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3643 pcad->directive = Safe_strdup( asdir );
3646 va_start(ap, argfmt);
3648 memset(buffer, 0, sizeof(buffer));
3649 if(argfmt && *argfmt)
3650 vsprintf(buffer, argfmt, ap);
3654 while(isspace(*lbp))lbp++;
3657 pcad->arg = Safe_strdup( lbp );
3659 return ((pCode *)pcad);
3662 /*-----------------------------------------------------------------*/
3663 /* pCodeLabelDestruct - free memory used by a label. */
3664 /*-----------------------------------------------------------------*/
3665 static void pCodeLabelDestruct(pCode *pc)
3671 if((pc->type == PC_LABEL) && PCL(pc)->label)
3672 free(PCL(pc)->label);
3678 pCode *pic16_newpCodeLabel(char *name, int key)
3684 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3686 pcl->pc.type = PC_LABEL;
3687 pcl->pc.prev = pcl->pc.next = NULL;
3688 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3691 // pcl->pc.analyze = genericAnalyze;
3692 pcl->pc.destruct = pCodeLabelDestruct;
3693 pcl->pc.print = pCodePrintLabel;
3700 sprintf(s,"_%05d_DS_",key);
3705 pcl->label = Safe_strdup(s);
3707 // if(pic16_pcode_verbose)
3708 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3711 return ( (pCode *)pcl);
3715 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3717 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3721 return ( (pCode *)pcl );
3725 /*-----------------------------------------------------------------*/
3726 /* newpBlock - create and return a pointer to a new pBlock */
3727 /*-----------------------------------------------------------------*/
3728 static pBlock *newpBlock(void)
3733 PpB = Safe_calloc(1,sizeof(pBlock) );
3734 PpB->next = PpB->prev = NULL;
3736 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3737 PpB->tregisters = NULL;
3739 PpB->FlowTree = NULL;
3745 /*-----------------------------------------------------------------*/
3746 /* pic16_newpCodeChain - create a new chain of pCodes */
3747 /*-----------------------------------------------------------------*
3749 * This function will create a new pBlock and the pointer to the
3750 * pCode that is passed in will be the first pCode in the block.
3751 *-----------------------------------------------------------------*/
3754 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3757 pBlock *pB = newpBlock();
3759 pB->pcHead = pB->pcTail = pc;
3766 /*-----------------------------------------------------------------*/
3767 /* pic16_newpCodeOpLabel - Create a new label given the key */
3768 /* Note, a negative key means that the label is part of wild card */
3769 /* (and hence a wild card label) used in the pCodePeep */
3770 /* optimizations). */
3771 /*-----------------------------------------------------------------*/
3773 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3776 static int label_key=-1;
3780 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3781 pcop->type = PO_LABEL;
3786 sprintf(s=buffer,"_%05d_DS_",key);
3788 s = name, key = label_key--;
3791 pcop->name = Safe_strdup(s);
3793 ((pCodeOpLabel *)pcop)->key = key;
3795 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3799 /*-----------------------------------------------------------------*/
3800 /*-----------------------------------------------------------------*/
3801 pCodeOp *pic16_newpCodeOpLit(int lit)
3807 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3808 pcop->type = PO_LITERAL;
3812 sprintf(s,"0x%02x",lit);
3814 pcop->name = Safe_strdup(s);
3817 ((pCodeOpLit *)pcop)->lit = lit;
3822 /*-----------------------------------------------------------------*/
3823 /*-----------------------------------------------------------------*/
3824 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3826 char *s = buffer, tbuf[256], *tb=tbuf;
3830 tb = pic16_get_op(arg2, NULL, 0);
3831 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3832 pcop->type = PO_LITERAL;
3836 sprintf(s,"0x%02x, %s",lit, tb);
3838 pcop->name = Safe_strdup(s);
3841 ((pCodeOpLit2 *)pcop)->lit = lit;
3842 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3847 /*-----------------------------------------------------------------*/
3848 /*-----------------------------------------------------------------*/
3849 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3853 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3854 pcop->type = PO_IMMEDIATE;
3856 regs *r = pic16_dirregWithName(name);
3857 pcop->name = Safe_strdup(name);
3861 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3862 PCOI(pcop)->rIdx = r->rIdx;
3864 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3865 PCOI(pcop)->rIdx = -1;
3867 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3872 PCOI(pcop)->index = index;
3873 PCOI(pcop)->offset = offset;
3874 PCOI(pcop)->_const = code_space;
3879 /*-----------------------------------------------------------------*/
3880 /*-----------------------------------------------------------------*/
3881 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3887 if(!pcwb || !subtype) {
3888 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3892 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3893 pcop->type = PO_WILD;
3894 sprintf(s,"%%%d",id);
3895 pcop->name = Safe_strdup(s);
3897 PCOW(pcop)->id = id;
3898 PCOW(pcop)->pcwb = pcwb;
3899 PCOW(pcop)->subtype = subtype;
3900 PCOW(pcop)->matched = NULL;
3902 PCOW(pcop)->pcop2 = NULL;
3907 /*-----------------------------------------------------------------*/
3908 /*-----------------------------------------------------------------*/
3909 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3915 if(!pcwb || !subtype || !subtype2) {
3916 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3920 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3921 pcop->type = PO_WILD;
3922 sprintf(s,"%%%d",id);
3923 pcop->name = Safe_strdup(s);
3925 PCOW(pcop)->id = id;
3926 PCOW(pcop)->pcwb = pcwb;
3927 PCOW(pcop)->subtype = subtype;
3928 PCOW(pcop)->matched = NULL;
3930 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3932 if(!subtype2->name) {
3933 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3934 PCOW2(pcop)->pcop.type = PO_WILD;
3935 sprintf(s, "%%%d", id2);
3936 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3937 PCOW2(pcop)->id = id2;
3938 PCOW2(pcop)->subtype = subtype2;
3940 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3941 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3943 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
3945 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3946 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3955 /*-----------------------------------------------------------------*/
3956 /*-----------------------------------------------------------------*/
3957 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
3961 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3962 pcop->type = PO_GPR_BIT;
3964 pcop->name = Safe_strdup(s);
3968 PCORB(pcop)->bit = bit;
3969 PCORB(pcop)->inBitSpace = inBitSpace;
3970 PCORB(pcop)->subtype = subt;
3972 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3973 PCOR(pcop)->r = pic16_dirregWithName(s); //NULL;
3974 // PCOR(pcop)->rIdx = 0;
3979 /*-----------------------------------------------------------------*
3980 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3982 * If rIdx >=0 then a specific register from the set of registers
3983 * will be selected. If rIdx <0, then a new register will be searched
3985 *-----------------------------------------------------------------*/
3987 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3991 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3996 PCOR(pcop)->rIdx = rIdx;
3997 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3999 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4002 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4004 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4005 __FUNCTION__, __LINE__);
4010 pcop->type = PCOR(pcop)->r->pc_type;
4015 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4020 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4021 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4022 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4023 pcop->type = PCOR(pcop)->r->pc_type;
4024 pcop->name = PCOR(pcop)->r->name;
4026 // if(pic16_pcode_verbose) {
4027 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4028 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4034 /*-----------------------------------------------------------------*/
4035 /*-----------------------------------------------------------------*/
4037 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4044 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4048 pcop = pic16_newpCodeOpLit(-1);
4052 pcop = pic16_newpCodeOpLabel(NULL,-1);
4055 pcop = pic16_newpCodeOpReg(-1);
4058 case PO_GPR_REGISTER:
4060 pcop = pic16_newpCodeOpRegFromStr(name);
4062 pcop = pic16_newpCodeOpReg(-1);
4066 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4069 pcop->name = Safe_strdup(name);
4077 #define DB_ITEMS_PER_LINE 8
4079 typedef struct DBdata
4086 static int DBd_init = -1;
4088 /*-----------------------------------------------------------------*/
4089 /* Initialiase "DB" data buffer */
4090 /*-----------------------------------------------------------------*/
4091 void pic16_initDB(void)
4097 /*-----------------------------------------------------------------*/
4098 /* Flush pending "DB" data to a pBlock */
4100 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4101 /*-----------------------------------------------------------------*/
4102 void pic16_flushDB(char ptype, void *p)
4106 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4109 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4112 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4116 DBd.buffer[0] = '\0';
4121 /*-----------------------------------------------------------------*/
4122 /* Add "DB" directives to a pBlock */
4123 /*-----------------------------------------------------------------*/
4124 void pic16_emitDB(char c, char ptype, void *p)
4129 // we need to initialize
4132 DBd.buffer[0] = '\0';
4135 l = strlen(DBd.buffer);
4136 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4138 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4141 if (DBd.count>= DB_ITEMS_PER_LINE)
4142 pic16_flushDB(ptype, p);
4145 void pic16_emitDS(char *s, char ptype, void *p)
4150 // we need to initialize
4153 DBd.buffer[0] = '\0';
4156 l = strlen(DBd.buffer);
4157 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4159 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4161 DBd.count++; //=strlen(s);
4163 pic16_flushDB(ptype, p);
4167 /*-----------------------------------------------------------------*/
4168 /*-----------------------------------------------------------------*/
4169 void pic16_pCodeConstString(char *name, char *value)
4173 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4178 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4180 pic16_addpBlock(pb);
4182 sprintf(buffer,"; %s = %s",name,value);
4184 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4185 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4188 pic16_emitDB(*value, 'p', (void *)pb);
4190 pic16_flushDB('p', (void *)pb);
4193 /*-----------------------------------------------------------------*/
4194 /*-----------------------------------------------------------------*/
4196 static void pCodeReadCodeTable(void)
4200 fprintf(stderr, " %s\n",__FUNCTION__);
4202 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4204 pic16_addpBlock(pb);
4206 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4207 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4208 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4209 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4211 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4212 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4213 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4214 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4219 /*-----------------------------------------------------------------*/
4220 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4221 /*-----------------------------------------------------------------*/
4222 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4229 /* If this is the first pcode to be added to a block that
4230 * was initialized with a NULL pcode, then go ahead and
4231 * make this pcode the head and tail */
4232 pb->pcHead = pb->pcTail = pc;
4235 pb->pcTail->next = pc;
4237 pc->prev = pb->pcTail;
4244 /*-----------------------------------------------------------------*/
4245 /* pic16_addpBlock - place a pBlock into the pFile */
4246 /*-----------------------------------------------------------------*/
4247 void pic16_addpBlock(pBlock *pb)
4249 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4252 /* First time called, we'll pass through here. */
4253 //_ALLOC(the_pFile,sizeof(pFile));
4254 the_pFile = Safe_calloc(1,sizeof(pFile));
4255 the_pFile->pbHead = the_pFile->pbTail = pb;
4256 the_pFile->functions = NULL;
4260 the_pFile->pbTail->next = pb;
4261 pb->prev = the_pFile->pbTail;
4263 the_pFile->pbTail = pb;
4266 /*-----------------------------------------------------------------*/
4267 /* removepBlock - remove a pBlock from the pFile */
4268 /*-----------------------------------------------------------------*/
4269 static void removepBlock(pBlock *pb)
4277 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4279 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4282 if(pbs == the_pFile->pbHead)
4283 the_pFile->pbHead = pbs->next;
4285 if (pbs == the_pFile->pbTail)
4286 the_pFile->pbTail = pbs->prev;
4289 pbs->next->prev = pbs->prev;
4292 pbs->prev->next = pbs->next;
4299 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4303 /*-----------------------------------------------------------------*/
4304 /* printpCode - write the contents of a pCode to a file */
4305 /*-----------------------------------------------------------------*/
4306 static void printpCode(FILE *of, pCode *pc)
4317 fprintf(of,"warning - unable to print pCode\n");
4320 /*-----------------------------------------------------------------*/
4321 /* pic16_printpBlock - write the contents of a pBlock to a file */
4322 /*-----------------------------------------------------------------*/
4323 void pic16_printpBlock(FILE *of, pBlock *pb)
4331 for(pc = pb->pcHead; pc; pc = pc->next) {
4332 if(isPCF(pc) && PCF(pc)->fname) {
4333 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4334 if(pb->dbName == 'A') {
4336 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4337 if(!strcmp(ab->name, PCF(pc)->fname)) {
4338 fprintf(of, "\t0X%06X", ab->address);
4349 /*-----------------------------------------------------------------*/
4351 /* pCode processing */
4355 /*-----------------------------------------------------------------*/
4357 void pic16_unlinkpCode(pCode *pc)
4363 fprintf(stderr,"Unlinking: ");
4364 printpCode(stderr, pc);
4367 pc->prev->next = pc->next;
4369 pc->next->prev = pc->prev;
4371 pc->prev = pc->next = NULL;
4375 /*-----------------------------------------------------------------*/
4376 /*-----------------------------------------------------------------*/
4378 static void genericDestruct(pCode *pc)
4381 pic16_unlinkpCode(pc);
4384 /* For instructions, tell the register (if there's one used)
4385 * that it's no longer needed */
4386 regs *reg = pic16_getRegFromInstruction(pc);
4388 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4390 if(PCI(pc)->is2MemOp) {
4391 reg = pic16_getRegFromInstruction2(pc);
4393 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4397 /* Instead of deleting the memory used by this pCode, mark
4398 * the object as bad so that if there's a pointer to this pCode
4399 * dangling around somewhere then (hopefully) when the type is
4400 * checked we'll catch it.
4405 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4413 /*-----------------------------------------------------------------*/
4414 /*-----------------------------------------------------------------*/
4415 /* modifiers for constant immediate */
4416 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4418 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4423 int use_buffer = 1; // copy the string to the passed buffer pointer
4428 use_buffer = 0; // Don't bother copying the string to the buffer.
4432 switch(pcop->type) {
4438 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4441 return PCOR(pcop)->r->name;
4444 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4446 SAFE_snprintf(&buffer,&size,"%s",r->name);
4453 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4454 if(PCOI(pcop)->index) {
4455 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4456 immdmod[ PCOI(pcop)->offset ],
4460 SAFE_snprintf(&s,&size,"%s(%s)",
4461 immdmod[ PCOI(pcop)->offset ],
4465 if(PCOI(pcop)->index) {
4466 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4471 SAFE_snprintf(&s,&size, "%s(%s)",
4480 // size = sizeof(buffer);
4481 if( PCOR(pcop)->instance) {
4482 SAFE_snprintf(&s,&size,"(%s + %d)",
4484 PCOR(pcop)->instance );
4486 SAFE_snprintf(&s,&size,"%s",pcop->name);
4493 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4502 return "NO operand1";
4505 /*-----------------------------------------------------------------*/
4506 /* pic16_get_op2 - variant to support two memory operand commands */
4507 /*-----------------------------------------------------------------*/
4508 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4513 int use_buffer = 1; // copy the string to the passed buffer pointer
4518 use_buffer = 0; // Don't bother copying the string to the buffer.
4522 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",
4523 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4524 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4528 switch(PCOR2(pcop)->pcop2->type) {
4534 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4537 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4540 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4543 SAFE_snprintf(&buffer,&size,"%s",r->name);
4554 if(PCOI(pcop)->_const) {
4555 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4556 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4559 8 * PCOI(pcop)->offset );
4561 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4563 if( PCOI(pcop)->index) {
4564 SAFE_snprintf(&s,&size,"(%s + %d)",
4566 PCOI(pcop)->index );
4568 if(PCOI(pcop)->offset)
4569 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4571 SAFE_snprintf(&s,&size,"%s",pcop->name);
4578 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4579 SAFE_snprintf(&s,&size,"(%s + %d)",
4580 PCOR(PCOR2(pcop)->pcop2)->r->name,
4581 PCOR(PCOR2(pcop)->pcop2)->instance );
4583 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4588 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4590 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4593 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4598 return "NO operand2";
4601 /*-----------------------------------------------------------------*/
4602 /*-----------------------------------------------------------------*/
4603 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4607 return pic16_get_op(pcc->pcop,NULL,0);
4609 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4610 * return ("ERROR Null: "__FUNCTION__);
4612 return ("ERROR Null: pic16_get_op_from_instruction");
4616 /*-----------------------------------------------------------------*/
4617 /*-----------------------------------------------------------------*/
4618 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4621 fprintf(of,"pcodeopprint- not implemented\n");
4624 /*-----------------------------------------------------------------*/
4625 /* pic16_pCode2str - convert a pCode instruction to string */
4626 /*-----------------------------------------------------------------*/
4627 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4633 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4634 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4635 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4643 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4645 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4647 if(PCI(pc)->is2MemOp) {
4648 SAFE_snprintf(&s,&size, "%s, %s",
4649 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4650 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4654 if(PCI(pc)->is2LitOp) {
4655 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4659 if(PCI(pc)->isBitInst) {
4660 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4661 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4662 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4663 PCI(pc)->pcop->name ,
4664 PCI(pc)->pcop->name );
4666 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4667 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4668 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4669 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4671 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4672 //PCI(pc)->pcop->t.bit );
4675 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4676 if( PCI(pc)->num_ops == 3)
4677 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4679 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4682 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4684 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4685 if(PCI(pc)->num_ops == 3)
4686 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4688 r = pic16_getRegFromInstruction(pc);
4689 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4690 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4692 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4701 /* assuming that comment ends with a \n */
4702 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4706 /* assuming that inline code ends with a \n */
4707 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4711 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4714 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4717 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4720 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4723 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4724 SAFE_snprintf(&s,&size,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4727 if(PCAD(pc)->directive) {
4728 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4731 /* special case to handle inline labels without a tab */
4732 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4737 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4744 /*-----------------------------------------------------------------*/
4745 /* genericPrint - the contents of a pCode to a file */
4746 /*-----------------------------------------------------------------*/
4747 static void genericPrint(FILE *of, pCode *pc)
4755 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4759 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4763 // If the opcode has a label, print that first
4765 pBranch *pbl = PCI(pc)->label;
4766 while(pbl && pbl->pc) {
4767 if(pbl->pc->type == PC_LABEL)
4768 pCodePrintLabel(of, pbl->pc);
4774 genericPrint(of,PCODE(PCI(pc)->cline));
4779 pic16_pCode2str(str, 256, pc);
4781 fprintf(of,"%s",str);
4783 if(pic16_debug_verbose) {
4784 fprintf(of, "\t;key=%03x",pc->seq);
4786 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4793 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4794 if(PCW(pc)->pci.label)
4795 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4797 if(PCW(pc)->operand) {
4798 fprintf(of,";\toperand ");
4799 pCodeOpPrint(of,PCW(pc)->operand );
4804 if(pic16_debug_verbose) {
4805 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4806 if(PCFL(pc)->ancestor)
4807 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4814 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4815 fprintf(of,"#LINE\t%d; %s\t%s\n", PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4821 pBranch *pbl = PCAD(pc)->pci.label;
4822 while(pbl && pbl->pc) {
4823 if(pbl->pc->type == PC_LABEL)
4824 pCodePrintLabel(of, pbl->pc);
4828 if(PCAD(pc)->directive) {
4829 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4832 /* special case to handle inline labels without tab */
4833 fprintf(of, "%s\n", PCAD(pc)->arg);
4839 fprintf(of,"unknown pCode type %d\n",pc->type);
4844 /*-----------------------------------------------------------------*/
4845 /* pCodePrintFunction - prints function begin/end */
4846 /*-----------------------------------------------------------------*/
4848 static void pCodePrintFunction(FILE *of, pCode *pc)
4855 if( ((pCodeFunction *)pc)->modname)
4856 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4859 if(!PCF(pc)->absblock) {
4860 if(PCF(pc)->fname) {
4861 pBranch *exits = PCF(pc)->to;
4864 fprintf(of,"%s:", PCF(pc)->fname);
4866 if(pic16_pcode_verbose)
4867 fprintf(of, "\t;Function start");
4873 exits = exits->next;
4877 if(pic16_pcode_verbose)
4878 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4881 if((PCF(pc)->from &&
4882 PCF(pc)->from->pc->type == PC_FUNCTION &&
4883 PCF(PCF(pc)->from->pc)->fname) ) {
4885 if(pic16_pcode_verbose)
4886 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4888 if(pic16_pcode_verbose)
4889 fprintf(of,"; exit point [can't find entry point]\n");
4895 /*-----------------------------------------------------------------*/
4896 /* pCodePrintLabel - prints label */
4897 /*-----------------------------------------------------------------*/
4899 static void pCodePrintLabel(FILE *of, pCode *pc)
4906 fprintf(of,"%s:\n",PCL(pc)->label);
4907 else if (PCL(pc)->key >=0)
4908 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4910 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4913 /*-----------------------------------------------------------------*/
4914 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4915 /* remove it if it is found. */
4916 /*-----------------------------------------------------------------*/
4917 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4924 if(pcl->type == PC_OPCODE)
4925 b = PCI(pcl)->label;
4927 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4932 //fprintf (stderr, "%s \n",__FUNCTION__);
4933 //pcl->print(stderr,pcl);
4934 //pc->print(stderr,pc);
4937 //fprintf (stderr, "found label\n");
4938 //pc->print(stderr, pc);
4942 bprev->next = b->next; /* Not first pCode in chain */
4946 PCI(pcl)->label = b->next; /* First pCode in chain */
4949 return; /* A label can't occur more than once */
4957 /*-----------------------------------------------------------------*/
4958 /*-----------------------------------------------------------------*/
4959 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4978 /*-----------------------------------------------------------------*/
4979 /* pBranchLink - given two pcodes, this function will link them */
4980 /* together through their pBranches */
4981 /*-----------------------------------------------------------------*/
4982 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4986 // Declare a new branch object for the 'from' pCode.
4988 //_ALLOC(b,sizeof(pBranch));
4989 b = Safe_calloc(1,sizeof(pBranch));
4990 b->pc = PCODE(t); // The link to the 'to' pCode.
4993 f->to = pic16_pBranchAppend(f->to,b);
4995 // Now do the same for the 'to' pCode.
4997 //_ALLOC(b,sizeof(pBranch));
4998 b = Safe_calloc(1,sizeof(pBranch));
5002 t->from = pic16_pBranchAppend(t->from,b);
5007 /*-----------------------------------------------------------------*/
5008 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5010 /*-----------------------------------------------------------------*/
5011 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5024 /*-----------------------------------------------------------------*/
5025 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5026 /*-----------------------------------------------------------------*/
5027 void pic16_pCodeUnlink(pCode *pc)
5032 if(!pc->prev || !pc->next) {
5033 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5037 /* first remove the pCode from the chain */
5038 pc->prev->next = pc->next;
5039 pc->next->prev = pc->prev;
5041 /* Now for the hard part... */
5043 /* Remove the branches */
5045 pb1 = PCI(pc)->from;
5047 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5048 * one we're unlinking */
5050 /* search for the link back to this pCode (the one we're
5052 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5053 pb2->pc = PCI(pc)->to->pc; // make the replacement
5055 /* if the pCode we're unlinking contains multiple 'to'
5056 * branches (e.g. this a skip instruction) then we need
5057 * to copy these extra branches to the chain. */
5058 if(PCI(pc)->to->next)
5059 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5068 /*-----------------------------------------------------------------*/
5069 /*-----------------------------------------------------------------*/
5071 static void genericAnalyze(pCode *pc)
5081 // Go through the pCodes that are in pCode chain and link
5082 // them together through the pBranches. Note, the pCodes
5083 // are linked together as a contiguous stream like the
5084 // assembly source code lines. The linking here mimics this
5085 // except that comments are not linked in.
5087 pCode *npc = pc->next;
5089 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5090 pBranchLink(pc,npc);
5095 /* reached the end of the pcode chain without finding
5096 * an instruction we could link to. */
5100 fprintf(stderr,"analyze PC_FLOW\n");
5104 fprintf(stderr,,";A bad pCode is being used\n");
5110 /*-----------------------------------------------------------------*/
5111 /*-----------------------------------------------------------------*/
5112 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5116 if(pc->type == PC_LABEL) {
5117 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5120 if((pc->type == PC_OPCODE)
5121 || (pc->type == PC_ASMDIR)
5123 pbr = PCI(pc)->label;
5125 if(pbr->pc->type == PC_LABEL) {
5126 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5136 /*-----------------------------------------------------------------*/
5137 /*-----------------------------------------------------------------*/
5138 static int checkLabel(pCode *pc)
5142 if(pc && isPCI(pc)) {
5143 pbr = PCI(pc)->label;
5145 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5155 /*-----------------------------------------------------------------*/
5156 /* findLabelinpBlock - Search the pCode for a particular label */
5157 /*-----------------------------------------------------------------*/
5158 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5165 for(pc = pb->pcHead; pc; pc = pc->next)
5166 if(compareLabel(pc,pcop_label))
5172 /*-----------------------------------------------------------------*/
5173 /* findLabel - Search the pCode for a particular label */
5174 /*-----------------------------------------------------------------*/
5175 static pCode * findLabel(pCodeOpLabel *pcop_label)
5183 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5184 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5188 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5192 /*-----------------------------------------------------------------*/
5193 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5194 /* in the linked list */
5195 /*-----------------------------------------------------------------*/
5196 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5209 /*-----------------------------------------------------------------*/
5210 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5211 /* in the linked list */
5212 /*-----------------------------------------------------------------*/
5213 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5227 //#define PCODE_DEBUG
5228 /*-----------------------------------------------------------------*/
5229 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5230 /* in the linked list */
5231 /*-----------------------------------------------------------------*/
5232 pCode * pic16_findNextInstruction(pCode *pci)
5237 if((pc->type == PC_OPCODE)
5238 || (pc->type == PC_WILD)
5239 || (pc->type == PC_ASMDIR)
5244 fprintf(stderr,"pic16_findNextInstruction: ");
5245 printpCode(stderr, pc);
5250 //fprintf(stderr,"Couldn't find instruction\n");
5254 /*-----------------------------------------------------------------*/
5255 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5256 /* in the linked list */
5257 /*-----------------------------------------------------------------*/
5258 pCode * pic16_findPrevInstruction(pCode *pci)
5264 if((pc->type == PC_OPCODE)
5265 || (pc->type == PC_WILD)
5266 || (pc->type == PC_ASMDIR)
5272 fprintf(stderr,"pic16_findPrevInstruction: ");
5273 printpCode(stderr, pc);
5278 //fprintf(stderr,"Couldn't find instruction\n");
5285 /*-----------------------------------------------------------------*/
5286 /* findFunctionEnd - given a pCode find the end of the function */
5287 /* that contains it */
5288 /*-----------------------------------------------------------------*/
5289 static pCode * findFunctionEnd(pCode *pc)
5293 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5299 fprintf(stderr,"Couldn't find function end\n");
5304 /*-----------------------------------------------------------------*/
5305 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5306 /* instruction with which it is associated. */
5307 /*-----------------------------------------------------------------*/
5308 static void AnalyzeLabel(pCode *pc)
5311 pic16_pCodeUnlink(pc);
5317 static void AnalyzeGOTO(pCode *pc)
5320 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5324 static void AnalyzeSKIP(pCode *pc)
5327 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5328 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5332 static void AnalyzeRETURN(pCode *pc)
5335 // branch_link(pc,findFunctionEnd(pc->next));
5341 /*-----------------------------------------------------------------*/
5342 /*-----------------------------------------------------------------*/
5343 regs * pic16_getRegFromInstruction(pCode *pc)
5349 PCI(pc)->num_ops == 0 ||
5350 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5354 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5355 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5358 switch(PCI(pc)->pcop->type) {
5364 return PCOR(PCI(pc)->pcop)->r;
5368 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5369 return PCOR(PCI(pc)->pcop)->r;
5372 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5374 if(PCOI(PCI(pc)->pcop)->r)
5375 return (PCOI(PCI(pc)->pcop)->r);
5380 return PCOR(PCI(pc)->pcop)->r;
5383 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5384 return PCOR(PCI(pc)->pcop)->r;
5387 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5391 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5392 // genericPrint(stderr, pc);
5400 /*-------------------------------------------------------------------------------*/
5401 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5402 /*-------------------------------------------------------------------------------*/
5403 regs * pic16_getRegFromInstruction2(pCode *pc)
5409 PCI(pc)->num_ops == 0 ||
5410 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5415 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5416 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5420 * operands supported in MOVFF:
5427 switch(PCI(pc)->pcop->type) {
5433 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5435 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5439 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5440 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5444 // if(PCOI(PCI(pc)->pcop)->r)
5445 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5447 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5448 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5451 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5452 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5459 // return PCOR2(PCI(pc)->pcop)->r;
5462 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5463 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5467 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5470 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5471 //genericPrint(stderr, pc);
5479 /*-----------------------------------------------------------------*/
5480 /*-----------------------------------------------------------------*/
5482 static void AnalyzepBlock(pBlock *pb)
5489 /* Find all of the registers used in this pBlock
5490 * by looking at each instruction and examining it's
5493 for(pc = pb->pcHead; pc; pc = pc->next) {
5495 /* Is this an instruction with operands? */
5496 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5498 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5500 /* Loop through all of the registers declared so far in
5501 this block and see if we find this one there */
5503 regs *r = setFirstItem(pb->tregisters);
5506 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5507 PCOR(PCI(pc)->pcop)->r = r;
5510 r = setNextItem(pb->tregisters);
5514 /* register wasn't found */
5515 //r = Safe_calloc(1, sizeof(regs));
5516 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5517 //addSet(&pb->tregisters, r);
5518 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5519 //PCOR(PCI(pc)->pcop)->r = r;
5520 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5522 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5525 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5526 if(PCOR(PCI(pc)->pcop)->r) {
5527 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5528 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5530 if(PCI(pc)->pcop->name)
5531 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5533 fprintf(stderr,"ERROR: NULL register\n");
5542 /*-----------------------------------------------------------------*/
5544 /*-----------------------------------------------------------------*/
5545 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5547 static void InsertpFlow(pCode *pc, pCode **pflow)
5550 PCFL(*pflow)->end = pc;
5552 if(!pc || !pc->next)
5555 *pflow = pic16_newpCodeFlow();
5556 pic16_pCodeInsertAfter(pc, *pflow);
5559 /*-----------------------------------------------------------------*/
5560 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5561 /* the flow blocks. */
5563 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5564 * point the instruction flow changes.
5566 /*-----------------------------------------------------------------*/
5567 void pic16_BuildFlow(pBlock *pb)
5570 pCode *last_pci=NULL;
5577 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5578 /* Insert a pCodeFlow object at the beginning of a pBlock */
5580 InsertpFlow(pb->pcHead, &pflow);
5582 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5583 //pflow->next = pb->pcHead; /* Make the current head the next object */
5584 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5585 //pb->pcHead = pflow; /* Make the Flow object the head */
5588 for( pc = pic16_findNextInstruction(pb->pcHead);
5590 pc=pic16_findNextInstruction(pc)) {
5593 PCI(pc)->pcflow = PCFL(pflow);
5595 //fprintf(stderr," build: ");
5596 //pflow->print(stderr,pflow);
5598 if( PCI(pc)->isSkip) {
5600 /* The two instructions immediately following this one
5601 * mark the beginning of a new flow segment */
5603 while(pc && PCI(pc)->isSkip) {
5605 PCI(pc)->pcflow = PCFL(pflow);
5609 InsertpFlow(pc, &pflow);
5610 pc=pic16_findNextInstruction(pc->next);
5618 PCI(pc)->pcflow = PCFL(pflow);
5620 InsertpFlow(pc, &pflow);
5622 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5624 InsertpFlow(pc, &pflow);
5627 } else if (checkLabel(pc)) {
5629 /* This instruction marks the beginning of a
5630 * new flow segment */
5635 /* If the previous pCode is not a flow object, then
5636 * insert a new flow object. (This check prevents
5637 * two consecutive flow objects from being insert in
5638 * the case where a skip instruction preceeds an
5639 * instruction containing a label.) */
5641 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5642 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5644 PCI(pc)->pcflow = PCFL(pflow);
5651 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5653 PCFL(pflow)->end = pb->pcTail;
5656 /*-------------------------------------------------------------------*/
5657 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5658 /* the flow blocks. */
5660 * unBuildFlow removes pCodeFlow objects from a pCode chain
5662 /*-----------------------------------------------------------------*/
5663 static void unBuildFlow(pBlock *pb)
5678 if(PCI(pc)->pcflow) {
5679 //free(PCI(pc)->pcflow);
5680 PCI(pc)->pcflow = NULL;
5683 } else if(isPCFL(pc) )
5692 /*-----------------------------------------------------------------*/
5693 /*-----------------------------------------------------------------*/
5694 static void dumpCond(int cond)
5697 static char *pcc_str[] = {
5711 int ncond = sizeof(pcc_str) / sizeof(char *);
5714 fprintf(stderr, "0x%04X\n",cond);
5716 for(i=0,j=1; i<ncond; i++, j<<=1)
5718 fprintf(stderr, " %s\n",pcc_str[i]);
5724 /*-----------------------------------------------------------------*/
5725 /*-----------------------------------------------------------------*/
5726 static void FlowStats(pCodeFlow *pcflow)
5734 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5736 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5739 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5744 fprintf(stderr, " FlowStats inCond: ");
5745 dumpCond(pcflow->inCond);
5746 fprintf(stderr, " FlowStats outCond: ");
5747 dumpCond(pcflow->outCond);
5751 /*-----------------------------------------------------------------*
5752 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5753 * if it affects the banking bits.
5755 * return: -1 == Banking bits are unaffected by this pCode.
5757 * return: > 0 == Banking bits are affected.
5759 * If the banking bits are affected, then the returned value describes
5760 * which bits are affected and how they're affected. The lower half
5761 * of the integer maps to the bits that are affected, the upper half
5762 * to whether they're set or cleared.
5764 *-----------------------------------------------------------------*/
5766 static int isBankInstruction(pCode *pc)
5774 if( PCI(pc)->op == POC_MOVLB ||
5775 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5776 bank = PCOL(pc)->lit;
5783 /*-----------------------------------------------------------------*/
5784 /*-----------------------------------------------------------------*/
5785 static void FillFlow(pCodeFlow *pcflow)
5794 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5796 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5799 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5806 isBankInstruction(pc);
5808 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5812 fprintf(stderr, " FillFlow - Bad end of flow\n");
5814 fprintf(stderr, " FillFlow - Ending flow with\n ");
5815 pc->print(stderr,pc);
5818 fprintf(stderr, " FillFlow inCond: ");
5819 dumpCond(pcflow->inCond);
5820 fprintf(stderr, " FillFlow outCond: ");
5821 dumpCond(pcflow->outCond);
5825 /*-----------------------------------------------------------------*/
5826 /*-----------------------------------------------------------------*/
5827 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5829 pCodeFlowLink *fromLink, *toLink;
5831 if(!from || !to || !to->pcflow || !from->pcflow)
5834 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5835 toLink = pic16_newpCodeFlowLink(to->pcflow);
5837 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5838 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5842 /*-----------------------------------------------------------------*
5843 * void LinkFlow(pBlock *pb)
5845 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5846 * non-branching segments. In LinkFlow, we determine the execution
5847 * order of these segments. For example, if one of the segments ends
5848 * with a skip, then we know that there are two possible flow segments
5849 * to which control may be passed.
5850 *-----------------------------------------------------------------*/
5851 static void LinkFlow(pBlock *pb)
5857 //fprintf(stderr,"linkflow \n");
5859 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5861 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5864 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5866 //fprintf(stderr," link: ");
5867 //pcflow->print(stderr,pcflow);
5869 //FillFlow(PCFL(pcflow));
5871 pc = PCFL(pcflow)->end;
5873 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5874 if(isPCI_SKIP(pc)) {
5875 //fprintf(stderr, "ends with skip\n");
5876 //pc->print(stderr,pc);
5877 pct=pic16_findNextInstruction(pc->next);
5878 LinkFlow_pCode(PCI(pc),PCI(pct));
5879 pct=pic16_findNextInstruction(pct->next);
5880 LinkFlow_pCode(PCI(pc),PCI(pct));
5884 if(isPCI_BRANCH(pc)) {
5885 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5887 //fprintf(stderr, "ends with branch\n ");
5888 //pc->print(stderr,pc);
5890 if(!(pcol && isPCOLAB(pcol))) {
5891 if((PCI(pc)->op != POC_RETLW)
5892 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5894 /* continue if label is '$' which assembler knows how to parse */
5895 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5897 if(pic16_pcode_verbose) {
5898 pc->print(stderr,pc);
5899 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5905 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5906 LinkFlow_pCode(PCI(pc),PCI(pct));
5908 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5909 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5911 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5917 //fprintf(stderr, "ends with non-branching instruction:\n");
5918 //pc->print(stderr,pc);
5920 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5926 //fprintf(stderr, "ends with unknown\n");
5927 //pc->print(stderr,pc);
5931 //fprintf(stderr, "ends with nothing: ERROR\n");
5935 /*-----------------------------------------------------------------*/
5936 /*-----------------------------------------------------------------*/
5938 /*-----------------------------------------------------------------*/
5939 /*-----------------------------------------------------------------*/
5940 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5946 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5949 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5959 /*-----------------------------------------------------------------*/
5960 /* insertBankSwitch - inserts a bank switch statement in the */
5961 /* assembly listing */
5963 /* position == 0: insert before */
5964 /* position == 1: insert after pc */
5965 /* position == 2: like 0 but previous was a skip instruction */
5966 /*-----------------------------------------------------------------*/
5967 pCodeOp *pic16_popGetLabel(unsigned int key);
5968 extern int pic16_labelOffset;
5970 static void insertBankSwitch(int position, pCode *pc)
5978 /* emit BANKSEL [symbol] */
5980 reg = pic16_getRegFromInstruction(pc);
5982 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))return;
5984 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5986 // position = 0; // position is always before (sanity check!)
5989 fprintf(stderr, "%s:%d: inserting bank switch\n", __FUNCTION__, __LINE__);
5990 pc->print(stderr, pc);
5995 /* insert the bank switch after this pc instruction */
5996 pCode *pcnext = pic16_findNextInstruction(pc);
5998 pic16_pCodeInsertAfter(pc, new_pc);
5999 if(pcnext)pc = pcnext;
6003 /* insert the bank switch BEFORE this pc instruction */
6004 pic16_pCodeInsertAfter(pc->prev, new_pc);
6009 pCode *pcnext, *pcprev, *npci;
6011 /* just like 0, but previous was a skip instruction,
6012 * so some care should be taken */
6014 pic16_labelOffset += 10000;
6015 tlbl = newiTempLabel(NULL);
6017 /* invert skip instruction */
6018 pcprev = pic16_findPrevInstruction(pc->prev);
6019 ipci = PCI(pcprev)->inverted_op;
6020 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6023 PCI(npci)->from = PCI(pcprev)->from;
6024 PCI(npci)->to = PCI(pcprev)->to;
6025 PCI(npci)->label = PCI(pcprev)->label;
6026 PCI(npci)->pcflow = PCI(pcprev)->pcflow;
6027 PCI(npci)->cline = PCI(pcprev)->cline;
6030 // memmove(PCI(pcprev), PCI(npci), sizeof(pCode) + sizeof(PIC_OPCODE) + sizeof(char const * const));
6033 pic16_pCodeInsertAfter(pcprev->prev, npci);
6034 /* unlink the pCode */
6035 pcprev->prev->next = pcprev->next;
6036 pcprev->next->prev = pcprev->prev;
6039 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6040 pic16_pCodeInsertAfter(pc->prev, pcnext);
6041 pic16_pCodeInsertAfter(pc->prev, new_pc);
6043 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6044 pic16_pCodeInsertAfter(pc, pcnext);
6049 /* Move the label, if there is one */
6050 if(PCI(pc)->label) {
6051 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6052 // __FILE__, __LINE__, pc, new_pc);
6053 PCAD(new_pc)->pci.label = PCI(pc)->label;
6054 PCI(pc)->label = NULL;
6059 /*-----------------------------------------------------------------*/
6060 /*int compareBankFlow - compare the banking requirements between */
6062 /*-----------------------------------------------------------------*/
6063 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6066 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6069 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6072 if(pcflow->firstBank == -1)
6076 if(pcflowLink->pcflow->firstBank == -1) {
6077 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6078 pcflowLink->pcflow->to :
6079 pcflowLink->pcflow->from);
6080 return compareBankFlow(pcflow, pctl, toORfrom);
6084 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6087 pcflowLink->bank_conflict++;
6088 pcflowLink->pcflow->FromConflicts++;
6089 pcflow->ToConflicts++;
6092 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6095 pcflowLink->bank_conflict++;
6096 pcflowLink->pcflow->ToConflicts++;
6097 pcflow->FromConflicts++;
6101 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6102 pcflowLink->pcflow->pc.seq,
6103 pcflowLink->pcflow->FromConflicts,
6104 pcflowLink->pcflow->ToConflicts);
6111 /*-----------------------------------------------------------------*/
6112 /*-----------------------------------------------------------------*/
6113 static void DumpFlow(pBlock *pb)
6117 pCodeFlowLink *pcfl;
6120 fprintf(stderr,"Dump flow \n");
6121 pb->pcHead->print(stderr, pb->pcHead);
6123 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6124 pcflow->print(stderr,pcflow);
6126 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6128 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6130 if(!isPCFL(pcflow)) {
6131 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6134 fprintf(stderr,"dumping: ");
6135 pcflow->print(stderr,pcflow);
6136 FlowStats(PCFL(pcflow));
6138 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6140 pc = PCODE(pcfl->pcflow);
6142 fprintf(stderr, " from seq %d:\n",pc->seq);
6144 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6145 pc->print(stderr,pc);
6150 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6152 pc = PCODE(pcfl->pcflow);
6154 fprintf(stderr, " to seq %d:\n",pc->seq);
6156 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6157 pc->print(stderr,pc);
6166 /*-----------------------------------------------------------------*/
6167 /*-----------------------------------------------------------------*/
6168 static int OptimizepBlock(pBlock *pb)
6173 if(!pb || !peepOptimizing)
6176 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6178 for(pc = pb->pcHead; pc; pc = pc->next)
6179 matches += pic16_pCodePeepMatchRule(pc);
6182 pc = pic16_findNextInstruction(pb->pcHead);
6190 if(pic16_pCodePeepMatchRule(pc)) {
6195 pc = pic16_findNextInstruction(pcprev->next);
6197 pc = pic16_findNextInstruction(pb->pcHead);
6199 pc = pic16_findNextInstruction(pc->next);
6203 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6208 /*-----------------------------------------------------------------*/
6209 /*-----------------------------------------------------------------*/
6210 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6214 for(pc = pcs; pc; pc = pc->next) {
6216 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6218 (PCI(pc)->pcop->type == PO_LABEL) &&
6219 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6227 /*-----------------------------------------------------------------*/
6228 /*-----------------------------------------------------------------*/
6229 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6236 (PCI(pc)->pcop->type == PO_LABEL)) {
6238 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6240 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6242 free(pcol->pcop.name);
6244 /* If the key is negative, then we (probably) have a label to
6245 * a function and the name is already defined */
6248 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6252 //sprintf(buffer,"_%05d_DS_",pcl->key);
6254 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6256 pcol->pcop.name = Safe_strdup(s);
6257 pcol->key = pcl->key;
6258 //pc->print(stderr,pc);
6265 /*-----------------------------------------------------------------*/
6266 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6267 /* pCode chain if they're not used. */
6268 /*-----------------------------------------------------------------*/
6269 static void pBlockRemoveUnusedLabels(pBlock *pb)
6271 pCode *pc; pCodeLabel *pcl;
6276 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6278 pBranch *pbr = PCI(pc)->label;
6279 if(pbr && pbr->next) {
6280 pCode *pcd = pb->pcHead;
6282 // fprintf(stderr, "multiple labels\n");
6283 // pc->print(stderr,pc);
6288 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6289 //fprintf(stderr,"Used by:\n");
6290 //pcd->print(stderr,pcd);
6292 exchangeLabels(PCL(pbr->pc),pcd);
6301 for(pc = pb->pcHead; pc; pc = pc->next) {
6303 if(isPCL(pc)) // pc->type == PC_LABEL)
6305 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6306 pcl = PCL(PCI(pc)->label->pc);
6309 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6311 /* This pCode is a label, so search the pBlock to see if anyone
6314 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6316 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6317 /* Couldn't find an instruction that refers to this label
6318 * So, unlink the pCode label from it's pCode chain
6319 * and destroy the label */
6320 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6322 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6323 if(pc->type == PC_LABEL) {
6324 pic16_unlinkpCode(pc);
6325 pCodeLabelDestruct(pc);
6327 unlinkpCodeFromBranch(pc, PCODE(pcl));
6328 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6339 /*-----------------------------------------------------------------*/
6340 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6341 /* chain and put them into pBranches that are */
6342 /* associated with the appropriate pCode */
6344 /*-----------------------------------------------------------------*/
6345 void pic16_pBlockMergeLabels(pBlock *pb)
6348 pCode *pc, *pcnext=NULL;
6353 /* First, Try to remove any unused labels */
6354 //pBlockRemoveUnusedLabels(pb);
6356 /* Now loop through the pBlock and merge the labels with the opcodes */
6359 // for(pc = pb->pcHead; pc; pc = pc->next) {
6362 pCode *pcn = pc->next;
6364 if(pc->type == PC_LABEL) {
6366 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6367 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6369 if((pcnext = pic16_findNextInstruction(pc) )) {
6371 // pcnext->print(stderr, pcnext);
6373 // Unlink the pCode label from it's pCode chain
6374 pic16_unlinkpCode(pc);
6376 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6377 // And link it into the instruction's pBranch labels. (Note, since
6378 // it's possible to have multiple labels associated with one instruction
6379 // we must provide a means to accomodate the additional labels. Thus
6380 // the labels are placed into the singly-linked list "label" as
6381 // opposed to being a single member of the pCodeInstruction.)
6383 //_ALLOC(pbr,sizeof(pBranch));
6385 pbr = Safe_calloc(1,sizeof(pBranch));
6389 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6392 if(pic16_pcode_verbose)
6393 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6395 } else if(pc->type == PC_CSOURCE) {
6397 /* merge the source line symbolic info into the next instruction */
6398 if((pcnext = pic16_findNextInstruction(pc) )) {
6400 // Unlink the pCode label from it's pCode chain
6401 pic16_unlinkpCode(pc);
6402 PCI(pcnext)->cline = PCCS(pc);
6403 //fprintf(stderr, "merging CSRC\n");
6404 //genericPrint(stderr,pcnext);
6410 pBlockRemoveUnusedLabels(pb);
6414 /*-----------------------------------------------------------------*/
6415 /*-----------------------------------------------------------------*/
6416 static int OptimizepCode(char dbName)
6418 #define MAX_PASSES 4
6427 DFPRINTF((stderr," Optimizing pCode\n"));
6431 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6432 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6433 matches += OptimizepBlock(pb);
6436 while(matches && ++passes < MAX_PASSES);
6443 const char *pic16_pCodeOpType(pCodeOp *pcop);
6444 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6447 /*-----------------------------------------------------------------*/
6448 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6449 /*-----------------------------------------------------------------*/
6451 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6455 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6456 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6458 if( !( (pcop->type == PO_LABEL) ||
6459 (pcop->type == PO_LITERAL) ||
6460 (pcop->type == PO_STR) ))
6461 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6462 PCOR(pcop)->r->wasUsed = 1;
6468 /*----------------------------------------------------------------------*
6469 * pic16_areRegsSame - check to see if the names of two registers match *
6470 *----------------------------------------------------------------------*/
6471 int pic16_areRegsSame(regs *r1, regs *r2)
6473 if(!strcmp(r1->name, r2->name))return 1;
6479 /*-----------------------------------------------------------------*/
6480 /*-----------------------------------------------------------------*/
6481 static void pic16_FixRegisterBanking(pBlock *pb)
6485 regs *reg, *prevreg;
6491 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6494 /* loop through all of the flow blocks with in one pblock */
6496 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6500 /* at this point, pc should point to a PC_FLOW object */
6501 /* for each flow block, determine the register banking
6504 if(!isPCI(pc))goto loop;
6506 if(PCI(pc)->is2MemOp)goto loop;
6508 reg = pic16_getRegFromInstruction(pc);
6511 pc->print(stderr, pc);
6512 fprintf(stderr, "reg = %p\n", reg);
6515 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6516 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6517 reg->address,reg->isBitField, reg->isFixed);
6521 /* we can be 99% that within a pBlock, between two consequtive
6522 * refernces to the same register, the extra banksel is needless */
6525 /* now make some tests to make sure that instruction needs bank switch */
6527 /* if not no register exists, and if not a bit opcode goto loop */
6529 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6532 if(isPCI_SKIP(pc)) {
6533 // fprintf(stderr, "instruction is SKIP instruction\n");
6535 if((reg && isACCESS_BANK(reg)) || !isBankInstruction(pc))goto loop;
6537 if(isPCI_LIT(pc))goto loop;
6539 if(PCI(pc)->op == POC_CALL)goto loop;
6541 /* Examine the instruction before this one to make sure it is
6542 * not a skip type instruction */
6543 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6545 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6546 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6548 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6551 insertBankSwitch(flag, pc);
6554 // fprintf(stderr, "BANK SWITCH inserted\n");
6563 static void pBlockDestruct(pBlock *pb)
6574 /*-----------------------------------------------------------------*/
6575 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6576 /* name dbName and combine them */
6577 /* into one block */
6578 /*-----------------------------------------------------------------*/
6579 static void mergepBlocks(char dbName)
6582 pBlock *pb, *pbmerged = NULL,*pbn;
6584 pb = the_pFile->pbHead;
6586 //fprintf(stderr," merging blocks named %c\n",dbName);
6590 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6591 if( getpBlock_dbName(pb) == dbName) {
6593 //fprintf(stderr," merged block %c\n",dbName);
6598 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6599 /* pic16_addpCode2pBlock doesn't handle the tail: */
6600 pbmerged->pcTail = pb->pcTail;
6602 pb->prev->next = pbn;
6604 pbn->prev = pb->prev;
6609 //pic16_printpBlock(stderr, pbmerged);
6616 /*-----------------------------------------------------------------*/
6617 /* AnalyzeFlow - Examine the flow of the code and optimize */
6619 /* level 0 == minimal optimization */
6620 /* optimize registers that are used only by two instructions */
6621 /* level 1 == maximal optimization */
6622 /* optimize by looking at pairs of instructions that use the */
6624 /*-----------------------------------------------------------------*/
6626 static void AnalyzeFlow(int level)
6628 static int times_called=0;
6633 /* remove unused allocated registers before exiting */
6634 pic16_RemoveUnusedRegisters();
6640 /* if this is not the first time this function has been called,
6641 then clean up old flow information */
6642 if(times_called++) {
6643 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6646 pic16_RegsUnMapLiveRanges();
6651 /* Phase 2 - Flow Analysis - Register Banking
6653 * In this phase, the individual flow blocks are examined
6654 * and register banking is fixed.
6658 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6659 pic16_FixRegisterBanking(pb);
6662 /* Phase 2 - Flow Analysis
6664 * In this phase, the pCode is partition into pCodeFlow
6665 * blocks. The flow blocks mark the points where a continuous
6666 * stream of instructions changes flow (e.g. because of
6667 * a call or goto or whatever).
6670 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6671 pic16_BuildFlow(pb);
6674 /* Phase 2 - Flow Analysis - linking flow blocks
6676 * In this phase, the individual flow blocks are examined
6677 * to determine their order of excution.
6680 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6683 /* Phase 3 - Flow Analysis - Flow Tree
6685 * In this phase, the individual flow blocks are examined
6686 * to determine their order of execution.
6689 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6690 pic16_BuildFlowTree(pb);
6693 /* Phase x - Flow Analysis - Used Banks
6695 * In this phase, the individual flow blocks are examined
6696 * to determine the Register Banks they use
6700 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6705 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6706 pic16_pCodeRegMapLiveRanges(pb);
6708 pic16_RemoveUnusedRegisters();
6710 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6711 pic16_pCodeRegOptimizeRegUsage(level);
6719 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6724 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6726 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6727 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6728 pcflow = pcflow->next) {
6730 FillFlow(PCFL(pcflow));
6735 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6738 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6739 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6740 pcflow = pcflow->next) {
6742 FlowStats(PCFL(pcflow));
6748 /* VR -- no need to analyze banking in flow, but left here :
6749 * 1. because it may be used in the future for other purposes
6750 * 2. because if omitted we'll miss some optimization done here
6752 * Perhaps I should rename it to something else
6755 /*-----------------------------------------------------------------*/
6756 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6757 /* assigned to the registers. */
6759 /*-----------------------------------------------------------------*/
6761 void pic16_AnalyzeBanking(void)
6765 if(!pic16_picIsInitialized()) {
6766 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6767 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6768 fprintf(stderr,"support/scripts/inc2h.pl\n");
6769 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6771 /* I think it took a long long time to fix this bug! ;-) -- VR */
6777 /* Phase x - Flow Analysis - Used Banks
6779 * In this phase, the individual flow blocks are examined
6780 * to determine the Register Banks they use
6786 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6787 // BanksUsedFlow(pb);
6789 if(!the_pFile)return;
6792 if(!pic16_options.no_banksel) {
6793 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6794 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6795 pic16_FixRegisterBanking(pb);
6801 /*-----------------------------------------------------------------*/
6802 /* buildCallTree - Look at the flow and extract all of the calls. */
6803 /*-----------------------------------------------------------------*/
6804 static set *register_usage(pBlock *pb);
6806 static void buildCallTree(void )
6818 /* Now build the call tree.
6819 First we examine all of the pCodes for functions.
6820 Keep in mind that the function boundaries coincide
6821 with pBlock boundaries.
6823 The algorithm goes something like this:
6824 We have two nested loops. The outer loop iterates
6825 through all of the pBlocks/functions. The inner
6826 loop iterates through all of the pCodes for
6827 a given pBlock. When we begin iterating through
6828 a pBlock, the variable pc_fstart, pCode of the start
6829 of a function, is cleared. We then search for pCodes
6830 of type PC_FUNCTION. When one is encountered, we
6831 initialize pc_fstart to this and at the same time
6832 associate a new pBranch object that signifies a
6833 branch entry. If a return is found, then this signifies
6834 a function exit point. We'll link the pCodes of these
6835 returns to the matching pc_fstart.
6837 When we're done, a doubly linked list of pBranches
6838 will exist. The head of this list is stored in
6839 `the_pFile', which is the meta structure for all
6840 of the pCode. Look at the pic16_printCallTree function
6841 on how the pBranches are linked together.
6844 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6845 pCode *pc_fstart=NULL;
6846 for(pc = pb->pcHead; pc; pc = pc->next) {
6848 if(isPCI(pc) && pc_fstart) {
6849 if(PCI(pc)->is2MemOp) {
6850 r = pic16_getRegFromInstruction2(pc);
6851 if(r && !strcmp(r->name, "POSTDEC1"))
6852 PCF(pc_fstart)->stackusage++;
6854 r = pic16_getRegFromInstruction(pc);
6855 if(r && !strcmp(r->name, "PREINC1"))
6856 PCF(pc_fstart)->stackusage--;
6861 if (PCF(pc)->fname) {
6863 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6864 //fprintf(stderr," found main \n");
6865 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6869 pbr = Safe_calloc(1,sizeof(pBranch));
6870 pbr->pc = pc_fstart = pc;
6873 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6875 // Here's a better way of doing the same:
6876 addSet(&pb->function_entries, pc);
6879 // Found an exit point in a function, e.g. return
6880 // (Note, there may be more than one return per function)
6882 pBranchLink(PCF(pc_fstart), PCF(pc));
6884 addSet(&pb->function_exits, pc);
6886 } else if(isCALL(pc)) {
6887 addSet(&pb->function_calls,pc);
6894 /* This is not needed because currently all register used
6895 * by a function are stored in stack -- VR */
6897 /* Re-allocate the registers so that there are no collisions
6898 * between local variables when one function call another */
6901 // pic16_deallocateAllRegs();
6903 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6911 /*-----------------------------------------------------------------*/
6912 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6913 /* all of the logical connections. */
6915 /* Essentially what's done here is that the pCode flow is */
6917 /*-----------------------------------------------------------------*/
6919 void pic16_AnalyzepCode(char dbName)
6930 /* Phase 1 - Register allocation and peep hole optimization
6932 * The first part of the analysis is to determine the registers
6933 * that are used in the pCode. Once that is done, the peep rules
6934 * are applied to the code. We continue to loop until no more
6935 * peep rule optimizations are found (or until we exceed the
6936 * MAX_PASSES threshold).
6938 * When done, the required registers will be determined.
6944 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6945 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6947 /* First, merge the labels with the instructions */
6948 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6949 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6951 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6952 //fprintf(stderr," analyze and merging block %c\n",dbName);
6953 pic16_pBlockMergeLabels(pb);
6956 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6961 changes = OptimizepCode(dbName);
6964 } while(changes && (i++ < MAX_PASSES));
6969 /*-----------------------------------------------------------------*/
6970 /* ispCodeFunction - returns true if *pc is the pCode of a */
6972 /*-----------------------------------------------------------------*/
6973 static bool ispCodeFunction(pCode *pc)
6976 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6982 /*-----------------------------------------------------------------*/
6983 /* findFunction - Search for a function by name (given the name) */
6984 /* in the set of all functions that are in a pBlock */
6985 /* (note - I expect this to change because I'm planning to limit */
6986 /* pBlock's to just one function declaration */
6987 /*-----------------------------------------------------------------*/
6988 static pCode *findFunction(char *fname)
6995 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6997 pc = setFirstItem(pb->function_entries);
7000 if((pc->type == PC_FUNCTION) &&
7002 (strcmp(fname, PCF(pc)->fname)==0))
7005 pc = setNextItem(pb->function_entries);
7013 static void MarkUsedRegisters(set *regset)
7018 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7019 // fprintf(stderr, "marking register = %s\t", r1->name);
7020 r2 = pic16_regWithIdx(r1->rIdx);
7021 // fprintf(stderr, "to register = %s\n", r2->name);
7027 static void pBlockStats(FILE *of, pBlock *pb)
7033 if(!pic16_pcode_verbose)return;
7035 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7037 // for now just print the first element of each set
7038 pc = setFirstItem(pb->function_entries);
7040 fprintf(of,";entry: ");
7043 pc = setFirstItem(pb->function_exits);
7045 fprintf(of,";has an exit\n");
7049 pc = setFirstItem(pb->function_calls);
7051 fprintf(of,";functions called:\n");
7054 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7055 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7057 pc = setNextItem(pb->function_calls);
7061 r = setFirstItem(pb->tregisters);
7063 int n = elementsInSet(pb->tregisters);
7065 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7068 fprintf(of,"; %s\n",r->name);
7069 r = setNextItem(pb->tregisters);
7073 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7076 /*-----------------------------------------------------------------*/
7077 /*-----------------------------------------------------------------*/
7079 static void sequencepCode(void)
7085 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7087 pb->seq = GpCodeSequenceNumber+1;
7089 for( pc = pb->pcHead; pc; pc = pc->next)
7090 pc->seq = ++GpCodeSequenceNumber;
7096 /*-----------------------------------------------------------------*/
7097 /*-----------------------------------------------------------------*/
7098 static set *register_usage(pBlock *pb)
7101 set *registers=NULL;
7102 set *registersInCallPath = NULL;
7104 /* check recursion */
7106 pc = setFirstItem(pb->function_entries);
7113 if(pc->type != PC_FUNCTION)
7114 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7116 pc = setFirstItem(pb->function_calls);
7117 for( ; pc; pc = setNextItem(pb->function_calls)) {
7119 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7120 char *dest = pic16_get_op_from_instruction(PCI(pc));
7122 pcn = findFunction(dest);
7124 registersInCallPath = register_usage(pcn->pb);
7126 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7131 pBlockStats(stderr,pb); // debug
7134 // Mark the registers in this block as used.
7136 MarkUsedRegisters(pb->tregisters);
7137 if(registersInCallPath) {
7138 /* registers were used in the functions this pBlock has called */
7139 /* so now, we need to see if these collide with the ones we are */
7142 regs *r1,*r2, *newreg;
7144 DFPRINTF((stderr,"comparing registers\n"));
7146 r1 = setFirstItem(registersInCallPath);
7149 r2 = setFirstItem(pb->tregisters);
7151 while(r2 && (r1->type != REG_STK)) {
7153 if(r2->rIdx == r1->rIdx) {
7154 newreg = pic16_findFreeReg(REG_GPR);
7158 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7162 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7163 r1->rIdx, newreg->rIdx));
7164 r2->rIdx = newreg->rIdx;
7165 //if(r2->name) free(r2->name);
7167 r2->name = Safe_strdup(newreg->name);
7171 newreg->wasUsed = 1;
7173 r2 = setNextItem(pb->tregisters);
7176 r1 = setNextItem(registersInCallPath);
7179 /* Collisions have been resolved. Now free the registers in the call path */
7180 r1 = setFirstItem(registersInCallPath);
7182 if(r1->type != REG_STK) {
7183 newreg = pic16_regWithIdx(r1->rIdx);
7186 r1 = setNextItem(registersInCallPath);
7190 // MarkUsedRegisters(pb->registers);
7192 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7195 DFPRINTF((stderr,"returning regs\n"));
7197 DFPRINTF((stderr,"not returning regs\n"));
7199 DFPRINTF((stderr,"pBlock after register optim.\n"));
7200 pBlockStats(stderr,pb); // debug
7206 /*-----------------------------------------------------------------*/
7207 /* pct2 - writes the call tree to a file */
7209 /*-----------------------------------------------------------------*/
7210 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7214 // set *registersInCallPath = NULL;
7220 fprintf(of, "recursive function\n");
7221 return; //recursion ?
7224 pc = setFirstItem(pb->function_entries);
7231 for(i=0;i<indent;i++) // Indentation
7235 if(pc->type == PC_FUNCTION) {
7236 usedstack += PCF(pc)->stackusage;
7237 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7238 } else return; // ???
7241 pc = setFirstItem(pb->function_calls);
7242 for( ; pc; pc = setNextItem(pb->function_calls)) {
7244 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7245 char *dest = pic16_get_op_from_instruction(PCI(pc));
7247 pcn = findFunction(dest);
7249 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7251 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7259 /*-----------------------------------------------------------------*/
7260 /* pic16_printCallTree - writes the call tree to a file */
7262 /*-----------------------------------------------------------------*/
7264 void pic16_printCallTree(FILE *of)
7276 fprintf(of, "\npBlock statistics\n");
7277 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7281 fprintf(of,"Call Tree\n");
7282 pbr = the_pFile->functions;
7286 if(!ispCodeFunction(pc))
7287 fprintf(of,"bug in call tree");
7290 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7292 while(pc->next && !ispCodeFunction(pc->next)) {
7294 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7295 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7303 fprintf(of,"\n**************\n\na better call tree\n");
7304 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7309 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7310 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7316 /*-----------------------------------------------------------------*/
7318 /*-----------------------------------------------------------------*/
7320 static void InlineFunction(pBlock *pb)
7328 pc = setFirstItem(pb->function_calls);
7330 for( ; pc; pc = setNextItem(pb->function_calls)) {
7333 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7339 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7341 //fprintf(stderr,"Cool can inline:\n");
7342 //pcn->print(stderr,pcn);
7344 //fprintf(stderr,"recursive call Inline\n");
7345 InlineFunction(pcn->pb);
7346 //fprintf(stderr,"return from recursive call Inline\n");
7349 At this point, *pc points to a CALL mnemonic, and
7350 *pcn points to the function that is being called.
7352 To in-line this call, we need to remove the CALL
7353 and RETURN(s), and link the function pCode in with
7359 /* Remove the CALL */
7363 /* remove callee pBlock from the pBlock linked list */
7364 removepBlock(pcn->pb);
7372 /* Remove the Function pCode */
7373 pct = pic16_findNextInstruction(pcn->next);
7375 /* Link the function with the callee */
7376 pc->next = pcn->next;
7377 pcn->next->prev = pc;
7379 /* Convert the function name into a label */
7381 pbr = Safe_calloc(1,sizeof(pBranch));
7382 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7384 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7385 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7387 /* turn all of the return's except the last into goto's */
7388 /* check case for 2 instruction pBlocks */
7389 pce = pic16_findNextInstruction(pcn->next);
7391 pCode *pce_next = pic16_findNextInstruction(pce->next);
7393 if(pce_next == NULL) {
7394 /* found the last return */
7395 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7397 //fprintf(stderr,"found last return\n");
7398 //pce->print(stderr,pce);
7399 pce->prev->next = pc_call->next;
7400 pc_call->next->prev = pce->prev;
7401 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7411 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7417 /*-----------------------------------------------------------------*/
7419 /*-----------------------------------------------------------------*/
7421 void pic16_InlinepCode(void)
7430 if(!functionInlining)
7433 /* Loop through all of the function definitions and count the
7434 * number of times each one is called */
7435 //fprintf(stderr,"inlining %d\n",__LINE__);
7437 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7439 pc = setFirstItem(pb->function_calls);
7441 for( ; pc; pc = setNextItem(pb->function_calls)) {
7444 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7445 if(pcn && isPCF(pcn)) {
7446 PCF(pcn)->ncalled++;
7449 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7454 //fprintf(stderr,"inlining %d\n",__LINE__);
7456 /* Now, Loop through the function definitions again, but this
7457 * time inline those functions that have only been called once. */
7459 InlineFunction(the_pFile->pbHead);
7460 //fprintf(stderr,"inlining %d\n",__LINE__);
7462 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7467 char *pic_optype_names[]={
7468 "PO_NONE", // No operand e.g. NOP
7469 "PO_W", // The working register (as a destination)
7470 "PO_WREG", // The working register (as a file register)
7471 "PO_STATUS", // The 'STATUS' register
7472 "PO_BSR", // The 'BSR' register
7473 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7475 "PO_INDF0", // The Indirect register
7476 "PO_INTCON", // Interrupt Control register
7477 "PO_GPR_REGISTER", // A general purpose register
7478 "PO_GPR_BIT", // A bit of a general purpose register
7479 "PO_GPR_TEMP", // A general purpose temporary register
7480 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7481 "PO_PCL", // Program counter Low register
7482 "PO_PCLATH", // Program counter Latch high register
7483 "PO_PCLATU", // Program counter Latch upper register
7484 "PO_PRODL", // Product Register Low
7485 "PO_PRODH", // Product Register High
7486 "PO_LITERAL", // A constant
7487 "PO_REL_ADDR", // A relative address
7488 "PO_IMMEDIATE", // (8051 legacy)
7489 "PO_DIR", // Direct memory (8051 legacy)
7490 "PO_CRY", // bit memory (8051 legacy)
7491 "PO_BIT", // bit operand.
7492 "PO_STR", // (8051 legacy)
7494 "PO_WILD" // Wild card operand in peep optimizer
7498 char *dumpPicOptype(PIC_OPTYPE type)
7500 return (pic_optype_names[ type ]);