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%02hhx",(char)(lit));
3869 // sprintf(s, "%i", lit);
3872 pcop->name = Safe_strdup(s);
3874 ((pCodeOpLit *)pcop)->lit = lit;
3879 /*-----------------------------------------------------------------*/
3880 /*-----------------------------------------------------------------*/
3881 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3883 char *s = buffer, tbuf[256], *tb=tbuf;
3887 tb = pic16_get_op(arg2, NULL, 0);
3888 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3889 pcop->type = PO_LITERAL;
3893 sprintf(s,"0x%02x, %s",lit, tb);
3895 pcop->name = Safe_strdup(s);
3898 ((pCodeOpLit2 *)pcop)->lit = lit;
3899 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3904 /*-----------------------------------------------------------------*/
3905 /*-----------------------------------------------------------------*/
3906 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3910 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3911 pcop->type = PO_IMMEDIATE;
3913 regs *r = pic16_dirregWithName(name);
3914 pcop->name = Safe_strdup(name);
3918 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3919 PCOI(pcop)->rIdx = r->rIdx;
3921 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3922 PCOI(pcop)->rIdx = -1;
3924 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3929 PCOI(pcop)->index = index;
3930 PCOI(pcop)->offset = offset;
3931 PCOI(pcop)->_const = code_space;
3936 /*-----------------------------------------------------------------*/
3937 /*-----------------------------------------------------------------*/
3938 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3944 if(!pcwb || !subtype) {
3945 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3949 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3950 pcop->type = PO_WILD;
3951 sprintf(s,"%%%d",id);
3952 pcop->name = Safe_strdup(s);
3954 PCOW(pcop)->id = id;
3955 PCOW(pcop)->pcwb = pcwb;
3956 PCOW(pcop)->subtype = subtype;
3957 PCOW(pcop)->matched = NULL;
3959 PCOW(pcop)->pcop2 = NULL;
3964 /*-----------------------------------------------------------------*/
3965 /*-----------------------------------------------------------------*/
3966 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3972 if(!pcwb || !subtype || !subtype2) {
3973 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3977 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3978 pcop->type = PO_WILD;
3979 sprintf(s,"%%%d",id);
3980 pcop->name = Safe_strdup(s);
3982 PCOW(pcop)->id = id;
3983 PCOW(pcop)->pcwb = pcwb;
3984 PCOW(pcop)->subtype = subtype;
3985 PCOW(pcop)->matched = NULL;
3987 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3989 if(!subtype2->name) {
3990 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3991 PCOW2(pcop)->pcop.type = PO_WILD;
3992 sprintf(s, "%%%d", id2);
3993 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3994 PCOW2(pcop)->id = id2;
3995 PCOW2(pcop)->subtype = subtype2;
3997 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3998 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4000 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4002 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4003 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4012 /*-----------------------------------------------------------------*/
4013 /*-----------------------------------------------------------------*/
4014 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4018 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4019 pcop->type = PO_GPR_BIT;
4021 pcop->name = Safe_strdup(s);
4025 PCORB(pcop)->bit = bit;
4026 PCORB(pcop)->inBitSpace = inBitSpace;
4027 PCORB(pcop)->subtype = subt;
4029 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4030 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4031 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4032 // PCOR(pcop)->rIdx = 0;
4037 /*-----------------------------------------------------------------*
4038 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4040 * If rIdx >=0 then a specific register from the set of registers
4041 * will be selected. If rIdx <0, then a new register will be searched
4043 *-----------------------------------------------------------------*/
4045 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4049 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4054 PCOR(pcop)->rIdx = rIdx;
4055 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4057 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4060 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4062 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4063 __FUNCTION__, __LINE__);
4068 pcop->type = PCOR(pcop)->r->pc_type;
4073 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4078 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4079 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4080 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4081 pcop->type = PCOR(pcop)->r->pc_type;
4082 pcop->name = PCOR(pcop)->r->name;
4084 // if(pic16_pcode_verbose) {
4085 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4086 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4092 /*-----------------------------------------------------------------*/
4093 /*-----------------------------------------------------------------*/
4094 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4098 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4101 pcop->key = Safe_strdup( key );
4103 return (PCOP(pcop));
4107 /*-----------------------------------------------------------------*/
4108 /*-----------------------------------------------------------------*/
4110 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4117 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4121 pcop = pic16_newpCodeOpLit(-1);
4125 pcop = pic16_newpCodeOpLabel(NULL,-1);
4128 pcop = pic16_newpCodeOpReg(-1);
4131 case PO_GPR_REGISTER:
4133 pcop = pic16_newpCodeOpRegFromStr(name);
4135 pcop = pic16_newpCodeOpReg(-1);
4139 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4142 pcop->name = Safe_strdup(name);
4150 #define DB_ITEMS_PER_LINE 8
4152 typedef struct DBdata
4159 static int DBd_init = -1;
4161 /*-----------------------------------------------------------------*/
4162 /* Initialiase "DB" data buffer */
4163 /*-----------------------------------------------------------------*/
4164 void pic16_initDB(void)
4170 /*-----------------------------------------------------------------*/
4171 /* Flush pending "DB" data to a pBlock */
4173 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4174 /*-----------------------------------------------------------------*/
4175 void pic16_flushDB(char ptype, void *p)
4179 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4182 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4185 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4189 DBd.buffer[0] = '\0';
4194 /*-----------------------------------------------------------------*/
4195 /* Add "DB" directives to a pBlock */
4196 /*-----------------------------------------------------------------*/
4197 void pic16_emitDB(char c, char ptype, void *p)
4202 // we need to initialize
4205 DBd.buffer[0] = '\0';
4208 l = strlen(DBd.buffer);
4209 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4211 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4214 if (DBd.count>= DB_ITEMS_PER_LINE)
4215 pic16_flushDB(ptype, p);
4218 void pic16_emitDS(char *s, char ptype, void *p)
4223 // we need to initialize
4226 DBd.buffer[0] = '\0';
4229 l = strlen(DBd.buffer);
4230 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4232 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4234 DBd.count++; //=strlen(s);
4236 pic16_flushDB(ptype, p);
4240 /*-----------------------------------------------------------------*/
4241 /*-----------------------------------------------------------------*/
4242 void pic16_pCodeConstString(char *name, char *value)
4246 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4251 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4253 pic16_addpBlock(pb);
4255 sprintf(buffer,"; %s = %s",name,value);
4257 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4258 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4261 pic16_emitDB(*value, 'p', (void *)pb);
4263 pic16_flushDB('p', (void *)pb);
4266 /*-----------------------------------------------------------------*/
4267 /*-----------------------------------------------------------------*/
4269 static void pCodeReadCodeTable(void)
4273 fprintf(stderr, " %s\n",__FUNCTION__);
4275 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4277 pic16_addpBlock(pb);
4279 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4280 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4281 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4282 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4284 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4285 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4286 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4287 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4292 /*-----------------------------------------------------------------*/
4293 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4294 /*-----------------------------------------------------------------*/
4295 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4302 /* If this is the first pcode to be added to a block that
4303 * was initialized with a NULL pcode, then go ahead and
4304 * make this pcode the head and tail */
4305 pb->pcHead = pb->pcTail = pc;
4308 pb->pcTail->next = pc;
4310 pc->prev = pb->pcTail;
4317 /*-----------------------------------------------------------------*/
4318 /* pic16_addpBlock - place a pBlock into the pFile */
4319 /*-----------------------------------------------------------------*/
4320 void pic16_addpBlock(pBlock *pb)
4322 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4325 /* First time called, we'll pass through here. */
4326 //_ALLOC(the_pFile,sizeof(pFile));
4327 the_pFile = Safe_calloc(1,sizeof(pFile));
4328 the_pFile->pbHead = the_pFile->pbTail = pb;
4329 the_pFile->functions = NULL;
4333 the_pFile->pbTail->next = pb;
4334 pb->prev = the_pFile->pbTail;
4336 the_pFile->pbTail = pb;
4339 /*-----------------------------------------------------------------*/
4340 /* removepBlock - remove a pBlock from the pFile */
4341 /*-----------------------------------------------------------------*/
4342 static void removepBlock(pBlock *pb)
4350 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4352 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4355 if(pbs == the_pFile->pbHead)
4356 the_pFile->pbHead = pbs->next;
4358 if (pbs == the_pFile->pbTail)
4359 the_pFile->pbTail = pbs->prev;
4362 pbs->next->prev = pbs->prev;
4365 pbs->prev->next = pbs->next;
4372 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4376 /*-----------------------------------------------------------------*/
4377 /* printpCode - write the contents of a pCode to a file */
4378 /*-----------------------------------------------------------------*/
4379 static void printpCode(FILE *of, pCode *pc)
4390 fprintf(of,"warning - unable to print pCode\n");
4393 /*-----------------------------------------------------------------*/
4394 /* pic16_printpBlock - write the contents of a pBlock to a file */
4395 /*-----------------------------------------------------------------*/
4396 void pic16_printpBlock(FILE *of, pBlock *pb)
4404 for(pc = pb->pcHead; pc; pc = pc->next) {
4405 if(isPCF(pc) && PCF(pc)->fname) {
4406 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4407 if(pb->dbName == 'A') {
4409 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4410 if(!strcmp(ab->name, PCF(pc)->fname)) {
4411 fprintf(of, "\t0X%06X", ab->address);
4422 /*-----------------------------------------------------------------*/
4424 /* pCode processing */
4428 /*-----------------------------------------------------------------*/
4430 void pic16_unlinkpCode(pCode *pc)
4436 fprintf(stderr,"Unlinking: ");
4437 printpCode(stderr, pc);
4440 pc->prev->next = pc->next;
4442 pc->next->prev = pc->prev;
4444 pc->prev = pc->next = NULL;
4448 /*-----------------------------------------------------------------*/
4449 /*-----------------------------------------------------------------*/
4451 static void genericDestruct(pCode *pc)
4454 pic16_unlinkpCode(pc);
4457 /* For instructions, tell the register (if there's one used)
4458 * that it's no longer needed */
4459 regs *reg = pic16_getRegFromInstruction(pc);
4461 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4463 if(PCI(pc)->is2MemOp) {
4464 reg = pic16_getRegFromInstruction2(pc);
4466 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4470 /* Instead of deleting the memory used by this pCode, mark
4471 * the object as bad so that if there's a pointer to this pCode
4472 * dangling around somewhere then (hopefully) when the type is
4473 * checked we'll catch it.
4477 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4483 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4484 /*-----------------------------------------------------------------*/
4485 /*-----------------------------------------------------------------*/
4486 /* modifiers for constant immediate */
4487 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4489 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4494 int use_buffer = 1; // copy the string to the passed buffer pointer
4499 use_buffer = 0; // Don't bother copying the string to the buffer.
4503 switch(pcop->type) {
4511 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4514 return PCOR(pcop)->r->name;
4517 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4519 SAFE_snprintf(&buffer,&size,"%s",r->name);
4526 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4527 if(PCOI(pcop)->index) {
4528 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4529 immdmod[ PCOI(pcop)->offset ],
4533 SAFE_snprintf(&s,&size,"%s(%s)",
4534 immdmod[ PCOI(pcop)->offset ],
4538 if(PCOI(pcop)->index) {
4539 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4544 SAFE_snprintf(&s,&size, "%s(%s)",
4551 case PO_GPR_REGISTER:
4554 // size = sizeof(buffer);
4555 if( PCOR(pcop)->instance) {
4556 SAFE_snprintf(&s,&size,"(%s + %d)",
4558 PCOR(pcop)->instance );
4560 SAFE_snprintf(&s,&size,"%s",pcop->name);
4567 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4576 return "NO operand1";
4579 /*-----------------------------------------------------------------*/
4580 /* pic16_get_op2 - variant to support two memory operand commands */
4581 /*-----------------------------------------------------------------*/
4582 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4587 int use_buffer = 1; // copy the string to the passed buffer pointer
4592 use_buffer = 0; // Don't bother copying the string to the buffer.
4596 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",
4597 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4598 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4602 switch(PCOR2(pcop)->pcop2->type) {
4610 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4613 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4616 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4619 SAFE_snprintf(&buffer,&size,"%s",r->name);
4630 if(PCOI(pcop)->_const) {
4631 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4632 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4635 8 * PCOI(pcop)->offset );
4637 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4639 if( PCOI(pcop)->index) {
4640 SAFE_snprintf(&s,&size,"(%s + %d)",
4642 PCOI(pcop)->index );
4644 if(PCOI(pcop)->offset)
4645 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4647 SAFE_snprintf(&s,&size,"%s",pcop->name);
4654 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4655 SAFE_snprintf(&s,&size,"(%s + %d)",
4656 PCOR(PCOR2(pcop)->pcop2)->r->name,
4657 PCOR(PCOR2(pcop)->pcop2)->instance );
4659 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4664 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4666 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4669 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4674 return "NO operand2";
4677 /*-----------------------------------------------------------------*/
4678 /*-----------------------------------------------------------------*/
4679 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4683 return pic16_get_op(pcc->pcop,NULL,0);
4685 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4686 * return ("ERROR Null: "__FUNCTION__);
4688 return ("ERROR Null: pic16_get_op_from_instruction");
4692 /*-----------------------------------------------------------------*/
4693 /*-----------------------------------------------------------------*/
4694 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4697 fprintf(of,"pcodeopprint- not implemented\n");
4700 /*-----------------------------------------------------------------*/
4701 /* pic16_pCode2str - convert a pCode instruction to string */
4702 /*-----------------------------------------------------------------*/
4703 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4709 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4710 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4711 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4719 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4721 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4723 if(PCI(pc)->is2MemOp) {
4724 SAFE_snprintf(&s,&size, "%s, %s",
4725 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4726 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4730 if(PCI(pc)->is2LitOp) {
4731 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4735 if(PCI(pc)->isBitInst) {
4736 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4737 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4738 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4739 PCI(pc)->pcop->name ,
4740 PCI(pc)->pcop->name );
4742 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4743 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4744 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4745 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4747 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4748 //PCI(pc)->pcop->t.bit );
4751 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4752 if( PCI(pc)->num_ops == 3)
4753 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4755 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4758 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4760 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4761 if(PCI(pc)->num_ops == 3)
4762 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4764 r = pic16_getRegFromInstruction(pc);
4765 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4766 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4768 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4777 /* assuming that comment ends with a \n */
4778 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4782 /* assuming that inline code ends with a \n */
4783 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4787 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4790 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4793 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4796 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4799 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4800 SAFE_snprintf(&s,&size,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4801 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4804 if(PCAD(pc)->directive) {
4805 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4808 /* special case to handle inline labels without a tab */
4809 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4814 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4818 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4826 /*-----------------------------------------------------------------*/
4827 /* genericPrint - the contents of a pCode to a file */
4828 /*-----------------------------------------------------------------*/
4829 static void genericPrint(FILE *of, pCode *pc)
4837 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4841 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4845 // If the opcode has a label, print that first
4847 pBranch *pbl = PCI(pc)->label;
4848 while(pbl && pbl->pc) {
4849 if(pbl->pc->type == PC_LABEL)
4850 pCodePrintLabel(of, pbl->pc);
4856 genericPrint(of,PCODE(PCI(pc)->cline));
4861 pic16_pCode2str(str, 256, pc);
4863 fprintf(of,"%s",str);
4865 if(pic16_debug_verbose) {
4866 fprintf(of, "\t;key=%03x",pc->seq);
4868 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4875 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4876 if(PCW(pc)->pci.label)
4877 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4879 if(PCW(pc)->operand) {
4880 fprintf(of,";\toperand ");
4881 pCodeOpPrint(of,PCW(pc)->operand );
4886 if(pic16_debug_verbose) {
4887 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4888 if(PCFL(pc)->ancestor)
4889 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4896 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4897 fprintf(of,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4898 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4904 pBranch *pbl = PCAD(pc)->pci.label;
4905 while(pbl && pbl->pc) {
4906 if(pbl->pc->type == PC_LABEL)
4907 pCodePrintLabel(of, pbl->pc);
4911 if(PCAD(pc)->directive) {
4912 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4915 /* special case to handle inline labels without tab */
4916 fprintf(of, "%s\n", PCAD(pc)->arg);
4922 fprintf(of,"unknown pCode type %d\n",pc->type);
4927 /*-----------------------------------------------------------------*/
4928 /* pCodePrintFunction - prints function begin/end */
4929 /*-----------------------------------------------------------------*/
4931 static void pCodePrintFunction(FILE *of, pCode *pc)
4938 if( ((pCodeFunction *)pc)->modname)
4939 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4942 if(!PCF(pc)->absblock) {
4943 if(PCF(pc)->fname) {
4944 pBranch *exits = PCF(pc)->to;
4947 fprintf(of,"%s:", PCF(pc)->fname);
4949 if(pic16_pcode_verbose)
4950 fprintf(of, "\t;Function start");
4956 exits = exits->next;
4960 if(pic16_pcode_verbose)
4961 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4964 if((PCF(pc)->from &&
4965 PCF(pc)->from->pc->type == PC_FUNCTION &&
4966 PCF(PCF(pc)->from->pc)->fname) ) {
4968 if(pic16_pcode_verbose)
4969 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4971 if(pic16_pcode_verbose)
4972 fprintf(of,"; exit point [can't find entry point]\n");
4978 /*-----------------------------------------------------------------*/
4979 /* pCodePrintLabel - prints label */
4980 /*-----------------------------------------------------------------*/
4982 static void pCodePrintLabel(FILE *of, pCode *pc)
4989 fprintf(of,"%s:\n",PCL(pc)->label);
4990 else if (PCL(pc)->key >=0)
4991 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4993 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4996 /*-----------------------------------------------------------------*/
4997 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4998 /* remove it if it is found. */
4999 /*-----------------------------------------------------------------*/
5000 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5007 if(pcl->type == PC_OPCODE)
5008 b = PCI(pcl)->label;
5010 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5015 //fprintf (stderr, "%s \n",__FUNCTION__);
5016 //pcl->print(stderr,pcl);
5017 //pc->print(stderr,pc);
5020 //fprintf (stderr, "found label\n");
5021 //pc->print(stderr, pc);
5025 bprev->next = b->next; /* Not first pCode in chain */
5029 PCI(pcl)->label = b->next; /* First pCode in chain */
5032 return; /* A label can't occur more than once */
5040 /*-----------------------------------------------------------------*/
5041 /*-----------------------------------------------------------------*/
5042 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5061 /*-----------------------------------------------------------------*/
5062 /* pBranchLink - given two pcodes, this function will link them */
5063 /* together through their pBranches */
5064 /*-----------------------------------------------------------------*/
5065 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5069 // Declare a new branch object for the 'from' pCode.
5071 //_ALLOC(b,sizeof(pBranch));
5072 b = Safe_calloc(1,sizeof(pBranch));
5073 b->pc = PCODE(t); // The link to the 'to' pCode.
5076 f->to = pic16_pBranchAppend(f->to,b);
5078 // Now do the same for the 'to' pCode.
5080 //_ALLOC(b,sizeof(pBranch));
5081 b = Safe_calloc(1,sizeof(pBranch));
5085 t->from = pic16_pBranchAppend(t->from,b);
5090 /*-----------------------------------------------------------------*/
5091 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5093 /*-----------------------------------------------------------------*/
5094 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5107 /*-----------------------------------------------------------------*/
5108 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5109 /*-----------------------------------------------------------------*/
5110 void pic16_pCodeUnlink(pCode *pc)
5115 if(!pc->prev || !pc->next) {
5116 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5120 /* first remove the pCode from the chain */
5121 pc->prev->next = pc->next;
5122 pc->next->prev = pc->prev;
5124 /* Now for the hard part... */
5126 /* Remove the branches */
5128 pb1 = PCI(pc)->from;
5130 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5131 * one we're unlinking */
5133 /* search for the link back to this pCode (the one we're
5135 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5136 pb2->pc = PCI(pc)->to->pc; // make the replacement
5138 /* if the pCode we're unlinking contains multiple 'to'
5139 * branches (e.g. this a skip instruction) then we need
5140 * to copy these extra branches to the chain. */
5141 if(PCI(pc)->to->next)
5142 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5151 /*-----------------------------------------------------------------*/
5152 /*-----------------------------------------------------------------*/
5154 static void genericAnalyze(pCode *pc)
5164 // Go through the pCodes that are in pCode chain and link
5165 // them together through the pBranches. Note, the pCodes
5166 // are linked together as a contiguous stream like the
5167 // assembly source code lines. The linking here mimics this
5168 // except that comments are not linked in.
5170 pCode *npc = pc->next;
5172 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5173 pBranchLink(pc,npc);
5178 /* reached the end of the pcode chain without finding
5179 * an instruction we could link to. */
5183 fprintf(stderr,"analyze PC_FLOW\n");
5187 fprintf(stderr,,";A bad pCode is being used\n");
5193 /*-----------------------------------------------------------------*/
5194 /*-----------------------------------------------------------------*/
5195 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5199 if(pc->type == PC_LABEL) {
5200 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5203 if((pc->type == PC_OPCODE)
5204 || (pc->type == PC_ASMDIR)
5206 pbr = PCI(pc)->label;
5208 if(pbr->pc->type == PC_LABEL) {
5209 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5219 /*-----------------------------------------------------------------*/
5220 /*-----------------------------------------------------------------*/
5221 static int checkLabel(pCode *pc)
5225 if(pc && isPCI(pc)) {
5226 pbr = PCI(pc)->label;
5228 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5238 /*-----------------------------------------------------------------*/
5239 /* findLabelinpBlock - Search the pCode for a particular label */
5240 /*-----------------------------------------------------------------*/
5241 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5248 for(pc = pb->pcHead; pc; pc = pc->next)
5249 if(compareLabel(pc,pcop_label))
5255 /*-----------------------------------------------------------------*/
5256 /* findLabel - Search the pCode for a particular label */
5257 /*-----------------------------------------------------------------*/
5258 static pCode * findLabel(pCodeOpLabel *pcop_label)
5266 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5267 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5271 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5275 /*-----------------------------------------------------------------*/
5276 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5277 /* in the linked list */
5278 /*-----------------------------------------------------------------*/
5279 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5292 /*-----------------------------------------------------------------*/
5293 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5294 /* in the linked list */
5295 /*-----------------------------------------------------------------*/
5296 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5310 //#define PCODE_DEBUG
5311 /*-----------------------------------------------------------------*/
5312 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5313 /* in the linked list */
5314 /*-----------------------------------------------------------------*/
5315 pCode * pic16_findNextInstruction(pCode *pci)
5320 if((pc->type == PC_OPCODE)
5321 || (pc->type == PC_WILD)
5322 || (pc->type == PC_ASMDIR)
5327 fprintf(stderr,"pic16_findNextInstruction: ");
5328 printpCode(stderr, pc);
5333 //fprintf(stderr,"Couldn't find instruction\n");
5337 /*-----------------------------------------------------------------*/
5338 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5339 /* in the linked list */
5340 /*-----------------------------------------------------------------*/
5341 pCode * pic16_findPrevInstruction(pCode *pci)
5347 if((pc->type == PC_OPCODE)
5348 || (pc->type == PC_WILD)
5349 || (pc->type == PC_ASMDIR)
5355 fprintf(stderr,"pic16_findPrevInstruction: ");
5356 printpCode(stderr, pc);
5361 //fprintf(stderr,"Couldn't find instruction\n");
5368 /*-----------------------------------------------------------------*/
5369 /* findFunctionEnd - given a pCode find the end of the function */
5370 /* that contains it */
5371 /*-----------------------------------------------------------------*/
5372 static pCode * findFunctionEnd(pCode *pc)
5376 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5382 fprintf(stderr,"Couldn't find function end\n");
5387 /*-----------------------------------------------------------------*/
5388 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5389 /* instruction with which it is associated. */
5390 /*-----------------------------------------------------------------*/
5391 static void AnalyzeLabel(pCode *pc)
5394 pic16_pCodeUnlink(pc);
5400 static void AnalyzeGOTO(pCode *pc)
5403 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5407 static void AnalyzeSKIP(pCode *pc)
5410 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5411 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5415 static void AnalyzeRETURN(pCode *pc)
5418 // branch_link(pc,findFunctionEnd(pc->next));
5424 /*-----------------------------------------------------------------*/
5425 /*-----------------------------------------------------------------*/
5426 regs * pic16_getRegFromInstruction(pCode *pc)
5432 PCI(pc)->num_ops == 0 ||
5433 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5437 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5438 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5441 switch(PCI(pc)->pcop->type) {
5447 return PCOR(PCI(pc)->pcop)->r;
5451 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5452 return PCOR(PCI(pc)->pcop)->r;
5455 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5457 if(PCOI(PCI(pc)->pcop)->r)
5458 return (PCOI(PCI(pc)->pcop)->r);
5463 return PCOR(PCI(pc)->pcop)->r;
5465 case PO_GPR_REGISTER:
5467 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5468 return PCOR(PCI(pc)->pcop)->r;
5471 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5475 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5476 // genericPrint(stderr, pc);
5484 /*-------------------------------------------------------------------------------*/
5485 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5486 /*-------------------------------------------------------------------------------*/
5487 regs * pic16_getRegFromInstruction2(pCode *pc)
5493 PCI(pc)->num_ops == 0 ||
5494 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5499 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5500 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5504 * operands supported in MOVFF:
5511 switch(PCI(pc)->pcop->type) {
5517 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5519 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5523 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5524 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5528 // if(PCOI(PCI(pc)->pcop)->r)
5529 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5531 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5532 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5535 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5536 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5543 // return PCOR2(PCI(pc)->pcop)->r;
5545 case PO_GPR_REGISTER:
5547 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5548 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5552 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5555 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5556 //genericPrint(stderr, pc);
5564 /*-----------------------------------------------------------------*/
5565 /*-----------------------------------------------------------------*/
5567 static void AnalyzepBlock(pBlock *pb)
5574 /* Find all of the registers used in this pBlock
5575 * by looking at each instruction and examining it's
5578 for(pc = pb->pcHead; pc; pc = pc->next) {
5580 /* Is this an instruction with operands? */
5581 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5583 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5585 /* Loop through all of the registers declared so far in
5586 this block and see if we find this one there */
5588 regs *r = setFirstItem(pb->tregisters);
5591 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5592 PCOR(PCI(pc)->pcop)->r = r;
5595 r = setNextItem(pb->tregisters);
5599 /* register wasn't found */
5600 //r = Safe_calloc(1, sizeof(regs));
5601 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5602 //addSet(&pb->tregisters, r);
5603 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5604 //PCOR(PCI(pc)->pcop)->r = r;
5605 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5607 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5610 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5611 if(PCOR(PCI(pc)->pcop)->r) {
5612 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5613 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5615 if(PCI(pc)->pcop->name)
5616 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5618 fprintf(stderr,"ERROR: NULL register\n");
5627 /*-----------------------------------------------------------------*/
5629 /*-----------------------------------------------------------------*/
5630 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5632 static void InsertpFlow(pCode *pc, pCode **pflow)
5635 PCFL(*pflow)->end = pc;
5637 if(!pc || !pc->next)
5640 *pflow = pic16_newpCodeFlow();
5641 pic16_pCodeInsertAfter(pc, *pflow);
5644 /*-----------------------------------------------------------------*/
5645 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5646 /* the flow blocks. */
5648 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5649 * point the instruction flow changes.
5651 /*-----------------------------------------------------------------*/
5652 void pic16_BuildFlow(pBlock *pb)
5655 pCode *last_pci=NULL;
5662 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5663 /* Insert a pCodeFlow object at the beginning of a pBlock */
5665 InsertpFlow(pb->pcHead, &pflow);
5667 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5668 //pflow->next = pb->pcHead; /* Make the current head the next object */
5669 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5670 //pb->pcHead = pflow; /* Make the Flow object the head */
5673 for( pc = pic16_findNextInstruction(pb->pcHead);
5675 pc=pic16_findNextInstruction(pc)) {
5678 PCI(pc)->pcflow = PCFL(pflow);
5680 //fprintf(stderr," build: ");
5681 //pflow->print(stderr,pflow);
5683 if( PCI(pc)->isSkip) {
5685 /* The two instructions immediately following this one
5686 * mark the beginning of a new flow segment */
5688 while(pc && PCI(pc)->isSkip) {
5690 PCI(pc)->pcflow = PCFL(pflow);
5694 InsertpFlow(pc, &pflow);
5695 pc=pic16_findNextInstruction(pc->next);
5703 PCI(pc)->pcflow = PCFL(pflow);
5705 InsertpFlow(pc, &pflow);
5707 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5709 InsertpFlow(pc, &pflow);
5712 } else if (checkLabel(pc)) {
5714 /* This instruction marks the beginning of a
5715 * new flow segment */
5720 /* If the previous pCode is not a flow object, then
5721 * insert a new flow object. (This check prevents
5722 * two consecutive flow objects from being insert in
5723 * the case where a skip instruction preceeds an
5724 * instruction containing a label.) */
5726 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5727 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5729 PCI(pc)->pcflow = PCFL(pflow);
5736 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5738 PCFL(pflow)->end = pb->pcTail;
5741 /*-------------------------------------------------------------------*/
5742 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5743 /* the flow blocks. */
5745 * unBuildFlow removes pCodeFlow objects from a pCode chain
5747 /*-----------------------------------------------------------------*/
5748 static void unBuildFlow(pBlock *pb)
5763 if(PCI(pc)->pcflow) {
5764 //free(PCI(pc)->pcflow);
5765 PCI(pc)->pcflow = NULL;
5768 } else if(isPCFL(pc) )
5777 /*-----------------------------------------------------------------*/
5778 /*-----------------------------------------------------------------*/
5779 static void dumpCond(int cond)
5782 static char *pcc_str[] = {
5796 int ncond = sizeof(pcc_str) / sizeof(char *);
5799 fprintf(stderr, "0x%04X\n",cond);
5801 for(i=0,j=1; i<ncond; i++, j<<=1)
5803 fprintf(stderr, " %s\n",pcc_str[i]);
5809 /*-----------------------------------------------------------------*/
5810 /*-----------------------------------------------------------------*/
5811 static void FlowStats(pCodeFlow *pcflow)
5819 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5821 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5824 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5829 fprintf(stderr, " FlowStats inCond: ");
5830 dumpCond(pcflow->inCond);
5831 fprintf(stderr, " FlowStats outCond: ");
5832 dumpCond(pcflow->outCond);
5836 /*-----------------------------------------------------------------*
5837 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5838 * if it affects the banking bits.
5840 * return: -1 == Banking bits are unaffected by this pCode.
5842 * return: > 0 == Banking bits are affected.
5844 * If the banking bits are affected, then the returned value describes
5845 * which bits are affected and how they're affected. The lower half
5846 * of the integer maps to the bits that are affected, the upper half
5847 * to whether they're set or cleared.
5849 *-----------------------------------------------------------------*/
5851 static int isBankInstruction(pCode *pc)
5859 if( PCI(pc)->op == POC_MOVLB ||
5860 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5861 bank = PCOL(pc)->lit;
5868 /*-----------------------------------------------------------------*/
5869 /*-----------------------------------------------------------------*/
5870 static void FillFlow(pCodeFlow *pcflow)
5879 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5881 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5884 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5891 isBankInstruction(pc);
5893 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5897 fprintf(stderr, " FillFlow - Bad end of flow\n");
5899 fprintf(stderr, " FillFlow - Ending flow with\n ");
5900 pc->print(stderr,pc);
5903 fprintf(stderr, " FillFlow inCond: ");
5904 dumpCond(pcflow->inCond);
5905 fprintf(stderr, " FillFlow outCond: ");
5906 dumpCond(pcflow->outCond);
5910 /*-----------------------------------------------------------------*/
5911 /*-----------------------------------------------------------------*/
5912 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5914 pCodeFlowLink *fromLink, *toLink;
5916 if(!from || !to || !to->pcflow || !from->pcflow)
5919 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5920 toLink = pic16_newpCodeFlowLink(to->pcflow);
5922 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5923 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5927 /*-----------------------------------------------------------------*
5928 * void LinkFlow(pBlock *pb)
5930 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5931 * non-branching segments. In LinkFlow, we determine the execution
5932 * order of these segments. For example, if one of the segments ends
5933 * with a skip, then we know that there are two possible flow segments
5934 * to which control may be passed.
5935 *-----------------------------------------------------------------*/
5936 static void LinkFlow(pBlock *pb)
5942 //fprintf(stderr,"linkflow \n");
5944 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5946 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5949 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5951 //fprintf(stderr," link: ");
5952 //pcflow->print(stderr,pcflow);
5954 //FillFlow(PCFL(pcflow));
5956 pc = PCFL(pcflow)->end;
5958 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5959 if(isPCI_SKIP(pc)) {
5960 //fprintf(stderr, "ends with skip\n");
5961 //pc->print(stderr,pc);
5962 pct=pic16_findNextInstruction(pc->next);
5963 LinkFlow_pCode(PCI(pc),PCI(pct));
5964 pct=pic16_findNextInstruction(pct->next);
5965 LinkFlow_pCode(PCI(pc),PCI(pct));
5969 if(isPCI_BRANCH(pc)) {
5970 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5972 //fprintf(stderr, "ends with branch\n ");
5973 //pc->print(stderr,pc);
5975 if(!(pcol && isPCOLAB(pcol))) {
5976 if((PCI(pc)->op != POC_RETLW)
5977 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5979 /* continue if label is '$' which assembler knows how to parse */
5980 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5982 if(pic16_pcode_verbose) {
5983 pc->print(stderr,pc);
5984 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5990 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5991 LinkFlow_pCode(PCI(pc),PCI(pct));
5993 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5994 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5996 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6002 //fprintf(stderr, "ends with non-branching instruction:\n");
6003 //pc->print(stderr,pc);
6005 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6011 //fprintf(stderr, "ends with unknown\n");
6012 //pc->print(stderr,pc);
6016 //fprintf(stderr, "ends with nothing: ERROR\n");
6020 /*-----------------------------------------------------------------*/
6021 /*-----------------------------------------------------------------*/
6023 /*-----------------------------------------------------------------*/
6024 /*-----------------------------------------------------------------*/
6025 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6031 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6034 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6044 /*-----------------------------------------------------------------*/
6045 /* insertBankSwitch - inserts a bank switch statement in the */
6046 /* assembly listing */
6048 /* position == 0: insert before */
6049 /* position == 1: insert after pc */
6050 /* position == 2: like 0 but previous was a skip instruction */
6051 /*-----------------------------------------------------------------*/
6052 pCodeOp *pic16_popGetLabel(unsigned int key);
6053 extern int pic16_labelOffset;
6055 static void insertBankSwitch(unsigned char position, pCode *pc)
6062 /* emit BANKSEL [symbol] */
6065 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6067 // position = 0; // position is always before (sanity check!)
6070 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6071 pc->print(stderr, pc);
6076 /* insert the bank switch after this pc instruction */
6077 pCode *pcnext = pic16_findNextInstruction(pc);
6079 pic16_pCodeInsertAfter(pc, new_pc);
6080 if(pcnext)pc = pcnext;
6084 /* insert the bank switch BEFORE this pc instruction */
6085 pic16_pCodeInsertAfter(pc->prev, new_pc);
6090 pCode *pcnext, *pcprev, *npci, *ppc;
6092 int ofs1=0, ofs2=0, len=0;
6094 /* just like 0, but previous was a skip instruction,
6095 * so some care should be taken */
6097 pic16_labelOffset += 10000;
6098 tlbl = newiTempLabel(NULL);
6100 /* invert skip instruction */
6101 pcprev = pic16_findPrevInstruction(pc->prev);
6102 ipci = PCI(pcprev)->inverted_op;
6103 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6105 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6107 /* copy info from old pCode */
6108 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6109 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6110 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6111 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6112 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6113 PCI(npci)->op = PCI(pcprev)->inverted_op;
6115 /* unlink old pCode */
6117 ppc->next = pcprev->next;
6118 pcprev->next->prev = ppc;
6119 pic16_pCodeInsertAfter(ppc, npci);
6121 /* extra instructions to handle invertion */
6122 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6123 pic16_pCodeInsertAfter(npci, pcnext);
6124 pic16_pCodeInsertAfter(pc->prev, new_pc);
6126 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6127 pic16_pCodeInsertAfter(pc, pcnext);
6132 /* Move the label, if there is one */
6133 if(PCI(pc)->label) {
6134 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6135 // __FILE__, __LINE__, pc, new_pc);
6136 PCAD(new_pc)->pci.label = PCI(pc)->label;
6137 PCI(pc)->label = NULL;
6142 /*-----------------------------------------------------------------*/
6143 /*int compareBankFlow - compare the banking requirements between */
6145 /*-----------------------------------------------------------------*/
6146 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6149 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6152 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6155 if(pcflow->firstBank == -1)
6159 if(pcflowLink->pcflow->firstBank == -1) {
6160 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6161 pcflowLink->pcflow->to :
6162 pcflowLink->pcflow->from);
6163 return compareBankFlow(pcflow, pctl, toORfrom);
6167 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6170 pcflowLink->bank_conflict++;
6171 pcflowLink->pcflow->FromConflicts++;
6172 pcflow->ToConflicts++;
6175 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6178 pcflowLink->bank_conflict++;
6179 pcflowLink->pcflow->ToConflicts++;
6180 pcflow->FromConflicts++;
6184 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6185 pcflowLink->pcflow->pc.seq,
6186 pcflowLink->pcflow->FromConflicts,
6187 pcflowLink->pcflow->ToConflicts);
6194 /*-----------------------------------------------------------------*/
6195 /*-----------------------------------------------------------------*/
6196 static void DumpFlow(pBlock *pb)
6200 pCodeFlowLink *pcfl;
6203 fprintf(stderr,"Dump flow \n");
6204 pb->pcHead->print(stderr, pb->pcHead);
6206 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6207 pcflow->print(stderr,pcflow);
6209 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6211 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6213 if(!isPCFL(pcflow)) {
6214 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6217 fprintf(stderr,"dumping: ");
6218 pcflow->print(stderr,pcflow);
6219 FlowStats(PCFL(pcflow));
6221 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6223 pc = PCODE(pcfl->pcflow);
6225 fprintf(stderr, " from seq %d:\n",pc->seq);
6227 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6228 pc->print(stderr,pc);
6233 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6235 pc = PCODE(pcfl->pcflow);
6237 fprintf(stderr, " to seq %d:\n",pc->seq);
6239 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6240 pc->print(stderr,pc);
6249 /*-----------------------------------------------------------------*/
6250 /*-----------------------------------------------------------------*/
6251 static int OptimizepBlock(pBlock *pb)
6256 if(!pb || !peepOptimizing)
6259 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6261 for(pc = pb->pcHead; pc; pc = pc->next)
6262 matches += pic16_pCodePeepMatchRule(pc);
6265 pc = pic16_findNextInstruction(pb->pcHead);
6273 if(pic16_pCodePeepMatchRule(pc)) {
6278 pc = pic16_findNextInstruction(pcprev->next);
6280 pc = pic16_findNextInstruction(pb->pcHead);
6282 pc = pic16_findNextInstruction(pc->next);
6286 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6291 /*-----------------------------------------------------------------*/
6292 /*-----------------------------------------------------------------*/
6293 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6297 for(pc = pcs; pc; pc = pc->next) {
6299 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6301 (PCI(pc)->pcop->type == PO_LABEL) &&
6302 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6310 /*-----------------------------------------------------------------*/
6311 /*-----------------------------------------------------------------*/
6312 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6319 (PCI(pc)->pcop->type == PO_LABEL)) {
6321 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6323 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6324 // if(pcol->pcop.name)
6325 // free(pcol->pcop.name);
6327 /* If the key is negative, then we (probably) have a label to
6328 * a function and the name is already defined */
6331 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6335 //sprintf(buffer,"_%05d_DS_",pcl->key);
6337 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6339 pcol->pcop.name = Safe_strdup(s);
6340 pcol->key = pcl->key;
6341 //pc->print(stderr,pc);
6348 /*-----------------------------------------------------------------*/
6349 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6350 /* pCode chain if they're not used. */
6351 /*-----------------------------------------------------------------*/
6352 static void pBlockRemoveUnusedLabels(pBlock *pb)
6354 pCode *pc; pCodeLabel *pcl;
6359 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6361 pBranch *pbr = PCI(pc)->label;
6362 if(pbr && pbr->next) {
6363 pCode *pcd = pb->pcHead;
6365 // fprintf(stderr, "multiple labels\n");
6366 // pc->print(stderr,pc);
6371 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6372 //fprintf(stderr,"Used by:\n");
6373 //pcd->print(stderr,pcd);
6375 exchangeLabels(PCL(pbr->pc),pcd);
6384 for(pc = pb->pcHead; pc; pc = pc->next) {
6386 if(isPCL(pc)) // pc->type == PC_LABEL)
6388 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6389 pcl = PCL(PCI(pc)->label->pc);
6392 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6394 /* This pCode is a label, so search the pBlock to see if anyone
6397 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6399 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6400 /* Couldn't find an instruction that refers to this label
6401 * So, unlink the pCode label from it's pCode chain
6402 * and destroy the label */
6403 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6405 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6406 if(pc->type == PC_LABEL) {
6407 pic16_unlinkpCode(pc);
6408 pCodeLabelDestruct(pc);
6410 unlinkpCodeFromBranch(pc, PCODE(pcl));
6411 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6422 /*-----------------------------------------------------------------*/
6423 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6424 /* chain and put them into pBranches that are */
6425 /* associated with the appropriate pCode */
6427 /*-----------------------------------------------------------------*/
6428 void pic16_pBlockMergeLabels(pBlock *pb)
6431 pCode *pc, *pcnext=NULL;
6436 /* First, Try to remove any unused labels */
6437 //pBlockRemoveUnusedLabels(pb);
6439 /* Now loop through the pBlock and merge the labels with the opcodes */
6442 // for(pc = pb->pcHead; pc; pc = pc->next) {
6445 pCode *pcn = pc->next;
6447 if(pc->type == PC_LABEL) {
6449 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6450 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6452 if((pcnext = pic16_findNextInstruction(pc) )) {
6454 // pcnext->print(stderr, pcnext);
6456 // Unlink the pCode label from it's pCode chain
6457 pic16_unlinkpCode(pc);
6459 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6460 // And link it into the instruction's pBranch labels. (Note, since
6461 // it's possible to have multiple labels associated with one instruction
6462 // we must provide a means to accomodate the additional labels. Thus
6463 // the labels are placed into the singly-linked list "label" as
6464 // opposed to being a single member of the pCodeInstruction.)
6466 //_ALLOC(pbr,sizeof(pBranch));
6468 pbr = Safe_calloc(1,sizeof(pBranch));
6472 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6475 if(pic16_pcode_verbose)
6476 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6478 } else if(pc->type == PC_CSOURCE) {
6480 /* merge the source line symbolic info into the next instruction */
6481 if((pcnext = pic16_findNextInstruction(pc) )) {
6483 // Unlink the pCode label from it's pCode chain
6484 pic16_unlinkpCode(pc);
6485 PCI(pcnext)->cline = PCCS(pc);
6486 //fprintf(stderr, "merging CSRC\n");
6487 //genericPrint(stderr,pcnext);
6493 pBlockRemoveUnusedLabels(pb);
6497 /*-----------------------------------------------------------------*/
6498 /*-----------------------------------------------------------------*/
6499 static int OptimizepCode(char dbName)
6501 #define MAX_PASSES 4
6510 DFPRINTF((stderr," Optimizing pCode\n"));
6514 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6515 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6516 matches += OptimizepBlock(pb);
6519 while(matches && ++passes < MAX_PASSES);
6526 const char *pic16_pCodeOpType(pCodeOp *pcop);
6527 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6530 /*-----------------------------------------------------------------*/
6531 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6532 /*-----------------------------------------------------------------*/
6534 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6538 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6539 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6541 if( !( (pcop->type == PO_LABEL) ||
6542 (pcop->type == PO_LITERAL) ||
6543 (pcop->type == PO_STR) ))
6544 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6545 PCOR(pcop)->r->wasUsed = 1;
6551 /*----------------------------------------------------------------------*
6552 * pic16_areRegsSame - check to see if the names of two registers match *
6553 *----------------------------------------------------------------------*/
6554 int pic16_areRegsSame(regs *r1, regs *r2)
6556 if(!strcmp(r1->name, r2->name))return 1;
6562 /*-----------------------------------------------------------------*/
6563 /*-----------------------------------------------------------------*/
6564 static void pic16_FixRegisterBanking(pBlock *pb)
6568 regs *reg, *prevreg;
6569 unsigned char flag=0;
6574 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6577 /* loop through all of the flow blocks with in one pblock */
6579 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6583 /* at this point, pc should point to a PC_FLOW object */
6584 /* for each flow block, determine the register banking
6587 if(!isPCI(pc))goto loop;
6589 if(PCI(pc)->is2MemOp)goto loop;
6591 reg = pic16_getRegFromInstruction(pc);
6594 pc->print(stderr, pc);
6595 fprintf(stderr, "reg = %p\n", reg);
6598 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6599 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6600 reg->address,reg->isBitField, reg->isFixed);
6604 /* now make some tests to make sure that instruction needs bank switch */
6606 /* if no register exists, and if not a bit opcode goto loop */
6608 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6611 if(isPCI_SKIP(pc)) {
6612 // fprintf(stderr, "instruction is SKIP instruction\n");
6614 if(reg && isACCESS_BANK(reg))goto loop;
6616 if(!isBankInstruction(pc))goto loop;
6618 if(isPCI_LIT(pc))goto loop;
6620 if(PCI(pc)->op == POC_CALL)goto loop;
6622 /* Examine the instruction before this one to make sure it is
6623 * not a skip type instruction */
6624 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6626 flag = 0; /* add before this instruction */
6628 /* if previous instruction is a skip one, then set flag
6629 * to 2 and call insertBankSwitch */
6630 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6633 insertBankSwitch(flag, pc);
6636 // fprintf(stderr, "BANK SWITCH inserted\n");
6645 static void pBlockDestruct(pBlock *pb)
6656 /*-----------------------------------------------------------------*/
6657 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6658 /* name dbName and combine them */
6659 /* into one block */
6660 /*-----------------------------------------------------------------*/
6661 static void mergepBlocks(char dbName)
6664 pBlock *pb, *pbmerged = NULL,*pbn;
6666 pb = the_pFile->pbHead;
6668 //fprintf(stderr," merging blocks named %c\n",dbName);
6672 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6673 if( getpBlock_dbName(pb) == dbName) {
6675 //fprintf(stderr," merged block %c\n",dbName);
6680 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6681 /* pic16_addpCode2pBlock doesn't handle the tail: */
6682 pbmerged->pcTail = pb->pcTail;
6684 pb->prev->next = pbn;
6686 pbn->prev = pb->prev;
6691 //pic16_printpBlock(stderr, pbmerged);
6698 /*-----------------------------------------------------------------*/
6699 /* AnalyzeFlow - Examine the flow of the code and optimize */
6701 /* level 0 == minimal optimization */
6702 /* optimize registers that are used only by two instructions */
6703 /* level 1 == maximal optimization */
6704 /* optimize by looking at pairs of instructions that use the */
6706 /*-----------------------------------------------------------------*/
6708 static void AnalyzeFlow(int level)
6710 static int times_called=0;
6715 /* remove unused allocated registers before exiting */
6716 pic16_RemoveUnusedRegisters();
6722 /* if this is not the first time this function has been called,
6723 then clean up old flow information */
6724 if(times_called++) {
6725 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6728 pic16_RegsUnMapLiveRanges();
6733 /* Phase 2 - Flow Analysis - Register Banking
6735 * In this phase, the individual flow blocks are examined
6736 * and register banking is fixed.
6740 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6741 pic16_FixRegisterBanking(pb);
6744 /* Phase 2 - Flow Analysis
6746 * In this phase, the pCode is partition into pCodeFlow
6747 * blocks. The flow blocks mark the points where a continuous
6748 * stream of instructions changes flow (e.g. because of
6749 * a call or goto or whatever).
6752 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6753 pic16_BuildFlow(pb);
6756 /* Phase 2 - Flow Analysis - linking flow blocks
6758 * In this phase, the individual flow blocks are examined
6759 * to determine their order of excution.
6762 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6765 /* Phase 3 - Flow Analysis - Flow Tree
6767 * In this phase, the individual flow blocks are examined
6768 * to determine their order of execution.
6771 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6772 pic16_BuildFlowTree(pb);
6775 /* Phase x - Flow Analysis - Used Banks
6777 * In this phase, the individual flow blocks are examined
6778 * to determine the Register Banks they use
6782 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6787 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6788 pic16_pCodeRegMapLiveRanges(pb);
6790 pic16_RemoveUnusedRegisters();
6792 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6793 pic16_pCodeRegOptimizeRegUsage(level);
6801 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6806 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6808 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6809 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6810 pcflow = pcflow->next) {
6812 FillFlow(PCFL(pcflow));
6817 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6820 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6821 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6822 pcflow = pcflow->next) {
6824 FlowStats(PCFL(pcflow));
6830 /* VR -- no need to analyze banking in flow, but left here :
6831 * 1. because it may be used in the future for other purposes
6832 * 2. because if omitted we'll miss some optimization done here
6834 * Perhaps I should rename it to something else
6837 /*-----------------------------------------------------------------*/
6838 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6839 /* assigned to the registers. */
6841 /*-----------------------------------------------------------------*/
6843 void pic16_AnalyzeBanking(void)
6848 /* Phase x - Flow Analysis - Used Banks
6850 * In this phase, the individual flow blocks are examined
6851 * to determine the Register Banks they use
6857 if(!the_pFile)return;
6859 if(!pic16_options.no_banksel) {
6860 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6861 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6862 pic16_FixRegisterBanking(pb);
6868 /*-----------------------------------------------------------------*/
6869 /* buildCallTree - Look at the flow and extract all of the calls. */
6870 /*-----------------------------------------------------------------*/
6871 static set *register_usage(pBlock *pb);
6873 static void buildCallTree(void )
6885 /* Now build the call tree.
6886 First we examine all of the pCodes for functions.
6887 Keep in mind that the function boundaries coincide
6888 with pBlock boundaries.
6890 The algorithm goes something like this:
6891 We have two nested loops. The outer loop iterates
6892 through all of the pBlocks/functions. The inner
6893 loop iterates through all of the pCodes for
6894 a given pBlock. When we begin iterating through
6895 a pBlock, the variable pc_fstart, pCode of the start
6896 of a function, is cleared. We then search for pCodes
6897 of type PC_FUNCTION. When one is encountered, we
6898 initialize pc_fstart to this and at the same time
6899 associate a new pBranch object that signifies a
6900 branch entry. If a return is found, then this signifies
6901 a function exit point. We'll link the pCodes of these
6902 returns to the matching pc_fstart.
6904 When we're done, a doubly linked list of pBranches
6905 will exist. The head of this list is stored in
6906 `the_pFile', which is the meta structure for all
6907 of the pCode. Look at the pic16_printCallTree function
6908 on how the pBranches are linked together.
6911 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6912 pCode *pc_fstart=NULL;
6913 for(pc = pb->pcHead; pc; pc = pc->next) {
6915 if(isPCI(pc) && pc_fstart) {
6916 if(PCI(pc)->is2MemOp) {
6917 r = pic16_getRegFromInstruction2(pc);
6918 if(r && !strcmp(r->name, "POSTDEC1"))
6919 PCF(pc_fstart)->stackusage++;
6921 r = pic16_getRegFromInstruction(pc);
6922 if(r && !strcmp(r->name, "PREINC1"))
6923 PCF(pc_fstart)->stackusage--;
6928 if (PCF(pc)->fname) {
6930 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6931 //fprintf(stderr," found main \n");
6932 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6936 pbr = Safe_calloc(1,sizeof(pBranch));
6937 pbr->pc = pc_fstart = pc;
6940 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6942 // Here's a better way of doing the same:
6943 addSet(&pb->function_entries, pc);
6946 // Found an exit point in a function, e.g. return
6947 // (Note, there may be more than one return per function)
6949 pBranchLink(PCF(pc_fstart), PCF(pc));
6951 addSet(&pb->function_exits, pc);
6953 } else if(isCALL(pc)) {
6954 addSet(&pb->function_calls,pc);
6961 /* This is not needed because currently all register used
6962 * by a function are stored in stack -- VR */
6964 /* Re-allocate the registers so that there are no collisions
6965 * between local variables when one function call another */
6968 // pic16_deallocateAllRegs();
6970 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6978 /*-----------------------------------------------------------------*/
6979 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6980 /* all of the logical connections. */
6982 /* Essentially what's done here is that the pCode flow is */
6984 /*-----------------------------------------------------------------*/
6986 void pic16_AnalyzepCode(char dbName)
6997 /* Phase 1 - Register allocation and peep hole optimization
6999 * The first part of the analysis is to determine the registers
7000 * that are used in the pCode. Once that is done, the peep rules
7001 * are applied to the code. We continue to loop until no more
7002 * peep rule optimizations are found (or until we exceed the
7003 * MAX_PASSES threshold).
7005 * When done, the required registers will be determined.
7011 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7012 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7014 /* First, merge the labels with the instructions */
7015 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7016 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7018 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7019 //fprintf(stderr," analyze and merging block %c\n",dbName);
7020 pic16_pBlockMergeLabels(pb);
7023 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7028 changes = OptimizepCode(dbName);
7031 } while(changes && (i++ < MAX_PASSES));
7036 /*-----------------------------------------------------------------*/
7037 /* ispCodeFunction - returns true if *pc is the pCode of a */
7039 /*-----------------------------------------------------------------*/
7040 static bool ispCodeFunction(pCode *pc)
7043 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7049 /*-----------------------------------------------------------------*/
7050 /* findFunction - Search for a function by name (given the name) */
7051 /* in the set of all functions that are in a pBlock */
7052 /* (note - I expect this to change because I'm planning to limit */
7053 /* pBlock's to just one function declaration */
7054 /*-----------------------------------------------------------------*/
7055 static pCode *findFunction(char *fname)
7062 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7064 pc = setFirstItem(pb->function_entries);
7067 if((pc->type == PC_FUNCTION) &&
7069 (strcmp(fname, PCF(pc)->fname)==0))
7072 pc = setNextItem(pb->function_entries);
7080 static void MarkUsedRegisters(set *regset)
7085 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7086 // fprintf(stderr, "marking register = %s\t", r1->name);
7087 r2 = pic16_regWithIdx(r1->rIdx);
7088 // fprintf(stderr, "to register = %s\n", r2->name);
7094 static void pBlockStats(FILE *of, pBlock *pb)
7100 if(!pic16_pcode_verbose)return;
7102 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7104 // for now just print the first element of each set
7105 pc = setFirstItem(pb->function_entries);
7107 fprintf(of,";entry: ");
7110 pc = setFirstItem(pb->function_exits);
7112 fprintf(of,";has an exit\n");
7116 pc = setFirstItem(pb->function_calls);
7118 fprintf(of,";functions called:\n");
7121 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7122 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7124 pc = setNextItem(pb->function_calls);
7128 r = setFirstItem(pb->tregisters);
7130 int n = elementsInSet(pb->tregisters);
7132 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7135 fprintf(of,"; %s\n",r->name);
7136 r = setNextItem(pb->tregisters);
7140 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7143 /*-----------------------------------------------------------------*/
7144 /*-----------------------------------------------------------------*/
7146 static void sequencepCode(void)
7152 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7154 pb->seq = GpCodeSequenceNumber+1;
7156 for( pc = pb->pcHead; pc; pc = pc->next)
7157 pc->seq = ++GpCodeSequenceNumber;
7163 /*-----------------------------------------------------------------*/
7164 /*-----------------------------------------------------------------*/
7165 static set *register_usage(pBlock *pb)
7168 set *registers=NULL;
7169 set *registersInCallPath = NULL;
7171 /* check recursion */
7173 pc = setFirstItem(pb->function_entries);
7180 if(pc->type != PC_FUNCTION)
7181 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7183 pc = setFirstItem(pb->function_calls);
7184 for( ; pc; pc = setNextItem(pb->function_calls)) {
7186 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7187 char *dest = pic16_get_op_from_instruction(PCI(pc));
7189 pcn = findFunction(dest);
7191 registersInCallPath = register_usage(pcn->pb);
7193 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7198 pBlockStats(stderr,pb); // debug
7201 // Mark the registers in this block as used.
7203 MarkUsedRegisters(pb->tregisters);
7204 if(registersInCallPath) {
7205 /* registers were used in the functions this pBlock has called */
7206 /* so now, we need to see if these collide with the ones we are */
7209 regs *r1,*r2, *newreg;
7211 DFPRINTF((stderr,"comparing registers\n"));
7213 r1 = setFirstItem(registersInCallPath);
7216 r2 = setFirstItem(pb->tregisters);
7218 while(r2 && (r1->type != REG_STK)) {
7220 if(r2->rIdx == r1->rIdx) {
7221 newreg = pic16_findFreeReg(REG_GPR);
7225 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7229 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7230 r1->rIdx, newreg->rIdx));
7231 r2->rIdx = newreg->rIdx;
7232 //if(r2->name) free(r2->name);
7234 r2->name = Safe_strdup(newreg->name);
7238 newreg->wasUsed = 1;
7240 r2 = setNextItem(pb->tregisters);
7243 r1 = setNextItem(registersInCallPath);
7246 /* Collisions have been resolved. Now free the registers in the call path */
7247 r1 = setFirstItem(registersInCallPath);
7249 if(r1->type != REG_STK) {
7250 newreg = pic16_regWithIdx(r1->rIdx);
7253 r1 = setNextItem(registersInCallPath);
7257 // MarkUsedRegisters(pb->registers);
7259 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7262 DFPRINTF((stderr,"returning regs\n"));
7264 DFPRINTF((stderr,"not returning regs\n"));
7266 DFPRINTF((stderr,"pBlock after register optim.\n"));
7267 pBlockStats(stderr,pb); // debug
7273 /*-----------------------------------------------------------------*/
7274 /* pct2 - writes the call tree to a file */
7276 /*-----------------------------------------------------------------*/
7277 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7281 // set *registersInCallPath = NULL;
7287 fprintf(of, "recursive function\n");
7288 return; //recursion ?
7291 pc = setFirstItem(pb->function_entries);
7298 for(i=0;i<indent;i++) // Indentation
7302 if(pc->type == PC_FUNCTION) {
7303 usedstack += PCF(pc)->stackusage;
7304 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7305 } else return; // ???
7308 pc = setFirstItem(pb->function_calls);
7309 for( ; pc; pc = setNextItem(pb->function_calls)) {
7311 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7312 char *dest = pic16_get_op_from_instruction(PCI(pc));
7314 pcn = findFunction(dest);
7316 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7318 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7326 /*-----------------------------------------------------------------*/
7327 /* pic16_printCallTree - writes the call tree to a file */
7329 /*-----------------------------------------------------------------*/
7331 void pic16_printCallTree(FILE *of)
7343 fprintf(of, "\npBlock statistics\n");
7344 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7348 fprintf(of,"Call Tree\n");
7349 pbr = the_pFile->functions;
7353 if(!ispCodeFunction(pc))
7354 fprintf(of,"bug in call tree");
7357 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7359 while(pc->next && !ispCodeFunction(pc->next)) {
7361 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7362 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7370 fprintf(of,"\n**************\n\na better call tree\n");
7371 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7376 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7377 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7383 /*-----------------------------------------------------------------*/
7385 /*-----------------------------------------------------------------*/
7387 static void InlineFunction(pBlock *pb)
7395 pc = setFirstItem(pb->function_calls);
7397 for( ; pc; pc = setNextItem(pb->function_calls)) {
7400 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7406 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7408 //fprintf(stderr,"Cool can inline:\n");
7409 //pcn->print(stderr,pcn);
7411 //fprintf(stderr,"recursive call Inline\n");
7412 InlineFunction(pcn->pb);
7413 //fprintf(stderr,"return from recursive call Inline\n");
7416 At this point, *pc points to a CALL mnemonic, and
7417 *pcn points to the function that is being called.
7419 To in-line this call, we need to remove the CALL
7420 and RETURN(s), and link the function pCode in with
7426 /* Remove the CALL */
7430 /* remove callee pBlock from the pBlock linked list */
7431 removepBlock(pcn->pb);
7439 /* Remove the Function pCode */
7440 pct = pic16_findNextInstruction(pcn->next);
7442 /* Link the function with the callee */
7443 pc->next = pcn->next;
7444 pcn->next->prev = pc;
7446 /* Convert the function name into a label */
7448 pbr = Safe_calloc(1,sizeof(pBranch));
7449 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7451 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7452 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7454 /* turn all of the return's except the last into goto's */
7455 /* check case for 2 instruction pBlocks */
7456 pce = pic16_findNextInstruction(pcn->next);
7458 pCode *pce_next = pic16_findNextInstruction(pce->next);
7460 if(pce_next == NULL) {
7461 /* found the last return */
7462 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7464 //fprintf(stderr,"found last return\n");
7465 //pce->print(stderr,pce);
7466 pce->prev->next = pc_call->next;
7467 pc_call->next->prev = pce->prev;
7468 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7478 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7484 /*-----------------------------------------------------------------*/
7486 /*-----------------------------------------------------------------*/
7488 void pic16_InlinepCode(void)
7497 if(!functionInlining)
7500 /* Loop through all of the function definitions and count the
7501 * number of times each one is called */
7502 //fprintf(stderr,"inlining %d\n",__LINE__);
7504 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7506 pc = setFirstItem(pb->function_calls);
7508 for( ; pc; pc = setNextItem(pb->function_calls)) {
7511 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7512 if(pcn && isPCF(pcn)) {
7513 PCF(pcn)->ncalled++;
7516 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7521 //fprintf(stderr,"inlining %d\n",__LINE__);
7523 /* Now, Loop through the function definitions again, but this
7524 * time inline those functions that have only been called once. */
7526 InlineFunction(the_pFile->pbHead);
7527 //fprintf(stderr,"inlining %d\n",__LINE__);
7529 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7534 char *pic_optype_names[]={
7535 "PO_NONE", // No operand e.g. NOP
7536 "PO_W", // The working register (as a destination)
7537 "PO_WREG", // The working register (as a file register)
7538 "PO_STATUS", // The 'STATUS' register
7539 "PO_BSR", // The 'BSR' register
7540 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7542 "PO_INDF0", // The Indirect register
7543 "PO_INTCON", // Interrupt Control register
7544 "PO_GPR_REGISTER", // A general purpose register
7545 "PO_GPR_BIT", // A bit of a general purpose register
7546 "PO_GPR_TEMP", // A general purpose temporary register
7547 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7548 "PO_PCL", // Program counter Low register
7549 "PO_PCLATH", // Program counter Latch high register
7550 "PO_PCLATU", // Program counter Latch upper register
7551 "PO_PRODL", // Product Register Low
7552 "PO_PRODH", // Product Register High
7553 "PO_LITERAL", // A constant
7554 "PO_REL_ADDR", // A relative address
7555 "PO_IMMEDIATE", // (8051 legacy)
7556 "PO_DIR", // Direct memory (8051 legacy)
7557 "PO_CRY", // bit memory (8051 legacy)
7558 "PO_BIT", // bit operand.
7559 "PO_STR", // (8051 legacy)
7561 "PO_WILD" // Wild card operand in peep optimizer
7565 char *dumpPicOptype(PIC_OPTYPE type)
7567 return (pic_optype_names[ type ]);