1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 static int mnemonics_initialized = 0;
118 static hTab *pic16MnemonicsHash = NULL;
119 static hTab *pic16pCodePeepCommandsHash = NULL;
121 static pFile *the_pFile = NULL;
122 static pBlock *pb_dead_pcodes = NULL;
124 /* Hardcoded flags to change the behavior of the PIC port */
125 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
126 static int functionInlining = 1; /* inline functions if nonzero */
127 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
129 int pic16_pcode_verbose = 0;
131 //static int GpCodeSequenceNumber = 1;
132 static int GpcFlowSeq = 1;
134 extern void pic16_RemoveUnusedRegisters(void);
135 extern void pic16_RegsUnMapLiveRanges(void);
136 extern void pic16_BuildFlowTree(pBlock *pb);
137 extern void pic16_pCodeRegOptimizeRegUsage(int level);
138 extern int pic16_picIsInitialized(void);
139 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
140 extern int mnem2key(char const *mnem);
142 /****************************************************************/
143 /* Forward declarations */
144 /****************************************************************/
146 void pic16_unlinkpCode(pCode *pc);
148 static void genericAnalyze(pCode *pc);
149 static void AnalyzeGOTO(pCode *pc);
150 static void AnalyzeSKIP(pCode *pc);
151 static void AnalyzeRETURN(pCode *pc);
154 static void genericDestruct(pCode *pc);
155 static void genericPrint(FILE *of,pCode *pc);
157 static void pCodePrintLabel(FILE *of, pCode *pc);
158 static void pCodePrintFunction(FILE *of, pCode *pc);
159 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
160 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
161 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
162 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
163 int pic16_pCodePeepMatchRule(pCode *pc);
164 static void pBlockStats(FILE *of, pBlock *pb);
165 static pBlock *newpBlock(void);
166 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
167 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
168 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
169 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
171 char *dumpPicOptype(PIC_OPTYPE type);
173 /****************************************************************/
174 /* PIC Instructions */
175 /****************************************************************/
177 pCodeInstruction pic16_pciADDWF = {
178 {PC_OPCODE, NULL, NULL, 0, NULL,
191 1,0, // dest, bit instruction
193 0, // literal operand
195 0, // fast call/return mode select bit
196 0, // second memory operand
197 0, // second literal operand
199 (PCC_W | PCC_REGISTER), // inCond
200 (PCC_REGISTER | PCC_Z), // outCond
204 pCodeInstruction pic16_pciADDFW = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
223 0, // second memory operand
224 0, // second literal operand
226 (PCC_W | PCC_REGISTER), // inCond
227 (PCC_W | PCC_Z), // outCond
231 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
232 {PC_OPCODE, NULL, NULL, 0, NULL,
245 1,0, // dest, bit instruction
247 0, // literal operand
249 0, // fast call/return mode select bit
250 0, // second memory operand
251 0, // second literal operand
253 (PCC_W | PCC_REGISTER | PCC_C), // inCond
254 (PCC_REGISTER | PCC_Z), // outCond
258 pCodeInstruction pic16_pciADDFWC = {
259 {PC_OPCODE, NULL, NULL, 0, NULL,
272 0,0, // dest, bit instruction
274 0, // literal operand
276 0, // fast call/return mode select bit
277 0, // second memory operand
278 0, // second literal operand
280 (PCC_W | PCC_REGISTER | PCC_C), // inCond
281 (PCC_W | PCC_Z), // outCond
285 pCodeInstruction pic16_pciADDLW = {
286 {PC_OPCODE, NULL, NULL, 0, NULL,
299 0,0, // dest, bit instruction
301 1, // literal operand
303 0, // fast call/return mode select bit
304 0, // second memory operand
305 0, // second literal operand
307 (PCC_W | PCC_LITERAL), // inCond
308 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
312 pCodeInstruction pic16_pciANDLW = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,0, // dest, bit instruction
328 1, // literal operand
330 0, // fast call/return mode select bit
331 0, // second memory operand
332 0, // second literal operand
334 (PCC_W | PCC_LITERAL), // inCond
335 (PCC_W | PCC_Z | PCC_N), // outCond
339 pCodeInstruction pic16_pciANDWF = {
340 {PC_OPCODE, NULL, NULL, 0, NULL,
353 1,0, // dest, bit instruction
355 0, // literal operand
357 0, // fast call/return mode select bit
358 0, // second memory operand
359 0, // second literal operand
361 (PCC_W | PCC_REGISTER), // inCond
362 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
366 pCodeInstruction pic16_pciANDFW = {
367 {PC_OPCODE, NULL, NULL, 0, NULL,
380 0,0, // dest, bit instruction
382 0, // literal operand
384 0, // fast call/return mode select bit
385 0, // second memory operand
386 0, // second literal operand
388 (PCC_W | PCC_REGISTER), // inCond
389 (PCC_W | PCC_Z) // outCond
392 pCodeInstruction pic16_pciBC = { // mdubuc - New
393 {PC_OPCODE, NULL, NULL, 0, NULL,
406 0,0, // dest, bit instruction
408 0, // literal operand
410 0, // fast call/return mode select bit
411 0, // second memory operand
412 0, // second literal operand
414 (PCC_REL_ADDR | PCC_C), // inCond
419 pCodeInstruction pic16_pciBCF = {
420 {PC_OPCODE, NULL, NULL, 0, NULL,
433 1,1, // dest, bit instruction
435 0, // literal operand
437 0, // fast call/return mode select bit
438 0, // second memory operand
439 0, // second literal operand
441 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
442 PCC_REGISTER, // outCond
446 pCodeInstruction pic16_pciBN = { // mdubuc - New
447 {PC_OPCODE, NULL, NULL, 0, NULL,
460 0,0, // dest, bit instruction
462 0, // literal operand
464 0, // fast call/return mode select bit
465 0, // second memory operand
466 0, // second literal operand
468 (PCC_REL_ADDR | PCC_N), // inCond
469 PCC_NONE , // outCond
473 pCodeInstruction pic16_pciBNC = { // mdubuc - New
474 {PC_OPCODE, NULL, NULL, 0, NULL,
487 0,0, // dest, bit instruction
489 0, // literal operand
491 0, // fast call/return mode select bit
492 0, // second memory operand
493 0, // second literal operand
495 (PCC_REL_ADDR | PCC_C), // inCond
496 PCC_NONE , // outCond
500 pCodeInstruction pic16_pciBNN = { // mdubuc - New
501 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 0, // fast call/return mode select bit
519 0, // second memory operand
520 0, // second literal operand
522 (PCC_REL_ADDR | PCC_N), // inCond
523 PCC_NONE , // outCond
527 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
528 {PC_OPCODE, NULL, NULL, 0, NULL,
541 0,0, // dest, bit instruction
543 0, // literal operand
545 0, // fast call/return mode select bit
546 0, // second memory operand
547 0, // second literal operand
549 (PCC_REL_ADDR | PCC_OV), // inCond
550 PCC_NONE , // outCond
554 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
555 {PC_OPCODE, NULL, NULL, 0, NULL,
568 0,0, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
574 0, // second literal operand
576 (PCC_REL_ADDR | PCC_Z), // inCond
577 PCC_NONE , // outCond
581 pCodeInstruction pic16_pciBOV = { // mdubuc - New
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 0,0, // dest, bit instruction
597 0, // literal operand
599 0, // fast call/return mode select bit
600 0, // second memory operand
601 0, // second literal operand
603 (PCC_REL_ADDR | PCC_OV), // inCond
604 PCC_NONE , // outCond
608 pCodeInstruction pic16_pciBRA = { // mdubuc - New
609 {PC_OPCODE, NULL, NULL, 0, NULL,
622 0,0, // dest, bit instruction
624 0, // literal operand
626 0, // fast call/return mode select bit
627 0, // second memory operand
628 0, // second literal operand
630 PCC_REL_ADDR, // inCond
631 PCC_NONE , // outCond
635 pCodeInstruction pic16_pciBSF = {
636 {PC_OPCODE, NULL, NULL, 0, NULL,
649 1,1, // dest, bit instruction
651 0, // literal operand
653 0, // fast call/return mode select bit
654 0, // second memory operand
655 0, // second literal operand
657 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
658 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
662 pCodeInstruction pic16_pciBTFSC = {
663 {PC_OPCODE, NULL, NULL, 0, NULL,
676 0,1, // dest, bit instruction
678 0, // literal operand
680 0, // fast call/return mode select bit
681 0, // second memory operand
682 0, // second literal operand
684 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
685 PCC_EXAMINE_PCOP, // outCond
689 pCodeInstruction pic16_pciBTFSS = {
690 {PC_OPCODE, NULL, NULL, 0, NULL,
703 0,1, // dest, bit instruction
705 0, // literal operand
707 0, // fast call/return mode select bit
708 0, // second memory operand
709 0, // second literal operand
711 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
712 PCC_EXAMINE_PCOP, // outCond
716 pCodeInstruction pic16_pciBTG = { // mdubuc - New
717 {PC_OPCODE, NULL, NULL, 0, NULL,
730 0,1, // dest, bit instruction
732 0, // literal operand
734 0, // fast call/return mode select bit
735 0, // second memory operand
736 0, // second literal operand
738 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
739 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
743 pCodeInstruction pic16_pciBZ = { // mdubuc - New
744 {PC_OPCODE, NULL, NULL, 0, NULL,
757 0,0, // dest, bit instruction
759 0, // literal operand
761 0, // fast call/return mode select bit
762 0, // second memory operand
763 0, // second literal operand
770 pCodeInstruction pic16_pciCALL = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
786 0, // literal operand
788 1, // fast call/return mode select bit
789 0, // second memory operand
790 0, // second literal operand
793 PCC_NONE , // outCond
797 pCodeInstruction pic16_pciCOMF = {
798 {PC_OPCODE, NULL, NULL, 0, NULL,
811 1,0, // dest, bit instruction
813 0, // literal operand
815 0, // fast call/return mode select bit
816 0, // second memory operand
817 0, // second literal operand
819 PCC_REGISTER, // inCond
820 PCC_REGISTER , // outCond
824 pCodeInstruction pic16_pciCOMFW = {
825 {PC_OPCODE, NULL, NULL, 0, NULL,
838 0,0, // dest, bit instruction
840 0, // literal operand
842 0, // fast call/return mode select bit
843 0, // second memory operand
844 0, // second literal operand
846 PCC_REGISTER, // inCond
851 pCodeInstruction pic16_pciCLRF = {
852 {PC_OPCODE, NULL, NULL, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
869 0, // fast call/return mode select bit
870 0, // second memory operand
871 0, // second literal operand
873 PCC_REGISTER, // inCond
874 PCC_REGISTER , // outCond
878 pCodeInstruction pic16_pciCLRWDT = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
894 0, // literal operand
896 0, // fast call/return mode select bit
897 0, // second memory operand
898 0, // second literal operand
901 PCC_NONE , // outCond
905 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
906 {PC_OPCODE, NULL, NULL, 0, NULL,
919 0,0, // dest, bit instruction
921 0, // literal operand
923 0, // fast call/return mode select bit
924 0, // second memory operand
925 0, // second literal operand
927 (PCC_W | PCC_REGISTER), // inCond
928 PCC_NONE , // outCond
932 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
933 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
954 (PCC_W | PCC_REGISTER), // inCond
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 1,0, // dest, bit instruction
975 0, // literal operand
977 0, // fast call/return mode select bit
978 0, // second memory operand
979 0, // second literal operand
981 (PCC_W | PCC_REGISTER), // inCond
982 PCC_NONE , // outCond
986 pCodeInstruction pic16_pciDAW = {
987 {PC_OPCODE, NULL, NULL, 0, NULL,
1000 0,0, // dest, bit instruction
1001 0,0, // branch, skip
1002 0, // literal operand
1003 0, // RAM access bit
1004 0, // fast call/return mode select bit
1005 0, // second memory operand
1006 0, // second literal operand
1009 (PCC_W | PCC_C), // outCond
1013 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1014 {PC_OPCODE, NULL, NULL, 0, NULL,
1020 NULL, // from branch
1027 1,0, // dest, bit instruction
1028 1,1, // branch, skip
1029 0, // literal operand
1030 1, // RAM access bit
1031 0, // fast call/return mode select bit
1032 0, // second memory operand
1033 0, // second literal operand
1035 PCC_REGISTER, // inCond
1036 PCC_REGISTER , // outCond
1040 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1041 {PC_OPCODE, NULL, NULL, 0, NULL,
1047 NULL, // from branch
1054 0,0, // dest, bit instruction
1055 1,1, // branch, skip
1056 0, // literal operand
1057 1, // RAM access bit
1058 0, // fast call/return mode select bit
1059 0, // second memory operand
1060 0, // second literal operand
1062 PCC_REGISTER, // inCond
1067 pCodeInstruction pic16_pciDECF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1084 1, // RAM access bit
1085 0, // fast call/return mode select bit
1086 0, // second memory operand
1087 0, // second literal operand
1089 PCC_REGISTER, // inCond
1090 PCC_REGISTER , // outCond
1094 pCodeInstruction pic16_pciDECFW = {
1095 {PC_OPCODE, NULL, NULL, 0, NULL,
1101 NULL, // from branch
1108 0,0, // dest, bit instruction
1109 0,0, // branch, skip
1110 0, // literal operand
1111 1, // RAM access bit
1112 0, // fast call/return mode select bit
1113 0, // second memory operand
1114 0, // second literal operand
1116 PCC_REGISTER, // inCond
1121 pCodeInstruction pic16_pciDECFSZ = {
1122 {PC_OPCODE, NULL, NULL, 0, NULL,
1128 NULL, // from branch
1135 1,0, // dest, bit instruction
1136 1,1, // branch, skip
1137 0, // literal operand
1138 1, // RAM access bit
1139 0, // fast call/return mode select bit
1140 0, // second memory operand
1141 0, // second literal operand
1143 PCC_REGISTER, // inCond
1144 PCC_REGISTER , // outCond
1148 pCodeInstruction pic16_pciDECFSZW = {
1149 {PC_OPCODE, NULL, NULL, 0, NULL,
1155 NULL, // from branch
1162 0,0, // dest, bit instruction
1163 1,1, // branch, skip
1164 0, // literal operand
1165 1, // RAM access bit
1166 0, // fast call/return mode select bit
1167 0, // second memory operand
1168 0, // second literal operand
1170 PCC_REGISTER, // inCond
1175 pCodeInstruction pic16_pciGOTO = {
1176 {PC_OPCODE, NULL, NULL, 0, NULL,
1182 NULL, // from branch
1189 0,0, // dest, bit instruction
1190 1,0, // branch, skip
1191 0, // literal operand
1192 0, // RAM access bit
1193 0, // fast call/return mode select bit
1194 0, // second memory operand
1195 0, // second literal operand
1197 PCC_REL_ADDR, // inCond
1198 PCC_NONE , // outCond
1202 pCodeInstruction pic16_pciINCF = {
1203 {PC_OPCODE, NULL, NULL, 0, NULL,
1209 NULL, // from branch
1216 1,0, // dest, bit instruction
1217 0,0, // branch, skip
1218 0, // literal operand
1219 1, // RAM access bit
1220 0, // fast call/return mode select bit
1221 0, // second memory operand
1222 0, // second literal operand
1224 PCC_REGISTER, // inCond
1225 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1229 pCodeInstruction pic16_pciINCFW = {
1230 {PC_OPCODE, NULL, NULL, 0, NULL,
1236 NULL, // from branch
1243 0,0, // dest, bit instruction
1244 0,0, // branch, skip
1245 0, // literal operand
1246 1, // RAM access bit
1247 0, // fast call/return mode select bit
1248 0, // second memory operand
1249 0, // second literal operand
1251 PCC_REGISTER, // inCond
1256 pCodeInstruction pic16_pciINCFSZ = {
1257 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 1,0, // dest, bit instruction
1271 1,1, // branch, skip
1272 0, // literal operand
1273 1, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1276 0, // second literal operand
1278 PCC_REGISTER, // inCond
1279 PCC_REGISTER , // outCond
1283 pCodeInstruction pic16_pciINCFSZW = {
1284 {PC_OPCODE, NULL, NULL, 0, NULL,
1290 NULL, // from branch
1297 0,0, // dest, bit instruction
1298 1,1, // branch, skip
1299 0, // literal operand
1300 1, // RAM access bit
1301 0, // fast call/return mode select bit
1302 0, // second memory operand
1303 0, // second literal operand
1305 PCC_REGISTER, // inCond
1310 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1311 {PC_OPCODE, NULL, NULL, 0, NULL,
1317 NULL, // from branch
1324 1,0, // dest, bit instruction
1325 1,1, // branch, skip
1326 0, // literal operand
1327 1, // RAM access bit
1328 0, // fast call/return mode select bit
1329 0, // second memory operand
1330 0, // second literal operand
1332 PCC_REGISTER, // inCond
1333 PCC_REGISTER , // outCond
1337 pCodeInstruction pic16_pciIORWF = {
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1344 NULL, // from branch
1351 1,0, // dest, bit instruction
1352 0,0, // branch, skip
1353 0, // literal operand
1354 1, // RAM access bit
1355 0, // fast call/return mode select bit
1356 0, // second memory operand
1357 0, // second literal operand
1359 (PCC_W | PCC_REGISTER), // inCond
1360 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1364 pCodeInstruction pic16_pciIORFW = {
1365 {PC_OPCODE, NULL, NULL, 0, NULL,
1371 NULL, // from branch
1378 0,0, // dest, bit instruction
1379 0,0, // branch, skip
1380 0, // literal operand
1381 1, // RAM access bit
1382 0, // fast call/return mode select bit
1383 0, // second memory operand
1384 0, // second literal operand
1386 (PCC_W | PCC_REGISTER), // inCond
1387 (PCC_W | PCC_Z | PCC_N), // outCond
1391 pCodeInstruction pic16_pciIORLW = {
1392 {PC_OPCODE, NULL, NULL, 0, NULL,
1398 NULL, // from branch
1405 0,0, // dest, bit instruction
1406 0,0, // branch, skip
1407 1, // literal operand
1408 0, // RAM access bit
1409 0, // fast call/return mode select bit
1410 0, // second memory operand
1411 0, // second literal operand
1413 (PCC_W | PCC_LITERAL), // inCond
1414 (PCC_W | PCC_Z | PCC_N), // outCond
1418 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1419 {PC_OPCODE, NULL, NULL, 0, NULL,
1425 NULL, // from branch
1432 0,0, // dest, bit instruction
1433 0,0, // branch, skip
1434 1, // literal operand
1435 0, // RAM access bit
1436 0, // fast call/return mode select bit
1437 0, // second memory operand
1438 1, // second literal operand
1440 (PCC_REGISTER | PCC_LITERAL),
1441 PCC_REGISTER, // outCond
1445 pCodeInstruction pic16_pciMOVF = {
1446 {PC_OPCODE, NULL, NULL, 0, NULL,
1452 NULL, // from branch
1459 1,0, // dest, bit instruction
1460 0,0, // branch, skip
1461 0, // literal operand
1462 1, // RAM access bit
1463 0, // fast call/return mode select bit
1464 0, // second memory operand
1465 0, // second literal operand
1467 PCC_REGISTER, // inCond
1468 (PCC_Z | PCC_N), // outCond
1472 pCodeInstruction pic16_pciMOVFW = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1479 NULL, // from branch
1486 0,0, // dest, bit instruction
1487 0,0, // branch, skip
1488 0, // literal operand
1489 1, // RAM access bit
1490 0, // fast call/return mode select bit
1491 0, // second memory operand
1492 0, // second literal operand
1494 PCC_REGISTER, // inCond
1495 (PCC_W | PCC_Z), // outCond
1499 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1500 {PC_OPCODE, NULL, NULL, 0, NULL,
1506 NULL, // from branch
1513 0,0, // dest, bit instruction
1514 0,0, // branch, skip
1515 0, // literal operand
1516 0, // RAM access bit
1517 0, // fast call/return mode select bit
1518 1, // second memory operand
1519 0, // second literal operand
1521 PCC_REGISTER, // inCond
1522 PCC_REGISTER2, // outCond
1526 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1532 NULL, // from branch
1539 0,0, // dest, bit instruction
1540 0,0, // branch, skip
1541 1, // literal operand
1542 0, // RAM access bit
1543 0, // fast call/return mode select bit
1544 0, // second memory operand
1545 0, // second literal operand
1547 (PCC_NONE | PCC_LITERAL), // inCond
1548 PCC_REGISTER, // outCond - BSR
1552 pCodeInstruction pic16_pciMOVLW = {
1553 {PC_OPCODE, NULL, NULL, 0, NULL,
1558 NULL, // from branch
1565 0,0, // dest, bit instruction
1566 0,0, // branch, skip
1567 1, // literal operand
1568 0, // RAM access bit
1569 0, // fast call/return mode select bit
1570 0, // second memory operand
1571 0, // second literal operand
1573 (PCC_NONE | PCC_LITERAL), // inCond
1578 pCodeInstruction pic16_pciMOVWF = {
1579 {PC_OPCODE, NULL, NULL, 0, NULL,
1585 NULL, // from branch
1592 0,0, // dest, bit instruction
1593 0,0, // branch, skip
1594 0, // literal operand
1595 1, // RAM access bit
1596 0, // fast call/return mode select bit
1597 0, // second memory operand
1598 0, // second literal operand
1600 PCC_REGISTER, // inCond
1605 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1606 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 1, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 0, // second memory operand
1624 0, // second literal operand
1626 (PCC_W | PCC_LITERAL), // inCond
1627 PCC_REGISTER, // outCond - PROD
1631 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1637 NULL, // from branch
1644 0,0, // dest, bit instruction
1645 0,0, // branch, skip
1646 0, // literal operand
1647 1, // RAM access bit
1648 0, // fast call/return mode select bit
1649 0, // second memory operand
1650 0, // second literal operand
1652 (PCC_W | PCC_REGISTER), // inCond
1653 PCC_REGISTER, // outCond - PROD
1657 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1658 {PC_OPCODE, NULL, NULL, 0, NULL,
1663 NULL, // from branch
1670 0,0, // dest, bit instruction
1671 0,0, // branch, skip
1672 0, // literal operand
1673 1, // RAM access bit
1674 0, // fast call/return mode select bit
1675 0, // second memory operand
1676 0, // second literal operand
1678 PCC_REGISTER, // inCond
1679 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1683 pCodeInstruction pic16_pciNOP = {
1684 {PC_OPCODE, NULL, NULL, 0, NULL,
1689 NULL, // from branch
1696 0,0, // dest, bit instruction
1697 0,0, // branch, skip
1698 0, // literal operand
1699 0, // RAM access bit
1700 0, // fast call/return mode select bit
1701 0, // second memory operand
1702 0, // second literal operand
1705 PCC_NONE, // outCond
1709 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1710 {PC_OPCODE, NULL, NULL, 0, NULL,
1715 NULL, // from branch
1722 0,0, // dest, bit instruction
1723 0,0, // branch, skip
1724 0, // literal operand
1725 0, // RAM access bit
1726 0, // fast call/return mode select bit
1727 0, // second memory operand
1728 0, // second literal operand
1731 PCC_NONE , // outCond
1735 pCodeInstruction pic16_pciPUSH = {
1736 {PC_OPCODE, NULL, NULL, 0, NULL,
1741 NULL, // from branch
1748 0,0, // dest, bit instruction
1749 0,0, // branch, skip
1750 0, // literal operand
1751 0, // RAM access bit
1752 0, // fast call/return mode select bit
1753 0, // second memory operand
1754 0, // second literal operand
1757 PCC_NONE , // outCond
1761 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1762 {PC_OPCODE, NULL, NULL, 0, NULL,
1767 NULL, // from branch
1774 0,0, // dest, bit instruction
1775 0,0, // branch, skip
1776 0, // literal operand
1777 0, // RAM access bit
1778 0, // fast call/return mode select bit
1779 0, // second memory operand
1780 0, // second literal operand
1782 PCC_REL_ADDR, // inCond
1783 PCC_NONE , // outCond
1787 pCodeInstruction pic16_pciRETFIE = {
1788 {PC_OPCODE, NULL, NULL, 0, NULL,
1794 NULL, // from branch
1801 0,0, // dest, bit instruction
1802 1,0, // branch, skip
1803 0, // literal operand
1804 0, // RAM access bit
1805 1, // fast call/return mode select bit
1806 0, // second memory operand
1807 0, // second literal operand
1810 PCC_NONE, // outCond (not true... affects the GIE bit too)
1814 pCodeInstruction pic16_pciRETLW = {
1815 {PC_OPCODE, NULL, NULL, 0, NULL,
1821 NULL, // from branch
1828 0,0, // dest, bit instruction
1829 1,0, // branch, skip
1830 1, // literal operand
1831 0, // RAM access bit
1832 0, // fast call/return mode select bit
1833 0, // second memory operand
1834 0, // second literal operand
1836 PCC_LITERAL, // inCond
1841 pCodeInstruction pic16_pciRETURN = {
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 0,0, // dest, bit instruction
1856 1,0, // branch, skip
1857 0, // literal operand
1858 0, // RAM access bit
1859 1, // fast call/return mode select bit
1860 0, // second memory operand
1861 0, // second literal operand
1864 PCC_NONE, // outCond
1867 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1868 {PC_OPCODE, NULL, NULL, 0, NULL,
1874 NULL, // from branch
1881 1,0, // dest, bit instruction
1882 0,0, // branch, skip
1883 0, // literal operand
1884 1, // RAM access bit
1885 0, // fast call/return mode select bit
1886 0, // second memory operand
1887 0, // second literal operand
1889 (PCC_C | PCC_REGISTER), // inCond
1890 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1894 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1895 {PC_OPCODE, NULL, NULL, 0, NULL,
1901 NULL, // from branch
1908 0,0, // dest, bit instruction
1909 0,0, // branch, skip
1910 0, // literal operand
1911 1, // RAM access bit
1912 0, // fast call/return mode select bit
1913 0, // second memory operand
1914 0, // second literal operand
1916 (PCC_C | PCC_REGISTER), // inCond
1917 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1921 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1922 {PC_OPCODE, NULL, NULL, 0, NULL,
1928 NULL, // from branch
1935 1,0, // dest, bit instruction
1936 0,0, // branch, skip
1937 0, // literal operand
1938 1, // RAM access bit
1939 0, // fast call/return mode select bit
1940 0, // second memory operand
1941 0, // second literal operand
1943 PCC_REGISTER, // inCond
1944 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1947 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1948 {PC_OPCODE, NULL, NULL, 0, NULL,
1954 NULL, // from branch
1961 0,0, // dest, bit instruction
1962 0,0, // branch, skip
1963 0, // literal operand
1964 1, // RAM access bit
1965 0, // fast call/return mode select bit
1966 0, // second memory operand
1967 0, // second literal operand
1969 PCC_REGISTER, // inCond
1970 (PCC_W | PCC_Z | PCC_N), // outCond
1973 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1974 {PC_OPCODE, NULL, NULL, 0, NULL,
1980 NULL, // from branch
1987 1,0, // dest, bit instruction
1988 0,0, // branch, skip
1989 0, // literal operand
1990 1, // RAM access bit
1991 0, // fast call/return mode select bit
1992 0, // second memory operand
1993 0, // second literal operand
1995 (PCC_C | PCC_REGISTER), // inCond
1996 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1999 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2000 {PC_OPCODE, NULL, NULL, 0, NULL,
2006 NULL, // from branch
2013 0,0, // dest, bit instruction
2014 0,0, // branch, skip
2015 0, // literal operand
2016 1, // RAM access bit
2017 0, // fast call/return mode select bit
2018 0, // second memory operand
2019 0, // second literal operand
2021 (PCC_C | PCC_REGISTER), // inCond
2022 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2025 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2026 {PC_OPCODE, NULL, NULL, 0, NULL,
2032 NULL, // from branch
2039 1,0, // dest, bit instruction
2040 0,0, // branch, skip
2041 0, // literal operand
2042 1, // RAM access bit
2043 0, // fast call/return mode select bit
2044 0, // second memory operand
2045 0, // second literal operand
2047 PCC_REGISTER, // inCond
2048 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2052 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2053 {PC_OPCODE, NULL, NULL, 0, NULL,
2059 NULL, // from branch
2066 0,0, // dest, bit instruction
2067 0,0, // branch, skip
2068 0, // literal operand
2069 1, // RAM access bit
2070 0, // fast call/return mode select bit
2071 0, // second memory operand
2072 0, // second literal operand
2074 PCC_REGISTER, // inCond
2075 (PCC_W | PCC_Z | PCC_N), // outCond
2079 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2080 {PC_OPCODE, NULL, NULL, 0, NULL,
2086 NULL, // from branch
2093 0,0, // dest, bit instruction
2094 0,0, // branch, skip
2095 0, // literal operand
2096 1, // RAM access bit
2097 0, // fast call/return mode select bit
2098 0, // second memory operand
2099 0, // second literal operand
2101 PCC_REGISTER, // inCond
2102 PCC_REGISTER , // outCond
2106 pCodeInstruction pic16_pciSUBLW = {
2107 {PC_OPCODE, NULL, NULL, 0, NULL,
2113 NULL, // from branch
2120 0,0, // dest, bit instruction
2121 0,0, // branch, skip
2122 1, // literal operand
2123 0, // RAM access bit
2124 0, // fast call/return mode select bit
2125 0, // second memory operand
2126 0, // second literal operand
2128 (PCC_W | PCC_LITERAL), // inCond
2129 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2133 pCodeInstruction pic16_pciSUBFWB = {
2134 {PC_OPCODE, NULL, NULL, 0, NULL,
2140 NULL, // from branch
2147 1,0, // dest, bit instruction
2148 0,0, // branch, skip
2149 0, // literal operand
2150 1, // RAM access bit
2151 0, // fast call/return mode select bit
2152 0, // second memory operand
2153 0, // second literal operand
2155 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2156 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2160 pCodeInstruction pic16_pciSUBWF = {
2161 {PC_OPCODE, NULL, NULL, 0, NULL,
2167 NULL, // from branch
2174 1,0, // dest, bit instruction
2175 0,0, // branch, skip
2176 0, // literal operand
2177 1, // RAM access bit
2178 0, // fast call/return mode select bit
2179 0, // second memory operand
2180 0, // second literal operand
2182 (PCC_W | PCC_REGISTER), // inCond
2183 (PCC_REGISTER | PCC_Z), // outCond
2187 pCodeInstruction pic16_pciSUBFW = {
2188 {PC_OPCODE, NULL, NULL, 0, NULL,
2194 NULL, // from branch
2201 0,0, // dest, bit instruction
2202 0,0, // branch, skip
2203 0, // literal operand
2204 1, // RAM access bit
2205 0, // fast call/return mode select bit
2206 0, // second memory operand
2207 0, // second literal operand
2209 (PCC_W | PCC_REGISTER), // inCond
2210 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2214 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2215 {PC_OPCODE, NULL, NULL, 0, NULL,
2221 NULL, // from branch
2228 1,0, // dest, bit instruction
2229 0,0, // branch, skip
2230 0, // literal operand
2231 1, // RAM access bit
2232 0, // fast call/return mode select bit
2233 0, // second memory operand
2234 0, // second literal operand
2236 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2237 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2241 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2242 {PC_OPCODE, NULL, NULL, 0, NULL,
2248 NULL, // from branch
2255 0,0, // dest, bit instruction
2256 0,0, // branch, skip
2257 0, // literal operand
2258 1, // RAM access bit
2259 0, // fast call/return mode select bit
2260 0, // second memory operand
2261 0, // second literal operand
2263 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2264 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2268 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2269 {PC_OPCODE, NULL, NULL, 0, NULL,
2275 NULL, // from branch
2282 1,0, // dest, bit instruction
2283 0,0, // branch, skip
2284 0, // literal operand
2285 1, // RAM access bit
2286 0, // fast call/return mode select bit
2287 0, // second memory operand
2288 0, // second literal operand
2290 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2291 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2295 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2296 {PC_OPCODE, NULL, NULL, 0, NULL,
2302 NULL, // from branch
2309 0,0, // dest, bit instruction
2310 0,0, // branch, skip
2311 0, // literal operand
2312 1, // RAM access bit
2313 0, // fast call/return mode select bit
2314 0, // second memory operand
2315 0, // second literal operand
2317 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2318 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2322 pCodeInstruction pic16_pciSWAPF = {
2323 {PC_OPCODE, NULL, NULL, 0, NULL,
2329 NULL, // from branch
2336 1,0, // dest, bit instruction
2337 0,0, // branch, skip
2338 0, // literal operand
2339 1, // RAM access bit
2340 0, // fast call/return mode select bit
2341 0, // second memory operand
2342 0, // second literal operand
2344 (PCC_REGISTER), // inCond
2345 (PCC_REGISTER), // outCond
2349 pCodeInstruction pic16_pciSWAPFW = {
2350 {PC_OPCODE, NULL, NULL, 0, NULL,
2356 NULL, // from branch
2363 0,0, // dest, bit instruction
2364 0,0, // branch, skip
2365 0, // literal operand
2366 1, // RAM access bit
2367 0, // fast call/return mode select bit
2368 0, // second memory operand
2369 0, // second literal operand
2371 (PCC_REGISTER), // inCond
2376 pCodeInstruction pic16_pciTBLRD = { // patch 15
2377 {PC_OPCODE, NULL, NULL, 0, NULL,
2382 NULL, // from branch
2389 0,0, // dest, bit instruction
2390 0,0, // branch, skip
2391 0, // literal operand
2392 0, // RAM access bit
2393 0, // fast call/return mode select bit
2394 0, // second memory operand
2395 0, // second literal operand
2398 PCC_NONE , // outCond
2402 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2403 {PC_OPCODE, NULL, NULL, 0, NULL,
2408 NULL, // from branch
2415 0,0, // dest, bit instruction
2416 0,0, // branch, skip
2417 0, // literal operand
2418 0, // RAM access bit
2419 0, // fast call/return mode select bit
2420 0, // second memory operand
2421 0, // second literal operand
2424 PCC_NONE , // outCond
2428 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2429 {PC_OPCODE, NULL, NULL, 0, NULL,
2434 NULL, // from branch
2441 0,0, // dest, bit instruction
2442 0,0, // branch, skip
2443 0, // literal operand
2444 0, // RAM access bit
2445 0, // fast call/return mode select bit
2446 0, // second memory operand
2447 0, // second literal operand
2450 PCC_NONE , // outCond
2454 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2455 {PC_OPCODE, NULL, NULL, 0, NULL,
2460 NULL, // from branch
2467 0,0, // dest, bit instruction
2468 0,0, // branch, skip
2469 0, // literal operand
2470 0, // RAM access bit
2471 0, // fast call/return mode select bit
2472 0, // second memory operand
2473 0, // second literal operand
2476 PCC_NONE , // outCond
2480 pCodeInstruction pic16_pciTBLWT = { // patch 15
2481 {PC_OPCODE, NULL, NULL, 0, NULL,
2486 NULL, // from branch
2493 0,0, // dest, bit instruction
2494 0,0, // branch, skip
2495 0, // literal operand
2496 0, // RAM access bit
2497 0, // fast call/return mode select bit
2498 0, // second memory operand
2499 0, // second literal operand
2502 PCC_NONE , // outCond
2506 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2507 {PC_OPCODE, NULL, NULL, 0, NULL,
2512 NULL, // from branch
2519 0,0, // dest, bit instruction
2520 0,0, // branch, skip
2521 0, // literal operand
2522 0, // RAM access bit
2523 0, // fast call/return mode select bit
2524 0, // second memory operand
2525 0, // second literal operand
2528 PCC_NONE , // outCond
2532 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2533 {PC_OPCODE, NULL, NULL, 0, NULL,
2538 NULL, // from branch
2545 0,0, // dest, bit instruction
2546 0,0, // branch, skip
2547 0, // literal operand
2548 0, // RAM access bit
2549 0, // fast call/return mode select bit
2550 0, // second memory operand
2551 0, // second literal operand
2554 PCC_NONE , // outCond
2558 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2559 {PC_OPCODE, NULL, NULL, 0, NULL,
2564 NULL, // from branch
2571 0,0, // dest, bit instruction
2572 0,0, // branch, skip
2573 0, // literal operand
2574 0, // RAM access bit
2575 0, // fast call/return mode select bit
2576 0, // second memory operand
2577 0, // second literal operand
2580 PCC_NONE , // outCond
2584 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2585 {PC_OPCODE, NULL, NULL, 0, NULL,
2591 NULL, // from branch
2598 0,0, // dest, bit instruction
2599 1,1, // branch, skip
2600 0, // literal operand
2601 1, // RAM access bit
2602 0, // fast call/return mode select bit
2603 0, // second memory operand
2604 0, // second literal operand
2606 PCC_REGISTER, // inCond
2607 PCC_NONE, // outCond
2611 pCodeInstruction pic16_pciXORWF = {
2612 {PC_OPCODE, NULL, NULL, 0, NULL,
2618 NULL, // from branch
2625 1,0, // dest, bit instruction
2626 0,0, // branch, skip
2627 0, // literal operand
2628 1, // RAM access bit
2629 0, // fast call/return mode select bit
2630 0, // second memory operand
2631 0, // second literal operand
2633 (PCC_W | PCC_REGISTER), // inCond
2634 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2638 pCodeInstruction pic16_pciXORFW = {
2639 {PC_OPCODE, NULL, NULL, 0, NULL,
2645 NULL, // from branch
2652 0,0, // dest, bit instruction
2653 0,0, // branch, skip
2654 0, // literal operand
2655 1, // RAM access bit
2656 0, // fast call/return mode select bit
2657 0, // second memory operand
2658 0, // second literal operand
2660 (PCC_W | PCC_REGISTER), // inCond
2661 (PCC_W | PCC_Z | PCC_N), // outCond
2665 pCodeInstruction pic16_pciXORLW = {
2666 {PC_OPCODE, NULL, NULL, 0, NULL,
2672 NULL, // from branch
2679 0,0, // dest, bit instruction
2680 0,0, // branch, skip
2681 1, // literal operand
2682 1, // RAM access bit
2683 0, // fast call/return mode select bit
2684 0, // second memory operand
2685 0, // second literal operand
2687 (PCC_W | PCC_LITERAL), // inCond
2688 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2693 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 return ( (pCode *)pcf);
3513 /*-----------------------------------------------------------------*/
3514 /* pic16_newpCodeFlow */
3515 /*-----------------------------------------------------------------*/
3516 static void destructpCodeFlow(pCode *pc)
3518 if(!pc || !isPCFL(pc))
3525 pic16_unlinkpCode(pc);
3527 deleteSet(&PCFL(pc)->registers);
3528 deleteSet(&PCFL(pc)->from);
3529 deleteSet(&PCFL(pc)->to);
3534 pCode *pic16_newpCodeFlow(void )
3538 //_ALLOC(pcflow,sizeof(pCodeFlow));
3539 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3541 pcflow->pc.type = PC_FLOW;
3542 pcflow->pc.prev = pcflow->pc.next = NULL;
3543 pcflow->pc.pb = NULL;
3545 // pcflow->pc.analyze = genericAnalyze;
3546 pcflow->pc.destruct = destructpCodeFlow;
3547 pcflow->pc.print = genericPrint;
3549 pcflow->pc.seq = GpcFlowSeq++;
3551 pcflow->from = pcflow->to = NULL;
3553 pcflow->inCond = PCC_NONE;
3554 pcflow->outCond = PCC_NONE;
3556 pcflow->firstBank = -1;
3557 pcflow->lastBank = -1;
3559 pcflow->FromConflicts = 0;
3560 pcflow->ToConflicts = 0;
3564 pcflow->registers = newSet();
3566 return ( (pCode *)pcflow);
3570 /*-----------------------------------------------------------------*/
3571 /*-----------------------------------------------------------------*/
3572 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3574 pCodeFlowLink *pcflowLink;
3576 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3578 pcflowLink->pcflow = pcflow;
3579 pcflowLink->bank_conflict = 0;
3584 /*-----------------------------------------------------------------*/
3585 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3586 /*-----------------------------------------------------------------*/
3588 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3593 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3595 pccs->pc.type = PC_CSOURCE;
3596 pccs->pc.prev = pccs->pc.next = NULL;
3599 pccs->pc.destruct = genericDestruct;
3600 pccs->pc.print = genericPrint;
3602 pccs->line_number = ln;
3604 pccs->line = Safe_strdup(l);
3609 pccs->file_name = Safe_strdup(f);
3611 pccs->file_name = NULL;
3613 return ( (pCode *)pccs);
3618 /*******************************************************************/
3619 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3620 /* added by VR 6-Jun-2003 */
3621 /*******************************************************************/
3623 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3630 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3631 pcad->pci.pc.type = PC_ASMDIR;
3632 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3633 pcad->pci.pc.pb = NULL;
3635 pcad->pci.pc.destruct = genericDestruct;
3636 pcad->pci.pc.print = genericPrint;
3638 if(asdir && *asdir) {
3640 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3642 pcad->directive = Safe_strdup( asdir );
3645 va_start(ap, argfmt);
3647 memset(buffer, 0, sizeof(buffer));
3648 if(argfmt && *argfmt)
3649 vsprintf(buffer, argfmt, ap);
3653 while(isspace(*lbp))lbp++;
3656 pcad->arg = Safe_strdup( lbp );
3658 return ((pCode *)pcad);
3661 /*-----------------------------------------------------------------*/
3662 /* pCodeLabelDestruct - free memory used by a label. */
3663 /*-----------------------------------------------------------------*/
3664 static void pCodeLabelDestruct(pCode *pc)
3670 if((pc->type == PC_LABEL) && PCL(pc)->label)
3671 free(PCL(pc)->label);
3677 pCode *pic16_newpCodeLabel(char *name, int key)
3683 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3685 pcl->pc.type = PC_LABEL;
3686 pcl->pc.prev = pcl->pc.next = NULL;
3687 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3690 // pcl->pc.analyze = genericAnalyze;
3691 pcl->pc.destruct = pCodeLabelDestruct;
3692 pcl->pc.print = pCodePrintLabel;
3699 sprintf(s,"_%05d_DS_",key);
3704 pcl->label = Safe_strdup(s);
3706 // if(pic16_pcode_verbose)
3707 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3710 return ( (pCode *)pcl);
3714 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3716 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3720 return ( (pCode *)pcl );
3724 /*-----------------------------------------------------------------*/
3725 /* newpBlock - create and return a pointer to a new pBlock */
3726 /*-----------------------------------------------------------------*/
3727 static pBlock *newpBlock(void)
3732 PpB = Safe_calloc(1,sizeof(pBlock) );
3733 PpB->next = PpB->prev = NULL;
3735 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3736 PpB->tregisters = NULL;
3738 PpB->FlowTree = NULL;
3744 /*-----------------------------------------------------------------*/
3745 /* pic16_newpCodeChain - create a new chain of pCodes */
3746 /*-----------------------------------------------------------------*
3748 * This function will create a new pBlock and the pointer to the
3749 * pCode that is passed in will be the first pCode in the block.
3750 *-----------------------------------------------------------------*/
3753 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3756 pBlock *pB = newpBlock();
3758 pB->pcHead = pB->pcTail = pc;
3765 /*-----------------------------------------------------------------*/
3766 /* pic16_newpCodeOpLabel - Create a new label given the key */
3767 /* Note, a negative key means that the label is part of wild card */
3768 /* (and hence a wild card label) used in the pCodePeep */
3769 /* optimizations). */
3770 /*-----------------------------------------------------------------*/
3772 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3775 static int label_key=-1;
3779 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3780 pcop->type = PO_LABEL;
3785 sprintf(s=buffer,"_%05d_DS_",key);
3787 s = name, key = label_key--;
3790 pcop->name = Safe_strdup(s);
3792 ((pCodeOpLabel *)pcop)->key = key;
3794 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3798 /*-----------------------------------------------------------------*/
3799 /*-----------------------------------------------------------------*/
3800 pCodeOp *pic16_newpCodeOpLit(int lit)
3806 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3807 pcop->type = PO_LITERAL;
3811 sprintf(s,"0x%02x",lit);
3813 pcop->name = Safe_strdup(s);
3816 ((pCodeOpLit *)pcop)->lit = lit;
3821 /*-----------------------------------------------------------------*/
3822 /*-----------------------------------------------------------------*/
3823 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3825 char *s = buffer, tbuf[256], *tb=tbuf;
3829 tb = pic16_get_op(arg2, NULL, 0);
3830 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3831 pcop->type = PO_LITERAL;
3835 sprintf(s,"0x%02x, %s",lit, tb);
3837 pcop->name = Safe_strdup(s);
3840 ((pCodeOpLit2 *)pcop)->lit = lit;
3841 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3846 /*-----------------------------------------------------------------*/
3847 /*-----------------------------------------------------------------*/
3848 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3852 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3853 pcop->type = PO_IMMEDIATE;
3855 regs *r = pic16_dirregWithName(name);
3856 pcop->name = Safe_strdup(name);
3860 // fprintf(stderr, "%s:%d %s reg %s exists\n",__FILE__, __LINE__, __FUNCTION__, name);
3861 PCOI(pcop)->rIdx = r->rIdx;
3863 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n",
3864 // __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 = 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)
5265 if((pc->type == PC_OPCODE)
5266 || (pc->type == PC_WILD)
5267 || (pc->type == PC_ASMDIR)
5273 fprintf(stderr,"pic16_findPrevInstruction: ");
5274 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 if(PCOI(PCI(pc)->pcop)->r)
5373 return (PCOI(PCI(pc)->pcop)->r);
5376 return PCOR(PCI(pc)->pcop)->r;
5379 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5380 return PCOR(PCI(pc)->pcop)->r;
5383 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5387 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5388 // genericPrint(stderr, pc);
5396 /*-------------------------------------------------------------------------------*/
5397 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5398 /*-------------------------------------------------------------------------------*/
5399 regs * pic16_getRegFromInstruction2(pCode *pc)
5405 PCI(pc)->num_ops == 0 ||
5406 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5411 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5412 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5416 * operands supported in MOVFF:
5423 switch(PCI(pc)->pcop->type) {
5429 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5431 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5435 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5436 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5441 // if(PCOI(PCI(pc)->pcop)->r)
5442 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5444 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5445 return pic16_dirregWithName(PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5446 //return NULL; // PCOR(PCI(pc)->pcop)->r;
5451 // return PCOR2(PCI(pc)->pcop)->r;
5454 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5455 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5459 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5462 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5463 //genericPrint(stderr, pc);
5471 /*-----------------------------------------------------------------*/
5472 /*-----------------------------------------------------------------*/
5474 static void AnalyzepBlock(pBlock *pb)
5481 /* Find all of the registers used in this pBlock
5482 * by looking at each instruction and examining it's
5485 for(pc = pb->pcHead; pc; pc = pc->next) {
5487 /* Is this an instruction with operands? */
5488 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5490 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5492 /* Loop through all of the registers declared so far in
5493 this block and see if we find this one there */
5495 regs *r = setFirstItem(pb->tregisters);
5498 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5499 PCOR(PCI(pc)->pcop)->r = r;
5502 r = setNextItem(pb->tregisters);
5506 /* register wasn't found */
5507 //r = Safe_calloc(1, sizeof(regs));
5508 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5509 //addSet(&pb->tregisters, r);
5510 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5511 //PCOR(PCI(pc)->pcop)->r = r;
5512 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5514 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5517 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5518 if(PCOR(PCI(pc)->pcop)->r) {
5519 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5520 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5522 if(PCI(pc)->pcop->name)
5523 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5525 fprintf(stderr,"ERROR: NULL register\n");
5534 /*-----------------------------------------------------------------*/
5536 /*-----------------------------------------------------------------*/
5537 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5539 static void InsertpFlow(pCode *pc, pCode **pflow)
5542 PCFL(*pflow)->end = pc;
5544 if(!pc || !pc->next)
5547 *pflow = pic16_newpCodeFlow();
5548 pic16_pCodeInsertAfter(pc, *pflow);
5551 /*-----------------------------------------------------------------*/
5552 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5553 /* the flow blocks. */
5555 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5556 * point the instruction flow changes.
5558 /*-----------------------------------------------------------------*/
5559 void pic16_BuildFlow(pBlock *pb)
5562 pCode *last_pci=NULL;
5569 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5570 /* Insert a pCodeFlow object at the beginning of a pBlock */
5572 InsertpFlow(pb->pcHead, &pflow);
5574 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5575 //pflow->next = pb->pcHead; /* Make the current head the next object */
5576 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5577 //pb->pcHead = pflow; /* Make the Flow object the head */
5580 for( pc = pic16_findNextInstruction(pb->pcHead);
5582 pc=pic16_findNextInstruction(pc)) {
5585 PCI(pc)->pcflow = PCFL(pflow);
5587 //fprintf(stderr," build: ");
5588 //pflow->print(stderr,pflow);
5590 if( PCI(pc)->isSkip) {
5592 /* The two instructions immediately following this one
5593 * mark the beginning of a new flow segment */
5595 while(pc && PCI(pc)->isSkip) {
5597 PCI(pc)->pcflow = PCFL(pflow);
5601 InsertpFlow(pc, &pflow);
5602 pc=pic16_findNextInstruction(pc->next);
5610 PCI(pc)->pcflow = PCFL(pflow);
5612 InsertpFlow(pc, &pflow);
5614 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5616 InsertpFlow(pc, &pflow);
5619 } else if (checkLabel(pc)) {
5621 /* This instruction marks the beginning of a
5622 * new flow segment */
5627 /* If the previous pCode is not a flow object, then
5628 * insert a new flow object. (This check prevents
5629 * two consecutive flow objects from being insert in
5630 * the case where a skip instruction preceeds an
5631 * instruction containing a label.) */
5633 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5634 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5636 PCI(pc)->pcflow = PCFL(pflow);
5643 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5645 PCFL(pflow)->end = pb->pcTail;
5648 /*-------------------------------------------------------------------*/
5649 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5650 /* the flow blocks. */
5652 * unBuildFlow removes pCodeFlow objects from a pCode chain
5654 /*-----------------------------------------------------------------*/
5655 static void unBuildFlow(pBlock *pb)
5670 if(PCI(pc)->pcflow) {
5671 //free(PCI(pc)->pcflow);
5672 PCI(pc)->pcflow = NULL;
5675 } else if(isPCFL(pc) )
5684 /*-----------------------------------------------------------------*/
5685 /*-----------------------------------------------------------------*/
5686 static void dumpCond(int cond)
5689 static char *pcc_str[] = {
5704 int ncond = sizeof(pcc_str) / sizeof(char *);
5707 fprintf(stderr, "0x%04X\n",cond);
5709 for(i=0,j=1; i<ncond; i++, j<<=1)
5711 fprintf(stderr, " %s\n",pcc_str[i]);
5717 /*-----------------------------------------------------------------*/
5718 /*-----------------------------------------------------------------*/
5719 static void FlowStats(pCodeFlow *pcflow)
5727 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5729 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5732 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5737 fprintf(stderr, " FlowStats inCond: ");
5738 dumpCond(pcflow->inCond);
5739 fprintf(stderr, " FlowStats outCond: ");
5740 dumpCond(pcflow->outCond);
5744 /*-----------------------------------------------------------------*
5745 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5746 * if it affects the banking bits.
5748 * return: -1 == Banking bits are unaffected by this pCode.
5750 * return: > 0 == Banking bits are affected.
5752 * If the banking bits are affected, then the returned value describes
5753 * which bits are affected and how they're affected. The lower half
5754 * of the integer maps to the bits that are affected, the upper half
5755 * to whether they're set or cleared.
5757 *-----------------------------------------------------------------*/
5759 static int isBankInstruction(pCode *pc)
5767 if( PCI(pc)->op == POC_MOVLB ||
5768 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5769 bank = PCOL(pc)->lit;
5776 /*-----------------------------------------------------------------*/
5777 /*-----------------------------------------------------------------*/
5778 static void FillFlow(pCodeFlow *pcflow)
5787 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5789 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5792 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5799 isBankInstruction(pc);
5801 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5805 fprintf(stderr, " FillFlow - Bad end of flow\n");
5807 fprintf(stderr, " FillFlow - Ending flow with\n ");
5808 pc->print(stderr,pc);
5811 fprintf(stderr, " FillFlow inCond: ");
5812 dumpCond(pcflow->inCond);
5813 fprintf(stderr, " FillFlow outCond: ");
5814 dumpCond(pcflow->outCond);
5818 /*-----------------------------------------------------------------*/
5819 /*-----------------------------------------------------------------*/
5820 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5822 pCodeFlowLink *fromLink, *toLink;
5824 if(!from || !to || !to->pcflow || !from->pcflow)
5827 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5828 toLink = pic16_newpCodeFlowLink(to->pcflow);
5830 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5831 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5835 /*-----------------------------------------------------------------*
5836 * void LinkFlow(pBlock *pb)
5838 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5839 * non-branching segments. In LinkFlow, we determine the execution
5840 * order of these segments. For example, if one of the segments ends
5841 * with a skip, then we know that there are two possible flow segments
5842 * to which control may be passed.
5843 *-----------------------------------------------------------------*/
5844 static void LinkFlow(pBlock *pb)
5850 //fprintf(stderr,"linkflow \n");
5852 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5854 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5857 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5859 //fprintf(stderr," link: ");
5860 //pcflow->print(stderr,pcflow);
5862 //FillFlow(PCFL(pcflow));
5864 pc = PCFL(pcflow)->end;
5866 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5867 if(isPCI_SKIP(pc)) {
5868 //fprintf(stderr, "ends with skip\n");
5869 //pc->print(stderr,pc);
5870 pct=pic16_findNextInstruction(pc->next);
5871 LinkFlow_pCode(PCI(pc),PCI(pct));
5872 pct=pic16_findNextInstruction(pct->next);
5873 LinkFlow_pCode(PCI(pc),PCI(pct));
5877 if(isPCI_BRANCH(pc)) {
5878 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5880 //fprintf(stderr, "ends with branch\n ");
5881 //pc->print(stderr,pc);
5883 if(!(pcol && isPCOLAB(pcol))) {
5884 if((PCI(pc)->op != POC_RETLW)
5885 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5887 /* continue if label is '$' which assembler knows how to parse */
5888 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5890 if(pic16_pcode_verbose) {
5891 pc->print(stderr,pc);
5892 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5898 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5899 LinkFlow_pCode(PCI(pc),PCI(pct));
5901 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5902 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5904 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5910 //fprintf(stderr, "ends with non-branching instruction:\n");
5911 //pc->print(stderr,pc);
5913 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5919 //fprintf(stderr, "ends with unknown\n");
5920 //pc->print(stderr,pc);
5924 //fprintf(stderr, "ends with nothing: ERROR\n");
5928 /*-----------------------------------------------------------------*/
5929 /*-----------------------------------------------------------------*/
5931 /*-----------------------------------------------------------------*/
5932 /*-----------------------------------------------------------------*/
5933 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5939 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5942 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5952 /*-----------------------------------------------------------------*/
5953 /* insertBankSwitch - inserts a bank switch statement in the */
5954 /* assembly listing */
5956 /* position == 0: insert before */
5957 /* position == 1: insert after pc */
5958 /* position == 2: like 0 but previous was a skip instruction */
5959 /*-----------------------------------------------------------------*/
5960 pCodeOp *pic16_popGetLabel(unsigned int key);
5961 extern int pic16_labelOffset;
5963 static void insertBankSwitch(int position, pCode *pc)
5971 /* emit BANKSEL [symbol] */
5973 reg = pic16_getRegFromInstruction(pc);
5975 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))return;
5977 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
5979 // position = 0; // position is always before (sanity check!)
5982 fprintf(stderr, "%s:%d: inserting bank switch\n", __FUNCTION__, __LINE__);
5983 pc->print(stderr, pc);
5988 /* insert the bank switch after this pc instruction */
5989 pCode *pcnext = pic16_findNextInstruction(pc);
5991 pic16_pCodeInsertAfter(pc, new_pc);
5992 if(pcnext)pc = pcnext;
5996 /* insert the bank switch BEFORE this pc instruction */
5997 pic16_pCodeInsertAfter(pc->prev, new_pc);
6001 /* just like 0, but previous was a skip instruction,
6002 * so some care should be taken */
6004 pCode *pcnext, *pcprev, *npci;;
6007 pic16_labelOffset += 10000;
6008 tlbl = newiTempLabel(NULL);
6010 /* invert skip instruction */
6011 pcprev = pic16_findPrevInstruction(pc);
6012 ipci = PCI(pcprev)->inverted_op;
6013 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6016 PCI(npci)->from = PCI(pcprev)->from;
6017 PCI(npci)->to = PCI(pcprev)->to;
6018 PCI(npci)->label = PCI(pcprev)->label;
6019 PCI(npci)->pcflow = PCI(pcprev)->pcflow;
6020 PCI(npci)->cline = PCI(pcprev)->cline;
6023 // memmove(PCI(pcprev), PCI(npci), sizeof(pCode) + sizeof(PIC_OPCODE) + sizeof(char const * const));
6026 pic16_pCodeInsertAfter(pcprev->prev, npci);
6027 /* unlink the pCode */
6028 pcprev->prev->next = pcprev->next;
6029 pcprev->next->prev = pcprev->prev;
6032 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6033 pic16_pCodeInsertAfter(pc->prev, pcnext);
6034 pic16_pCodeInsertAfter(pc->prev, new_pc);
6036 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6037 pic16_pCodeInsertAfter(pc, pcnext);
6042 /* Move the label, if there is one */
6043 if(PCI(pc)->label) {
6044 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6045 // __FILE__, __LINE__, pc, new_pc);
6046 PCAD(new_pc)->pci.label = PCI(pc)->label;
6047 PCI(pc)->label = NULL;
6052 /*-----------------------------------------------------------------*/
6053 /*int compareBankFlow - compare the banking requirements between */
6055 /*-----------------------------------------------------------------*/
6056 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6059 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6062 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6065 if(pcflow->firstBank == -1)
6069 if(pcflowLink->pcflow->firstBank == -1) {
6070 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6071 pcflowLink->pcflow->to :
6072 pcflowLink->pcflow->from);
6073 return compareBankFlow(pcflow, pctl, toORfrom);
6077 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6080 pcflowLink->bank_conflict++;
6081 pcflowLink->pcflow->FromConflicts++;
6082 pcflow->ToConflicts++;
6085 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6088 pcflowLink->bank_conflict++;
6089 pcflowLink->pcflow->ToConflicts++;
6090 pcflow->FromConflicts++;
6094 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6095 pcflowLink->pcflow->pc.seq,
6096 pcflowLink->pcflow->FromConflicts,
6097 pcflowLink->pcflow->ToConflicts);
6104 /*-----------------------------------------------------------------*/
6105 /*-----------------------------------------------------------------*/
6106 static void DumpFlow(pBlock *pb)
6110 pCodeFlowLink *pcfl;
6113 fprintf(stderr,"Dump flow \n");
6114 pb->pcHead->print(stderr, pb->pcHead);
6116 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6117 pcflow->print(stderr,pcflow);
6119 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6121 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6123 if(!isPCFL(pcflow)) {
6124 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6127 fprintf(stderr,"dumping: ");
6128 pcflow->print(stderr,pcflow);
6129 FlowStats(PCFL(pcflow));
6131 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6133 pc = PCODE(pcfl->pcflow);
6135 fprintf(stderr, " from seq %d:\n",pc->seq);
6137 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6138 pc->print(stderr,pc);
6143 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6145 pc = PCODE(pcfl->pcflow);
6147 fprintf(stderr, " to seq %d:\n",pc->seq);
6149 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6150 pc->print(stderr,pc);
6159 /*-----------------------------------------------------------------*/
6160 /*-----------------------------------------------------------------*/
6161 static int OptimizepBlock(pBlock *pb)
6166 if(!pb || !peepOptimizing)
6169 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6171 for(pc = pb->pcHead; pc; pc = pc->next)
6172 matches += pic16_pCodePeepMatchRule(pc);
6175 pc = pic16_findNextInstruction(pb->pcHead);
6183 if(pic16_pCodePeepMatchRule(pc)) {
6188 pc = pic16_findNextInstruction(pcprev->next);
6190 pc = pic16_findNextInstruction(pb->pcHead);
6192 pc = pic16_findNextInstruction(pc->next);
6196 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6201 /*-----------------------------------------------------------------*/
6202 /*-----------------------------------------------------------------*/
6203 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6207 for(pc = pcs; pc; pc = pc->next) {
6209 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6211 (PCI(pc)->pcop->type == PO_LABEL) &&
6212 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6220 /*-----------------------------------------------------------------*/
6221 /*-----------------------------------------------------------------*/
6222 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6229 (PCI(pc)->pcop->type == PO_LABEL)) {
6231 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6233 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6235 free(pcol->pcop.name);
6237 /* If the key is negative, then we (probably) have a label to
6238 * a function and the name is already defined */
6241 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6245 //sprintf(buffer,"_%05d_DS_",pcl->key);
6247 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6249 pcol->pcop.name = Safe_strdup(s);
6250 pcol->key = pcl->key;
6251 //pc->print(stderr,pc);
6258 /*-----------------------------------------------------------------*/
6259 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6260 /* pCode chain if they're not used. */
6261 /*-----------------------------------------------------------------*/
6262 static void pBlockRemoveUnusedLabels(pBlock *pb)
6264 pCode *pc; pCodeLabel *pcl;
6269 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6271 pBranch *pbr = PCI(pc)->label;
6272 if(pbr && pbr->next) {
6273 pCode *pcd = pb->pcHead;
6275 // fprintf(stderr, "multiple labels\n");
6276 // pc->print(stderr,pc);
6281 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6282 //fprintf(stderr,"Used by:\n");
6283 //pcd->print(stderr,pcd);
6285 exchangeLabels(PCL(pbr->pc),pcd);
6294 for(pc = pb->pcHead; pc; pc = pc->next) {
6296 if(isPCL(pc)) // pc->type == PC_LABEL)
6298 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6299 pcl = PCL(PCI(pc)->label->pc);
6302 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6304 /* This pCode is a label, so search the pBlock to see if anyone
6307 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6309 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6310 /* Couldn't find an instruction that refers to this label
6311 * So, unlink the pCode label from it's pCode chain
6312 * and destroy the label */
6313 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6315 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6316 if(pc->type == PC_LABEL) {
6317 pic16_unlinkpCode(pc);
6318 pCodeLabelDestruct(pc);
6320 unlinkpCodeFromBranch(pc, PCODE(pcl));
6321 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6332 /*-----------------------------------------------------------------*/
6333 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6334 /* chain and put them into pBranches that are */
6335 /* associated with the appropriate pCode */
6337 /*-----------------------------------------------------------------*/
6338 void pic16_pBlockMergeLabels(pBlock *pb)
6341 pCode *pc, *pcnext=NULL;
6346 /* First, Try to remove any unused labels */
6347 //pBlockRemoveUnusedLabels(pb);
6349 /* Now loop through the pBlock and merge the labels with the opcodes */
6352 // for(pc = pb->pcHead; pc; pc = pc->next) {
6355 pCode *pcn = pc->next;
6357 if(pc->type == PC_LABEL) {
6359 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6360 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6362 if((pcnext = pic16_findNextInstruction(pc) )) {
6364 // pcnext->print(stderr, pcnext);
6366 // Unlink the pCode label from it's pCode chain
6367 pic16_unlinkpCode(pc);
6369 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6370 // And link it into the instruction's pBranch labels. (Note, since
6371 // it's possible to have multiple labels associated with one instruction
6372 // we must provide a means to accomodate the additional labels. Thus
6373 // the labels are placed into the singly-linked list "label" as
6374 // opposed to being a single member of the pCodeInstruction.)
6376 //_ALLOC(pbr,sizeof(pBranch));
6378 pbr = Safe_calloc(1,sizeof(pBranch));
6382 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6385 if(pic16_pcode_verbose)
6386 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6388 } else if(pc->type == PC_CSOURCE) {
6390 /* merge the source line symbolic info into the next instruction */
6391 if((pcnext = pic16_findNextInstruction(pc) )) {
6393 // Unlink the pCode label from it's pCode chain
6394 pic16_unlinkpCode(pc);
6395 PCI(pcnext)->cline = PCCS(pc);
6396 //fprintf(stderr, "merging CSRC\n");
6397 //genericPrint(stderr,pcnext);
6403 pBlockRemoveUnusedLabels(pb);
6407 /*-----------------------------------------------------------------*/
6408 /*-----------------------------------------------------------------*/
6409 static int OptimizepCode(char dbName)
6411 #define MAX_PASSES 4
6420 DFPRINTF((stderr," Optimizing pCode\n"));
6424 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6425 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6426 matches += OptimizepBlock(pb);
6429 while(matches && ++passes < MAX_PASSES);
6436 const char *pic16_pCodeOpType(pCodeOp *pcop);
6437 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6440 /*-----------------------------------------------------------------*/
6441 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6442 /*-----------------------------------------------------------------*/
6444 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6448 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6449 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6451 if( !( (pcop->type == PO_LABEL) ||
6452 (pcop->type == PO_LITERAL) ||
6453 (pcop->type == PO_STR) ))
6454 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6455 PCOR(pcop)->r->wasUsed = 1;
6461 /*----------------------------------------------------------------------*
6462 * pic16_areRegsSame - check to see if the names of two registers match *
6463 *----------------------------------------------------------------------*/
6464 int pic16_areRegsSame(regs *r1, regs *r2)
6466 if(!strcmp(r1->name, r2->name))return 1;
6472 /*-----------------------------------------------------------------*/
6473 /*-----------------------------------------------------------------*/
6474 static void pic16_FixRegisterBanking(pBlock *pb)
6478 regs *reg, *prevreg;
6484 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6487 /* loop through all of the flow blocks with in one pblock */
6489 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6493 /* at this point, pc should point to a PC_FLOW object */
6494 /* for each flow block, determine the register banking
6497 if(!isPCI(pc))goto loop;
6499 if(PCI(pc)->is2MemOp)goto loop;
6501 reg = pic16_getRegFromInstruction(pc);
6504 pc->print(stderr, pc);
6505 fprintf(stderr, "reg = %p\n", reg);
6508 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6509 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6510 reg->address,reg->isBitField, reg->isFixed);
6514 /* we can be 99% that within a pBlock, between two consequtive
6515 * refernces to the same register, the extra banksel is needless */
6518 /* now make some tests to make sure that instruction needs bank switch */
6520 /* if not no register exists, and if not a bit opcode goto loop */
6522 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6525 if(isPCI_SKIP(pc)) {
6526 // fprintf(stderr, "instruction is SKIP instruction\n");
6528 if((reg && isACCESS_BANK(reg)) || !isBankInstruction(pc))goto loop;
6530 if(isPCI_LIT(pc))goto loop;
6532 if(PCI(pc)->op == POC_CALL)goto loop;
6534 /* Examine the instruction before this one to make sure it is
6535 * not a skip type instruction */
6536 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6538 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6539 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6541 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6544 insertBankSwitch(flag, pc);
6547 // fprintf(stderr, "BANK SWITCH inserted\n");
6556 static void pBlockDestruct(pBlock *pb)
6567 /*-----------------------------------------------------------------*/
6568 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6569 /* name dbName and combine them */
6570 /* into one block */
6571 /*-----------------------------------------------------------------*/
6572 static void mergepBlocks(char dbName)
6575 pBlock *pb, *pbmerged = NULL,*pbn;
6577 pb = the_pFile->pbHead;
6579 //fprintf(stderr," merging blocks named %c\n",dbName);
6583 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6584 if( getpBlock_dbName(pb) == dbName) {
6586 //fprintf(stderr," merged block %c\n",dbName);
6591 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6592 /* pic16_addpCode2pBlock doesn't handle the tail: */
6593 pbmerged->pcTail = pb->pcTail;
6595 pb->prev->next = pbn;
6597 pbn->prev = pb->prev;
6602 //pic16_printpBlock(stderr, pbmerged);
6609 /*-----------------------------------------------------------------*/
6610 /* AnalyzeFlow - Examine the flow of the code and optimize */
6612 /* level 0 == minimal optimization */
6613 /* optimize registers that are used only by two instructions */
6614 /* level 1 == maximal optimization */
6615 /* optimize by looking at pairs of instructions that use the */
6617 /*-----------------------------------------------------------------*/
6619 static void AnalyzeFlow(int level)
6621 static int times_called=0;
6626 /* remove unused allocated registers before exiting */
6627 pic16_RemoveUnusedRegisters();
6633 /* if this is not the first time this function has been called,
6634 then clean up old flow information */
6635 if(times_called++) {
6636 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6639 pic16_RegsUnMapLiveRanges();
6644 /* Phase 2 - Flow Analysis - Register Banking
6646 * In this phase, the individual flow blocks are examined
6647 * and register banking is fixed.
6651 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6652 pic16_FixRegisterBanking(pb);
6655 /* Phase 2 - Flow Analysis
6657 * In this phase, the pCode is partition into pCodeFlow
6658 * blocks. The flow blocks mark the points where a continuous
6659 * stream of instructions changes flow (e.g. because of
6660 * a call or goto or whatever).
6663 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6664 pic16_BuildFlow(pb);
6667 /* Phase 2 - Flow Analysis - linking flow blocks
6669 * In this phase, the individual flow blocks are examined
6670 * to determine their order of excution.
6673 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6676 /* Phase 3 - Flow Analysis - Flow Tree
6678 * In this phase, the individual flow blocks are examined
6679 * to determine their order of execution.
6682 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6683 pic16_BuildFlowTree(pb);
6686 /* Phase x - Flow Analysis - Used Banks
6688 * In this phase, the individual flow blocks are examined
6689 * to determine the Register Banks they use
6693 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6698 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6699 pic16_pCodeRegMapLiveRanges(pb);
6701 pic16_RemoveUnusedRegisters();
6703 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6704 pic16_pCodeRegOptimizeRegUsage(level);
6712 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6717 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6719 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6720 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6721 pcflow = pcflow->next) {
6723 FillFlow(PCFL(pcflow));
6728 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6731 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6732 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6733 pcflow = pcflow->next) {
6735 FlowStats(PCFL(pcflow));
6741 /* VR -- no need to analyze banking in flow, but left here :
6742 * 1. because it may be used in the future for other purposes
6743 * 2. because if omitted we'll miss some optimization done here
6745 * Perhaps I should rename it to something else
6748 /*-----------------------------------------------------------------*/
6749 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6750 /* assigned to the registers. */
6752 /*-----------------------------------------------------------------*/
6754 void pic16_AnalyzeBanking(void)
6758 if(!pic16_picIsInitialized()) {
6759 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6760 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6761 fprintf(stderr,"support/scripts/inc2h.pl\n");
6762 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6764 /* I think it took a long long time to fix this bug! ;-) -- VR */
6770 /* Phase x - Flow Analysis - Used Banks
6772 * In this phase, the individual flow blocks are examined
6773 * to determine the Register Banks they use
6779 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6780 // BanksUsedFlow(pb);
6782 if(!the_pFile)return;
6785 if(!pic16_options.no_banksel) {
6786 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6787 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6788 pic16_FixRegisterBanking(pb);
6794 /*-----------------------------------------------------------------*/
6795 /* buildCallTree - Look at the flow and extract all of the calls. */
6796 /*-----------------------------------------------------------------*/
6797 static set *register_usage(pBlock *pb);
6799 static void buildCallTree(void )
6810 /* Now build the call tree.
6811 First we examine all of the pCodes for functions.
6812 Keep in mind that the function boundaries coincide
6813 with pBlock boundaries.
6815 The algorithm goes something like this:
6816 We have two nested loops. The outer loop iterates
6817 through all of the pBlocks/functions. The inner
6818 loop iterates through all of the pCodes for
6819 a given pBlock. When we begin iterating through
6820 a pBlock, the variable pc_fstart, pCode of the start
6821 of a function, is cleared. We then search for pCodes
6822 of type PC_FUNCTION. When one is encountered, we
6823 initialize pc_fstart to this and at the same time
6824 associate a new pBranch object that signifies a
6825 branch entry. If a return is found, then this signifies
6826 a function exit point. We'll link the pCodes of these
6827 returns to the matching pc_fstart.
6829 When we're done, a doubly linked list of pBranches
6830 will exist. The head of this list is stored in
6831 `the_pFile', which is the meta structure for all
6832 of the pCode. Look at the pic16_printCallTree function
6833 on how the pBranches are linked together.
6836 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6837 pCode *pc_fstart=NULL;
6838 for(pc = pb->pcHead; pc; pc = pc->next) {
6840 if (PCF(pc)->fname) {
6842 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6843 //fprintf(stderr," found main \n");
6844 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6848 pbr = Safe_calloc(1,sizeof(pBranch));
6849 pbr->pc = pc_fstart = pc;
6852 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6854 // Here's a better way of doing the same:
6855 addSet(&pb->function_entries, pc);
6858 // Found an exit point in a function, e.g. return
6859 // (Note, there may be more than one return per function)
6861 pBranchLink(PCF(pc_fstart), PCF(pc));
6863 addSet(&pb->function_exits, pc);
6865 } else if(isCALL(pc)) {
6866 addSet(&pb->function_calls,pc);
6873 /* This is not needed because currently all register used
6874 * by a function are stored in stack -- VR */
6876 /* Re-allocate the registers so that there are no collisions
6877 * between local variables when one function call another */
6880 // pic16_deallocateAllRegs();
6882 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6890 /*-----------------------------------------------------------------*/
6891 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6892 /* all of the logical connections. */
6894 /* Essentially what's done here is that the pCode flow is */
6896 /*-----------------------------------------------------------------*/
6898 void pic16_AnalyzepCode(char dbName)
6909 /* Phase 1 - Register allocation and peep hole optimization
6911 * The first part of the analysis is to determine the registers
6912 * that are used in the pCode. Once that is done, the peep rules
6913 * are applied to the code. We continue to loop until no more
6914 * peep rule optimizations are found (or until we exceed the
6915 * MAX_PASSES threshold).
6917 * When done, the required registers will be determined.
6923 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6924 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6926 /* First, merge the labels with the instructions */
6927 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6928 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6930 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6931 //fprintf(stderr," analyze and merging block %c\n",dbName);
6932 pic16_pBlockMergeLabels(pb);
6935 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6940 changes = OptimizepCode(dbName);
6943 } while(changes && (i++ < MAX_PASSES));
6948 /*-----------------------------------------------------------------*/
6949 /* ispCodeFunction - returns true if *pc is the pCode of a */
6951 /*-----------------------------------------------------------------*/
6952 static bool ispCodeFunction(pCode *pc)
6955 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6961 /*-----------------------------------------------------------------*/
6962 /* findFunction - Search for a function by name (given the name) */
6963 /* in the set of all functions that are in a pBlock */
6964 /* (note - I expect this to change because I'm planning to limit */
6965 /* pBlock's to just one function declaration */
6966 /*-----------------------------------------------------------------*/
6967 static pCode *findFunction(char *fname)
6974 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6976 pc = setFirstItem(pb->function_entries);
6979 if((pc->type == PC_FUNCTION) &&
6981 (strcmp(fname, PCF(pc)->fname)==0))
6984 pc = setNextItem(pb->function_entries);
6992 static void MarkUsedRegisters(set *regset)
6997 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6998 // fprintf(stderr, "marking register = %s\t", r1->name);
6999 r2 = pic16_regWithIdx(r1->rIdx);
7000 // fprintf(stderr, "to register = %s\n", r2->name);
7006 static void pBlockStats(FILE *of, pBlock *pb)
7012 if(!pic16_pcode_verbose)return;
7014 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7016 // for now just print the first element of each set
7017 pc = setFirstItem(pb->function_entries);
7019 fprintf(of,";entry: ");
7022 pc = setFirstItem(pb->function_exits);
7024 fprintf(of,";has an exit\n");
7028 pc = setFirstItem(pb->function_calls);
7030 fprintf(of,";functions called:\n");
7033 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7034 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7036 pc = setNextItem(pb->function_calls);
7040 r = setFirstItem(pb->tregisters);
7042 int n = elementsInSet(pb->tregisters);
7044 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7047 fprintf(of,"; %s\n",r->name);
7048 r = setNextItem(pb->tregisters);
7053 /*-----------------------------------------------------------------*/
7054 /*-----------------------------------------------------------------*/
7056 static void sequencepCode(void)
7062 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7064 pb->seq = GpCodeSequenceNumber+1;
7066 for( pc = pb->pcHead; pc; pc = pc->next)
7067 pc->seq = ++GpCodeSequenceNumber;
7073 /*-----------------------------------------------------------------*/
7074 /*-----------------------------------------------------------------*/
7075 static set *register_usage(pBlock *pb)
7078 set *registers=NULL;
7079 set *registersInCallPath = NULL;
7081 /* check recursion */
7083 pc = setFirstItem(pb->function_entries);
7090 if(pc->type != PC_FUNCTION)
7091 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7093 pc = setFirstItem(pb->function_calls);
7094 for( ; pc; pc = setNextItem(pb->function_calls)) {
7096 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7097 char *dest = pic16_get_op_from_instruction(PCI(pc));
7099 pcn = findFunction(dest);
7101 registersInCallPath = register_usage(pcn->pb);
7103 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7108 pBlockStats(stderr,pb); // debug
7111 // Mark the registers in this block as used.
7113 MarkUsedRegisters(pb->tregisters);
7114 if(registersInCallPath) {
7115 /* registers were used in the functions this pBlock has called */
7116 /* so now, we need to see if these collide with the ones we are */
7119 regs *r1,*r2, *newreg;
7121 DFPRINTF((stderr,"comparing registers\n"));
7123 r1 = setFirstItem(registersInCallPath);
7126 r2 = setFirstItem(pb->tregisters);
7128 while(r2 && (r1->type != REG_STK)) {
7130 if(r2->rIdx == r1->rIdx) {
7131 newreg = pic16_findFreeReg(REG_GPR);
7135 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7139 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7140 r1->rIdx, newreg->rIdx));
7141 r2->rIdx = newreg->rIdx;
7142 //if(r2->name) free(r2->name);
7144 r2->name = Safe_strdup(newreg->name);
7148 newreg->wasUsed = 1;
7150 r2 = setNextItem(pb->tregisters);
7153 r1 = setNextItem(registersInCallPath);
7156 /* Collisions have been resolved. Now free the registers in the call path */
7157 r1 = setFirstItem(registersInCallPath);
7159 if(r1->type != REG_STK) {
7160 newreg = pic16_regWithIdx(r1->rIdx);
7163 r1 = setNextItem(registersInCallPath);
7167 // MarkUsedRegisters(pb->registers);
7169 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7172 DFPRINTF((stderr,"returning regs\n"));
7174 DFPRINTF((stderr,"not returning regs\n"));
7176 DFPRINTF((stderr,"pBlock after register optim.\n"));
7177 pBlockStats(stderr,pb); // debug
7183 /*-----------------------------------------------------------------*/
7184 /* pct2 - writes the call tree to a file */
7186 /*-----------------------------------------------------------------*/
7187 static void pct2(FILE *of,pBlock *pb,int indent)
7191 // set *registersInCallPath = NULL;
7197 return; //recursion ?
7199 pc = setFirstItem(pb->function_entries);
7206 for(i=0;i<indent;i++) // Indentation
7209 if(pc->type == PC_FUNCTION)
7210 fprintf(of,"%s\n",PCF(pc)->fname);
7215 pc = setFirstItem(pb->function_calls);
7216 for( ; pc; pc = setNextItem(pb->function_calls)) {
7218 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7219 char *dest = pic16_get_op_from_instruction(PCI(pc));
7221 pcn = findFunction(dest);
7223 pct2(of,pcn->pb,indent+1);
7225 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7233 /*-----------------------------------------------------------------*/
7234 /* pic16_printCallTree - writes the call tree to a file */
7236 /*-----------------------------------------------------------------*/
7238 void pic16_printCallTree(FILE *of)
7250 fprintf(of, "\npBlock statistics\n");
7251 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7256 fprintf(of,"Call Tree\n");
7257 pbr = the_pFile->functions;
7261 if(!ispCodeFunction(pc))
7262 fprintf(of,"bug in call tree");
7265 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7267 while(pc->next && !ispCodeFunction(pc->next)) {
7269 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7270 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7278 fprintf(of,"\n**************\n\na better call tree\n");
7279 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7284 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7285 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7291 /*-----------------------------------------------------------------*/
7293 /*-----------------------------------------------------------------*/
7295 static void InlineFunction(pBlock *pb)
7303 pc = setFirstItem(pb->function_calls);
7305 for( ; pc; pc = setNextItem(pb->function_calls)) {
7308 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7314 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7316 //fprintf(stderr,"Cool can inline:\n");
7317 //pcn->print(stderr,pcn);
7319 //fprintf(stderr,"recursive call Inline\n");
7320 InlineFunction(pcn->pb);
7321 //fprintf(stderr,"return from recursive call Inline\n");
7324 At this point, *pc points to a CALL mnemonic, and
7325 *pcn points to the function that is being called.
7327 To in-line this call, we need to remove the CALL
7328 and RETURN(s), and link the function pCode in with
7334 /* Remove the CALL */
7338 /* remove callee pBlock from the pBlock linked list */
7339 removepBlock(pcn->pb);
7347 /* Remove the Function pCode */
7348 pct = pic16_findNextInstruction(pcn->next);
7350 /* Link the function with the callee */
7351 pc->next = pcn->next;
7352 pcn->next->prev = pc;
7354 /* Convert the function name into a label */
7356 pbr = Safe_calloc(1,sizeof(pBranch));
7357 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7359 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7360 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7362 /* turn all of the return's except the last into goto's */
7363 /* check case for 2 instruction pBlocks */
7364 pce = pic16_findNextInstruction(pcn->next);
7366 pCode *pce_next = pic16_findNextInstruction(pce->next);
7368 if(pce_next == NULL) {
7369 /* found the last return */
7370 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7372 //fprintf(stderr,"found last return\n");
7373 //pce->print(stderr,pce);
7374 pce->prev->next = pc_call->next;
7375 pc_call->next->prev = pce->prev;
7376 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7386 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7392 /*-----------------------------------------------------------------*/
7394 /*-----------------------------------------------------------------*/
7396 void pic16_InlinepCode(void)
7405 if(!functionInlining)
7408 /* Loop through all of the function definitions and count the
7409 * number of times each one is called */
7410 //fprintf(stderr,"inlining %d\n",__LINE__);
7412 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7414 pc = setFirstItem(pb->function_calls);
7416 for( ; pc; pc = setNextItem(pb->function_calls)) {
7419 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7420 if(pcn && isPCF(pcn)) {
7421 PCF(pcn)->ncalled++;
7424 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7429 //fprintf(stderr,"inlining %d\n",__LINE__);
7431 /* Now, Loop through the function definitions again, but this
7432 * time inline those functions that have only been called once. */
7434 InlineFunction(the_pFile->pbHead);
7435 //fprintf(stderr,"inlining %d\n",__LINE__);
7437 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7442 char *pic_optype_names[]={
7443 "PO_NONE", // No operand e.g. NOP
7444 "PO_W", // The working register (as a destination)
7445 "PO_WREG", // The working register (as a file register)
7446 "PO_STATUS", // The 'STATUS' register
7447 "PO_BSR", // The 'BSR' register
7448 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7450 "PO_INDF0", // The Indirect register
7451 "PO_INTCON", // Interrupt Control register
7452 "PO_GPR_REGISTER", // A general purpose register
7453 "PO_GPR_BIT", // A bit of a general purpose register
7454 "PO_GPR_TEMP", // A general purpose temporary register
7455 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7456 "PO_PCL", // Program counter Low register
7457 "PO_PCLATH", // Program counter Latch high register
7458 "PO_PCLATU", // Program counter Latch upper register
7459 "PO_PRODL", // Product Register Low
7460 "PO_PRODH", // Product Register High
7461 "PO_LITERAL", // A constant
7462 "PO_REL_ADDR", // A relative address
7463 "PO_IMMEDIATE", // (8051 legacy)
7464 "PO_DIR", // Direct memory (8051 legacy)
7465 "PO_CRY", // bit memory (8051 legacy)
7466 "PO_BIT", // bit operand.
7467 "PO_STR", // (8051 legacy)
7469 "PO_WILD" // Wild card operand in peep optimizer
7473 char *dumpPicOptype(PIC_OPTYPE type)
7475 return (pic_optype_names[ type ]);