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_pciINFSNZW = { // vrokas - New
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1344 NULL, // from branch
1351 0,0, // dest, bit instruction
1352 1,1, // 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_REGISTER, // inCond
1364 pCodeInstruction pic16_pciIORWF = {
1365 {PC_OPCODE, NULL, NULL, 0, NULL,
1371 NULL, // from branch
1378 1,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_REGISTER | PCC_Z | PCC_N), // outCond
1391 pCodeInstruction pic16_pciIORFW = {
1392 {PC_OPCODE, NULL, NULL, 0, NULL,
1398 NULL, // from branch
1405 0,0, // dest, bit instruction
1406 0,0, // branch, skip
1407 0, // literal operand
1408 1, // 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_REGISTER), // inCond
1414 (PCC_W | PCC_Z | PCC_N), // outCond
1418 pCodeInstruction pic16_pciIORLW = {
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 0, // second literal operand
1440 (PCC_W | PCC_LITERAL), // inCond
1441 (PCC_W | PCC_Z | PCC_N), // outCond
1445 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1446 {PC_OPCODE, NULL, NULL, 0, NULL,
1452 NULL, // from branch
1459 0,0, // dest, bit instruction
1460 0,0, // branch, skip
1461 1, // literal operand
1462 0, // RAM access bit
1463 0, // fast call/return mode select bit
1464 0, // second memory operand
1465 1, // second literal operand
1467 (PCC_REGISTER | PCC_LITERAL),
1468 PCC_REGISTER, // outCond
1472 pCodeInstruction pic16_pciMOVF = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1479 NULL, // from branch
1486 1,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_Z | PCC_N), // outCond
1499 pCodeInstruction pic16_pciMOVFW = {
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 1, // RAM access bit
1517 0, // fast call/return mode select bit
1518 0, // second memory operand
1519 0, // second literal operand
1521 PCC_REGISTER, // inCond
1522 (PCC_W | PCC_Z), // outCond
1526 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1533 NULL, // from branch
1540 0,0, // dest, bit instruction
1541 0,0, // branch, skip
1542 0, // literal operand
1543 0, // RAM access bit
1544 0, // fast call/return mode select bit
1545 1, // second memory operand
1546 0, // second literal operand
1548 PCC_REGISTER, // inCond
1549 PCC_REGISTER, // outCond
1553 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1554 {PC_OPCODE, NULL, NULL, 0, NULL,
1559 NULL, // from branch
1566 0,0, // dest, bit instruction
1567 0,0, // branch, skip
1568 1, // literal operand
1569 0, // RAM access bit
1570 0, // fast call/return mode select bit
1571 0, // second memory operand
1572 0, // second literal operand
1574 (PCC_NONE | PCC_LITERAL), // inCond
1575 PCC_REGISTER, // outCond - BSR
1579 pCodeInstruction pic16_pciMOVLW = {
1580 {PC_OPCODE, NULL, NULL, 0, NULL,
1585 NULL, // from branch
1592 0,0, // dest, bit instruction
1593 0,0, // branch, skip
1594 1, // literal operand
1595 0, // RAM access bit
1596 0, // fast call/return mode select bit
1597 0, // second memory operand
1598 0, // second literal operand
1600 (PCC_NONE | PCC_LITERAL), // inCond
1605 pCodeInstruction pic16_pciMOVWF = {
1606 {PC_OPCODE, NULL, NULL, 0, NULL,
1612 NULL, // from branch
1619 0,0, // dest, bit instruction
1620 0,0, // branch, skip
1621 0, // literal operand
1622 1, // RAM access bit
1623 0, // fast call/return mode select bit
1624 0, // second memory operand
1625 0, // second literal operand
1627 PCC_REGISTER, // inCond
1632 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1633 {PC_OPCODE, NULL, NULL, 0, NULL,
1638 NULL, // from branch
1645 0,0, // dest, bit instruction
1646 0,0, // branch, skip
1647 1, // literal operand
1648 0, // RAM access bit
1649 0, // fast call/return mode select bit
1650 0, // second memory operand
1651 0, // second literal operand
1653 (PCC_W | PCC_LITERAL), // inCond
1654 PCC_REGISTER, // outCond - PROD
1658 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1659 {PC_OPCODE, NULL, NULL, 0, NULL,
1664 NULL, // from branch
1671 0,0, // dest, bit instruction
1672 0,0, // branch, skip
1673 0, // literal operand
1674 1, // RAM access bit
1675 0, // fast call/return mode select bit
1676 0, // second memory operand
1677 0, // second literal operand
1679 (PCC_W | PCC_REGISTER), // inCond
1680 PCC_REGISTER, // outCond - PROD
1684 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1685 {PC_OPCODE, NULL, NULL, 0, NULL,
1690 NULL, // from branch
1697 0,0, // dest, bit instruction
1698 0,0, // branch, skip
1699 0, // literal operand
1700 1, // RAM access bit
1701 0, // fast call/return mode select bit
1702 0, // second memory operand
1703 0, // second literal operand
1705 PCC_REGISTER, // inCond
1706 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1710 pCodeInstruction pic16_pciNOP = {
1711 {PC_OPCODE, NULL, NULL, 0, NULL,
1716 NULL, // from branch
1723 0,0, // dest, bit instruction
1724 0,0, // branch, skip
1725 0, // literal operand
1726 0, // RAM access bit
1727 0, // fast call/return mode select bit
1728 0, // second memory operand
1729 0, // second literal operand
1732 PCC_NONE, // outCond
1736 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1737 {PC_OPCODE, NULL, NULL, 0, NULL,
1742 NULL, // from branch
1749 0,0, // dest, bit instruction
1750 0,0, // branch, skip
1751 0, // literal operand
1752 0, // RAM access bit
1753 0, // fast call/return mode select bit
1754 0, // second memory operand
1755 0, // second literal operand
1758 PCC_NONE , // outCond
1762 pCodeInstruction pic16_pciPUSH = {
1763 {PC_OPCODE, NULL, NULL, 0, NULL,
1768 NULL, // from branch
1775 0,0, // dest, bit instruction
1776 0,0, // branch, skip
1777 0, // literal operand
1778 0, // RAM access bit
1779 0, // fast call/return mode select bit
1780 0, // second memory operand
1781 0, // second literal operand
1784 PCC_NONE , // outCond
1788 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1789 {PC_OPCODE, NULL, NULL, 0, NULL,
1794 NULL, // from branch
1801 0,0, // dest, bit instruction
1802 0,0, // branch, skip
1803 0, // literal operand
1804 0, // RAM access bit
1805 0, // fast call/return mode select bit
1806 0, // second memory operand
1807 0, // second literal operand
1809 PCC_REL_ADDR, // inCond
1810 PCC_NONE , // outCond
1814 pCodeInstruction pic16_pciRETFIE = {
1815 {PC_OPCODE, NULL, NULL, 0, NULL,
1821 NULL, // from branch
1828 0,0, // dest, bit instruction
1829 1,0, // branch, skip
1830 0, // literal operand
1831 0, // RAM access bit
1832 1, // fast call/return mode select bit
1833 0, // second memory operand
1834 0, // second literal operand
1837 PCC_NONE, // outCond (not true... affects the GIE bit too)
1841 pCodeInstruction pic16_pciRETLW = {
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 0,0, // dest, bit instruction
1856 1,0, // branch, skip
1857 1, // literal operand
1858 0, // RAM access bit
1859 0, // fast call/return mode select bit
1860 0, // second memory operand
1861 0, // second literal operand
1863 PCC_LITERAL, // inCond
1868 pCodeInstruction pic16_pciRETURN = {
1869 {PC_OPCODE, NULL, NULL, 0, NULL,
1875 NULL, // from branch
1882 0,0, // dest, bit instruction
1883 1,0, // branch, skip
1884 0, // literal operand
1885 0, // RAM access bit
1886 1, // fast call/return mode select bit
1887 0, // second memory operand
1888 0, // second literal operand
1891 PCC_NONE, // outCond
1894 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1895 {PC_OPCODE, NULL, NULL, 0, NULL,
1901 NULL, // from branch
1908 1,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_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1921 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1922 {PC_OPCODE, NULL, NULL, 0, NULL,
1928 NULL, // from branch
1935 0,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_C | PCC_REGISTER), // inCond
1944 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1948 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1949 {PC_OPCODE, NULL, NULL, 0, NULL,
1955 NULL, // from branch
1962 1,0, // dest, bit instruction
1963 0,0, // branch, skip
1964 0, // literal operand
1965 1, // RAM access bit
1966 0, // fast call/return mode select bit
1967 0, // second memory operand
1968 0, // second literal operand
1970 PCC_REGISTER, // inCond
1971 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1974 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1975 {PC_OPCODE, NULL, NULL, 0, NULL,
1981 NULL, // from branch
1988 0,0, // dest, bit instruction
1989 0,0, // branch, skip
1990 0, // literal operand
1991 1, // RAM access bit
1992 0, // fast call/return mode select bit
1993 0, // second memory operand
1994 0, // second literal operand
1996 PCC_REGISTER, // inCond
1997 (PCC_W | PCC_Z | PCC_N), // outCond
2000 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2001 {PC_OPCODE, NULL, NULL, 0, NULL,
2007 NULL, // from branch
2014 1,0, // dest, bit instruction
2015 0,0, // branch, skip
2016 0, // literal operand
2017 1, // RAM access bit
2018 0, // fast call/return mode select bit
2019 0, // second memory operand
2020 0, // second literal operand
2022 (PCC_C | PCC_REGISTER), // inCond
2023 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2026 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2027 {PC_OPCODE, NULL, NULL, 0, NULL,
2033 NULL, // from branch
2040 0,0, // dest, bit instruction
2041 0,0, // branch, skip
2042 0, // literal operand
2043 1, // RAM access bit
2044 0, // fast call/return mode select bit
2045 0, // second memory operand
2046 0, // second literal operand
2048 (PCC_C | PCC_REGISTER), // inCond
2049 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2052 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2053 {PC_OPCODE, NULL, NULL, 0, NULL,
2059 NULL, // from branch
2066 1,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_REGISTER | PCC_Z | PCC_N), // outCond
2079 pCodeInstruction pic16_pciRRNCFW = { // 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_W | PCC_Z | PCC_N), // outCond
2106 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2107 {PC_OPCODE, NULL, NULL, 0, NULL,
2113 NULL, // from branch
2120 0,0, // dest, bit instruction
2121 0,0, // branch, skip
2122 0, // literal operand
2123 1, // RAM access bit
2124 0, // fast call/return mode select bit
2125 0, // second memory operand
2126 0, // second literal operand
2128 PCC_REGISTER, // inCond
2129 PCC_REGISTER , // outCond
2133 pCodeInstruction pic16_pciSUBLW = {
2134 {PC_OPCODE, NULL, NULL, 0, NULL,
2140 NULL, // from branch
2147 0,0, // dest, bit instruction
2148 0,0, // branch, skip
2149 1, // literal operand
2150 0, // 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_LITERAL), // inCond
2156 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2160 pCodeInstruction pic16_pciSUBFWB = {
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 | PCC_C), // inCond
2183 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2187 pCodeInstruction pic16_pciSUBWF = {
2188 {PC_OPCODE, NULL, NULL, 0, NULL,
2194 NULL, // from branch
2201 1,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_REGISTER | PCC_Z), // outCond
2214 pCodeInstruction pic16_pciSUBFW = {
2215 {PC_OPCODE, NULL, NULL, 0, NULL,
2221 NULL, // from branch
2228 0,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), // inCond
2237 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2241 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2242 {PC_OPCODE, NULL, NULL, 0, NULL,
2248 NULL, // from branch
2255 1,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_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2268 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2269 {PC_OPCODE, NULL, NULL, 0, NULL,
2275 NULL, // from branch
2282 0,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_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2295 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2296 {PC_OPCODE, NULL, NULL, 0, NULL,
2302 NULL, // from branch
2309 1,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_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2322 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2323 {PC_OPCODE, NULL, NULL, 0, NULL,
2329 NULL, // from branch
2336 0,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_W | PCC_REGISTER | PCC_C), // inCond
2345 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2349 pCodeInstruction pic16_pciSWAPF = {
2350 {PC_OPCODE, NULL, NULL, 0, NULL,
2356 NULL, // from branch
2363 1,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
2372 (PCC_REGISTER), // outCond
2376 pCodeInstruction pic16_pciSWAPFW = {
2377 {PC_OPCODE, NULL, NULL, 0, NULL,
2383 NULL, // from branch
2390 0,0, // dest, bit instruction
2391 0,0, // branch, skip
2392 0, // literal operand
2393 1, // RAM access bit
2394 0, // fast call/return mode select bit
2395 0, // second memory operand
2396 0, // second literal operand
2398 (PCC_REGISTER), // inCond
2403 pCodeInstruction pic16_pciTBLRD = { // patch 15
2404 {PC_OPCODE, NULL, NULL, 0, NULL,
2409 NULL, // from branch
2416 0,0, // dest, bit instruction
2417 0,0, // branch, skip
2418 0, // literal operand
2419 0, // RAM access bit
2420 0, // fast call/return mode select bit
2421 0, // second memory operand
2422 0, // second literal operand
2425 PCC_NONE , // outCond
2429 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2430 {PC_OPCODE, NULL, NULL, 0, NULL,
2435 NULL, // from branch
2442 0,0, // dest, bit instruction
2443 0,0, // branch, skip
2444 0, // literal operand
2445 0, // RAM access bit
2446 0, // fast call/return mode select bit
2447 0, // second memory operand
2448 0, // second literal operand
2451 PCC_NONE , // outCond
2455 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2456 {PC_OPCODE, NULL, NULL, 0, NULL,
2461 NULL, // from branch
2468 0,0, // dest, bit instruction
2469 0,0, // branch, skip
2470 0, // literal operand
2471 0, // RAM access bit
2472 0, // fast call/return mode select bit
2473 0, // second memory operand
2474 0, // second literal operand
2477 PCC_NONE , // outCond
2481 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2482 {PC_OPCODE, NULL, NULL, 0, NULL,
2487 NULL, // from branch
2494 0,0, // dest, bit instruction
2495 0,0, // branch, skip
2496 0, // literal operand
2497 0, // RAM access bit
2498 0, // fast call/return mode select bit
2499 0, // second memory operand
2500 0, // second literal operand
2503 PCC_NONE , // outCond
2507 pCodeInstruction pic16_pciTBLWT = { // patch 15
2508 {PC_OPCODE, NULL, NULL, 0, NULL,
2513 NULL, // from branch
2520 0,0, // dest, bit instruction
2521 0,0, // branch, skip
2522 0, // literal operand
2523 0, // RAM access bit
2524 0, // fast call/return mode select bit
2525 0, // second memory operand
2526 0, // second literal operand
2529 PCC_NONE , // outCond
2533 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2534 {PC_OPCODE, NULL, NULL, 0, NULL,
2539 NULL, // from branch
2546 0,0, // dest, bit instruction
2547 0,0, // branch, skip
2548 0, // literal operand
2549 0, // RAM access bit
2550 0, // fast call/return mode select bit
2551 0, // second memory operand
2552 0, // second literal operand
2555 PCC_NONE , // outCond
2559 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2560 {PC_OPCODE, NULL, NULL, 0, NULL,
2565 NULL, // from branch
2572 0,0, // dest, bit instruction
2573 0,0, // branch, skip
2574 0, // literal operand
2575 0, // RAM access bit
2576 0, // fast call/return mode select bit
2577 0, // second memory operand
2578 0, // second literal operand
2581 PCC_NONE , // outCond
2585 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2586 {PC_OPCODE, NULL, NULL, 0, NULL,
2591 NULL, // from branch
2598 0,0, // dest, bit instruction
2599 0,0, // branch, skip
2600 0, // literal operand
2601 0, // RAM access bit
2602 0, // fast call/return mode select bit
2603 0, // second memory operand
2604 0, // second literal operand
2607 PCC_NONE , // outCond
2611 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2612 {PC_OPCODE, NULL, NULL, 0, NULL,
2618 NULL, // from branch
2625 0,0, // dest, bit instruction
2626 1,1, // 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_REGISTER, // inCond
2634 PCC_NONE, // outCond
2638 pCodeInstruction pic16_pciXORWF = {
2639 {PC_OPCODE, NULL, NULL, 0, NULL,
2645 NULL, // from branch
2652 1,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_REGISTER | PCC_Z | PCC_N), // outCond
2665 pCodeInstruction pic16_pciXORFW = {
2666 {PC_OPCODE, NULL, NULL, 0, NULL,
2672 NULL, // from branch
2679 0,0, // dest, bit instruction
2680 0,0, // branch, skip
2681 0, // 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_REGISTER), // inCond
2688 (PCC_W | PCC_Z | PCC_N), // outCond
2692 pCodeInstruction pic16_pciXORLW = {
2693 {PC_OPCODE, NULL, NULL, 0, NULL,
2699 NULL, // from branch
2706 0,0, // dest, bit instruction
2707 0,0, // branch, skip
2708 1, // literal operand
2709 1, // RAM access bit
2710 0, // fast call/return mode select bit
2711 0, // second memory operand
2712 0, // second literal operand
2714 (PCC_W | PCC_LITERAL), // inCond
2715 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2720 pCodeInstruction pic16_pciBANKSEL = {
2721 {PC_OPCODE, NULL, NULL, 0, NULL,
2726 NULL, // from branch
2733 0,0, // dest, bit instruction
2734 0,0, // branch, skip
2735 0, // literal operand
2736 0, // RAM access bit
2737 0, // fast call/return mode select bit
2738 0, // second memory operand
2739 0, // second literal operand
2742 PCC_NONE, // outCond
2747 #define MAX_PIC16MNEMONICS 100
2748 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2750 //#define USE_VSNPRINTF
2753 #ifdef USE_VSNPRINTF
2754 // Alas, vsnprintf is not ANSI standard, and does not exist
2755 // on Solaris (and probably other non-Gnu flavored Unixes).
2757 /*-----------------------------------------------------------------*/
2758 /* SAFE_snprintf - like snprintf except the string pointer is */
2759 /* after the string has been printed to. This is */
2760 /* useful for printing to string as though if it */
2761 /* were a stream. */
2762 /*-----------------------------------------------------------------*/
2763 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2771 va_start(val, format);
2773 vsnprintf(*str, *size, format, val);
2779 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2780 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2789 // This version is *not* safe, despite the name.
2791 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2795 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2800 va_start(val, format);
2802 vsprintf(buffer, format, val);
2805 len = strlen(buffer);
2807 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2808 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2811 strcpy(*str, buffer);
2817 #endif // USE_VSNPRINTF
2820 extern void pic16_initStack(int base_address, int size);
2821 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2822 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2823 extern void pic16_init_pic(char *);
2825 void pic16_pCodeInitRegisters(void)
2827 static int initialized=0;
2834 // pic16_initStack(0xfff, 8);
2835 pic16_init_pic(port->processor);
2837 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2838 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2839 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2840 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2841 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2842 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2843 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2845 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2846 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2847 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2849 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2850 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2851 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2852 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2854 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2855 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2856 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2857 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2858 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2859 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2861 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2862 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2863 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2864 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2865 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2867 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2868 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2869 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2870 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2871 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2873 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2874 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2875 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2876 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2877 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2879 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2880 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2883 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2884 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2885 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2886 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2889 pic16_pc_status.rIdx = IDX_STATUS;
2890 pic16_pc_intcon.rIdx = IDX_INTCON;
2891 pic16_pc_pcl.rIdx = IDX_PCL;
2892 pic16_pc_pclath.rIdx = IDX_PCLATH;
2893 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2894 pic16_pc_wreg.rIdx = IDX_WREG;
2895 pic16_pc_bsr.rIdx = IDX_BSR;
2897 pic16_pc_tosl.rIdx = IDX_TOSL;
2898 pic16_pc_tosh.rIdx = IDX_TOSH;
2899 pic16_pc_tosu.rIdx = IDX_TOSU;
2901 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2902 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2903 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2904 pic16_pc_tablat.rIdx = IDX_TABLAT;
2906 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2907 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2908 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2909 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2910 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2911 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2912 pic16_pc_indf0.rIdx = IDX_INDF0;
2913 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2914 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2915 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2916 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2917 pic16_pc_indf1.rIdx = IDX_INDF1;
2918 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2919 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2920 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2921 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2922 pic16_pc_indf2.rIdx = IDX_INDF2;
2923 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2924 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2925 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2926 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2927 pic16_pc_prodl.rIdx = IDX_PRODL;
2928 pic16_pc_prodh.rIdx = IDX_PRODH;
2930 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2931 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2932 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2934 pic16_pc_kzero.rIdx = IDX_KZ;
2935 pic16_pc_wsave.rIdx = IDX_WSAVE;
2936 pic16_pc_ssave.rIdx = IDX_SSAVE;
2938 pic16_pc_eecon1.rIdx = IDX_EECON1;
2939 pic16_pc_eecon2.rIdx = IDX_EECON2;
2940 pic16_pc_eedata.rIdx = IDX_EEDATA;
2941 pic16_pc_eeadr.rIdx = IDX_EEADR;
2944 /* probably should put this in a separate initialization routine */
2945 pb_dead_pcodes = newpBlock();
2950 /*-----------------------------------------------------------------*/
2951 /* mnem2key - convert a pic mnemonic into a hash key */
2952 /* (BTW - this spreads the mnemonics quite well) */
2954 /*-----------------------------------------------------------------*/
2956 int mnem2key(char const *mnem)
2965 key += toupper(*mnem++) +1;
2969 return (key & 0x1f);
2974 void pic16initMnemonics(void)
2979 pCodeInstruction *pci;
2981 if(mnemonics_initialized)
2984 // NULL out the array before making the assignments
2985 // since we check the array contents below this initialization.
2987 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2988 pic16Mnemonics[i] = NULL;
2991 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2992 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2993 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2994 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2995 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2996 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2997 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2998 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2999 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3000 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3001 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3002 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3003 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3004 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3005 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3006 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3007 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3008 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3009 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3010 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3011 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3012 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3013 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3014 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3015 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3016 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3017 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3018 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3019 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3020 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3021 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3022 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3023 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3024 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3025 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3026 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3027 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3028 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3029 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3030 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3031 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3032 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3033 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3034 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3035 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3036 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3037 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3038 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3039 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3040 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3041 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3042 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3043 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3044 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3045 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3046 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3047 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3048 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3049 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3050 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3051 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3052 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3053 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3054 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3055 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3056 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3057 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3058 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3059 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3060 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3061 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3062 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3063 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3064 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3065 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3066 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3067 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3068 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3069 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3070 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3071 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3072 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3073 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3074 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3075 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3076 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3077 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3078 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3079 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3080 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3081 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3082 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3083 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3084 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3086 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3087 if(pic16Mnemonics[i])
3088 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3089 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3092 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3093 pci = hTabNextItem(pic16MnemonicsHash, &key);
3096 mnemonics_initialized = 1;
3099 int pic16_getpCodePeepCommand(char *cmd);
3101 int pic16_getpCode(char *mnem,unsigned dest)
3104 pCodeInstruction *pci;
3105 int key = mnem2key(mnem);
3107 if(!mnemonics_initialized)
3108 pic16initMnemonics();
3110 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3114 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3115 if((pci->num_ops <= 1)
3116 || (pci->isModReg == dest)
3118 || (pci->num_ops <= 2 && pci->isAccess)
3119 || (pci->num_ops <= 2 && pci->isFastCall)
3120 || (pci->num_ops <= 2 && pci->is2MemOp)
3121 || (pci->num_ops <= 2 && pci->is2LitOp) )
3125 pci = hTabNextItemWK (pic16MnemonicsHash);
3132 /*-----------------------------------------------------------------*
3133 * pic16initpCodePeepCommands
3135 *-----------------------------------------------------------------*/
3136 void pic16initpCodePeepCommands(void)
3144 hTabAddItem(&pic16pCodePeepCommandsHash,
3145 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3147 } while (peepCommands[i].cmd);
3149 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3152 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3153 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3158 /*-----------------------------------------------------------------
3161 *-----------------------------------------------------------------*/
3163 int pic16_getpCodePeepCommand(char *cmd)
3167 int key = mnem2key(cmd);
3170 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3173 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3174 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3178 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3185 static char getpBlock_dbName(pBlock *pb)
3191 return pb->cmemmap->dbName;
3195 void pic16_pBlockConvert2ISR(pBlock *pb)
3199 if(pb->cmemmap)pb->cmemmap = NULL;
3203 if(pic16_pcode_verbose)
3204 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3207 void pic16_pBlockConvert2Absolute(pBlock *pb)
3210 if(pb->cmemmap)pb->cmemmap = NULL;
3214 if(pic16_pcode_verbose)
3215 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3218 /*-----------------------------------------------------------------*/
3219 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3220 /* instances to the front of the doubly linked */
3221 /* list of pBlocks */
3222 /*-----------------------------------------------------------------*/
3224 void pic16_movepBlock2Head(char dbName)
3229 /* this can happen in sources without code,
3230 * only variable definitions */
3231 if(!the_pFile)return;
3233 pb = the_pFile->pbHead;
3237 if(getpBlock_dbName(pb) == dbName) {
3238 pBlock *pbn = pb->next;
3239 pb->next = the_pFile->pbHead;
3240 the_pFile->pbHead->prev = pb;
3241 the_pFile->pbHead = pb;
3244 pb->prev->next = pbn;
3246 // If the pBlock that we just moved was the last
3247 // one in the link of all of the pBlocks, then we
3248 // need to point the tail to the block just before
3249 // the one we moved.
3250 // Note: if pb->next is NULL, then pb must have
3251 // been the last pBlock in the chain.
3254 pbn->prev = pb->prev;
3256 the_pFile->pbTail = pb->prev;
3267 void pic16_copypCode(FILE *of, char dbName)
3271 if(!of || !the_pFile)
3274 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3275 if(getpBlock_dbName(pb) == dbName) {
3276 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3278 pic16_printpBlock(of,pb);
3283 void pic16_pcode_test(void)
3286 DFPRINTF((stderr,"pcode is alive!\n"));
3296 /* create the file name */
3297 strcpy(buffer,dstFileName);
3298 strcat(buffer,".p");
3300 if( !(pFile = fopen(buffer, "w" ))) {
3301 werror(E_FILE_OPEN_ERR,buffer);
3305 fprintf(pFile,"pcode dump\n\n");
3307 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3308 fprintf(pFile,"\n\tNew pBlock\n\n");
3310 fprintf(pFile,"%s",pb->cmemmap->sname);
3312 fprintf(pFile,"internal pblock");
3314 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3315 pic16_printpBlock(pFile,pb);
3319 /*-----------------------------------------------------------------*/
3320 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3321 /* ister, RegCond will return the bit being referenced. */
3323 /* fixme - why not just OR in the pcop bit field */
3324 /*-----------------------------------------------------------------*/
3326 static int RegCond(pCodeOp *pcop)
3332 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3333 switch(PCORB(pcop)->bit) {
3347 /*-----------------------------------------------------------------*/
3348 /* pic16_newpCode - create and return a newly initialized pCode */
3350 /* fixme - rename this */
3352 /* The purpose of this routine is to create a new Instruction */
3353 /* pCode. This is called by gen.c while the assembly code is being */
3357 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3358 /* (note that the op is analogous to but not the */
3359 /* same thing as the opcode of the instruction.) */
3360 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3363 /* a pointer to the new malloc'd pCode is returned. */
3367 /*-----------------------------------------------------------------*/
3368 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3370 pCodeInstruction *pci ;
3372 if(!mnemonics_initialized)
3373 pic16initMnemonics();
3375 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3377 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3378 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3381 if(pci->inCond & PCC_EXAMINE_PCOP)
3382 pci->inCond |= RegCond(pcop);
3384 if(pci->outCond & PCC_EXAMINE_PCOP)
3385 pci->outCond |= RegCond(pcop);
3387 pci->pc.prev = pci->pc.next = NULL;
3388 return (pCode *)pci;
3391 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3397 /*-----------------------------------------------------------------*/
3398 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3400 /* Wild pcodes are used during the peep hole optimizer to serve */
3401 /* as place holders for any instruction. When a snippet of code is */
3402 /* compared to a peep hole rule, the wild card opcode will match */
3403 /* any instruction. However, the optional operand and label are */
3404 /* additional qualifiers that must also be matched before the */
3405 /* line (of assembly code) is declared matched. Note that the */
3406 /* operand may be wild too. */
3408 /* Note, a wild instruction is specified just like a wild var: */
3409 /* %4 ; A wild instruction, */
3410 /* See the peeph.def file for additional examples */
3412 /*-----------------------------------------------------------------*/
3414 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3419 pcw = Safe_calloc(1,sizeof(pCodeWild));
3421 pcw->pci.pc.type = PC_WILD;
3422 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3423 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3424 pcw->pci.pc.pb = NULL;
3426 // pcw->pci.pc.analyze = genericAnalyze;
3427 pcw->pci.pc.destruct = genericDestruct;
3428 pcw->pci.pc.print = genericPrint;
3430 pcw->id = pCodeID; // this is the 'n' in %n
3431 pcw->operand = optional_operand;
3432 pcw->label = optional_label;
3434 pcw->mustBeBitSkipInst = 0;
3435 pcw->mustNotBeBitSkipInst = 0;
3436 pcw->invertBitSkipInst = 0;
3438 return ( (pCode *)pcw);
3442 /*-----------------------------------------------------------------*/
3443 /* newPcodeInlineP - create a new pCode from a char string */
3444 /*-----------------------------------------------------------------*/
3447 pCode *pic16_newpCodeInlineP(char *cP)
3452 pcc = Safe_calloc(1,sizeof(pCodeComment));
3454 pcc->pc.type = PC_INLINE;
3455 pcc->pc.prev = pcc->pc.next = NULL;
3456 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3459 // pcc->pc.analyze = genericAnalyze;
3460 pcc->pc.destruct = genericDestruct;
3461 pcc->pc.print = genericPrint;
3464 pcc->comment = Safe_strdup(cP);
3466 pcc->comment = NULL;
3468 return ( (pCode *)pcc);
3472 /*-----------------------------------------------------------------*/
3473 /* newPcodeCharP - create a new pCode from a char string */
3474 /*-----------------------------------------------------------------*/
3476 pCode *pic16_newpCodeCharP(char *cP)
3481 pcc = Safe_calloc(1,sizeof(pCodeComment));
3483 pcc->pc.type = PC_COMMENT;
3484 pcc->pc.prev = pcc->pc.next = NULL;
3485 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3488 // pcc->pc.analyze = genericAnalyze;
3489 pcc->pc.destruct = genericDestruct;
3490 pcc->pc.print = genericPrint;
3493 pcc->comment = Safe_strdup(cP);
3495 pcc->comment = NULL;
3497 return ( (pCode *)pcc);
3501 /*-----------------------------------------------------------------*/
3502 /* pic16_newpCodeFunction - */
3503 /*-----------------------------------------------------------------*/
3506 pCode *pic16_newpCodeFunction(char *mod,char *f)
3510 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3512 pcf->pc.type = PC_FUNCTION;
3513 pcf->pc.prev = pcf->pc.next = NULL;
3514 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3517 // pcf->pc.analyze = genericAnalyze;
3518 pcf->pc.destruct = genericDestruct;
3519 pcf->pc.print = pCodePrintFunction;
3525 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3526 strcpy(pcf->modname,mod);
3528 pcf->modname = NULL;
3531 pcf->fname = Safe_calloc(1,strlen(f)+1);
3532 strcpy(pcf->fname,f);
3536 pcf->stackusage = 0;
3538 return ( (pCode *)pcf);
3541 /*-----------------------------------------------------------------*/
3542 /* pic16_newpCodeFlow */
3543 /*-----------------------------------------------------------------*/
3544 static void destructpCodeFlow(pCode *pc)
3546 if(!pc || !isPCFL(pc))
3553 pic16_unlinkpCode(pc);
3555 deleteSet(&PCFL(pc)->registers);
3556 deleteSet(&PCFL(pc)->from);
3557 deleteSet(&PCFL(pc)->to);
3559 /* Instead of deleting the memory used by this pCode, mark
3560 * the object as bad so that if there's a pointer to this pCode
3561 * dangling around somewhere then (hopefully) when the type is
3562 * checked we'll catch it.
3566 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3572 pCode *pic16_newpCodeFlow(void )
3576 //_ALLOC(pcflow,sizeof(pCodeFlow));
3577 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3579 pcflow->pc.type = PC_FLOW;
3580 pcflow->pc.prev = pcflow->pc.next = NULL;
3581 pcflow->pc.pb = NULL;
3583 // pcflow->pc.analyze = genericAnalyze;
3584 pcflow->pc.destruct = destructpCodeFlow;
3585 pcflow->pc.print = genericPrint;
3587 pcflow->pc.seq = GpcFlowSeq++;
3589 pcflow->from = pcflow->to = NULL;
3591 pcflow->inCond = PCC_NONE;
3592 pcflow->outCond = PCC_NONE;
3594 pcflow->firstBank = -1;
3595 pcflow->lastBank = -1;
3597 pcflow->FromConflicts = 0;
3598 pcflow->ToConflicts = 0;
3602 pcflow->registers = newSet();
3604 return ( (pCode *)pcflow);
3608 /*-----------------------------------------------------------------*/
3609 /*-----------------------------------------------------------------*/
3610 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3612 pCodeFlowLink *pcflowLink;
3614 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3616 pcflowLink->pcflow = pcflow;
3617 pcflowLink->bank_conflict = 0;
3622 /*-----------------------------------------------------------------*/
3623 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3624 /*-----------------------------------------------------------------*/
3626 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3631 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3633 pccs->pc.type = PC_CSOURCE;
3634 pccs->pc.prev = pccs->pc.next = NULL;
3637 pccs->pc.destruct = genericDestruct;
3638 pccs->pc.print = genericPrint;
3640 pccs->line_number = ln;
3642 pccs->line = Safe_strdup(l);
3647 pccs->file_name = Safe_strdup(f);
3649 pccs->file_name = NULL;
3651 return ( (pCode *)pccs);
3656 /*******************************************************************/
3657 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3658 /* added by VR 6-Jun-2003 */
3659 /*******************************************************************/
3661 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3668 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3669 pcad->pci.pc.type = PC_ASMDIR;
3670 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3671 pcad->pci.pc.pb = NULL;
3673 pcad->pci.pc.destruct = genericDestruct;
3674 pcad->pci.pc.print = genericPrint;
3676 if(asdir && *asdir) {
3678 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3680 pcad->directive = Safe_strdup( asdir );
3683 va_start(ap, argfmt);
3685 memset(buffer, 0, sizeof(buffer));
3686 if(argfmt && *argfmt)
3687 vsprintf(buffer, argfmt, ap);
3691 while(isspace(*lbp))lbp++;
3694 pcad->arg = Safe_strdup( lbp );
3696 return ((pCode *)pcad);
3699 /*-----------------------------------------------------------------*/
3700 /* pCodeLabelDestruct - free memory used by a label. */
3701 /*-----------------------------------------------------------------*/
3702 static void pCodeLabelDestruct(pCode *pc)
3708 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3709 // free(PCL(pc)->label);
3711 /* Instead of deleting the memory used by this pCode, mark
3712 * the object as bad so that if there's a pointer to this pCode
3713 * dangling around somewhere then (hopefully) when the type is
3714 * checked we'll catch it.
3718 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3724 pCode *pic16_newpCodeLabel(char *name, int key)
3730 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3732 pcl->pc.type = PC_LABEL;
3733 pcl->pc.prev = pcl->pc.next = NULL;
3734 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3737 // pcl->pc.analyze = genericAnalyze;
3738 pcl->pc.destruct = pCodeLabelDestruct;
3739 pcl->pc.print = pCodePrintLabel;
3746 sprintf(s,"_%05d_DS_",key);
3751 pcl->label = Safe_strdup(s);
3753 // if(pic16_pcode_verbose)
3754 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3757 return ( (pCode *)pcl);
3761 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3763 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3767 return ( (pCode *)pcl );
3771 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3778 /*-----------------------------------------------------------------*/
3779 /* newpBlock - create and return a pointer to a new pBlock */
3780 /*-----------------------------------------------------------------*/
3781 static pBlock *newpBlock(void)
3786 PpB = Safe_calloc(1,sizeof(pBlock) );
3787 PpB->next = PpB->prev = NULL;
3789 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3790 PpB->tregisters = NULL;
3792 PpB->FlowTree = NULL;
3798 /*-----------------------------------------------------------------*/
3799 /* pic16_newpCodeChain - create a new chain of pCodes */
3800 /*-----------------------------------------------------------------*
3802 * This function will create a new pBlock and the pointer to the
3803 * pCode that is passed in will be the first pCode in the block.
3804 *-----------------------------------------------------------------*/
3807 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3810 pBlock *pB = newpBlock();
3812 pB->pcHead = pB->pcTail = pc;
3821 /*-----------------------------------------------------------------*/
3822 /* pic16_newpCodeOpLabel - Create a new label given the key */
3823 /* Note, a negative key means that the label is part of wild card */
3824 /* (and hence a wild card label) used in the pCodePeep */
3825 /* optimizations). */
3826 /*-----------------------------------------------------------------*/
3828 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3831 static int label_key=-1;
3835 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3836 pcop->type = PO_LABEL;
3841 sprintf(s=buffer,"_%05d_DS_",key);
3843 s = name, key = label_key--;
3846 pcop->name = Safe_strdup(s);
3848 ((pCodeOpLabel *)pcop)->key = key;
3850 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3854 /*-----------------------------------------------------------------*/
3855 /*-----------------------------------------------------------------*/
3856 pCodeOp *pic16_newpCodeOpLit(int lit)
3862 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3863 pcop->type = PO_LITERAL;
3867 sprintf(s,"0x%02x",lit);
3869 pcop->name = Safe_strdup(s);
3872 ((pCodeOpLit *)pcop)->lit = lit;
3877 /*-----------------------------------------------------------------*/
3878 /*-----------------------------------------------------------------*/
3879 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3881 char *s = buffer, tbuf[256], *tb=tbuf;
3885 tb = pic16_get_op(arg2, NULL, 0);
3886 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3887 pcop->type = PO_LITERAL;
3891 sprintf(s,"0x%02x, %s",lit, tb);
3893 pcop->name = Safe_strdup(s);
3896 ((pCodeOpLit2 *)pcop)->lit = lit;
3897 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3902 /*-----------------------------------------------------------------*/
3903 /*-----------------------------------------------------------------*/
3904 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3908 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3909 pcop->type = PO_IMMEDIATE;
3911 regs *r = pic16_dirregWithName(name);
3912 pcop->name = Safe_strdup(name);
3916 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3917 PCOI(pcop)->rIdx = r->rIdx;
3919 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3920 PCOI(pcop)->rIdx = -1;
3922 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3927 PCOI(pcop)->index = index;
3928 PCOI(pcop)->offset = offset;
3929 PCOI(pcop)->_const = code_space;
3934 /*-----------------------------------------------------------------*/
3935 /*-----------------------------------------------------------------*/
3936 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3942 if(!pcwb || !subtype) {
3943 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3947 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3948 pcop->type = PO_WILD;
3949 sprintf(s,"%%%d",id);
3950 pcop->name = Safe_strdup(s);
3952 PCOW(pcop)->id = id;
3953 PCOW(pcop)->pcwb = pcwb;
3954 PCOW(pcop)->subtype = subtype;
3955 PCOW(pcop)->matched = NULL;
3957 PCOW(pcop)->pcop2 = NULL;
3962 /*-----------------------------------------------------------------*/
3963 /*-----------------------------------------------------------------*/
3964 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3970 if(!pcwb || !subtype || !subtype2) {
3971 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3975 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3976 pcop->type = PO_WILD;
3977 sprintf(s,"%%%d",id);
3978 pcop->name = Safe_strdup(s);
3980 PCOW(pcop)->id = id;
3981 PCOW(pcop)->pcwb = pcwb;
3982 PCOW(pcop)->subtype = subtype;
3983 PCOW(pcop)->matched = NULL;
3985 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3987 if(!subtype2->name) {
3988 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3989 PCOW2(pcop)->pcop.type = PO_WILD;
3990 sprintf(s, "%%%d", id2);
3991 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3992 PCOW2(pcop)->id = id2;
3993 PCOW2(pcop)->subtype = subtype2;
3995 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3996 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3998 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4000 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4001 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4010 /*-----------------------------------------------------------------*/
4011 /*-----------------------------------------------------------------*/
4012 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4016 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4017 pcop->type = PO_GPR_BIT;
4019 pcop->name = Safe_strdup(s);
4023 PCORB(pcop)->bit = bit;
4024 PCORB(pcop)->inBitSpace = inBitSpace;
4025 PCORB(pcop)->subtype = subt;
4027 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4028 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4029 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4030 // PCOR(pcop)->rIdx = 0;
4035 /*-----------------------------------------------------------------*
4036 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4038 * If rIdx >=0 then a specific register from the set of registers
4039 * will be selected. If rIdx <0, then a new register will be searched
4041 *-----------------------------------------------------------------*/
4043 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4047 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4052 PCOR(pcop)->rIdx = rIdx;
4053 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4055 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4058 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4060 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4061 __FUNCTION__, __LINE__);
4066 pcop->type = PCOR(pcop)->r->pc_type;
4071 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4076 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4077 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4078 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4079 pcop->type = PCOR(pcop)->r->pc_type;
4080 pcop->name = PCOR(pcop)->r->name;
4082 // if(pic16_pcode_verbose) {
4083 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4084 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4090 /*-----------------------------------------------------------------*/
4091 /*-----------------------------------------------------------------*/
4092 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4096 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4099 pcop->key = Safe_strdup( key );
4101 return (PCOP(pcop));
4105 /*-----------------------------------------------------------------*/
4106 /*-----------------------------------------------------------------*/
4108 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4115 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4119 pcop = pic16_newpCodeOpLit(-1);
4123 pcop = pic16_newpCodeOpLabel(NULL,-1);
4126 pcop = pic16_newpCodeOpReg(-1);
4129 case PO_GPR_REGISTER:
4131 pcop = pic16_newpCodeOpRegFromStr(name);
4133 pcop = pic16_newpCodeOpReg(-1);
4137 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4140 pcop->name = Safe_strdup(name);
4148 #define DB_ITEMS_PER_LINE 8
4150 typedef struct DBdata
4157 static int DBd_init = -1;
4159 /*-----------------------------------------------------------------*/
4160 /* Initialiase "DB" data buffer */
4161 /*-----------------------------------------------------------------*/
4162 void pic16_initDB(void)
4168 /*-----------------------------------------------------------------*/
4169 /* Flush pending "DB" data to a pBlock */
4171 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4172 /*-----------------------------------------------------------------*/
4173 void pic16_flushDB(char ptype, void *p)
4177 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4180 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4183 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4187 DBd.buffer[0] = '\0';
4192 /*-----------------------------------------------------------------*/
4193 /* Add "DB" directives to a pBlock */
4194 /*-----------------------------------------------------------------*/
4195 void pic16_emitDB(char c, char ptype, void *p)
4200 // we need to initialize
4203 DBd.buffer[0] = '\0';
4206 l = strlen(DBd.buffer);
4207 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4209 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4212 if (DBd.count>= DB_ITEMS_PER_LINE)
4213 pic16_flushDB(ptype, p);
4216 void pic16_emitDS(char *s, char ptype, void *p)
4221 // we need to initialize
4224 DBd.buffer[0] = '\0';
4227 l = strlen(DBd.buffer);
4228 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4230 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4232 DBd.count++; //=strlen(s);
4234 pic16_flushDB(ptype, p);
4238 /*-----------------------------------------------------------------*/
4239 /*-----------------------------------------------------------------*/
4240 void pic16_pCodeConstString(char *name, char *value)
4244 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4249 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4251 pic16_addpBlock(pb);
4253 sprintf(buffer,"; %s = %s",name,value);
4255 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4256 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4259 pic16_emitDB(*value, 'p', (void *)pb);
4261 pic16_flushDB('p', (void *)pb);
4264 /*-----------------------------------------------------------------*/
4265 /*-----------------------------------------------------------------*/
4267 static void pCodeReadCodeTable(void)
4271 fprintf(stderr, " %s\n",__FUNCTION__);
4273 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4275 pic16_addpBlock(pb);
4277 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4278 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4279 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4280 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4282 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4283 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4284 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4285 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4290 /*-----------------------------------------------------------------*/
4291 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4292 /*-----------------------------------------------------------------*/
4293 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4300 /* If this is the first pcode to be added to a block that
4301 * was initialized with a NULL pcode, then go ahead and
4302 * make this pcode the head and tail */
4303 pb->pcHead = pb->pcTail = pc;
4306 pb->pcTail->next = pc;
4308 pc->prev = pb->pcTail;
4315 /*-----------------------------------------------------------------*/
4316 /* pic16_addpBlock - place a pBlock into the pFile */
4317 /*-----------------------------------------------------------------*/
4318 void pic16_addpBlock(pBlock *pb)
4320 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4323 /* First time called, we'll pass through here. */
4324 //_ALLOC(the_pFile,sizeof(pFile));
4325 the_pFile = Safe_calloc(1,sizeof(pFile));
4326 the_pFile->pbHead = the_pFile->pbTail = pb;
4327 the_pFile->functions = NULL;
4331 the_pFile->pbTail->next = pb;
4332 pb->prev = the_pFile->pbTail;
4334 the_pFile->pbTail = pb;
4337 /*-----------------------------------------------------------------*/
4338 /* removepBlock - remove a pBlock from the pFile */
4339 /*-----------------------------------------------------------------*/
4340 static void removepBlock(pBlock *pb)
4348 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4350 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4353 if(pbs == the_pFile->pbHead)
4354 the_pFile->pbHead = pbs->next;
4356 if (pbs == the_pFile->pbTail)
4357 the_pFile->pbTail = pbs->prev;
4360 pbs->next->prev = pbs->prev;
4363 pbs->prev->next = pbs->next;
4370 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4374 /*-----------------------------------------------------------------*/
4375 /* printpCode - write the contents of a pCode to a file */
4376 /*-----------------------------------------------------------------*/
4377 static void printpCode(FILE *of, pCode *pc)
4388 fprintf(of,"warning - unable to print pCode\n");
4391 /*-----------------------------------------------------------------*/
4392 /* pic16_printpBlock - write the contents of a pBlock to a file */
4393 /*-----------------------------------------------------------------*/
4394 void pic16_printpBlock(FILE *of, pBlock *pb)
4402 for(pc = pb->pcHead; pc; pc = pc->next) {
4403 if(isPCF(pc) && PCF(pc)->fname) {
4404 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4405 if(pb->dbName == 'A') {
4407 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4408 if(!strcmp(ab->name, PCF(pc)->fname)) {
4409 fprintf(of, "\t0X%06X", ab->address);
4420 /*-----------------------------------------------------------------*/
4422 /* pCode processing */
4426 /*-----------------------------------------------------------------*/
4428 void pic16_unlinkpCode(pCode *pc)
4434 fprintf(stderr,"Unlinking: ");
4435 printpCode(stderr, pc);
4438 pc->prev->next = pc->next;
4440 pc->next->prev = pc->prev;
4442 pc->prev = pc->next = NULL;
4446 /*-----------------------------------------------------------------*/
4447 /*-----------------------------------------------------------------*/
4449 static void genericDestruct(pCode *pc)
4452 pic16_unlinkpCode(pc);
4455 /* For instructions, tell the register (if there's one used)
4456 * that it's no longer needed */
4457 regs *reg = pic16_getRegFromInstruction(pc);
4459 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4461 if(PCI(pc)->is2MemOp) {
4462 reg = pic16_getRegFromInstruction2(pc);
4464 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4468 /* Instead of deleting the memory used by this pCode, mark
4469 * the object as bad so that if there's a pointer to this pCode
4470 * dangling around somewhere then (hopefully) when the type is
4471 * checked we'll catch it.
4475 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4481 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4482 /*-----------------------------------------------------------------*/
4483 /*-----------------------------------------------------------------*/
4484 /* modifiers for constant immediate */
4485 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4487 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4492 int use_buffer = 1; // copy the string to the passed buffer pointer
4497 use_buffer = 0; // Don't bother copying the string to the buffer.
4501 switch(pcop->type) {
4509 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4512 return PCOR(pcop)->r->name;
4515 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4517 SAFE_snprintf(&buffer,&size,"%s",r->name);
4524 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4525 if(PCOI(pcop)->index) {
4526 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4527 immdmod[ PCOI(pcop)->offset ],
4531 SAFE_snprintf(&s,&size,"%s(%s)",
4532 immdmod[ PCOI(pcop)->offset ],
4536 if(PCOI(pcop)->index) {
4537 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4542 SAFE_snprintf(&s,&size, "%s(%s)",
4549 case PO_GPR_REGISTER:
4552 // size = sizeof(buffer);
4553 if( PCOR(pcop)->instance) {
4554 SAFE_snprintf(&s,&size,"(%s + %d)",
4556 PCOR(pcop)->instance );
4558 SAFE_snprintf(&s,&size,"%s",pcop->name);
4565 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4574 return "NO operand1";
4577 /*-----------------------------------------------------------------*/
4578 /* pic16_get_op2 - variant to support two memory operand commands */
4579 /*-----------------------------------------------------------------*/
4580 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4585 int use_buffer = 1; // copy the string to the passed buffer pointer
4590 use_buffer = 0; // Don't bother copying the string to the buffer.
4594 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",
4595 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4596 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4600 switch(PCOR2(pcop)->pcop2->type) {
4608 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4611 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4614 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4617 SAFE_snprintf(&buffer,&size,"%s",r->name);
4628 if(PCOI(pcop)->_const) {
4629 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4630 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4633 8 * PCOI(pcop)->offset );
4635 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4637 if( PCOI(pcop)->index) {
4638 SAFE_snprintf(&s,&size,"(%s + %d)",
4640 PCOI(pcop)->index );
4642 if(PCOI(pcop)->offset)
4643 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4645 SAFE_snprintf(&s,&size,"%s",pcop->name);
4652 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4653 SAFE_snprintf(&s,&size,"(%s + %d)",
4654 PCOR(PCOR2(pcop)->pcop2)->r->name,
4655 PCOR(PCOR2(pcop)->pcop2)->instance );
4657 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4662 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4664 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4667 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4672 return "NO operand2";
4675 /*-----------------------------------------------------------------*/
4676 /*-----------------------------------------------------------------*/
4677 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4681 return pic16_get_op(pcc->pcop,NULL,0);
4683 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4684 * return ("ERROR Null: "__FUNCTION__);
4686 return ("ERROR Null: pic16_get_op_from_instruction");
4690 /*-----------------------------------------------------------------*/
4691 /*-----------------------------------------------------------------*/
4692 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4695 fprintf(of,"pcodeopprint- not implemented\n");
4698 /*-----------------------------------------------------------------*/
4699 /* pic16_pCode2str - convert a pCode instruction to string */
4700 /*-----------------------------------------------------------------*/
4701 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4707 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4708 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4709 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4717 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4719 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4721 if(PCI(pc)->is2MemOp) {
4722 SAFE_snprintf(&s,&size, "%s, %s",
4723 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4724 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4728 if(PCI(pc)->is2LitOp) {
4729 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4733 if(PCI(pc)->isBitInst) {
4734 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4735 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4736 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4737 PCI(pc)->pcop->name ,
4738 PCI(pc)->pcop->name );
4740 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4741 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4742 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4743 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4745 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4746 //PCI(pc)->pcop->t.bit );
4749 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4750 if( PCI(pc)->num_ops == 3)
4751 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4753 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4756 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4758 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4759 if(PCI(pc)->num_ops == 3)
4760 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4762 r = pic16_getRegFromInstruction(pc);
4763 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4764 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4766 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4775 /* assuming that comment ends with a \n */
4776 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4780 /* assuming that inline code ends with a \n */
4781 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4785 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4788 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4791 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4794 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4797 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4798 SAFE_snprintf(&s,&size,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4799 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4802 if(PCAD(pc)->directive) {
4803 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4806 /* special case to handle inline labels without a tab */
4807 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4812 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4816 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4824 /*-----------------------------------------------------------------*/
4825 /* genericPrint - the contents of a pCode to a file */
4826 /*-----------------------------------------------------------------*/
4827 static void genericPrint(FILE *of, pCode *pc)
4835 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4839 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4843 // If the opcode has a label, print that first
4845 pBranch *pbl = PCI(pc)->label;
4846 while(pbl && pbl->pc) {
4847 if(pbl->pc->type == PC_LABEL)
4848 pCodePrintLabel(of, pbl->pc);
4854 genericPrint(of,PCODE(PCI(pc)->cline));
4859 pic16_pCode2str(str, 256, pc);
4861 fprintf(of,"%s",str);
4863 if(pic16_debug_verbose) {
4864 fprintf(of, "\t;key=%03x",pc->seq);
4866 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4873 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4874 if(PCW(pc)->pci.label)
4875 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4877 if(PCW(pc)->operand) {
4878 fprintf(of,";\toperand ");
4879 pCodeOpPrint(of,PCW(pc)->operand );
4884 if(pic16_debug_verbose) {
4885 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4886 if(PCFL(pc)->ancestor)
4887 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4894 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4895 fprintf(of,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4896 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4902 pBranch *pbl = PCAD(pc)->pci.label;
4903 while(pbl && pbl->pc) {
4904 if(pbl->pc->type == PC_LABEL)
4905 pCodePrintLabel(of, pbl->pc);
4909 if(PCAD(pc)->directive) {
4910 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4913 /* special case to handle inline labels without tab */
4914 fprintf(of, "%s\n", PCAD(pc)->arg);
4920 fprintf(of,"unknown pCode type %d\n",pc->type);
4925 /*-----------------------------------------------------------------*/
4926 /* pCodePrintFunction - prints function begin/end */
4927 /*-----------------------------------------------------------------*/
4929 static void pCodePrintFunction(FILE *of, pCode *pc)
4936 if( ((pCodeFunction *)pc)->modname)
4937 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4940 if(!PCF(pc)->absblock) {
4941 if(PCF(pc)->fname) {
4942 pBranch *exits = PCF(pc)->to;
4945 fprintf(of,"%s:", PCF(pc)->fname);
4947 if(pic16_pcode_verbose)
4948 fprintf(of, "\t;Function start");
4954 exits = exits->next;
4958 if(pic16_pcode_verbose)
4959 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4962 if((PCF(pc)->from &&
4963 PCF(pc)->from->pc->type == PC_FUNCTION &&
4964 PCF(PCF(pc)->from->pc)->fname) ) {
4966 if(pic16_pcode_verbose)
4967 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4969 if(pic16_pcode_verbose)
4970 fprintf(of,"; exit point [can't find entry point]\n");
4976 /*-----------------------------------------------------------------*/
4977 /* pCodePrintLabel - prints label */
4978 /*-----------------------------------------------------------------*/
4980 static void pCodePrintLabel(FILE *of, pCode *pc)
4987 fprintf(of,"%s:\n",PCL(pc)->label);
4988 else if (PCL(pc)->key >=0)
4989 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4991 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4994 /*-----------------------------------------------------------------*/
4995 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4996 /* remove it if it is found. */
4997 /*-----------------------------------------------------------------*/
4998 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5005 if(pcl->type == PC_OPCODE)
5006 b = PCI(pcl)->label;
5008 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5013 //fprintf (stderr, "%s \n",__FUNCTION__);
5014 //pcl->print(stderr,pcl);
5015 //pc->print(stderr,pc);
5018 //fprintf (stderr, "found label\n");
5019 //pc->print(stderr, pc);
5023 bprev->next = b->next; /* Not first pCode in chain */
5027 PCI(pcl)->label = b->next; /* First pCode in chain */
5030 return; /* A label can't occur more than once */
5038 /*-----------------------------------------------------------------*/
5039 /*-----------------------------------------------------------------*/
5040 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5059 /*-----------------------------------------------------------------*/
5060 /* pBranchLink - given two pcodes, this function will link them */
5061 /* together through their pBranches */
5062 /*-----------------------------------------------------------------*/
5063 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5067 // Declare a new branch object for the 'from' pCode.
5069 //_ALLOC(b,sizeof(pBranch));
5070 b = Safe_calloc(1,sizeof(pBranch));
5071 b->pc = PCODE(t); // The link to the 'to' pCode.
5074 f->to = pic16_pBranchAppend(f->to,b);
5076 // Now do the same for the 'to' pCode.
5078 //_ALLOC(b,sizeof(pBranch));
5079 b = Safe_calloc(1,sizeof(pBranch));
5083 t->from = pic16_pBranchAppend(t->from,b);
5088 /*-----------------------------------------------------------------*/
5089 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5091 /*-----------------------------------------------------------------*/
5092 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5105 /*-----------------------------------------------------------------*/
5106 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5107 /*-----------------------------------------------------------------*/
5108 void pic16_pCodeUnlink(pCode *pc)
5113 if(!pc->prev || !pc->next) {
5114 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5118 /* first remove the pCode from the chain */
5119 pc->prev->next = pc->next;
5120 pc->next->prev = pc->prev;
5122 /* Now for the hard part... */
5124 /* Remove the branches */
5126 pb1 = PCI(pc)->from;
5128 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5129 * one we're unlinking */
5131 /* search for the link back to this pCode (the one we're
5133 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5134 pb2->pc = PCI(pc)->to->pc; // make the replacement
5136 /* if the pCode we're unlinking contains multiple 'to'
5137 * branches (e.g. this a skip instruction) then we need
5138 * to copy these extra branches to the chain. */
5139 if(PCI(pc)->to->next)
5140 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5149 /*-----------------------------------------------------------------*/
5150 /*-----------------------------------------------------------------*/
5152 static void genericAnalyze(pCode *pc)
5162 // Go through the pCodes that are in pCode chain and link
5163 // them together through the pBranches. Note, the pCodes
5164 // are linked together as a contiguous stream like the
5165 // assembly source code lines. The linking here mimics this
5166 // except that comments are not linked in.
5168 pCode *npc = pc->next;
5170 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5171 pBranchLink(pc,npc);
5176 /* reached the end of the pcode chain without finding
5177 * an instruction we could link to. */
5181 fprintf(stderr,"analyze PC_FLOW\n");
5185 fprintf(stderr,,";A bad pCode is being used\n");
5191 /*-----------------------------------------------------------------*/
5192 /*-----------------------------------------------------------------*/
5193 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5197 if(pc->type == PC_LABEL) {
5198 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5201 if((pc->type == PC_OPCODE)
5202 || (pc->type == PC_ASMDIR)
5204 pbr = PCI(pc)->label;
5206 if(pbr->pc->type == PC_LABEL) {
5207 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5217 /*-----------------------------------------------------------------*/
5218 /*-----------------------------------------------------------------*/
5219 static int checkLabel(pCode *pc)
5223 if(pc && isPCI(pc)) {
5224 pbr = PCI(pc)->label;
5226 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5236 /*-----------------------------------------------------------------*/
5237 /* findLabelinpBlock - Search the pCode for a particular label */
5238 /*-----------------------------------------------------------------*/
5239 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5246 for(pc = pb->pcHead; pc; pc = pc->next)
5247 if(compareLabel(pc,pcop_label))
5253 /*-----------------------------------------------------------------*/
5254 /* findLabel - Search the pCode for a particular label */
5255 /*-----------------------------------------------------------------*/
5256 static pCode * findLabel(pCodeOpLabel *pcop_label)
5264 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5265 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5269 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5273 /*-----------------------------------------------------------------*/
5274 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5275 /* in the linked list */
5276 /*-----------------------------------------------------------------*/
5277 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5290 /*-----------------------------------------------------------------*/
5291 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5292 /* in the linked list */
5293 /*-----------------------------------------------------------------*/
5294 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5308 //#define PCODE_DEBUG
5309 /*-----------------------------------------------------------------*/
5310 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5311 /* in the linked list */
5312 /*-----------------------------------------------------------------*/
5313 pCode * pic16_findNextInstruction(pCode *pci)
5318 if((pc->type == PC_OPCODE)
5319 || (pc->type == PC_WILD)
5320 || (pc->type == PC_ASMDIR)
5325 fprintf(stderr,"pic16_findNextInstruction: ");
5326 printpCode(stderr, pc);
5331 //fprintf(stderr,"Couldn't find instruction\n");
5335 /*-----------------------------------------------------------------*/
5336 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5337 /* in the linked list */
5338 /*-----------------------------------------------------------------*/
5339 pCode * pic16_findPrevInstruction(pCode *pci)
5345 if((pc->type == PC_OPCODE)
5346 || (pc->type == PC_WILD)
5347 || (pc->type == PC_ASMDIR)
5353 fprintf(stderr,"pic16_findPrevInstruction: ");
5354 printpCode(stderr, pc);
5359 //fprintf(stderr,"Couldn't find instruction\n");
5366 /*-----------------------------------------------------------------*/
5367 /* findFunctionEnd - given a pCode find the end of the function */
5368 /* that contains it */
5369 /*-----------------------------------------------------------------*/
5370 static pCode * findFunctionEnd(pCode *pc)
5374 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5380 fprintf(stderr,"Couldn't find function end\n");
5385 /*-----------------------------------------------------------------*/
5386 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5387 /* instruction with which it is associated. */
5388 /*-----------------------------------------------------------------*/
5389 static void AnalyzeLabel(pCode *pc)
5392 pic16_pCodeUnlink(pc);
5398 static void AnalyzeGOTO(pCode *pc)
5401 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5405 static void AnalyzeSKIP(pCode *pc)
5408 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5409 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5413 static void AnalyzeRETURN(pCode *pc)
5416 // branch_link(pc,findFunctionEnd(pc->next));
5422 /*-----------------------------------------------------------------*/
5423 /*-----------------------------------------------------------------*/
5424 regs * pic16_getRegFromInstruction(pCode *pc)
5430 PCI(pc)->num_ops == 0 ||
5431 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5435 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5436 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5439 switch(PCI(pc)->pcop->type) {
5445 return PCOR(PCI(pc)->pcop)->r;
5449 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5450 return PCOR(PCI(pc)->pcop)->r;
5453 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5455 if(PCOI(PCI(pc)->pcop)->r)
5456 return (PCOI(PCI(pc)->pcop)->r);
5461 return PCOR(PCI(pc)->pcop)->r;
5463 case PO_GPR_REGISTER:
5465 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5466 return PCOR(PCI(pc)->pcop)->r;
5469 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5473 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5474 // genericPrint(stderr, pc);
5482 /*-------------------------------------------------------------------------------*/
5483 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5484 /*-------------------------------------------------------------------------------*/
5485 regs * pic16_getRegFromInstruction2(pCode *pc)
5491 PCI(pc)->num_ops == 0 ||
5492 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5497 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5498 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5502 * operands supported in MOVFF:
5509 switch(PCI(pc)->pcop->type) {
5515 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5517 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5521 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5522 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5526 // if(PCOI(PCI(pc)->pcop)->r)
5527 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5529 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5530 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5533 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5534 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5541 // return PCOR2(PCI(pc)->pcop)->r;
5543 case PO_GPR_REGISTER:
5545 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5546 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5550 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5553 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5554 //genericPrint(stderr, pc);
5562 /*-----------------------------------------------------------------*/
5563 /*-----------------------------------------------------------------*/
5565 static void AnalyzepBlock(pBlock *pb)
5572 /* Find all of the registers used in this pBlock
5573 * by looking at each instruction and examining it's
5576 for(pc = pb->pcHead; pc; pc = pc->next) {
5578 /* Is this an instruction with operands? */
5579 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5581 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5583 /* Loop through all of the registers declared so far in
5584 this block and see if we find this one there */
5586 regs *r = setFirstItem(pb->tregisters);
5589 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5590 PCOR(PCI(pc)->pcop)->r = r;
5593 r = setNextItem(pb->tregisters);
5597 /* register wasn't found */
5598 //r = Safe_calloc(1, sizeof(regs));
5599 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5600 //addSet(&pb->tregisters, r);
5601 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5602 //PCOR(PCI(pc)->pcop)->r = r;
5603 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5605 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5608 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5609 if(PCOR(PCI(pc)->pcop)->r) {
5610 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5611 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5613 if(PCI(pc)->pcop->name)
5614 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5616 fprintf(stderr,"ERROR: NULL register\n");
5625 /*-----------------------------------------------------------------*/
5627 /*-----------------------------------------------------------------*/
5628 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5630 static void InsertpFlow(pCode *pc, pCode **pflow)
5633 PCFL(*pflow)->end = pc;
5635 if(!pc || !pc->next)
5638 *pflow = pic16_newpCodeFlow();
5639 pic16_pCodeInsertAfter(pc, *pflow);
5642 /*-----------------------------------------------------------------*/
5643 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5644 /* the flow blocks. */
5646 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5647 * point the instruction flow changes.
5649 /*-----------------------------------------------------------------*/
5650 void pic16_BuildFlow(pBlock *pb)
5653 pCode *last_pci=NULL;
5660 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5661 /* Insert a pCodeFlow object at the beginning of a pBlock */
5663 InsertpFlow(pb->pcHead, &pflow);
5665 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5666 //pflow->next = pb->pcHead; /* Make the current head the next object */
5667 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5668 //pb->pcHead = pflow; /* Make the Flow object the head */
5671 for( pc = pic16_findNextInstruction(pb->pcHead);
5673 pc=pic16_findNextInstruction(pc)) {
5676 PCI(pc)->pcflow = PCFL(pflow);
5678 //fprintf(stderr," build: ");
5679 //pflow->print(stderr,pflow);
5681 if( PCI(pc)->isSkip) {
5683 /* The two instructions immediately following this one
5684 * mark the beginning of a new flow segment */
5686 while(pc && PCI(pc)->isSkip) {
5688 PCI(pc)->pcflow = PCFL(pflow);
5692 InsertpFlow(pc, &pflow);
5693 pc=pic16_findNextInstruction(pc->next);
5701 PCI(pc)->pcflow = PCFL(pflow);
5703 InsertpFlow(pc, &pflow);
5705 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5707 InsertpFlow(pc, &pflow);
5710 } else if (checkLabel(pc)) {
5712 /* This instruction marks the beginning of a
5713 * new flow segment */
5718 /* If the previous pCode is not a flow object, then
5719 * insert a new flow object. (This check prevents
5720 * two consecutive flow objects from being insert in
5721 * the case where a skip instruction preceeds an
5722 * instruction containing a label.) */
5724 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5725 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5727 PCI(pc)->pcflow = PCFL(pflow);
5734 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5736 PCFL(pflow)->end = pb->pcTail;
5739 /*-------------------------------------------------------------------*/
5740 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5741 /* the flow blocks. */
5743 * unBuildFlow removes pCodeFlow objects from a pCode chain
5745 /*-----------------------------------------------------------------*/
5746 static void unBuildFlow(pBlock *pb)
5761 if(PCI(pc)->pcflow) {
5762 //free(PCI(pc)->pcflow);
5763 PCI(pc)->pcflow = NULL;
5766 } else if(isPCFL(pc) )
5775 /*-----------------------------------------------------------------*/
5776 /*-----------------------------------------------------------------*/
5777 static void dumpCond(int cond)
5780 static char *pcc_str[] = {
5794 int ncond = sizeof(pcc_str) / sizeof(char *);
5797 fprintf(stderr, "0x%04X\n",cond);
5799 for(i=0,j=1; i<ncond; i++, j<<=1)
5801 fprintf(stderr, " %s\n",pcc_str[i]);
5807 /*-----------------------------------------------------------------*/
5808 /*-----------------------------------------------------------------*/
5809 static void FlowStats(pCodeFlow *pcflow)
5817 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5819 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5822 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5827 fprintf(stderr, " FlowStats inCond: ");
5828 dumpCond(pcflow->inCond);
5829 fprintf(stderr, " FlowStats outCond: ");
5830 dumpCond(pcflow->outCond);
5834 /*-----------------------------------------------------------------*
5835 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5836 * if it affects the banking bits.
5838 * return: -1 == Banking bits are unaffected by this pCode.
5840 * return: > 0 == Banking bits are affected.
5842 * If the banking bits are affected, then the returned value describes
5843 * which bits are affected and how they're affected. The lower half
5844 * of the integer maps to the bits that are affected, the upper half
5845 * to whether they're set or cleared.
5847 *-----------------------------------------------------------------*/
5849 static int isBankInstruction(pCode *pc)
5857 if( PCI(pc)->op == POC_MOVLB ||
5858 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5859 bank = PCOL(pc)->lit;
5866 /*-----------------------------------------------------------------*/
5867 /*-----------------------------------------------------------------*/
5868 static void FillFlow(pCodeFlow *pcflow)
5877 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5879 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5882 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5889 isBankInstruction(pc);
5891 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5895 fprintf(stderr, " FillFlow - Bad end of flow\n");
5897 fprintf(stderr, " FillFlow - Ending flow with\n ");
5898 pc->print(stderr,pc);
5901 fprintf(stderr, " FillFlow inCond: ");
5902 dumpCond(pcflow->inCond);
5903 fprintf(stderr, " FillFlow outCond: ");
5904 dumpCond(pcflow->outCond);
5908 /*-----------------------------------------------------------------*/
5909 /*-----------------------------------------------------------------*/
5910 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5912 pCodeFlowLink *fromLink, *toLink;
5914 if(!from || !to || !to->pcflow || !from->pcflow)
5917 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5918 toLink = pic16_newpCodeFlowLink(to->pcflow);
5920 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5921 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5925 /*-----------------------------------------------------------------*
5926 * void LinkFlow(pBlock *pb)
5928 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5929 * non-branching segments. In LinkFlow, we determine the execution
5930 * order of these segments. For example, if one of the segments ends
5931 * with a skip, then we know that there are two possible flow segments
5932 * to which control may be passed.
5933 *-----------------------------------------------------------------*/
5934 static void LinkFlow(pBlock *pb)
5940 //fprintf(stderr,"linkflow \n");
5942 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5944 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5947 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5949 //fprintf(stderr," link: ");
5950 //pcflow->print(stderr,pcflow);
5952 //FillFlow(PCFL(pcflow));
5954 pc = PCFL(pcflow)->end;
5956 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5957 if(isPCI_SKIP(pc)) {
5958 //fprintf(stderr, "ends with skip\n");
5959 //pc->print(stderr,pc);
5960 pct=pic16_findNextInstruction(pc->next);
5961 LinkFlow_pCode(PCI(pc),PCI(pct));
5962 pct=pic16_findNextInstruction(pct->next);
5963 LinkFlow_pCode(PCI(pc),PCI(pct));
5967 if(isPCI_BRANCH(pc)) {
5968 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5970 //fprintf(stderr, "ends with branch\n ");
5971 //pc->print(stderr,pc);
5973 if(!(pcol && isPCOLAB(pcol))) {
5974 if((PCI(pc)->op != POC_RETLW)
5975 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5977 /* continue if label is '$' which assembler knows how to parse */
5978 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5980 if(pic16_pcode_verbose) {
5981 pc->print(stderr,pc);
5982 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5988 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5989 LinkFlow_pCode(PCI(pc),PCI(pct));
5991 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5992 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5994 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6000 //fprintf(stderr, "ends with non-branching instruction:\n");
6001 //pc->print(stderr,pc);
6003 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6009 //fprintf(stderr, "ends with unknown\n");
6010 //pc->print(stderr,pc);
6014 //fprintf(stderr, "ends with nothing: ERROR\n");
6018 /*-----------------------------------------------------------------*/
6019 /*-----------------------------------------------------------------*/
6021 /*-----------------------------------------------------------------*/
6022 /*-----------------------------------------------------------------*/
6023 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6029 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6032 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6042 /*-----------------------------------------------------------------*/
6043 /* insertBankSwitch - inserts a bank switch statement in the */
6044 /* assembly listing */
6046 /* position == 0: insert before */
6047 /* position == 1: insert after pc */
6048 /* position == 2: like 0 but previous was a skip instruction */
6049 /*-----------------------------------------------------------------*/
6050 pCodeOp *pic16_popGetLabel(unsigned int key);
6051 extern int pic16_labelOffset;
6053 static void insertBankSwitch(unsigned char position, pCode *pc)
6060 /* emit BANKSEL [symbol] */
6063 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6065 // position = 0; // position is always before (sanity check!)
6068 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6069 pc->print(stderr, pc);
6074 /* insert the bank switch after this pc instruction */
6075 pCode *pcnext = pic16_findNextInstruction(pc);
6077 pic16_pCodeInsertAfter(pc, new_pc);
6078 if(pcnext)pc = pcnext;
6082 /* insert the bank switch BEFORE this pc instruction */
6083 pic16_pCodeInsertAfter(pc->prev, new_pc);
6088 pCode *pcnext, *pcprev, *npci, *ppc;
6090 int ofs1=0, ofs2=0, len=0;
6092 /* just like 0, but previous was a skip instruction,
6093 * so some care should be taken */
6095 pic16_labelOffset += 10000;
6096 tlbl = newiTempLabel(NULL);
6098 /* invert skip instruction */
6099 pcprev = pic16_findPrevInstruction(pc->prev);
6100 ipci = PCI(pcprev)->inverted_op;
6101 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6103 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6105 /* copy info from old pCode */
6106 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6107 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6108 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6109 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6110 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (unsigned int)(&(PCI(npci)->pci_magic)) - (unsigned int)(&(PCI(npci)->from)));
6111 PCI(npci)->op = PCI(pcprev)->inverted_op;
6113 /* unlink old pCode */
6115 ppc->next = pcprev->next;
6116 pcprev->next->prev = ppc;
6117 pic16_pCodeInsertAfter(ppc, npci);
6119 /* extra instructions to handle invertion */
6120 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6121 pic16_pCodeInsertAfter(pc->prev, pcnext);
6122 pic16_pCodeInsertAfter(pc->prev, new_pc);
6124 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6125 pic16_pCodeInsertAfter(pc, pcnext);
6130 /* Move the label, if there is one */
6131 if(PCI(pc)->label) {
6132 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6133 // __FILE__, __LINE__, pc, new_pc);
6134 PCAD(new_pc)->pci.label = PCI(pc)->label;
6135 PCI(pc)->label = NULL;
6140 /*-----------------------------------------------------------------*/
6141 /*int compareBankFlow - compare the banking requirements between */
6143 /*-----------------------------------------------------------------*/
6144 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6147 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6150 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6153 if(pcflow->firstBank == -1)
6157 if(pcflowLink->pcflow->firstBank == -1) {
6158 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6159 pcflowLink->pcflow->to :
6160 pcflowLink->pcflow->from);
6161 return compareBankFlow(pcflow, pctl, toORfrom);
6165 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6168 pcflowLink->bank_conflict++;
6169 pcflowLink->pcflow->FromConflicts++;
6170 pcflow->ToConflicts++;
6173 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6176 pcflowLink->bank_conflict++;
6177 pcflowLink->pcflow->ToConflicts++;
6178 pcflow->FromConflicts++;
6182 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6183 pcflowLink->pcflow->pc.seq,
6184 pcflowLink->pcflow->FromConflicts,
6185 pcflowLink->pcflow->ToConflicts);
6192 /*-----------------------------------------------------------------*/
6193 /*-----------------------------------------------------------------*/
6194 static void DumpFlow(pBlock *pb)
6198 pCodeFlowLink *pcfl;
6201 fprintf(stderr,"Dump flow \n");
6202 pb->pcHead->print(stderr, pb->pcHead);
6204 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6205 pcflow->print(stderr,pcflow);
6207 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6209 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6211 if(!isPCFL(pcflow)) {
6212 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6215 fprintf(stderr,"dumping: ");
6216 pcflow->print(stderr,pcflow);
6217 FlowStats(PCFL(pcflow));
6219 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6221 pc = PCODE(pcfl->pcflow);
6223 fprintf(stderr, " from seq %d:\n",pc->seq);
6225 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6226 pc->print(stderr,pc);
6231 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6233 pc = PCODE(pcfl->pcflow);
6235 fprintf(stderr, " to seq %d:\n",pc->seq);
6237 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6238 pc->print(stderr,pc);
6247 /*-----------------------------------------------------------------*/
6248 /*-----------------------------------------------------------------*/
6249 static int OptimizepBlock(pBlock *pb)
6254 if(!pb || !peepOptimizing)
6257 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6259 for(pc = pb->pcHead; pc; pc = pc->next)
6260 matches += pic16_pCodePeepMatchRule(pc);
6263 pc = pic16_findNextInstruction(pb->pcHead);
6271 if(pic16_pCodePeepMatchRule(pc)) {
6276 pc = pic16_findNextInstruction(pcprev->next);
6278 pc = pic16_findNextInstruction(pb->pcHead);
6280 pc = pic16_findNextInstruction(pc->next);
6284 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6289 /*-----------------------------------------------------------------*/
6290 /*-----------------------------------------------------------------*/
6291 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6295 for(pc = pcs; pc; pc = pc->next) {
6297 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6299 (PCI(pc)->pcop->type == PO_LABEL) &&
6300 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6308 /*-----------------------------------------------------------------*/
6309 /*-----------------------------------------------------------------*/
6310 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6317 (PCI(pc)->pcop->type == PO_LABEL)) {
6319 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6321 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6322 // if(pcol->pcop.name)
6323 // free(pcol->pcop.name);
6325 /* If the key is negative, then we (probably) have a label to
6326 * a function and the name is already defined */
6329 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6333 //sprintf(buffer,"_%05d_DS_",pcl->key);
6335 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6337 pcol->pcop.name = Safe_strdup(s);
6338 pcol->key = pcl->key;
6339 //pc->print(stderr,pc);
6346 /*-----------------------------------------------------------------*/
6347 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6348 /* pCode chain if they're not used. */
6349 /*-----------------------------------------------------------------*/
6350 static void pBlockRemoveUnusedLabels(pBlock *pb)
6352 pCode *pc; pCodeLabel *pcl;
6357 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6359 pBranch *pbr = PCI(pc)->label;
6360 if(pbr && pbr->next) {
6361 pCode *pcd = pb->pcHead;
6363 // fprintf(stderr, "multiple labels\n");
6364 // pc->print(stderr,pc);
6369 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6370 //fprintf(stderr,"Used by:\n");
6371 //pcd->print(stderr,pcd);
6373 exchangeLabels(PCL(pbr->pc),pcd);
6382 for(pc = pb->pcHead; pc; pc = pc->next) {
6384 if(isPCL(pc)) // pc->type == PC_LABEL)
6386 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6387 pcl = PCL(PCI(pc)->label->pc);
6390 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6392 /* This pCode is a label, so search the pBlock to see if anyone
6395 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6397 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6398 /* Couldn't find an instruction that refers to this label
6399 * So, unlink the pCode label from it's pCode chain
6400 * and destroy the label */
6401 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6403 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6404 if(pc->type == PC_LABEL) {
6405 pic16_unlinkpCode(pc);
6406 pCodeLabelDestruct(pc);
6408 unlinkpCodeFromBranch(pc, PCODE(pcl));
6409 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6420 /*-----------------------------------------------------------------*/
6421 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6422 /* chain and put them into pBranches that are */
6423 /* associated with the appropriate pCode */
6425 /*-----------------------------------------------------------------*/
6426 void pic16_pBlockMergeLabels(pBlock *pb)
6429 pCode *pc, *pcnext=NULL;
6434 /* First, Try to remove any unused labels */
6435 //pBlockRemoveUnusedLabels(pb);
6437 /* Now loop through the pBlock and merge the labels with the opcodes */
6440 // for(pc = pb->pcHead; pc; pc = pc->next) {
6443 pCode *pcn = pc->next;
6445 if(pc->type == PC_LABEL) {
6447 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6448 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6450 if((pcnext = pic16_findNextInstruction(pc) )) {
6452 // pcnext->print(stderr, pcnext);
6454 // Unlink the pCode label from it's pCode chain
6455 pic16_unlinkpCode(pc);
6457 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6458 // And link it into the instruction's pBranch labels. (Note, since
6459 // it's possible to have multiple labels associated with one instruction
6460 // we must provide a means to accomodate the additional labels. Thus
6461 // the labels are placed into the singly-linked list "label" as
6462 // opposed to being a single member of the pCodeInstruction.)
6464 //_ALLOC(pbr,sizeof(pBranch));
6466 pbr = Safe_calloc(1,sizeof(pBranch));
6470 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6473 if(pic16_pcode_verbose)
6474 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6476 } else if(pc->type == PC_CSOURCE) {
6478 /* merge the source line symbolic info into the next instruction */
6479 if((pcnext = pic16_findNextInstruction(pc) )) {
6481 // Unlink the pCode label from it's pCode chain
6482 pic16_unlinkpCode(pc);
6483 PCI(pcnext)->cline = PCCS(pc);
6484 //fprintf(stderr, "merging CSRC\n");
6485 //genericPrint(stderr,pcnext);
6491 pBlockRemoveUnusedLabels(pb);
6495 /*-----------------------------------------------------------------*/
6496 /*-----------------------------------------------------------------*/
6497 static int OptimizepCode(char dbName)
6499 #define MAX_PASSES 4
6508 DFPRINTF((stderr," Optimizing pCode\n"));
6512 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6513 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6514 matches += OptimizepBlock(pb);
6517 while(matches && ++passes < MAX_PASSES);
6524 const char *pic16_pCodeOpType(pCodeOp *pcop);
6525 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6528 /*-----------------------------------------------------------------*/
6529 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6530 /*-----------------------------------------------------------------*/
6532 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6536 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6537 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6539 if( !( (pcop->type == PO_LABEL) ||
6540 (pcop->type == PO_LITERAL) ||
6541 (pcop->type == PO_STR) ))
6542 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6543 PCOR(pcop)->r->wasUsed = 1;
6549 /*----------------------------------------------------------------------*
6550 * pic16_areRegsSame - check to see if the names of two registers match *
6551 *----------------------------------------------------------------------*/
6552 int pic16_areRegsSame(regs *r1, regs *r2)
6554 if(!strcmp(r1->name, r2->name))return 1;
6560 /*-----------------------------------------------------------------*/
6561 /*-----------------------------------------------------------------*/
6562 static void pic16_FixRegisterBanking(pBlock *pb)
6566 regs *reg, *prevreg;
6567 unsigned char flag=0;
6572 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6575 /* loop through all of the flow blocks with in one pblock */
6577 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6581 /* at this point, pc should point to a PC_FLOW object */
6582 /* for each flow block, determine the register banking
6585 if(!isPCI(pc))goto loop;
6587 if(PCI(pc)->is2MemOp)goto loop;
6589 reg = pic16_getRegFromInstruction(pc);
6592 pc->print(stderr, pc);
6593 fprintf(stderr, "reg = %p\n", reg);
6596 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6597 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6598 reg->address,reg->isBitField, reg->isFixed);
6602 /* now make some tests to make sure that instruction needs bank switch */
6604 /* if no register exists, and if not a bit opcode goto loop */
6606 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6609 if(isPCI_SKIP(pc)) {
6610 // fprintf(stderr, "instruction is SKIP instruction\n");
6612 if(reg && isACCESS_BANK(reg))goto loop;
6614 if(!isBankInstruction(pc))goto loop;
6616 if(isPCI_LIT(pc))goto loop;
6618 if(PCI(pc)->op == POC_CALL)goto loop;
6620 /* Examine the instruction before this one to make sure it is
6621 * not a skip type instruction */
6622 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6624 flag = 0; /* add before this instruction */
6626 /* if previous instruction is a skip one, then set flag
6627 * to 2 and call insertBankSwitch */
6628 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6631 insertBankSwitch(flag, pc);
6634 // fprintf(stderr, "BANK SWITCH inserted\n");
6643 static void pBlockDestruct(pBlock *pb)
6654 /*-----------------------------------------------------------------*/
6655 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6656 /* name dbName and combine them */
6657 /* into one block */
6658 /*-----------------------------------------------------------------*/
6659 static void mergepBlocks(char dbName)
6662 pBlock *pb, *pbmerged = NULL,*pbn;
6664 pb = the_pFile->pbHead;
6666 //fprintf(stderr," merging blocks named %c\n",dbName);
6670 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6671 if( getpBlock_dbName(pb) == dbName) {
6673 //fprintf(stderr," merged block %c\n",dbName);
6678 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6679 /* pic16_addpCode2pBlock doesn't handle the tail: */
6680 pbmerged->pcTail = pb->pcTail;
6682 pb->prev->next = pbn;
6684 pbn->prev = pb->prev;
6689 //pic16_printpBlock(stderr, pbmerged);
6696 /*-----------------------------------------------------------------*/
6697 /* AnalyzeFlow - Examine the flow of the code and optimize */
6699 /* level 0 == minimal optimization */
6700 /* optimize registers that are used only by two instructions */
6701 /* level 1 == maximal optimization */
6702 /* optimize by looking at pairs of instructions that use the */
6704 /*-----------------------------------------------------------------*/
6706 static void AnalyzeFlow(int level)
6708 static int times_called=0;
6713 /* remove unused allocated registers before exiting */
6714 pic16_RemoveUnusedRegisters();
6720 /* if this is not the first time this function has been called,
6721 then clean up old flow information */
6722 if(times_called++) {
6723 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6726 pic16_RegsUnMapLiveRanges();
6731 /* Phase 2 - Flow Analysis - Register Banking
6733 * In this phase, the individual flow blocks are examined
6734 * and register banking is fixed.
6738 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6739 pic16_FixRegisterBanking(pb);
6742 /* Phase 2 - Flow Analysis
6744 * In this phase, the pCode is partition into pCodeFlow
6745 * blocks. The flow blocks mark the points where a continuous
6746 * stream of instructions changes flow (e.g. because of
6747 * a call or goto or whatever).
6750 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6751 pic16_BuildFlow(pb);
6754 /* Phase 2 - Flow Analysis - linking flow blocks
6756 * In this phase, the individual flow blocks are examined
6757 * to determine their order of excution.
6760 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6763 /* Phase 3 - Flow Analysis - Flow Tree
6765 * In this phase, the individual flow blocks are examined
6766 * to determine their order of execution.
6769 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6770 pic16_BuildFlowTree(pb);
6773 /* Phase x - Flow Analysis - Used Banks
6775 * In this phase, the individual flow blocks are examined
6776 * to determine the Register Banks they use
6780 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6785 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6786 pic16_pCodeRegMapLiveRanges(pb);
6788 pic16_RemoveUnusedRegisters();
6790 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6791 pic16_pCodeRegOptimizeRegUsage(level);
6799 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6804 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6806 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6807 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6808 pcflow = pcflow->next) {
6810 FillFlow(PCFL(pcflow));
6815 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6818 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6819 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6820 pcflow = pcflow->next) {
6822 FlowStats(PCFL(pcflow));
6828 /* VR -- no need to analyze banking in flow, but left here :
6829 * 1. because it may be used in the future for other purposes
6830 * 2. because if omitted we'll miss some optimization done here
6832 * Perhaps I should rename it to something else
6835 /*-----------------------------------------------------------------*/
6836 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6837 /* assigned to the registers. */
6839 /*-----------------------------------------------------------------*/
6841 void pic16_AnalyzeBanking(void)
6846 /* Phase x - Flow Analysis - Used Banks
6848 * In this phase, the individual flow blocks are examined
6849 * to determine the Register Banks they use
6855 if(!the_pFile)return;
6857 if(!pic16_options.no_banksel) {
6858 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6859 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6860 pic16_FixRegisterBanking(pb);
6866 /*-----------------------------------------------------------------*/
6867 /* buildCallTree - Look at the flow and extract all of the calls. */
6868 /*-----------------------------------------------------------------*/
6869 static set *register_usage(pBlock *pb);
6871 static void buildCallTree(void )
6883 /* Now build the call tree.
6884 First we examine all of the pCodes for functions.
6885 Keep in mind that the function boundaries coincide
6886 with pBlock boundaries.
6888 The algorithm goes something like this:
6889 We have two nested loops. The outer loop iterates
6890 through all of the pBlocks/functions. The inner
6891 loop iterates through all of the pCodes for
6892 a given pBlock. When we begin iterating through
6893 a pBlock, the variable pc_fstart, pCode of the start
6894 of a function, is cleared. We then search for pCodes
6895 of type PC_FUNCTION. When one is encountered, we
6896 initialize pc_fstart to this and at the same time
6897 associate a new pBranch object that signifies a
6898 branch entry. If a return is found, then this signifies
6899 a function exit point. We'll link the pCodes of these
6900 returns to the matching pc_fstart.
6902 When we're done, a doubly linked list of pBranches
6903 will exist. The head of this list is stored in
6904 `the_pFile', which is the meta structure for all
6905 of the pCode. Look at the pic16_printCallTree function
6906 on how the pBranches are linked together.
6909 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6910 pCode *pc_fstart=NULL;
6911 for(pc = pb->pcHead; pc; pc = pc->next) {
6913 if(isPCI(pc) && pc_fstart) {
6914 if(PCI(pc)->is2MemOp) {
6915 r = pic16_getRegFromInstruction2(pc);
6916 if(r && !strcmp(r->name, "POSTDEC1"))
6917 PCF(pc_fstart)->stackusage++;
6919 r = pic16_getRegFromInstruction(pc);
6920 if(r && !strcmp(r->name, "PREINC1"))
6921 PCF(pc_fstart)->stackusage--;
6926 if (PCF(pc)->fname) {
6928 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6929 //fprintf(stderr," found main \n");
6930 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6934 pbr = Safe_calloc(1,sizeof(pBranch));
6935 pbr->pc = pc_fstart = pc;
6938 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6940 // Here's a better way of doing the same:
6941 addSet(&pb->function_entries, pc);
6944 // Found an exit point in a function, e.g. return
6945 // (Note, there may be more than one return per function)
6947 pBranchLink(PCF(pc_fstart), PCF(pc));
6949 addSet(&pb->function_exits, pc);
6951 } else if(isCALL(pc)) {
6952 addSet(&pb->function_calls,pc);
6959 /* This is not needed because currently all register used
6960 * by a function are stored in stack -- VR */
6962 /* Re-allocate the registers so that there are no collisions
6963 * between local variables when one function call another */
6966 // pic16_deallocateAllRegs();
6968 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6976 /*-----------------------------------------------------------------*/
6977 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6978 /* all of the logical connections. */
6980 /* Essentially what's done here is that the pCode flow is */
6982 /*-----------------------------------------------------------------*/
6984 void pic16_AnalyzepCode(char dbName)
6995 /* Phase 1 - Register allocation and peep hole optimization
6997 * The first part of the analysis is to determine the registers
6998 * that are used in the pCode. Once that is done, the peep rules
6999 * are applied to the code. We continue to loop until no more
7000 * peep rule optimizations are found (or until we exceed the
7001 * MAX_PASSES threshold).
7003 * When done, the required registers will be determined.
7009 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7010 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7012 /* First, merge the labels with the instructions */
7013 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7014 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7016 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7017 //fprintf(stderr," analyze and merging block %c\n",dbName);
7018 pic16_pBlockMergeLabels(pb);
7021 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7026 changes = OptimizepCode(dbName);
7029 } while(changes && (i++ < MAX_PASSES));
7034 /*-----------------------------------------------------------------*/
7035 /* ispCodeFunction - returns true if *pc is the pCode of a */
7037 /*-----------------------------------------------------------------*/
7038 static bool ispCodeFunction(pCode *pc)
7041 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7047 /*-----------------------------------------------------------------*/
7048 /* findFunction - Search for a function by name (given the name) */
7049 /* in the set of all functions that are in a pBlock */
7050 /* (note - I expect this to change because I'm planning to limit */
7051 /* pBlock's to just one function declaration */
7052 /*-----------------------------------------------------------------*/
7053 static pCode *findFunction(char *fname)
7060 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7062 pc = setFirstItem(pb->function_entries);
7065 if((pc->type == PC_FUNCTION) &&
7067 (strcmp(fname, PCF(pc)->fname)==0))
7070 pc = setNextItem(pb->function_entries);
7078 static void MarkUsedRegisters(set *regset)
7083 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7084 // fprintf(stderr, "marking register = %s\t", r1->name);
7085 r2 = pic16_regWithIdx(r1->rIdx);
7086 // fprintf(stderr, "to register = %s\n", r2->name);
7092 static void pBlockStats(FILE *of, pBlock *pb)
7098 if(!pic16_pcode_verbose)return;
7100 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7102 // for now just print the first element of each set
7103 pc = setFirstItem(pb->function_entries);
7105 fprintf(of,";entry: ");
7108 pc = setFirstItem(pb->function_exits);
7110 fprintf(of,";has an exit\n");
7114 pc = setFirstItem(pb->function_calls);
7116 fprintf(of,";functions called:\n");
7119 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7120 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7122 pc = setNextItem(pb->function_calls);
7126 r = setFirstItem(pb->tregisters);
7128 int n = elementsInSet(pb->tregisters);
7130 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7133 fprintf(of,"; %s\n",r->name);
7134 r = setNextItem(pb->tregisters);
7138 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7141 /*-----------------------------------------------------------------*/
7142 /*-----------------------------------------------------------------*/
7144 static void sequencepCode(void)
7150 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7152 pb->seq = GpCodeSequenceNumber+1;
7154 for( pc = pb->pcHead; pc; pc = pc->next)
7155 pc->seq = ++GpCodeSequenceNumber;
7161 /*-----------------------------------------------------------------*/
7162 /*-----------------------------------------------------------------*/
7163 static set *register_usage(pBlock *pb)
7166 set *registers=NULL;
7167 set *registersInCallPath = NULL;
7169 /* check recursion */
7171 pc = setFirstItem(pb->function_entries);
7178 if(pc->type != PC_FUNCTION)
7179 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7181 pc = setFirstItem(pb->function_calls);
7182 for( ; pc; pc = setNextItem(pb->function_calls)) {
7184 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7185 char *dest = pic16_get_op_from_instruction(PCI(pc));
7187 pcn = findFunction(dest);
7189 registersInCallPath = register_usage(pcn->pb);
7191 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7196 pBlockStats(stderr,pb); // debug
7199 // Mark the registers in this block as used.
7201 MarkUsedRegisters(pb->tregisters);
7202 if(registersInCallPath) {
7203 /* registers were used in the functions this pBlock has called */
7204 /* so now, we need to see if these collide with the ones we are */
7207 regs *r1,*r2, *newreg;
7209 DFPRINTF((stderr,"comparing registers\n"));
7211 r1 = setFirstItem(registersInCallPath);
7214 r2 = setFirstItem(pb->tregisters);
7216 while(r2 && (r1->type != REG_STK)) {
7218 if(r2->rIdx == r1->rIdx) {
7219 newreg = pic16_findFreeReg(REG_GPR);
7223 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7227 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7228 r1->rIdx, newreg->rIdx));
7229 r2->rIdx = newreg->rIdx;
7230 //if(r2->name) free(r2->name);
7232 r2->name = Safe_strdup(newreg->name);
7236 newreg->wasUsed = 1;
7238 r2 = setNextItem(pb->tregisters);
7241 r1 = setNextItem(registersInCallPath);
7244 /* Collisions have been resolved. Now free the registers in the call path */
7245 r1 = setFirstItem(registersInCallPath);
7247 if(r1->type != REG_STK) {
7248 newreg = pic16_regWithIdx(r1->rIdx);
7251 r1 = setNextItem(registersInCallPath);
7255 // MarkUsedRegisters(pb->registers);
7257 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7260 DFPRINTF((stderr,"returning regs\n"));
7262 DFPRINTF((stderr,"not returning regs\n"));
7264 DFPRINTF((stderr,"pBlock after register optim.\n"));
7265 pBlockStats(stderr,pb); // debug
7271 /*-----------------------------------------------------------------*/
7272 /* pct2 - writes the call tree to a file */
7274 /*-----------------------------------------------------------------*/
7275 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7279 // set *registersInCallPath = NULL;
7285 fprintf(of, "recursive function\n");
7286 return; //recursion ?
7289 pc = setFirstItem(pb->function_entries);
7296 for(i=0;i<indent;i++) // Indentation
7300 if(pc->type == PC_FUNCTION) {
7301 usedstack += PCF(pc)->stackusage;
7302 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7303 } else return; // ???
7306 pc = setFirstItem(pb->function_calls);
7307 for( ; pc; pc = setNextItem(pb->function_calls)) {
7309 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7310 char *dest = pic16_get_op_from_instruction(PCI(pc));
7312 pcn = findFunction(dest);
7314 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7316 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7324 /*-----------------------------------------------------------------*/
7325 /* pic16_printCallTree - writes the call tree to a file */
7327 /*-----------------------------------------------------------------*/
7329 void pic16_printCallTree(FILE *of)
7341 fprintf(of, "\npBlock statistics\n");
7342 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7346 fprintf(of,"Call Tree\n");
7347 pbr = the_pFile->functions;
7351 if(!ispCodeFunction(pc))
7352 fprintf(of,"bug in call tree");
7355 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7357 while(pc->next && !ispCodeFunction(pc->next)) {
7359 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7360 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7368 fprintf(of,"\n**************\n\na better call tree\n");
7369 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7374 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7375 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7381 /*-----------------------------------------------------------------*/
7383 /*-----------------------------------------------------------------*/
7385 static void InlineFunction(pBlock *pb)
7393 pc = setFirstItem(pb->function_calls);
7395 for( ; pc; pc = setNextItem(pb->function_calls)) {
7398 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7404 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7406 //fprintf(stderr,"Cool can inline:\n");
7407 //pcn->print(stderr,pcn);
7409 //fprintf(stderr,"recursive call Inline\n");
7410 InlineFunction(pcn->pb);
7411 //fprintf(stderr,"return from recursive call Inline\n");
7414 At this point, *pc points to a CALL mnemonic, and
7415 *pcn points to the function that is being called.
7417 To in-line this call, we need to remove the CALL
7418 and RETURN(s), and link the function pCode in with
7424 /* Remove the CALL */
7428 /* remove callee pBlock from the pBlock linked list */
7429 removepBlock(pcn->pb);
7437 /* Remove the Function pCode */
7438 pct = pic16_findNextInstruction(pcn->next);
7440 /* Link the function with the callee */
7441 pc->next = pcn->next;
7442 pcn->next->prev = pc;
7444 /* Convert the function name into a label */
7446 pbr = Safe_calloc(1,sizeof(pBranch));
7447 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7449 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7450 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7452 /* turn all of the return's except the last into goto's */
7453 /* check case for 2 instruction pBlocks */
7454 pce = pic16_findNextInstruction(pcn->next);
7456 pCode *pce_next = pic16_findNextInstruction(pce->next);
7458 if(pce_next == NULL) {
7459 /* found the last return */
7460 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7462 //fprintf(stderr,"found last return\n");
7463 //pce->print(stderr,pce);
7464 pce->prev->next = pc_call->next;
7465 pc_call->next->prev = pce->prev;
7466 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7476 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7482 /*-----------------------------------------------------------------*/
7484 /*-----------------------------------------------------------------*/
7486 void pic16_InlinepCode(void)
7495 if(!functionInlining)
7498 /* Loop through all of the function definitions and count the
7499 * number of times each one is called */
7500 //fprintf(stderr,"inlining %d\n",__LINE__);
7502 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7504 pc = setFirstItem(pb->function_calls);
7506 for( ; pc; pc = setNextItem(pb->function_calls)) {
7509 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7510 if(pcn && isPCF(pcn)) {
7511 PCF(pcn)->ncalled++;
7514 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7519 //fprintf(stderr,"inlining %d\n",__LINE__);
7521 /* Now, Loop through the function definitions again, but this
7522 * time inline those functions that have only been called once. */
7524 InlineFunction(the_pFile->pbHead);
7525 //fprintf(stderr,"inlining %d\n",__LINE__);
7527 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7532 char *pic_optype_names[]={
7533 "PO_NONE", // No operand e.g. NOP
7534 "PO_W", // The working register (as a destination)
7535 "PO_WREG", // The working register (as a file register)
7536 "PO_STATUS", // The 'STATUS' register
7537 "PO_BSR", // The 'BSR' register
7538 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7540 "PO_INDF0", // The Indirect register
7541 "PO_INTCON", // Interrupt Control register
7542 "PO_GPR_REGISTER", // A general purpose register
7543 "PO_GPR_BIT", // A bit of a general purpose register
7544 "PO_GPR_TEMP", // A general purpose temporary register
7545 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7546 "PO_PCL", // Program counter Low register
7547 "PO_PCLATH", // Program counter Latch high register
7548 "PO_PCLATU", // Program counter Latch upper register
7549 "PO_PRODL", // Product Register Low
7550 "PO_PRODH", // Product Register High
7551 "PO_LITERAL", // A constant
7552 "PO_REL_ADDR", // A relative address
7553 "PO_IMMEDIATE", // (8051 legacy)
7554 "PO_DIR", // Direct memory (8051 legacy)
7555 "PO_CRY", // bit memory (8051 legacy)
7556 "PO_BIT", // bit operand.
7557 "PO_STR", // (8051 legacy)
7559 "PO_WILD" // Wild card operand in peep optimizer
7563 char *dumpPicOptype(PIC_OPTYPE type)
7565 return (pic_optype_names[ type ]);