1 /*-------------------------------------------------------------------------
3 pcode.c - post code generation
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 #include "common.h" // Include everything in the SDCC src directory
31 #include "pcodeflow.h"
35 #if defined(__BORLANDC__) || defined(_MSC_VER)
36 #define STRCASECMP stricmp
38 #define STRCASECMP strcasecmp
41 /****************************************************************/
42 /****************************************************************/
44 static peepCommand peepCommands[] = {
46 {NOTBITSKIP, "_NOTBITSKIP_"},
47 {BITSKIP, "_BITSKIP_"},
48 {INVERTBITSKIP, "_INVERTBITSKIP_"},
55 // Eventually this will go into device dependent files:
56 pCodeOpReg pic16_pc_status = {{PO_STATUS, "STATUS"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_intcon = {{PO_INTCON, "INTCON"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_pcl = {{PO_PCL, "PCL"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclatu = {{PO_PCLATU, "PCLATU"}, -1, NULL,0,NULL}; // patch 14
61 pCodeOpReg pic16_pc_wreg = {{PO_WREG, "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr = {{PO_BSR, "BSR"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_tosl = {{PO_SFR_REGISTER, "TOSL"}, -1, NULL,0,NULL}; // patch 14
65 pCodeOpReg pic16_pc_tosh = {{PO_SFR_REGISTER, "TOSH"}, -1, NULL,0,NULL}; //
66 pCodeOpReg pic16_pc_tosu = {{PO_SFR_REGISTER, "TOSU"}, -1, NULL,0,NULL}; // patch 14
68 pCodeOpReg pic16_pc_tblptrl = {{PO_SFR_REGISTER, "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
69 pCodeOpReg pic16_pc_tblptrh = {{PO_SFR_REGISTER, "TBLPTRH"}, -1, NULL,0,NULL}; //
70 pCodeOpReg pic16_pc_tblptru = {{PO_SFR_REGISTER, "TBLPTRU"}, -1, NULL,0,NULL}; //
71 pCodeOpReg pic16_pc_tablat = {{PO_SFR_REGISTER, "TABLAT"}, -1, NULL,0,NULL}; // patch 15
73 //pCodeOpReg pic16_pc_fsr0 = {{PO_FSR0, "FSR0"}, -1, NULL,0,NULL}; //deprecated !
75 pCodeOpReg pic16_pc_fsr0l = {{PO_FSR0, "FSR0L"}, -1, NULL, 0, NULL};
76 pCodeOpReg pic16_pc_fsr0h = {{PO_FSR0, "FSR0H"}, -1, NULL, 0, NULL};
77 pCodeOpReg pic16_pc_fsr1l = {{PO_FSR0, "FSR1L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr1h = {{PO_FSR0, "FSR1H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr2l = {{PO_FSR0, "FSR2L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr2h = {{PO_FSR0, "FSR2H"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_indf0 = {{PO_INDF0, "INDF0"}, -1, NULL,0,NULL};
83 pCodeOpReg pic16_pc_postinc0 = {{PO_INDF0, "POSTINC0"}, -1, NULL, 0, NULL};
84 pCodeOpReg pic16_pc_postdec0 = {{PO_INDF0, "POSTDEC0"}, -1, NULL, 0, NULL};
85 pCodeOpReg pic16_pc_preinc0 = {{PO_INDF0, "PREINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_plusw0 = {{PO_INDF0, "PLUSW0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_indf1 = {{PO_INDF0, "INDF1"}, -1, NULL,0,NULL};
89 pCodeOpReg pic16_pc_postinc1 = {{PO_INDF0, "POSTINC1"}, -1, NULL, 0, NULL};
90 pCodeOpReg pic16_pc_postdec1 = {{PO_INDF0, "POSTDEC1"}, -1, NULL, 0, NULL};
91 pCodeOpReg pic16_pc_preinc1 = {{PO_INDF0, "PREINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_plusw1 = {{PO_INDF0, "PLUSW1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_indf2 = {{PO_INDF0, "INDF2"}, -1, NULL,0,NULL};
95 pCodeOpReg pic16_pc_postinc2 = {{PO_INDF0, "POSTINC2"}, -1, NULL, 0, NULL};
96 pCodeOpReg pic16_pc_postdec2 = {{PO_INDF0, "POSTDEC2"}, -1, NULL, 0, NULL};
97 pCodeOpReg pic16_pc_preinc2 = {{PO_INDF0, "PREINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_plusw2 = {{PO_INDF0, "PLUSW2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_prodl = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
101 pCodeOpReg pic16_pc_prodh = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
103 /* EEPROM registers */
104 pCodeOpReg pic16_pc_eecon1 = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
105 pCodeOpReg pic16_pc_eecon2 = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
106 pCodeOpReg pic16_pc_eedata = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eeadr = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
111 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
115 static int mnemonics_initialized = 0;
118 static hTab *pic16MnemonicsHash = NULL;
119 static hTab *pic16pCodePeepCommandsHash = NULL;
121 static pFile *the_pFile = NULL;
122 static pBlock *pb_dead_pcodes = NULL;
124 /* Hardcoded flags to change the behavior of the PIC port */
125 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
126 static int functionInlining = 1; /* inline functions if nonzero */
127 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
129 int pic16_pcode_verbose = 0;
131 //static int GpCodeSequenceNumber = 1;
132 static int GpcFlowSeq = 1;
134 extern void pic16_RemoveUnusedRegisters(void);
135 extern void pic16_RegsUnMapLiveRanges(void);
136 extern void pic16_BuildFlowTree(pBlock *pb);
137 extern void pic16_pCodeRegOptimizeRegUsage(int level);
138 extern int pic16_picIsInitialized(void);
139 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
140 extern int mnem2key(char const *mnem);
142 /****************************************************************/
143 /* Forward declarations */
144 /****************************************************************/
146 void pic16_unlinkpCode(pCode *pc);
148 static void genericAnalyze(pCode *pc);
149 static void AnalyzeGOTO(pCode *pc);
150 static void AnalyzeSKIP(pCode *pc);
151 static void AnalyzeRETURN(pCode *pc);
154 static void genericDestruct(pCode *pc);
155 static void genericPrint(FILE *of,pCode *pc);
157 static void pCodePrintLabel(FILE *of, pCode *pc);
158 static void pCodePrintFunction(FILE *of, pCode *pc);
159 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
160 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
161 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
162 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
163 int pic16_pCodePeepMatchRule(pCode *pc);
164 static void pBlockStats(FILE *of, pBlock *pb);
165 static pBlock *newpBlock(void);
166 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
167 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
168 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
169 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
171 char *dumpPicOptype(PIC_OPTYPE type);
173 /****************************************************************/
174 /* PIC Instructions */
175 /****************************************************************/
177 pCodeInstruction pic16_pciADDWF = {
178 {PC_OPCODE, NULL, NULL, 0, NULL,
191 1,0, // dest, bit instruction
193 0, // literal operand
195 0, // fast call/return mode select bit
196 0, // second memory operand
197 0, // second literal operand
199 (PCC_W | PCC_REGISTER), // inCond
200 (PCC_REGISTER | PCC_Z), // outCond
204 pCodeInstruction pic16_pciADDFW = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
218 0,0, // dest, bit instruction
220 0, // literal operand
222 0, // fast call/return mode select bit
223 0, // second memory operand
224 0, // second literal operand
226 (PCC_W | PCC_REGISTER), // inCond
227 (PCC_W | PCC_Z), // outCond
231 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
232 {PC_OPCODE, NULL, NULL, 0, NULL,
245 1,0, // dest, bit instruction
247 0, // literal operand
249 0, // fast call/return mode select bit
250 0, // second memory operand
251 0, // second literal operand
253 (PCC_W | PCC_REGISTER | PCC_C), // inCond
254 (PCC_REGISTER | PCC_Z), // outCond
258 pCodeInstruction pic16_pciADDFWC = {
259 {PC_OPCODE, NULL, NULL, 0, NULL,
272 0,0, // dest, bit instruction
274 0, // literal operand
276 0, // fast call/return mode select bit
277 0, // second memory operand
278 0, // second literal operand
280 (PCC_W | PCC_REGISTER | PCC_C), // inCond
281 (PCC_W | PCC_Z), // outCond
285 pCodeInstruction pic16_pciADDLW = {
286 {PC_OPCODE, NULL, NULL, 0, NULL,
299 0,0, // dest, bit instruction
301 1, // literal operand
303 0, // fast call/return mode select bit
304 0, // second memory operand
305 0, // second literal operand
307 (PCC_W | PCC_LITERAL), // inCond
308 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
312 pCodeInstruction pic16_pciANDLW = {
313 {PC_OPCODE, NULL, NULL, 0, NULL,
326 0,0, // dest, bit instruction
328 1, // literal operand
330 0, // fast call/return mode select bit
331 0, // second memory operand
332 0, // second literal operand
334 (PCC_W | PCC_LITERAL), // inCond
335 (PCC_W | PCC_Z | PCC_N), // outCond
339 pCodeInstruction pic16_pciANDWF = {
340 {PC_OPCODE, NULL, NULL, 0, NULL,
353 1,0, // dest, bit instruction
355 0, // literal operand
357 0, // fast call/return mode select bit
358 0, // second memory operand
359 0, // second literal operand
361 (PCC_W | PCC_REGISTER), // inCond
362 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
366 pCodeInstruction pic16_pciANDFW = {
367 {PC_OPCODE, NULL, NULL, 0, NULL,
380 0,0, // dest, bit instruction
382 0, // literal operand
384 0, // fast call/return mode select bit
385 0, // second memory operand
386 0, // second literal operand
388 (PCC_W | PCC_REGISTER), // inCond
389 (PCC_W | PCC_Z) // outCond
392 pCodeInstruction pic16_pciBC = { // mdubuc - New
393 {PC_OPCODE, NULL, NULL, 0, NULL,
406 0,0, // dest, bit instruction
408 0, // literal operand
410 0, // fast call/return mode select bit
411 0, // second memory operand
412 0, // second literal operand
414 (PCC_REL_ADDR | PCC_C), // inCond
419 pCodeInstruction pic16_pciBCF = {
420 {PC_OPCODE, NULL, NULL, 0, NULL,
433 1,1, // dest, bit instruction
435 0, // literal operand
437 0, // fast call/return mode select bit
438 0, // second memory operand
439 0, // second literal operand
441 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
442 PCC_REGISTER, // outCond
446 pCodeInstruction pic16_pciBN = { // mdubuc - New
447 {PC_OPCODE, NULL, NULL, 0, NULL,
460 0,0, // dest, bit instruction
462 0, // literal operand
464 0, // fast call/return mode select bit
465 0, // second memory operand
466 0, // second literal operand
468 (PCC_REL_ADDR | PCC_N), // inCond
469 PCC_NONE , // outCond
473 pCodeInstruction pic16_pciBNC = { // mdubuc - New
474 {PC_OPCODE, NULL, NULL, 0, NULL,
487 0,0, // dest, bit instruction
489 0, // literal operand
491 0, // fast call/return mode select bit
492 0, // second memory operand
493 0, // second literal operand
495 (PCC_REL_ADDR | PCC_C), // inCond
496 PCC_NONE , // outCond
500 pCodeInstruction pic16_pciBNN = { // mdubuc - New
501 {PC_OPCODE, NULL, NULL, 0, NULL,
514 0,0, // dest, bit instruction
516 0, // literal operand
518 0, // fast call/return mode select bit
519 0, // second memory operand
520 0, // second literal operand
522 (PCC_REL_ADDR | PCC_N), // inCond
523 PCC_NONE , // outCond
527 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
528 {PC_OPCODE, NULL, NULL, 0, NULL,
541 0,0, // dest, bit instruction
543 0, // literal operand
545 0, // fast call/return mode select bit
546 0, // second memory operand
547 0, // second literal operand
549 (PCC_REL_ADDR | PCC_OV), // inCond
550 PCC_NONE , // outCond
554 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
555 {PC_OPCODE, NULL, NULL, 0, NULL,
568 0,0, // dest, bit instruction
570 0, // literal operand
572 0, // fast call/return mode select bit
573 0, // second memory operand
574 0, // second literal operand
576 (PCC_REL_ADDR | PCC_Z), // inCond
577 PCC_NONE , // outCond
581 pCodeInstruction pic16_pciBOV = { // mdubuc - New
582 {PC_OPCODE, NULL, NULL, 0, NULL,
595 0,0, // dest, bit instruction
597 0, // literal operand
599 0, // fast call/return mode select bit
600 0, // second memory operand
601 0, // second literal operand
603 (PCC_REL_ADDR | PCC_OV), // inCond
604 PCC_NONE , // outCond
608 pCodeInstruction pic16_pciBRA = { // mdubuc - New
609 {PC_OPCODE, NULL, NULL, 0, NULL,
622 0,0, // dest, bit instruction
624 0, // literal operand
626 0, // fast call/return mode select bit
627 0, // second memory operand
628 0, // second literal operand
630 PCC_REL_ADDR, // inCond
631 PCC_NONE , // outCond
635 pCodeInstruction pic16_pciBSF = {
636 {PC_OPCODE, NULL, NULL, 0, NULL,
649 1,1, // dest, bit instruction
651 0, // literal operand
653 0, // fast call/return mode select bit
654 0, // second memory operand
655 0, // second literal operand
657 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
658 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
662 pCodeInstruction pic16_pciBTFSC = {
663 {PC_OPCODE, NULL, NULL, 0, NULL,
676 0,1, // dest, bit instruction
678 0, // literal operand
680 0, // fast call/return mode select bit
681 0, // second memory operand
682 0, // second literal operand
684 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
685 PCC_EXAMINE_PCOP, // outCond
689 pCodeInstruction pic16_pciBTFSS = {
690 {PC_OPCODE, NULL, NULL, 0, NULL,
703 0,1, // dest, bit instruction
705 0, // literal operand
707 0, // fast call/return mode select bit
708 0, // second memory operand
709 0, // second literal operand
711 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
712 PCC_EXAMINE_PCOP, // outCond
716 pCodeInstruction pic16_pciBTG = { // mdubuc - New
717 {PC_OPCODE, NULL, NULL, 0, NULL,
730 0,1, // dest, bit instruction
732 0, // literal operand
734 0, // fast call/return mode select bit
735 0, // second memory operand
736 0, // second literal operand
738 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
739 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
743 pCodeInstruction pic16_pciBZ = { // mdubuc - New
744 {PC_OPCODE, NULL, NULL, 0, NULL,
757 0,0, // dest, bit instruction
759 0, // literal operand
761 0, // fast call/return mode select bit
762 0, // second memory operand
763 0, // second literal operand
770 pCodeInstruction pic16_pciCALL = {
771 {PC_OPCODE, NULL, NULL, 0, NULL,
784 0,0, // dest, bit instruction
786 0, // literal operand
788 1, // fast call/return mode select bit
789 0, // second memory operand
790 0, // second literal operand
793 PCC_NONE , // outCond
797 pCodeInstruction pic16_pciCOMF = {
798 {PC_OPCODE, NULL, NULL, 0, NULL,
811 1,0, // dest, bit instruction
813 0, // literal operand
815 0, // fast call/return mode select bit
816 0, // second memory operand
817 0, // second literal operand
819 PCC_REGISTER, // inCond
820 PCC_REGISTER , // outCond
824 pCodeInstruction pic16_pciCOMFW = {
825 {PC_OPCODE, NULL, NULL, 0, NULL,
838 0,0, // dest, bit instruction
840 0, // literal operand
842 0, // fast call/return mode select bit
843 0, // second memory operand
844 0, // second literal operand
846 PCC_REGISTER, // inCond
851 pCodeInstruction pic16_pciCLRF = {
852 {PC_OPCODE, NULL, NULL, 0, NULL,
865 0,0, // dest, bit instruction
867 0, // literal operand
869 0, // fast call/return mode select bit
870 0, // second memory operand
871 0, // second literal operand
873 PCC_REGISTER, // inCond
874 PCC_REGISTER , // outCond
878 pCodeInstruction pic16_pciCLRWDT = {
879 {PC_OPCODE, NULL, NULL, 0, NULL,
892 0,0, // dest, bit instruction
894 0, // literal operand
896 0, // fast call/return mode select bit
897 0, // second memory operand
898 0, // second literal operand
901 PCC_NONE , // outCond
905 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
906 {PC_OPCODE, NULL, NULL, 0, NULL,
919 0,0, // dest, bit instruction
921 0, // literal operand
923 0, // fast call/return mode select bit
924 0, // second memory operand
925 0, // second literal operand
927 (PCC_W | PCC_REGISTER), // inCond
928 PCC_NONE , // outCond
932 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
933 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
954 (PCC_W | PCC_REGISTER), // inCond
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
973 1,0, // dest, bit instruction
975 0, // literal operand
977 0, // fast call/return mode select bit
978 0, // second memory operand
979 0, // second literal operand
981 (PCC_W | PCC_REGISTER), // inCond
982 PCC_NONE , // outCond
986 pCodeInstruction pic16_pciDAW = {
987 {PC_OPCODE, NULL, NULL, 0, NULL,
1000 0,0, // dest, bit instruction
1001 0,0, // branch, skip
1002 0, // literal operand
1003 0, // RAM access bit
1004 0, // fast call/return mode select bit
1005 0, // second memory operand
1006 0, // second literal operand
1009 (PCC_W | PCC_C), // outCond
1013 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1014 {PC_OPCODE, NULL, NULL, 0, NULL,
1020 NULL, // from branch
1027 1,0, // dest, bit instruction
1028 1,1, // branch, skip
1029 0, // literal operand
1030 1, // RAM access bit
1031 0, // fast call/return mode select bit
1032 0, // second memory operand
1033 0, // second literal operand
1035 PCC_REGISTER, // inCond
1036 PCC_REGISTER , // outCond
1040 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1041 {PC_OPCODE, NULL, NULL, 0, NULL,
1047 NULL, // from branch
1054 0,0, // dest, bit instruction
1055 1,1, // branch, skip
1056 0, // literal operand
1057 1, // RAM access bit
1058 0, // fast call/return mode select bit
1059 0, // second memory operand
1060 0, // second literal operand
1062 PCC_REGISTER, // inCond
1067 pCodeInstruction pic16_pciDECF = {
1068 {PC_OPCODE, NULL, NULL, 0, NULL,
1074 NULL, // from branch
1081 1,0, // dest, bit instruction
1082 0,0, // branch, skip
1083 0, // literal operand
1084 1, // RAM access bit
1085 0, // fast call/return mode select bit
1086 0, // second memory operand
1087 0, // second literal operand
1089 PCC_REGISTER, // inCond
1090 PCC_REGISTER , // outCond
1094 pCodeInstruction pic16_pciDECFW = {
1095 {PC_OPCODE, NULL, NULL, 0, NULL,
1101 NULL, // from branch
1108 0,0, // dest, bit instruction
1109 0,0, // branch, skip
1110 0, // literal operand
1111 1, // RAM access bit
1112 0, // fast call/return mode select bit
1113 0, // second memory operand
1114 0, // second literal operand
1116 PCC_REGISTER, // inCond
1121 pCodeInstruction pic16_pciDECFSZ = {
1122 {PC_OPCODE, NULL, NULL, 0, NULL,
1128 NULL, // from branch
1135 1,0, // dest, bit instruction
1136 1,1, // branch, skip
1137 0, // literal operand
1138 1, // RAM access bit
1139 0, // fast call/return mode select bit
1140 0, // second memory operand
1141 0, // second literal operand
1143 PCC_REGISTER, // inCond
1144 PCC_REGISTER , // outCond
1148 pCodeInstruction pic16_pciDECFSZW = {
1149 {PC_OPCODE, NULL, NULL, 0, NULL,
1155 NULL, // from branch
1162 0,0, // dest, bit instruction
1163 1,1, // branch, skip
1164 0, // literal operand
1165 1, // RAM access bit
1166 0, // fast call/return mode select bit
1167 0, // second memory operand
1168 0, // second literal operand
1170 PCC_REGISTER, // inCond
1175 pCodeInstruction pic16_pciGOTO = {
1176 {PC_OPCODE, NULL, NULL, 0, NULL,
1182 NULL, // from branch
1189 0,0, // dest, bit instruction
1190 1,0, // branch, skip
1191 0, // literal operand
1192 0, // RAM access bit
1193 0, // fast call/return mode select bit
1194 0, // second memory operand
1195 0, // second literal operand
1197 PCC_REL_ADDR, // inCond
1198 PCC_NONE , // outCond
1202 pCodeInstruction pic16_pciINCF = {
1203 {PC_OPCODE, NULL, NULL, 0, NULL,
1209 NULL, // from branch
1216 1,0, // dest, bit instruction
1217 0,0, // branch, skip
1218 0, // literal operand
1219 1, // RAM access bit
1220 0, // fast call/return mode select bit
1221 0, // second memory operand
1222 0, // second literal operand
1224 PCC_REGISTER, // inCond
1225 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1229 pCodeInstruction pic16_pciINCFW = {
1230 {PC_OPCODE, NULL, NULL, 0, NULL,
1236 NULL, // from branch
1243 0,0, // dest, bit instruction
1244 0,0, // branch, skip
1245 0, // literal operand
1246 1, // RAM access bit
1247 0, // fast call/return mode select bit
1248 0, // second memory operand
1249 0, // second literal operand
1251 PCC_REGISTER, // inCond
1256 pCodeInstruction pic16_pciINCFSZ = {
1257 {PC_OPCODE, NULL, NULL, 0, NULL,
1263 NULL, // from branch
1270 1,0, // dest, bit instruction
1271 1,1, // branch, skip
1272 0, // literal operand
1273 1, // RAM access bit
1274 0, // fast call/return mode select bit
1275 0, // second memory operand
1276 0, // second literal operand
1278 PCC_REGISTER, // inCond
1279 PCC_REGISTER , // outCond
1283 pCodeInstruction pic16_pciINCFSZW = {
1284 {PC_OPCODE, NULL, NULL, 0, NULL,
1290 NULL, // from branch
1297 0,0, // dest, bit instruction
1298 1,1, // branch, skip
1299 0, // literal operand
1300 1, // RAM access bit
1301 0, // fast call/return mode select bit
1302 0, // second memory operand
1303 0, // second literal operand
1305 PCC_REGISTER, // inCond
1310 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1311 {PC_OPCODE, NULL, NULL, 0, NULL,
1317 NULL, // from branch
1324 1,0, // dest, bit instruction
1325 1,1, // branch, skip
1326 0, // literal operand
1327 1, // RAM access bit
1328 0, // fast call/return mode select bit
1329 0, // second memory operand
1330 0, // second literal operand
1332 PCC_REGISTER, // inCond
1333 PCC_REGISTER , // outCond
1337 pCodeInstruction pic16_pciIORWF = {
1338 {PC_OPCODE, NULL, NULL, 0, NULL,
1344 NULL, // from branch
1351 1,0, // dest, bit instruction
1352 0,0, // branch, skip
1353 0, // literal operand
1354 1, // RAM access bit
1355 0, // fast call/return mode select bit
1356 0, // second memory operand
1357 0, // second literal operand
1359 (PCC_W | PCC_REGISTER), // inCond
1360 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1364 pCodeInstruction pic16_pciIORFW = {
1365 {PC_OPCODE, NULL, NULL, 0, NULL,
1371 NULL, // from branch
1378 0,0, // dest, bit instruction
1379 0,0, // branch, skip
1380 0, // literal operand
1381 1, // RAM access bit
1382 0, // fast call/return mode select bit
1383 0, // second memory operand
1384 0, // second literal operand
1386 (PCC_W | PCC_REGISTER), // inCond
1387 (PCC_W | PCC_Z | PCC_N), // outCond
1391 pCodeInstruction pic16_pciIORLW = {
1392 {PC_OPCODE, NULL, NULL, 0, NULL,
1398 NULL, // from branch
1405 0,0, // dest, bit instruction
1406 0,0, // branch, skip
1407 1, // literal operand
1408 0, // RAM access bit
1409 0, // fast call/return mode select bit
1410 0, // second memory operand
1411 0, // second literal operand
1413 (PCC_W | PCC_LITERAL), // inCond
1414 (PCC_W | PCC_Z | PCC_N), // outCond
1418 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1419 {PC_OPCODE, NULL, NULL, 0, NULL,
1425 NULL, // from branch
1432 0,0, // dest, bit instruction
1433 0,0, // branch, skip
1434 1, // literal operand
1435 0, // RAM access bit
1436 0, // fast call/return mode select bit
1437 0, // second memory operand
1438 1, // second literal operand
1440 (PCC_REGISTER | PCC_LITERAL),
1441 PCC_REGISTER, // outCond
1445 pCodeInstruction pic16_pciMOVF = {
1446 {PC_OPCODE, NULL, NULL, 0, NULL,
1452 NULL, // from branch
1459 1,0, // dest, bit instruction
1460 0,0, // branch, skip
1461 0, // literal operand
1462 1, // RAM access bit
1463 0, // fast call/return mode select bit
1464 0, // second memory operand
1465 0, // second literal operand
1467 PCC_REGISTER, // inCond
1468 (PCC_Z | PCC_N), // outCond
1472 pCodeInstruction pic16_pciMOVFW = {
1473 {PC_OPCODE, NULL, NULL, 0, NULL,
1479 NULL, // from branch
1486 0,0, // dest, bit instruction
1487 0,0, // branch, skip
1488 0, // literal operand
1489 1, // RAM access bit
1490 0, // fast call/return mode select bit
1491 0, // second memory operand
1492 0, // second literal operand
1494 PCC_REGISTER, // inCond
1495 (PCC_W | PCC_Z), // outCond
1499 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1500 {PC_OPCODE, NULL, NULL, 0, NULL,
1506 NULL, // from branch
1513 0,0, // dest, bit instruction
1514 0,0, // branch, skip
1515 0, // literal operand
1516 0, // RAM access bit
1517 0, // fast call/return mode select bit
1518 1, // second memory operand
1519 0, // second literal operand
1521 PCC_REGISTER, // inCond
1522 PCC_REGISTER, // outCond
1526 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1527 {PC_OPCODE, NULL, NULL, 0, NULL,
1532 NULL, // from branch
1539 0,0, // dest, bit instruction
1540 0,0, // branch, skip
1541 1, // literal operand
1542 0, // RAM access bit
1543 0, // fast call/return mode select bit
1544 0, // second memory operand
1545 0, // second literal operand
1547 (PCC_NONE | PCC_LITERAL), // inCond
1548 PCC_REGISTER, // outCond - BSR
1552 pCodeInstruction pic16_pciMOVLW = {
1553 {PC_OPCODE, NULL, NULL, 0, NULL,
1558 NULL, // from branch
1565 0,0, // dest, bit instruction
1566 0,0, // branch, skip
1567 1, // literal operand
1568 0, // RAM access bit
1569 0, // fast call/return mode select bit
1570 0, // second memory operand
1571 0, // second literal operand
1573 (PCC_NONE | PCC_LITERAL), // inCond
1578 pCodeInstruction pic16_pciMOVWF = {
1579 {PC_OPCODE, NULL, NULL, 0, NULL,
1585 NULL, // from branch
1592 0,0, // dest, bit instruction
1593 0,0, // branch, skip
1594 0, // literal operand
1595 1, // RAM access bit
1596 0, // fast call/return mode select bit
1597 0, // second memory operand
1598 0, // second literal operand
1600 PCC_REGISTER, // inCond
1605 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1606 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 1, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 0, // second memory operand
1624 0, // second literal operand
1626 (PCC_W | PCC_LITERAL), // inCond
1627 PCC_REGISTER, // outCond - PROD
1631 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1637 NULL, // from branch
1644 0,0, // dest, bit instruction
1645 0,0, // branch, skip
1646 0, // literal operand
1647 1, // RAM access bit
1648 0, // fast call/return mode select bit
1649 0, // second memory operand
1650 0, // second literal operand
1652 (PCC_W | PCC_REGISTER), // inCond
1653 PCC_REGISTER, // outCond - PROD
1657 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1658 {PC_OPCODE, NULL, NULL, 0, NULL,
1663 NULL, // from branch
1670 0,0, // dest, bit instruction
1671 0,0, // branch, skip
1672 0, // literal operand
1673 1, // RAM access bit
1674 0, // fast call/return mode select bit
1675 0, // second memory operand
1676 0, // second literal operand
1678 PCC_REGISTER, // inCond
1679 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1683 pCodeInstruction pic16_pciNOP = {
1684 {PC_OPCODE, NULL, NULL, 0, NULL,
1689 NULL, // from branch
1696 0,0, // dest, bit instruction
1697 0,0, // branch, skip
1698 0, // literal operand
1699 0, // RAM access bit
1700 0, // fast call/return mode select bit
1701 0, // second memory operand
1702 0, // second literal operand
1705 PCC_NONE, // outCond
1709 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1710 {PC_OPCODE, NULL, NULL, 0, NULL,
1715 NULL, // from branch
1722 0,0, // dest, bit instruction
1723 0,0, // branch, skip
1724 0, // literal operand
1725 0, // RAM access bit
1726 0, // fast call/return mode select bit
1727 0, // second memory operand
1728 0, // second literal operand
1731 PCC_NONE , // outCond
1735 pCodeInstruction pic16_pciPUSH = {
1736 {PC_OPCODE, NULL, NULL, 0, NULL,
1741 NULL, // from branch
1748 0,0, // dest, bit instruction
1749 0,0, // branch, skip
1750 0, // literal operand
1751 0, // RAM access bit
1752 0, // fast call/return mode select bit
1753 0, // second memory operand
1754 0, // second literal operand
1757 PCC_NONE , // outCond
1761 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1762 {PC_OPCODE, NULL, NULL, 0, NULL,
1767 NULL, // from branch
1774 0,0, // dest, bit instruction
1775 0,0, // branch, skip
1776 0, // literal operand
1777 0, // RAM access bit
1778 0, // fast call/return mode select bit
1779 0, // second memory operand
1780 0, // second literal operand
1782 PCC_REL_ADDR, // inCond
1783 PCC_NONE , // outCond
1787 pCodeInstruction pic16_pciRETFIE = {
1788 {PC_OPCODE, NULL, NULL, 0, NULL,
1794 NULL, // from branch
1801 0,0, // dest, bit instruction
1802 1,0, // branch, skip
1803 0, // literal operand
1804 0, // RAM access bit
1805 1, // fast call/return mode select bit
1806 0, // second memory operand
1807 0, // second literal operand
1810 PCC_NONE, // outCond (not true... affects the GIE bit too)
1814 pCodeInstruction pic16_pciRETLW = {
1815 {PC_OPCODE, NULL, NULL, 0, NULL,
1821 NULL, // from branch
1828 0,0, // dest, bit instruction
1829 1,0, // branch, skip
1830 1, // literal operand
1831 0, // RAM access bit
1832 0, // fast call/return mode select bit
1833 0, // second memory operand
1834 0, // second literal operand
1836 PCC_LITERAL, // inCond
1841 pCodeInstruction pic16_pciRETURN = {
1842 {PC_OPCODE, NULL, NULL, 0, NULL,
1848 NULL, // from branch
1855 0,0, // dest, bit instruction
1856 1,0, // branch, skip
1857 0, // literal operand
1858 0, // RAM access bit
1859 1, // fast call/return mode select bit
1860 0, // second memory operand
1861 0, // second literal operand
1864 PCC_NONE, // outCond
1867 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1868 {PC_OPCODE, NULL, NULL, 0, NULL,
1874 NULL, // from branch
1881 1,0, // dest, bit instruction
1882 0,0, // branch, skip
1883 0, // literal operand
1884 1, // RAM access bit
1885 0, // fast call/return mode select bit
1886 0, // second memory operand
1887 0, // second literal operand
1889 (PCC_C | PCC_REGISTER), // inCond
1890 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1894 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1895 {PC_OPCODE, NULL, NULL, 0, NULL,
1901 NULL, // from branch
1908 0,0, // dest, bit instruction
1909 0,0, // branch, skip
1910 0, // literal operand
1911 1, // RAM access bit
1912 0, // fast call/return mode select bit
1913 0, // second memory operand
1914 0, // second literal operand
1916 (PCC_C | PCC_REGISTER), // inCond
1917 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1921 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1922 {PC_OPCODE, NULL, NULL, 0, NULL,
1928 NULL, // from branch
1935 1,0, // dest, bit instruction
1936 0,0, // branch, skip
1937 0, // literal operand
1938 1, // RAM access bit
1939 0, // fast call/return mode select bit
1940 0, // second memory operand
1941 0, // second literal operand
1943 PCC_REGISTER, // inCond
1944 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1947 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1948 {PC_OPCODE, NULL, NULL, 0, NULL,
1954 NULL, // from branch
1961 0,0, // dest, bit instruction
1962 0,0, // branch, skip
1963 0, // literal operand
1964 1, // RAM access bit
1965 0, // fast call/return mode select bit
1966 0, // second memory operand
1967 0, // second literal operand
1969 PCC_REGISTER, // inCond
1970 (PCC_W | PCC_Z | PCC_N), // outCond
1973 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1974 {PC_OPCODE, NULL, NULL, 0, NULL,
1980 NULL, // from branch
1987 1,0, // dest, bit instruction
1988 0,0, // branch, skip
1989 0, // literal operand
1990 1, // RAM access bit
1991 0, // fast call/return mode select bit
1992 0, // second memory operand
1993 0, // second literal operand
1995 (PCC_C | PCC_REGISTER), // inCond
1996 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1999 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2000 {PC_OPCODE, NULL, NULL, 0, NULL,
2006 NULL, // from branch
2013 0,0, // dest, bit instruction
2014 0,0, // branch, skip
2015 0, // literal operand
2016 1, // RAM access bit
2017 0, // fast call/return mode select bit
2018 0, // second memory operand
2019 0, // second literal operand
2021 (PCC_C | PCC_REGISTER), // inCond
2022 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2025 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2026 {PC_OPCODE, NULL, NULL, 0, NULL,
2032 NULL, // from branch
2039 1,0, // dest, bit instruction
2040 0,0, // branch, skip
2041 0, // literal operand
2042 1, // RAM access bit
2043 0, // fast call/return mode select bit
2044 0, // second memory operand
2045 0, // second literal operand
2047 PCC_REGISTER, // inCond
2048 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2052 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2053 {PC_OPCODE, NULL, NULL, 0, NULL,
2059 NULL, // from branch
2066 0,0, // dest, bit instruction
2067 0,0, // branch, skip
2068 0, // literal operand
2069 1, // RAM access bit
2070 0, // fast call/return mode select bit
2071 0, // second memory operand
2072 0, // second literal operand
2074 PCC_REGISTER, // inCond
2075 (PCC_W | PCC_Z | PCC_N), // outCond
2079 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2080 {PC_OPCODE, NULL, NULL, 0, NULL,
2086 NULL, // from branch
2093 0,0, // dest, bit instruction
2094 0,0, // branch, skip
2095 0, // literal operand
2096 1, // RAM access bit
2097 0, // fast call/return mode select bit
2098 0, // second memory operand
2099 0, // second literal operand
2101 PCC_REGISTER, // inCond
2102 PCC_REGISTER , // outCond
2106 pCodeInstruction pic16_pciSUBLW = {
2107 {PC_OPCODE, NULL, NULL, 0, NULL,
2113 NULL, // from branch
2120 0,0, // dest, bit instruction
2121 0,0, // branch, skip
2122 1, // literal operand
2123 0, // RAM access bit
2124 0, // fast call/return mode select bit
2125 0, // second memory operand
2126 0, // second literal operand
2128 (PCC_W | PCC_LITERAL), // inCond
2129 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2133 pCodeInstruction pic16_pciSUBFWB = {
2134 {PC_OPCODE, NULL, NULL, 0, NULL,
2140 NULL, // from branch
2147 1,0, // dest, bit instruction
2148 0,0, // branch, skip
2149 0, // literal operand
2150 1, // RAM access bit
2151 0, // fast call/return mode select bit
2152 0, // second memory operand
2153 0, // second literal operand
2155 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2156 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2160 pCodeInstruction pic16_pciSUBWF = {
2161 {PC_OPCODE, NULL, NULL, 0, NULL,
2167 NULL, // from branch
2174 1,0, // dest, bit instruction
2175 0,0, // branch, skip
2176 0, // literal operand
2177 1, // RAM access bit
2178 0, // fast call/return mode select bit
2179 0, // second memory operand
2180 0, // second literal operand
2182 (PCC_W | PCC_REGISTER), // inCond
2183 (PCC_REGISTER | PCC_Z), // outCond
2187 pCodeInstruction pic16_pciSUBFW = {
2188 {PC_OPCODE, NULL, NULL, 0, NULL,
2194 NULL, // from branch
2201 0,0, // dest, bit instruction
2202 0,0, // branch, skip
2203 0, // literal operand
2204 1, // RAM access bit
2205 0, // fast call/return mode select bit
2206 0, // second memory operand
2207 0, // second literal operand
2209 (PCC_W | PCC_REGISTER), // inCond
2210 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2214 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2215 {PC_OPCODE, NULL, NULL, 0, NULL,
2221 NULL, // from branch
2228 1,0, // dest, bit instruction
2229 0,0, // branch, skip
2230 0, // literal operand
2231 1, // RAM access bit
2232 0, // fast call/return mode select bit
2233 0, // second memory operand
2234 0, // second literal operand
2236 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2237 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2241 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2242 {PC_OPCODE, NULL, NULL, 0, NULL,
2248 NULL, // from branch
2255 0,0, // dest, bit instruction
2256 0,0, // branch, skip
2257 0, // literal operand
2258 1, // RAM access bit
2259 0, // fast call/return mode select bit
2260 0, // second memory operand
2261 0, // second literal operand
2263 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2264 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2268 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2269 {PC_OPCODE, NULL, NULL, 0, NULL,
2275 NULL, // from branch
2282 1,0, // dest, bit instruction
2283 0,0, // branch, skip
2284 0, // literal operand
2285 1, // RAM access bit
2286 0, // fast call/return mode select bit
2287 0, // second memory operand
2288 0, // second literal operand
2290 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2291 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2295 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2296 {PC_OPCODE, NULL, NULL, 0, NULL,
2302 NULL, // from branch
2309 0,0, // dest, bit instruction
2310 0,0, // branch, skip
2311 0, // literal operand
2312 1, // RAM access bit
2313 0, // fast call/return mode select bit
2314 0, // second memory operand
2315 0, // second literal operand
2317 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2318 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2322 pCodeInstruction pic16_pciSWAPF = {
2323 {PC_OPCODE, NULL, NULL, 0, NULL,
2329 NULL, // from branch
2336 1,0, // dest, bit instruction
2337 0,0, // branch, skip
2338 0, // literal operand
2339 1, // RAM access bit
2340 0, // fast call/return mode select bit
2341 0, // second memory operand
2342 0, // second literal operand
2344 (PCC_REGISTER), // inCond
2345 (PCC_REGISTER), // outCond
2349 pCodeInstruction pic16_pciSWAPFW = {
2350 {PC_OPCODE, NULL, NULL, 0, NULL,
2356 NULL, // from branch
2363 0,0, // dest, bit instruction
2364 0,0, // branch, skip
2365 0, // literal operand
2366 1, // RAM access bit
2367 0, // fast call/return mode select bit
2368 0, // second memory operand
2369 0, // second literal operand
2371 (PCC_REGISTER), // inCond
2376 pCodeInstruction pic16_pciTBLRD = { // patch 15
2377 {PC_OPCODE, NULL, NULL, 0, NULL,
2382 NULL, // from branch
2389 0,0, // dest, bit instruction
2390 0,0, // branch, skip
2391 0, // literal operand
2392 0, // RAM access bit
2393 0, // fast call/return mode select bit
2394 0, // second memory operand
2395 0, // second literal operand
2398 PCC_NONE , // outCond
2402 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2403 {PC_OPCODE, NULL, NULL, 0, NULL,
2408 NULL, // from branch
2415 0,0, // dest, bit instruction
2416 0,0, // branch, skip
2417 0, // literal operand
2418 0, // RAM access bit
2419 0, // fast call/return mode select bit
2420 0, // second memory operand
2421 0, // second literal operand
2424 PCC_NONE , // outCond
2428 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2429 {PC_OPCODE, NULL, NULL, 0, NULL,
2434 NULL, // from branch
2441 0,0, // dest, bit instruction
2442 0,0, // branch, skip
2443 0, // literal operand
2444 0, // RAM access bit
2445 0, // fast call/return mode select bit
2446 0, // second memory operand
2447 0, // second literal operand
2450 PCC_NONE , // outCond
2454 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2455 {PC_OPCODE, NULL, NULL, 0, NULL,
2460 NULL, // from branch
2467 0,0, // dest, bit instruction
2468 0,0, // branch, skip
2469 0, // literal operand
2470 0, // RAM access bit
2471 0, // fast call/return mode select bit
2472 0, // second memory operand
2473 0, // second literal operand
2476 PCC_NONE , // outCond
2480 pCodeInstruction pic16_pciTBLWT = { // patch 15
2481 {PC_OPCODE, NULL, NULL, 0, NULL,
2486 NULL, // from branch
2493 0,0, // dest, bit instruction
2494 0,0, // branch, skip
2495 0, // literal operand
2496 0, // RAM access bit
2497 0, // fast call/return mode select bit
2498 0, // second memory operand
2499 0, // second literal operand
2502 PCC_NONE , // outCond
2506 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2507 {PC_OPCODE, NULL, NULL, 0, NULL,
2512 NULL, // from branch
2519 0,0, // dest, bit instruction
2520 0,0, // branch, skip
2521 0, // literal operand
2522 0, // RAM access bit
2523 0, // fast call/return mode select bit
2524 0, // second memory operand
2525 0, // second literal operand
2528 PCC_NONE , // outCond
2532 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2533 {PC_OPCODE, NULL, NULL, 0, NULL,
2538 NULL, // from branch
2545 0,0, // dest, bit instruction
2546 0,0, // branch, skip
2547 0, // literal operand
2548 0, // RAM access bit
2549 0, // fast call/return mode select bit
2550 0, // second memory operand
2551 0, // second literal operand
2554 PCC_NONE , // outCond
2558 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2559 {PC_OPCODE, NULL, NULL, 0, NULL,
2564 NULL, // from branch
2571 0,0, // dest, bit instruction
2572 0,0, // branch, skip
2573 0, // literal operand
2574 0, // RAM access bit
2575 0, // fast call/return mode select bit
2576 0, // second memory operand
2577 0, // second literal operand
2580 PCC_NONE , // outCond
2584 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2585 {PC_OPCODE, NULL, NULL, 0, NULL,
2591 NULL, // from branch
2598 0,0, // dest, bit instruction
2599 1,1, // branch, skip
2600 0, // literal operand
2601 1, // RAM access bit
2602 0, // fast call/return mode select bit
2603 0, // second memory operand
2604 0, // second literal operand
2606 PCC_REGISTER, // inCond
2607 PCC_NONE, // outCond
2611 pCodeInstruction pic16_pciXORWF = {
2612 {PC_OPCODE, NULL, NULL, 0, NULL,
2618 NULL, // from branch
2625 1,0, // dest, bit instruction
2626 0,0, // branch, skip
2627 0, // literal operand
2628 1, // RAM access bit
2629 0, // fast call/return mode select bit
2630 0, // second memory operand
2631 0, // second literal operand
2633 (PCC_W | PCC_REGISTER), // inCond
2634 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2638 pCodeInstruction pic16_pciXORFW = {
2639 {PC_OPCODE, NULL, NULL, 0, NULL,
2645 NULL, // from branch
2652 0,0, // dest, bit instruction
2653 0,0, // branch, skip
2654 0, // literal operand
2655 1, // RAM access bit
2656 0, // fast call/return mode select bit
2657 0, // second memory operand
2658 0, // second literal operand
2660 (PCC_W | PCC_REGISTER), // inCond
2661 (PCC_W | PCC_Z | PCC_N), // outCond
2665 pCodeInstruction pic16_pciXORLW = {
2666 {PC_OPCODE, NULL, NULL, 0, NULL,
2672 NULL, // from branch
2679 0,0, // dest, bit instruction
2680 0,0, // branch, skip
2681 1, // literal operand
2682 1, // RAM access bit
2683 0, // fast call/return mode select bit
2684 0, // second memory operand
2685 0, // second literal operand
2687 (PCC_W | PCC_LITERAL), // inCond
2688 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2693 pCodeInstruction pic16_pciBANKSEL = {
2694 {PC_OPCODE, NULL, NULL, 0, NULL,
2699 NULL, // from branch
2706 0,0, // dest, bit instruction
2707 0,0, // branch, skip
2708 0, // literal operand
2709 0, // RAM access bit
2710 0, // fast call/return mode select bit
2711 0, // second memory operand
2712 0, // second literal operand
2715 PCC_NONE, // outCond
2720 #define MAX_PIC16MNEMONICS 100
2721 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2723 //#define USE_VSNPRINTF
2726 #ifdef USE_VSNPRINTF
2727 // Alas, vsnprintf is not ANSI standard, and does not exist
2728 // on Solaris (and probably other non-Gnu flavored Unixes).
2730 /*-----------------------------------------------------------------*/
2731 /* SAFE_snprintf - like snprintf except the string pointer is */
2732 /* after the string has been printed to. This is */
2733 /* useful for printing to string as though if it */
2734 /* were a stream. */
2735 /*-----------------------------------------------------------------*/
2736 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2744 va_start(val, format);
2746 vsnprintf(*str, *size, format, val);
2752 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2753 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2762 // This version is *not* safe, despite the name.
2764 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2768 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2773 va_start(val, format);
2775 vsprintf(buffer, format, val);
2778 len = strlen(buffer);
2780 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2781 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2784 strcpy(*str, buffer);
2790 #endif // USE_VSNPRINTF
2793 extern void pic16_initStack(int base_address, int size);
2794 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2795 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2796 extern void pic16_init_pic(char *);
2798 void pic16_pCodeInitRegisters(void)
2800 static int initialized=0;
2807 // pic16_initStack(0xfff, 8);
2808 pic16_init_pic(port->processor);
2810 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2811 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2812 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2813 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2814 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2815 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2816 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2818 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2819 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2820 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2822 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2823 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2824 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2825 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2827 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2828 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2829 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2830 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2831 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2832 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2834 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2835 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2836 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2837 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2838 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2840 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2841 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2842 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2843 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2844 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2846 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2847 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2848 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2849 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2850 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2852 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2853 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2856 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2857 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2858 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2859 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2862 pic16_pc_status.rIdx = IDX_STATUS;
2863 pic16_pc_intcon.rIdx = IDX_INTCON;
2864 pic16_pc_pcl.rIdx = IDX_PCL;
2865 pic16_pc_pclath.rIdx = IDX_PCLATH;
2866 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2867 pic16_pc_wreg.rIdx = IDX_WREG;
2868 pic16_pc_bsr.rIdx = IDX_BSR;
2870 pic16_pc_tosl.rIdx = IDX_TOSL;
2871 pic16_pc_tosh.rIdx = IDX_TOSH;
2872 pic16_pc_tosu.rIdx = IDX_TOSU;
2874 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2875 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2876 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2877 pic16_pc_tablat.rIdx = IDX_TABLAT;
2879 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2880 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2881 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2882 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2883 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2884 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2885 pic16_pc_indf0.rIdx = IDX_INDF0;
2886 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2887 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2888 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2889 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2890 pic16_pc_indf1.rIdx = IDX_INDF1;
2891 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2892 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2893 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2894 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2895 pic16_pc_indf2.rIdx = IDX_INDF2;
2896 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2897 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2898 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2899 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2900 pic16_pc_prodl.rIdx = IDX_PRODL;
2901 pic16_pc_prodh.rIdx = IDX_PRODH;
2903 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2904 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2905 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2907 pic16_pc_kzero.rIdx = IDX_KZ;
2908 pic16_pc_wsave.rIdx = IDX_WSAVE;
2909 pic16_pc_ssave.rIdx = IDX_SSAVE;
2911 pic16_pc_eecon1.rIdx = IDX_EECON1;
2912 pic16_pc_eecon2.rIdx = IDX_EECON2;
2913 pic16_pc_eedata.rIdx = IDX_EEDATA;
2914 pic16_pc_eeadr.rIdx = IDX_EEADR;
2917 /* probably should put this in a separate initialization routine */
2918 pb_dead_pcodes = newpBlock();
2923 /*-----------------------------------------------------------------*/
2924 /* mnem2key - convert a pic mnemonic into a hash key */
2925 /* (BTW - this spreads the mnemonics quite well) */
2927 /*-----------------------------------------------------------------*/
2929 int mnem2key(char const *mnem)
2938 key += toupper(*mnem++) +1;
2942 return (key & 0x1f);
2947 void pic16initMnemonics(void)
2952 pCodeInstruction *pci;
2954 if(mnemonics_initialized)
2957 // NULL out the array before making the assignments
2958 // since we check the array contents below this initialization.
2960 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2961 pic16Mnemonics[i] = NULL;
2964 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2965 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2966 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2967 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2968 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2969 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2970 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2971 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2972 pic16Mnemonics[POC_BC] = &pic16_pciBC;
2973 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2974 pic16Mnemonics[POC_BN] = &pic16_pciBN;
2975 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2976 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2977 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2978 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2979 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2980 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2981 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2982 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2983 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2984 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2985 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2986 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2987 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2988 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2989 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2990 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2991 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2992 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2993 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2994 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2995 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2996 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2997 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2998 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2999 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3000 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3001 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3002 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3003 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3004 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3005 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3006 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3007 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3008 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3009 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3010 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3011 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3012 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3013 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3014 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3015 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3016 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3017 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3018 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3019 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3020 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3021 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3022 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3023 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3024 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3025 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3026 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3027 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3028 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3029 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3030 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3031 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3032 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3033 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3034 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3035 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3036 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3037 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3038 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3039 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3040 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3041 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3042 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3043 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3044 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3045 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3046 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3047 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3048 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3049 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3050 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3051 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3052 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3053 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3054 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3055 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3056 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3058 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3059 if(pic16Mnemonics[i])
3060 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3061 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3064 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3065 pci = hTabNextItem(pic16MnemonicsHash, &key);
3068 mnemonics_initialized = 1;
3071 int pic16_getpCodePeepCommand(char *cmd);
3073 int pic16_getpCode(char *mnem,unsigned dest)
3076 pCodeInstruction *pci;
3077 int key = mnem2key(mnem);
3079 if(!mnemonics_initialized)
3080 pic16initMnemonics();
3082 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3086 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3087 if((pci->num_ops <= 1)
3088 || (pci->isModReg == dest)
3090 || (pci->num_ops <= 2 && pci->isAccess)
3091 || (pci->num_ops <= 2 && pci->isFastCall)
3092 || (pci->num_ops <= 2 && pci->is2MemOp)
3093 || (pci->num_ops <= 2 && pci->is2LitOp) )
3097 pci = hTabNextItemWK (pic16MnemonicsHash);
3104 /*-----------------------------------------------------------------*
3105 * pic16initpCodePeepCommands
3107 *-----------------------------------------------------------------*/
3108 void pic16initpCodePeepCommands(void)
3116 hTabAddItem(&pic16pCodePeepCommandsHash,
3117 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3119 } while (peepCommands[i].cmd);
3121 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3124 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3125 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3130 /*-----------------------------------------------------------------
3133 *-----------------------------------------------------------------*/
3135 int pic16_getpCodePeepCommand(char *cmd)
3139 int key = mnem2key(cmd);
3142 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3145 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3146 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3150 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3157 static char getpBlock_dbName(pBlock *pb)
3163 return pb->cmemmap->dbName;
3167 void pic16_pBlockConvert2ISR(pBlock *pb)
3171 if(pb->cmemmap)pb->cmemmap = NULL;
3175 if(pic16_pcode_verbose)
3176 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3179 void pic16_pBlockConvert2Absolute(pBlock *pb)
3182 if(pb->cmemmap)pb->cmemmap = NULL;
3186 if(pic16_pcode_verbose)
3187 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3190 /*-----------------------------------------------------------------*/
3191 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3192 /* instances to the front of the doubly linked */
3193 /* list of pBlocks */
3194 /*-----------------------------------------------------------------*/
3196 void pic16_movepBlock2Head(char dbName)
3201 /* this can happen in sources without code,
3202 * only variable definitions */
3203 if(!the_pFile)return;
3205 pb = the_pFile->pbHead;
3209 if(getpBlock_dbName(pb) == dbName) {
3210 pBlock *pbn = pb->next;
3211 pb->next = the_pFile->pbHead;
3212 the_pFile->pbHead->prev = pb;
3213 the_pFile->pbHead = pb;
3216 pb->prev->next = pbn;
3218 // If the pBlock that we just moved was the last
3219 // one in the link of all of the pBlocks, then we
3220 // need to point the tail to the block just before
3221 // the one we moved.
3222 // Note: if pb->next is NULL, then pb must have
3223 // been the last pBlock in the chain.
3226 pbn->prev = pb->prev;
3228 the_pFile->pbTail = pb->prev;
3239 void pic16_copypCode(FILE *of, char dbName)
3243 if(!of || !the_pFile)
3246 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3247 if(getpBlock_dbName(pb) == dbName) {
3248 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3250 pic16_printpBlock(of,pb);
3255 void pic16_pcode_test(void)
3258 DFPRINTF((stderr,"pcode is alive!\n"));
3268 /* create the file name */
3269 strcpy(buffer,dstFileName);
3270 strcat(buffer,".p");
3272 if( !(pFile = fopen(buffer, "w" ))) {
3273 werror(E_FILE_OPEN_ERR,buffer);
3277 fprintf(pFile,"pcode dump\n\n");
3279 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3280 fprintf(pFile,"\n\tNew pBlock\n\n");
3282 fprintf(pFile,"%s",pb->cmemmap->sname);
3284 fprintf(pFile,"internal pblock");
3286 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3287 pic16_printpBlock(pFile,pb);
3291 /*-----------------------------------------------------------------*/
3292 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3293 /* ister, RegCond will return the bit being referenced. */
3295 /* fixme - why not just OR in the pcop bit field */
3296 /*-----------------------------------------------------------------*/
3298 static int RegCond(pCodeOp *pcop)
3304 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3305 switch(PCORB(pcop)->bit) {
3319 /*-----------------------------------------------------------------*/
3320 /* pic16_newpCode - create and return a newly initialized pCode */
3322 /* fixme - rename this */
3324 /* The purpose of this routine is to create a new Instruction */
3325 /* pCode. This is called by gen.c while the assembly code is being */
3329 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3330 /* (note that the op is analogous to but not the */
3331 /* same thing as the opcode of the instruction.) */
3332 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3335 /* a pointer to the new malloc'd pCode is returned. */
3339 /*-----------------------------------------------------------------*/
3340 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3342 pCodeInstruction *pci ;
3344 if(!mnemonics_initialized)
3345 pic16initMnemonics();
3347 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3349 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3350 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3353 if(pci->inCond & PCC_EXAMINE_PCOP)
3354 pci->inCond |= RegCond(pcop);
3356 if(pci->outCond & PCC_EXAMINE_PCOP)
3357 pci->outCond |= RegCond(pcop);
3359 pci->pc.prev = pci->pc.next = NULL;
3360 return (pCode *)pci;
3363 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3369 /*-----------------------------------------------------------------*/
3370 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3372 /* Wild pcodes are used during the peep hole optimizer to serve */
3373 /* as place holders for any instruction. When a snippet of code is */
3374 /* compared to a peep hole rule, the wild card opcode will match */
3375 /* any instruction. However, the optional operand and label are */
3376 /* additional qualifiers that must also be matched before the */
3377 /* line (of assembly code) is declared matched. Note that the */
3378 /* operand may be wild too. */
3380 /* Note, a wild instruction is specified just like a wild var: */
3381 /* %4 ; A wild instruction, */
3382 /* See the peeph.def file for additional examples */
3384 /*-----------------------------------------------------------------*/
3386 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3391 pcw = Safe_calloc(1,sizeof(pCodeWild));
3393 pcw->pci.pc.type = PC_WILD;
3394 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3395 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3396 pcw->pci.pc.pb = NULL;
3398 // pcw->pci.pc.analyze = genericAnalyze;
3399 pcw->pci.pc.destruct = genericDestruct;
3400 pcw->pci.pc.print = genericPrint;
3402 pcw->id = pCodeID; // this is the 'n' in %n
3403 pcw->operand = optional_operand;
3404 pcw->label = optional_label;
3406 pcw->mustBeBitSkipInst = 0;
3407 pcw->mustNotBeBitSkipInst = 0;
3408 pcw->invertBitSkipInst = 0;
3410 return ( (pCode *)pcw);
3414 /*-----------------------------------------------------------------*/
3415 /* newPcodeInlineP - create a new pCode from a char string */
3416 /*-----------------------------------------------------------------*/
3419 pCode *pic16_newpCodeInlineP(char *cP)
3424 pcc = Safe_calloc(1,sizeof(pCodeComment));
3426 pcc->pc.type = PC_INLINE;
3427 pcc->pc.prev = pcc->pc.next = NULL;
3428 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3431 // pcc->pc.analyze = genericAnalyze;
3432 pcc->pc.destruct = genericDestruct;
3433 pcc->pc.print = genericPrint;
3436 pcc->comment = Safe_strdup(cP);
3438 pcc->comment = NULL;
3440 return ( (pCode *)pcc);
3444 /*-----------------------------------------------------------------*/
3445 /* newPcodeCharP - create a new pCode from a char string */
3446 /*-----------------------------------------------------------------*/
3448 pCode *pic16_newpCodeCharP(char *cP)
3453 pcc = Safe_calloc(1,sizeof(pCodeComment));
3455 pcc->pc.type = PC_COMMENT;
3456 pcc->pc.prev = pcc->pc.next = NULL;
3457 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3460 // pcc->pc.analyze = genericAnalyze;
3461 pcc->pc.destruct = genericDestruct;
3462 pcc->pc.print = genericPrint;
3465 pcc->comment = Safe_strdup(cP);
3467 pcc->comment = NULL;
3469 return ( (pCode *)pcc);
3473 /*-----------------------------------------------------------------*/
3474 /* pic16_newpCodeFunction - */
3475 /*-----------------------------------------------------------------*/
3478 pCode *pic16_newpCodeFunction(char *mod,char *f)
3482 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3484 pcf->pc.type = PC_FUNCTION;
3485 pcf->pc.prev = pcf->pc.next = NULL;
3486 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3489 // pcf->pc.analyze = genericAnalyze;
3490 pcf->pc.destruct = genericDestruct;
3491 pcf->pc.print = pCodePrintFunction;
3497 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3498 strcpy(pcf->modname,mod);
3500 pcf->modname = NULL;
3503 pcf->fname = Safe_calloc(1,strlen(f)+1);
3504 strcpy(pcf->fname,f);
3508 pcf->stackusage = 0;
3510 return ( (pCode *)pcf);
3513 /*-----------------------------------------------------------------*/
3514 /* pic16_newpCodeFlow */
3515 /*-----------------------------------------------------------------*/
3516 static void destructpCodeFlow(pCode *pc)
3518 if(!pc || !isPCFL(pc))
3525 pic16_unlinkpCode(pc);
3527 deleteSet(&PCFL(pc)->registers);
3528 deleteSet(&PCFL(pc)->from);
3529 deleteSet(&PCFL(pc)->to);
3531 /* Instead of deleting the memory used by this pCode, mark
3532 * the object as bad so that if there's a pointer to this pCode
3533 * dangling around somewhere then (hopefully) when the type is
3534 * checked we'll catch it.
3538 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3544 pCode *pic16_newpCodeFlow(void )
3548 //_ALLOC(pcflow,sizeof(pCodeFlow));
3549 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3551 pcflow->pc.type = PC_FLOW;
3552 pcflow->pc.prev = pcflow->pc.next = NULL;
3553 pcflow->pc.pb = NULL;
3555 // pcflow->pc.analyze = genericAnalyze;
3556 pcflow->pc.destruct = destructpCodeFlow;
3557 pcflow->pc.print = genericPrint;
3559 pcflow->pc.seq = GpcFlowSeq++;
3561 pcflow->from = pcflow->to = NULL;
3563 pcflow->inCond = PCC_NONE;
3564 pcflow->outCond = PCC_NONE;
3566 pcflow->firstBank = -1;
3567 pcflow->lastBank = -1;
3569 pcflow->FromConflicts = 0;
3570 pcflow->ToConflicts = 0;
3574 pcflow->registers = newSet();
3576 return ( (pCode *)pcflow);
3580 /*-----------------------------------------------------------------*/
3581 /*-----------------------------------------------------------------*/
3582 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3584 pCodeFlowLink *pcflowLink;
3586 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3588 pcflowLink->pcflow = pcflow;
3589 pcflowLink->bank_conflict = 0;
3594 /*-----------------------------------------------------------------*/
3595 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3596 /*-----------------------------------------------------------------*/
3598 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3603 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3605 pccs->pc.type = PC_CSOURCE;
3606 pccs->pc.prev = pccs->pc.next = NULL;
3609 pccs->pc.destruct = genericDestruct;
3610 pccs->pc.print = genericPrint;
3612 pccs->line_number = ln;
3614 pccs->line = Safe_strdup(l);
3619 pccs->file_name = Safe_strdup(f);
3621 pccs->file_name = NULL;
3623 return ( (pCode *)pccs);
3628 /*******************************************************************/
3629 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3630 /* added by VR 6-Jun-2003 */
3631 /*******************************************************************/
3633 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3640 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3641 pcad->pci.pc.type = PC_ASMDIR;
3642 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3643 pcad->pci.pc.pb = NULL;
3645 pcad->pci.pc.destruct = genericDestruct;
3646 pcad->pci.pc.print = genericPrint;
3648 if(asdir && *asdir) {
3650 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3652 pcad->directive = Safe_strdup( asdir );
3655 va_start(ap, argfmt);
3657 memset(buffer, 0, sizeof(buffer));
3658 if(argfmt && *argfmt)
3659 vsprintf(buffer, argfmt, ap);
3663 while(isspace(*lbp))lbp++;
3666 pcad->arg = Safe_strdup( lbp );
3668 return ((pCode *)pcad);
3671 /*-----------------------------------------------------------------*/
3672 /* pCodeLabelDestruct - free memory used by a label. */
3673 /*-----------------------------------------------------------------*/
3674 static void pCodeLabelDestruct(pCode *pc)
3680 if((pc->type == PC_LABEL) && PCL(pc)->label)
3681 free(PCL(pc)->label);
3683 /* Instead of deleting the memory used by this pCode, mark
3684 * the object as bad so that if there's a pointer to this pCode
3685 * dangling around somewhere then (hopefully) when the type is
3686 * checked we'll catch it.
3690 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3696 pCode *pic16_newpCodeLabel(char *name, int key)
3702 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3704 pcl->pc.type = PC_LABEL;
3705 pcl->pc.prev = pcl->pc.next = NULL;
3706 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3709 // pcl->pc.analyze = genericAnalyze;
3710 pcl->pc.destruct = pCodeLabelDestruct;
3711 pcl->pc.print = pCodePrintLabel;
3718 sprintf(s,"_%05d_DS_",key);
3723 pcl->label = Safe_strdup(s);
3725 // if(pic16_pcode_verbose)
3726 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3729 return ( (pCode *)pcl);
3733 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3735 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3739 return ( (pCode *)pcl );
3743 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3750 /*-----------------------------------------------------------------*/
3751 /* newpBlock - create and return a pointer to a new pBlock */
3752 /*-----------------------------------------------------------------*/
3753 static pBlock *newpBlock(void)
3758 PpB = Safe_calloc(1,sizeof(pBlock) );
3759 PpB->next = PpB->prev = NULL;
3761 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3762 PpB->tregisters = NULL;
3764 PpB->FlowTree = NULL;
3770 /*-----------------------------------------------------------------*/
3771 /* pic16_newpCodeChain - create a new chain of pCodes */
3772 /*-----------------------------------------------------------------*
3774 * This function will create a new pBlock and the pointer to the
3775 * pCode that is passed in will be the first pCode in the block.
3776 *-----------------------------------------------------------------*/
3779 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3782 pBlock *pB = newpBlock();
3784 pB->pcHead = pB->pcTail = pc;
3793 /*-----------------------------------------------------------------*/
3794 /* pic16_newpCodeOpLabel - Create a new label given the key */
3795 /* Note, a negative key means that the label is part of wild card */
3796 /* (and hence a wild card label) used in the pCodePeep */
3797 /* optimizations). */
3798 /*-----------------------------------------------------------------*/
3800 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3803 static int label_key=-1;
3807 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3808 pcop->type = PO_LABEL;
3813 sprintf(s=buffer,"_%05d_DS_",key);
3815 s = name, key = label_key--;
3818 pcop->name = Safe_strdup(s);
3820 ((pCodeOpLabel *)pcop)->key = key;
3822 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3826 /*-----------------------------------------------------------------*/
3827 /*-----------------------------------------------------------------*/
3828 pCodeOp *pic16_newpCodeOpLit(int lit)
3834 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3835 pcop->type = PO_LITERAL;
3839 sprintf(s,"0x%02x",lit);
3841 pcop->name = Safe_strdup(s);
3844 ((pCodeOpLit *)pcop)->lit = lit;
3849 /*-----------------------------------------------------------------*/
3850 /*-----------------------------------------------------------------*/
3851 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3853 char *s = buffer, tbuf[256], *tb=tbuf;
3857 tb = pic16_get_op(arg2, NULL, 0);
3858 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3859 pcop->type = PO_LITERAL;
3863 sprintf(s,"0x%02x, %s",lit, tb);
3865 pcop->name = Safe_strdup(s);
3868 ((pCodeOpLit2 *)pcop)->lit = lit;
3869 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3874 /*-----------------------------------------------------------------*/
3875 /*-----------------------------------------------------------------*/
3876 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3880 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3881 pcop->type = PO_IMMEDIATE;
3883 regs *r = pic16_dirregWithName(name);
3884 pcop->name = Safe_strdup(name);
3888 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3889 PCOI(pcop)->rIdx = r->rIdx;
3891 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3892 PCOI(pcop)->rIdx = -1;
3894 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3899 PCOI(pcop)->index = index;
3900 PCOI(pcop)->offset = offset;
3901 PCOI(pcop)->_const = code_space;
3906 /*-----------------------------------------------------------------*/
3907 /*-----------------------------------------------------------------*/
3908 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3914 if(!pcwb || !subtype) {
3915 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3919 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3920 pcop->type = PO_WILD;
3921 sprintf(s,"%%%d",id);
3922 pcop->name = Safe_strdup(s);
3924 PCOW(pcop)->id = id;
3925 PCOW(pcop)->pcwb = pcwb;
3926 PCOW(pcop)->subtype = subtype;
3927 PCOW(pcop)->matched = NULL;
3929 PCOW(pcop)->pcop2 = NULL;
3934 /*-----------------------------------------------------------------*/
3935 /*-----------------------------------------------------------------*/
3936 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3942 if(!pcwb || !subtype || !subtype2) {
3943 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3947 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3948 pcop->type = PO_WILD;
3949 sprintf(s,"%%%d",id);
3950 pcop->name = Safe_strdup(s);
3952 PCOW(pcop)->id = id;
3953 PCOW(pcop)->pcwb = pcwb;
3954 PCOW(pcop)->subtype = subtype;
3955 PCOW(pcop)->matched = NULL;
3957 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3959 if(!subtype2->name) {
3960 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
3961 PCOW2(pcop)->pcop.type = PO_WILD;
3962 sprintf(s, "%%%d", id2);
3963 PCOW2(pcop)->pcop.name = Safe_strdup(s);
3964 PCOW2(pcop)->id = id2;
3965 PCOW2(pcop)->subtype = subtype2;
3967 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3968 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3970 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
3972 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
3973 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
3982 /*-----------------------------------------------------------------*/
3983 /*-----------------------------------------------------------------*/
3984 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
3988 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3989 pcop->type = PO_GPR_BIT;
3991 pcop->name = Safe_strdup(s);
3995 PCORB(pcop)->bit = bit;
3996 PCORB(pcop)->inBitSpace = inBitSpace;
3997 PCORB(pcop)->subtype = subt;
3999 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4000 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4001 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4002 // PCOR(pcop)->rIdx = 0;
4007 /*-----------------------------------------------------------------*
4008 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4010 * If rIdx >=0 then a specific register from the set of registers
4011 * will be selected. If rIdx <0, then a new register will be searched
4013 *-----------------------------------------------------------------*/
4015 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4019 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4024 PCOR(pcop)->rIdx = rIdx;
4025 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4027 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4030 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4032 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4033 __FUNCTION__, __LINE__);
4038 pcop->type = PCOR(pcop)->r->pc_type;
4043 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4048 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4049 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4050 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4051 pcop->type = PCOR(pcop)->r->pc_type;
4052 pcop->name = PCOR(pcop)->r->name;
4054 // if(pic16_pcode_verbose) {
4055 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4056 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4062 /*-----------------------------------------------------------------*/
4063 /*-----------------------------------------------------------------*/
4064 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4068 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4071 pcop->key = Safe_strdup( key );
4073 return (PCOP(pcop));
4077 /*-----------------------------------------------------------------*/
4078 /*-----------------------------------------------------------------*/
4080 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4087 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4091 pcop = pic16_newpCodeOpLit(-1);
4095 pcop = pic16_newpCodeOpLabel(NULL,-1);
4098 pcop = pic16_newpCodeOpReg(-1);
4101 case PO_GPR_REGISTER:
4103 pcop = pic16_newpCodeOpRegFromStr(name);
4105 pcop = pic16_newpCodeOpReg(-1);
4109 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4112 pcop->name = Safe_strdup(name);
4120 #define DB_ITEMS_PER_LINE 8
4122 typedef struct DBdata
4129 static int DBd_init = -1;
4131 /*-----------------------------------------------------------------*/
4132 /* Initialiase "DB" data buffer */
4133 /*-----------------------------------------------------------------*/
4134 void pic16_initDB(void)
4140 /*-----------------------------------------------------------------*/
4141 /* Flush pending "DB" data to a pBlock */
4143 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4144 /*-----------------------------------------------------------------*/
4145 void pic16_flushDB(char ptype, void *p)
4149 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4152 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4155 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4159 DBd.buffer[0] = '\0';
4164 /*-----------------------------------------------------------------*/
4165 /* Add "DB" directives to a pBlock */
4166 /*-----------------------------------------------------------------*/
4167 void pic16_emitDB(char c, char ptype, void *p)
4172 // we need to initialize
4175 DBd.buffer[0] = '\0';
4178 l = strlen(DBd.buffer);
4179 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4181 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4184 if (DBd.count>= DB_ITEMS_PER_LINE)
4185 pic16_flushDB(ptype, p);
4188 void pic16_emitDS(char *s, char ptype, void *p)
4193 // we need to initialize
4196 DBd.buffer[0] = '\0';
4199 l = strlen(DBd.buffer);
4200 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4202 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4204 DBd.count++; //=strlen(s);
4206 pic16_flushDB(ptype, p);
4210 /*-----------------------------------------------------------------*/
4211 /*-----------------------------------------------------------------*/
4212 void pic16_pCodeConstString(char *name, char *value)
4216 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4221 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4223 pic16_addpBlock(pb);
4225 sprintf(buffer,"; %s = %s",name,value);
4227 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4228 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4231 pic16_emitDB(*value, 'p', (void *)pb);
4233 pic16_flushDB('p', (void *)pb);
4236 /*-----------------------------------------------------------------*/
4237 /*-----------------------------------------------------------------*/
4239 static void pCodeReadCodeTable(void)
4243 fprintf(stderr, " %s\n",__FUNCTION__);
4245 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4247 pic16_addpBlock(pb);
4249 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4250 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4251 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4252 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4254 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4255 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4256 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4257 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4262 /*-----------------------------------------------------------------*/
4263 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4264 /*-----------------------------------------------------------------*/
4265 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4272 /* If this is the first pcode to be added to a block that
4273 * was initialized with a NULL pcode, then go ahead and
4274 * make this pcode the head and tail */
4275 pb->pcHead = pb->pcTail = pc;
4278 pb->pcTail->next = pc;
4280 pc->prev = pb->pcTail;
4287 /*-----------------------------------------------------------------*/
4288 /* pic16_addpBlock - place a pBlock into the pFile */
4289 /*-----------------------------------------------------------------*/
4290 void pic16_addpBlock(pBlock *pb)
4292 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4295 /* First time called, we'll pass through here. */
4296 //_ALLOC(the_pFile,sizeof(pFile));
4297 the_pFile = Safe_calloc(1,sizeof(pFile));
4298 the_pFile->pbHead = the_pFile->pbTail = pb;
4299 the_pFile->functions = NULL;
4303 the_pFile->pbTail->next = pb;
4304 pb->prev = the_pFile->pbTail;
4306 the_pFile->pbTail = pb;
4309 /*-----------------------------------------------------------------*/
4310 /* removepBlock - remove a pBlock from the pFile */
4311 /*-----------------------------------------------------------------*/
4312 static void removepBlock(pBlock *pb)
4320 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4322 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4325 if(pbs == the_pFile->pbHead)
4326 the_pFile->pbHead = pbs->next;
4328 if (pbs == the_pFile->pbTail)
4329 the_pFile->pbTail = pbs->prev;
4332 pbs->next->prev = pbs->prev;
4335 pbs->prev->next = pbs->next;
4342 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4346 /*-----------------------------------------------------------------*/
4347 /* printpCode - write the contents of a pCode to a file */
4348 /*-----------------------------------------------------------------*/
4349 static void printpCode(FILE *of, pCode *pc)
4360 fprintf(of,"warning - unable to print pCode\n");
4363 /*-----------------------------------------------------------------*/
4364 /* pic16_printpBlock - write the contents of a pBlock to a file */
4365 /*-----------------------------------------------------------------*/
4366 void pic16_printpBlock(FILE *of, pBlock *pb)
4374 for(pc = pb->pcHead; pc; pc = pc->next) {
4375 if(isPCF(pc) && PCF(pc)->fname) {
4376 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4377 if(pb->dbName == 'A') {
4379 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4380 if(!strcmp(ab->name, PCF(pc)->fname)) {
4381 fprintf(of, "\t0X%06X", ab->address);
4392 /*-----------------------------------------------------------------*/
4394 /* pCode processing */
4398 /*-----------------------------------------------------------------*/
4400 void pic16_unlinkpCode(pCode *pc)
4406 fprintf(stderr,"Unlinking: ");
4407 printpCode(stderr, pc);
4410 pc->prev->next = pc->next;
4412 pc->next->prev = pc->prev;
4414 pc->prev = pc->next = NULL;
4418 /*-----------------------------------------------------------------*/
4419 /*-----------------------------------------------------------------*/
4421 static void genericDestruct(pCode *pc)
4424 pic16_unlinkpCode(pc);
4427 /* For instructions, tell the register (if there's one used)
4428 * that it's no longer needed */
4429 regs *reg = pic16_getRegFromInstruction(pc);
4431 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4433 if(PCI(pc)->is2MemOp) {
4434 reg = pic16_getRegFromInstruction2(pc);
4436 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4440 /* Instead of deleting the memory used by this pCode, mark
4441 * the object as bad so that if there's a pointer to this pCode
4442 * dangling around somewhere then (hopefully) when the type is
4443 * checked we'll catch it.
4447 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4453 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4454 /*-----------------------------------------------------------------*/
4455 /*-----------------------------------------------------------------*/
4456 /* modifiers for constant immediate */
4457 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4459 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4464 int use_buffer = 1; // copy the string to the passed buffer pointer
4469 use_buffer = 0; // Don't bother copying the string to the buffer.
4473 switch(pcop->type) {
4481 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4484 return PCOR(pcop)->r->name;
4487 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4489 SAFE_snprintf(&buffer,&size,"%s",r->name);
4496 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4497 if(PCOI(pcop)->index) {
4498 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4499 immdmod[ PCOI(pcop)->offset ],
4503 SAFE_snprintf(&s,&size,"%s(%s)",
4504 immdmod[ PCOI(pcop)->offset ],
4508 if(PCOI(pcop)->index) {
4509 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4514 SAFE_snprintf(&s,&size, "%s(%s)",
4521 case PO_GPR_REGISTER:
4524 // size = sizeof(buffer);
4525 if( PCOR(pcop)->instance) {
4526 SAFE_snprintf(&s,&size,"(%s + %d)",
4528 PCOR(pcop)->instance );
4530 SAFE_snprintf(&s,&size,"%s",pcop->name);
4537 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4546 return "NO operand1";
4549 /*-----------------------------------------------------------------*/
4550 /* pic16_get_op2 - variant to support two memory operand commands */
4551 /*-----------------------------------------------------------------*/
4552 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4557 int use_buffer = 1; // copy the string to the passed buffer pointer
4562 use_buffer = 0; // Don't bother copying the string to the buffer.
4566 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",
4567 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4568 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4572 switch(PCOR2(pcop)->pcop2->type) {
4580 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4583 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4586 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4589 SAFE_snprintf(&buffer,&size,"%s",r->name);
4600 if(PCOI(pcop)->_const) {
4601 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4602 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4605 8 * PCOI(pcop)->offset );
4607 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4609 if( PCOI(pcop)->index) {
4610 SAFE_snprintf(&s,&size,"(%s + %d)",
4612 PCOI(pcop)->index );
4614 if(PCOI(pcop)->offset)
4615 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4617 SAFE_snprintf(&s,&size,"%s",pcop->name);
4624 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4625 SAFE_snprintf(&s,&size,"(%s + %d)",
4626 PCOR(PCOR2(pcop)->pcop2)->r->name,
4627 PCOR(PCOR2(pcop)->pcop2)->instance );
4629 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4634 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4636 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4639 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4644 return "NO operand2";
4647 /*-----------------------------------------------------------------*/
4648 /*-----------------------------------------------------------------*/
4649 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4653 return pic16_get_op(pcc->pcop,NULL,0);
4655 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4656 * return ("ERROR Null: "__FUNCTION__);
4658 return ("ERROR Null: pic16_get_op_from_instruction");
4662 /*-----------------------------------------------------------------*/
4663 /*-----------------------------------------------------------------*/
4664 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4667 fprintf(of,"pcodeopprint- not implemented\n");
4670 /*-----------------------------------------------------------------*/
4671 /* pic16_pCode2str - convert a pCode instruction to string */
4672 /*-----------------------------------------------------------------*/
4673 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4679 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4680 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4681 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4689 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4691 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4693 if(PCI(pc)->is2MemOp) {
4694 SAFE_snprintf(&s,&size, "%s, %s",
4695 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4696 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4700 if(PCI(pc)->is2LitOp) {
4701 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4705 if(PCI(pc)->isBitInst) {
4706 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4707 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4708 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4709 PCI(pc)->pcop->name ,
4710 PCI(pc)->pcop->name );
4712 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4713 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4714 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4715 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4717 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4718 //PCI(pc)->pcop->t.bit );
4721 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4722 if( PCI(pc)->num_ops == 3)
4723 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4725 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4728 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4730 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4731 if(PCI(pc)->num_ops == 3)
4732 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4734 r = pic16_getRegFromInstruction(pc);
4735 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4736 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4738 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4747 /* assuming that comment ends with a \n */
4748 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4752 /* assuming that inline code ends with a \n */
4753 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4757 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4760 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4763 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4766 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4769 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4770 SAFE_snprintf(&s,&size,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4771 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4774 if(PCAD(pc)->directive) {
4775 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4778 /* special case to handle inline labels without a tab */
4779 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4784 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4788 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4796 /*-----------------------------------------------------------------*/
4797 /* genericPrint - the contents of a pCode to a file */
4798 /*-----------------------------------------------------------------*/
4799 static void genericPrint(FILE *of, pCode *pc)
4807 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4811 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4815 // If the opcode has a label, print that first
4817 pBranch *pbl = PCI(pc)->label;
4818 while(pbl && pbl->pc) {
4819 if(pbl->pc->type == PC_LABEL)
4820 pCodePrintLabel(of, pbl->pc);
4826 genericPrint(of,PCODE(PCI(pc)->cline));
4831 pic16_pCode2str(str, 256, pc);
4833 fprintf(of,"%s",str);
4835 if(pic16_debug_verbose) {
4836 fprintf(of, "\t;key=%03x",pc->seq);
4838 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4845 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4846 if(PCW(pc)->pci.label)
4847 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4849 if(PCW(pc)->operand) {
4850 fprintf(of,";\toperand ");
4851 pCodeOpPrint(of,PCW(pc)->operand );
4856 if(pic16_debug_verbose) {
4857 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4858 if(PCFL(pc)->ancestor)
4859 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4866 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4867 fprintf(of,"%s#LINE\t%d; %s\t%s\n", (pic16_mplab_comp?";":""),
4868 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4874 pBranch *pbl = PCAD(pc)->pci.label;
4875 while(pbl && pbl->pc) {
4876 if(pbl->pc->type == PC_LABEL)
4877 pCodePrintLabel(of, pbl->pc);
4881 if(PCAD(pc)->directive) {
4882 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4885 /* special case to handle inline labels without tab */
4886 fprintf(of, "%s\n", PCAD(pc)->arg);
4892 fprintf(of,"unknown pCode type %d\n",pc->type);
4897 /*-----------------------------------------------------------------*/
4898 /* pCodePrintFunction - prints function begin/end */
4899 /*-----------------------------------------------------------------*/
4901 static void pCodePrintFunction(FILE *of, pCode *pc)
4908 if( ((pCodeFunction *)pc)->modname)
4909 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4912 if(!PCF(pc)->absblock) {
4913 if(PCF(pc)->fname) {
4914 pBranch *exits = PCF(pc)->to;
4917 fprintf(of,"%s:", PCF(pc)->fname);
4919 if(pic16_pcode_verbose)
4920 fprintf(of, "\t;Function start");
4926 exits = exits->next;
4930 if(pic16_pcode_verbose)
4931 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4934 if((PCF(pc)->from &&
4935 PCF(pc)->from->pc->type == PC_FUNCTION &&
4936 PCF(PCF(pc)->from->pc)->fname) ) {
4938 if(pic16_pcode_verbose)
4939 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4941 if(pic16_pcode_verbose)
4942 fprintf(of,"; exit point [can't find entry point]\n");
4948 /*-----------------------------------------------------------------*/
4949 /* pCodePrintLabel - prints label */
4950 /*-----------------------------------------------------------------*/
4952 static void pCodePrintLabel(FILE *of, pCode *pc)
4959 fprintf(of,"%s:\n",PCL(pc)->label);
4960 else if (PCL(pc)->key >=0)
4961 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4963 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4966 /*-----------------------------------------------------------------*/
4967 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
4968 /* remove it if it is found. */
4969 /*-----------------------------------------------------------------*/
4970 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4977 if(pcl->type == PC_OPCODE)
4978 b = PCI(pcl)->label;
4980 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4985 //fprintf (stderr, "%s \n",__FUNCTION__);
4986 //pcl->print(stderr,pcl);
4987 //pc->print(stderr,pc);
4990 //fprintf (stderr, "found label\n");
4991 //pc->print(stderr, pc);
4995 bprev->next = b->next; /* Not first pCode in chain */
4999 PCI(pcl)->label = b->next; /* First pCode in chain */
5002 return; /* A label can't occur more than once */
5010 /*-----------------------------------------------------------------*/
5011 /*-----------------------------------------------------------------*/
5012 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5031 /*-----------------------------------------------------------------*/
5032 /* pBranchLink - given two pcodes, this function will link them */
5033 /* together through their pBranches */
5034 /*-----------------------------------------------------------------*/
5035 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5039 // Declare a new branch object for the 'from' pCode.
5041 //_ALLOC(b,sizeof(pBranch));
5042 b = Safe_calloc(1,sizeof(pBranch));
5043 b->pc = PCODE(t); // The link to the 'to' pCode.
5046 f->to = pic16_pBranchAppend(f->to,b);
5048 // Now do the same for the 'to' pCode.
5050 //_ALLOC(b,sizeof(pBranch));
5051 b = Safe_calloc(1,sizeof(pBranch));
5055 t->from = pic16_pBranchAppend(t->from,b);
5060 /*-----------------------------------------------------------------*/
5061 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5063 /*-----------------------------------------------------------------*/
5064 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5077 /*-----------------------------------------------------------------*/
5078 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5079 /*-----------------------------------------------------------------*/
5080 void pic16_pCodeUnlink(pCode *pc)
5085 if(!pc->prev || !pc->next) {
5086 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5090 /* first remove the pCode from the chain */
5091 pc->prev->next = pc->next;
5092 pc->next->prev = pc->prev;
5094 /* Now for the hard part... */
5096 /* Remove the branches */
5098 pb1 = PCI(pc)->from;
5100 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5101 * one we're unlinking */
5103 /* search for the link back to this pCode (the one we're
5105 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5106 pb2->pc = PCI(pc)->to->pc; // make the replacement
5108 /* if the pCode we're unlinking contains multiple 'to'
5109 * branches (e.g. this a skip instruction) then we need
5110 * to copy these extra branches to the chain. */
5111 if(PCI(pc)->to->next)
5112 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5121 /*-----------------------------------------------------------------*/
5122 /*-----------------------------------------------------------------*/
5124 static void genericAnalyze(pCode *pc)
5134 // Go through the pCodes that are in pCode chain and link
5135 // them together through the pBranches. Note, the pCodes
5136 // are linked together as a contiguous stream like the
5137 // assembly source code lines. The linking here mimics this
5138 // except that comments are not linked in.
5140 pCode *npc = pc->next;
5142 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5143 pBranchLink(pc,npc);
5148 /* reached the end of the pcode chain without finding
5149 * an instruction we could link to. */
5153 fprintf(stderr,"analyze PC_FLOW\n");
5157 fprintf(stderr,,";A bad pCode is being used\n");
5163 /*-----------------------------------------------------------------*/
5164 /*-----------------------------------------------------------------*/
5165 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5169 if(pc->type == PC_LABEL) {
5170 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5173 if((pc->type == PC_OPCODE)
5174 || (pc->type == PC_ASMDIR)
5176 pbr = PCI(pc)->label;
5178 if(pbr->pc->type == PC_LABEL) {
5179 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5189 /*-----------------------------------------------------------------*/
5190 /*-----------------------------------------------------------------*/
5191 static int checkLabel(pCode *pc)
5195 if(pc && isPCI(pc)) {
5196 pbr = PCI(pc)->label;
5198 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5208 /*-----------------------------------------------------------------*/
5209 /* findLabelinpBlock - Search the pCode for a particular label */
5210 /*-----------------------------------------------------------------*/
5211 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5218 for(pc = pb->pcHead; pc; pc = pc->next)
5219 if(compareLabel(pc,pcop_label))
5225 /*-----------------------------------------------------------------*/
5226 /* findLabel - Search the pCode for a particular label */
5227 /*-----------------------------------------------------------------*/
5228 static pCode * findLabel(pCodeOpLabel *pcop_label)
5236 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5237 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5241 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5245 /*-----------------------------------------------------------------*/
5246 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5247 /* in the linked list */
5248 /*-----------------------------------------------------------------*/
5249 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5262 /*-----------------------------------------------------------------*/
5263 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5264 /* in the linked list */
5265 /*-----------------------------------------------------------------*/
5266 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5280 //#define PCODE_DEBUG
5281 /*-----------------------------------------------------------------*/
5282 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5283 /* in the linked list */
5284 /*-----------------------------------------------------------------*/
5285 pCode * pic16_findNextInstruction(pCode *pci)
5290 if((pc->type == PC_OPCODE)
5291 || (pc->type == PC_WILD)
5292 || (pc->type == PC_ASMDIR)
5297 fprintf(stderr,"pic16_findNextInstruction: ");
5298 printpCode(stderr, pc);
5303 //fprintf(stderr,"Couldn't find instruction\n");
5307 /*-----------------------------------------------------------------*/
5308 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5309 /* in the linked list */
5310 /*-----------------------------------------------------------------*/
5311 pCode * pic16_findPrevInstruction(pCode *pci)
5317 if((pc->type == PC_OPCODE)
5318 || (pc->type == PC_WILD)
5319 || (pc->type == PC_ASMDIR)
5325 fprintf(stderr,"pic16_findPrevInstruction: ");
5326 printpCode(stderr, pc);
5331 //fprintf(stderr,"Couldn't find instruction\n");
5338 /*-----------------------------------------------------------------*/
5339 /* findFunctionEnd - given a pCode find the end of the function */
5340 /* that contains it */
5341 /*-----------------------------------------------------------------*/
5342 static pCode * findFunctionEnd(pCode *pc)
5346 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5352 fprintf(stderr,"Couldn't find function end\n");
5357 /*-----------------------------------------------------------------*/
5358 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5359 /* instruction with which it is associated. */
5360 /*-----------------------------------------------------------------*/
5361 static void AnalyzeLabel(pCode *pc)
5364 pic16_pCodeUnlink(pc);
5370 static void AnalyzeGOTO(pCode *pc)
5373 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5377 static void AnalyzeSKIP(pCode *pc)
5380 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5381 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5385 static void AnalyzeRETURN(pCode *pc)
5388 // branch_link(pc,findFunctionEnd(pc->next));
5394 /*-----------------------------------------------------------------*/
5395 /*-----------------------------------------------------------------*/
5396 regs * pic16_getRegFromInstruction(pCode *pc)
5402 PCI(pc)->num_ops == 0 ||
5403 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5407 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5408 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5411 switch(PCI(pc)->pcop->type) {
5417 return PCOR(PCI(pc)->pcop)->r;
5421 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5422 return PCOR(PCI(pc)->pcop)->r;
5425 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5427 if(PCOI(PCI(pc)->pcop)->r)
5428 return (PCOI(PCI(pc)->pcop)->r);
5433 return PCOR(PCI(pc)->pcop)->r;
5435 case PO_GPR_REGISTER:
5437 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5438 return PCOR(PCI(pc)->pcop)->r;
5441 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5445 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5446 // genericPrint(stderr, pc);
5454 /*-------------------------------------------------------------------------------*/
5455 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5456 /*-------------------------------------------------------------------------------*/
5457 regs * pic16_getRegFromInstruction2(pCode *pc)
5463 PCI(pc)->num_ops == 0 ||
5464 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5469 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5470 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5474 * operands supported in MOVFF:
5481 switch(PCI(pc)->pcop->type) {
5487 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5489 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5493 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5494 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5498 // if(PCOI(PCI(pc)->pcop)->r)
5499 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5501 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5502 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5505 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5506 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5513 // return PCOR2(PCI(pc)->pcop)->r;
5515 case PO_GPR_REGISTER:
5517 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5518 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5522 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5525 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5526 //genericPrint(stderr, pc);
5534 /*-----------------------------------------------------------------*/
5535 /*-----------------------------------------------------------------*/
5537 static void AnalyzepBlock(pBlock *pb)
5544 /* Find all of the registers used in this pBlock
5545 * by looking at each instruction and examining it's
5548 for(pc = pb->pcHead; pc; pc = pc->next) {
5550 /* Is this an instruction with operands? */
5551 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5553 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5555 /* Loop through all of the registers declared so far in
5556 this block and see if we find this one there */
5558 regs *r = setFirstItem(pb->tregisters);
5561 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5562 PCOR(PCI(pc)->pcop)->r = r;
5565 r = setNextItem(pb->tregisters);
5569 /* register wasn't found */
5570 //r = Safe_calloc(1, sizeof(regs));
5571 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5572 //addSet(&pb->tregisters, r);
5573 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5574 //PCOR(PCI(pc)->pcop)->r = r;
5575 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5577 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5580 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5581 if(PCOR(PCI(pc)->pcop)->r) {
5582 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5583 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5585 if(PCI(pc)->pcop->name)
5586 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5588 fprintf(stderr,"ERROR: NULL register\n");
5597 /*-----------------------------------------------------------------*/
5599 /*-----------------------------------------------------------------*/
5600 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5602 static void InsertpFlow(pCode *pc, pCode **pflow)
5605 PCFL(*pflow)->end = pc;
5607 if(!pc || !pc->next)
5610 *pflow = pic16_newpCodeFlow();
5611 pic16_pCodeInsertAfter(pc, *pflow);
5614 /*-----------------------------------------------------------------*/
5615 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5616 /* the flow blocks. */
5618 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5619 * point the instruction flow changes.
5621 /*-----------------------------------------------------------------*/
5622 void pic16_BuildFlow(pBlock *pb)
5625 pCode *last_pci=NULL;
5632 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5633 /* Insert a pCodeFlow object at the beginning of a pBlock */
5635 InsertpFlow(pb->pcHead, &pflow);
5637 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5638 //pflow->next = pb->pcHead; /* Make the current head the next object */
5639 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5640 //pb->pcHead = pflow; /* Make the Flow object the head */
5643 for( pc = pic16_findNextInstruction(pb->pcHead);
5645 pc=pic16_findNextInstruction(pc)) {
5648 PCI(pc)->pcflow = PCFL(pflow);
5650 //fprintf(stderr," build: ");
5651 //pflow->print(stderr,pflow);
5653 if( PCI(pc)->isSkip) {
5655 /* The two instructions immediately following this one
5656 * mark the beginning of a new flow segment */
5658 while(pc && PCI(pc)->isSkip) {
5660 PCI(pc)->pcflow = PCFL(pflow);
5664 InsertpFlow(pc, &pflow);
5665 pc=pic16_findNextInstruction(pc->next);
5673 PCI(pc)->pcflow = PCFL(pflow);
5675 InsertpFlow(pc, &pflow);
5677 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5679 InsertpFlow(pc, &pflow);
5682 } else if (checkLabel(pc)) {
5684 /* This instruction marks the beginning of a
5685 * new flow segment */
5690 /* If the previous pCode is not a flow object, then
5691 * insert a new flow object. (This check prevents
5692 * two consecutive flow objects from being insert in
5693 * the case where a skip instruction preceeds an
5694 * instruction containing a label.) */
5696 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5697 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5699 PCI(pc)->pcflow = PCFL(pflow);
5706 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5708 PCFL(pflow)->end = pb->pcTail;
5711 /*-------------------------------------------------------------------*/
5712 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5713 /* the flow blocks. */
5715 * unBuildFlow removes pCodeFlow objects from a pCode chain
5717 /*-----------------------------------------------------------------*/
5718 static void unBuildFlow(pBlock *pb)
5733 if(PCI(pc)->pcflow) {
5734 //free(PCI(pc)->pcflow);
5735 PCI(pc)->pcflow = NULL;
5738 } else if(isPCFL(pc) )
5747 /*-----------------------------------------------------------------*/
5748 /*-----------------------------------------------------------------*/
5749 static void dumpCond(int cond)
5752 static char *pcc_str[] = {
5766 int ncond = sizeof(pcc_str) / sizeof(char *);
5769 fprintf(stderr, "0x%04X\n",cond);
5771 for(i=0,j=1; i<ncond; i++, j<<=1)
5773 fprintf(stderr, " %s\n",pcc_str[i]);
5779 /*-----------------------------------------------------------------*/
5780 /*-----------------------------------------------------------------*/
5781 static void FlowStats(pCodeFlow *pcflow)
5789 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5791 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5794 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5799 fprintf(stderr, " FlowStats inCond: ");
5800 dumpCond(pcflow->inCond);
5801 fprintf(stderr, " FlowStats outCond: ");
5802 dumpCond(pcflow->outCond);
5806 /*-----------------------------------------------------------------*
5807 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5808 * if it affects the banking bits.
5810 * return: -1 == Banking bits are unaffected by this pCode.
5812 * return: > 0 == Banking bits are affected.
5814 * If the banking bits are affected, then the returned value describes
5815 * which bits are affected and how they're affected. The lower half
5816 * of the integer maps to the bits that are affected, the upper half
5817 * to whether they're set or cleared.
5819 *-----------------------------------------------------------------*/
5821 static int isBankInstruction(pCode *pc)
5829 if( PCI(pc)->op == POC_MOVLB ||
5830 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5831 bank = PCOL(pc)->lit;
5838 /*-----------------------------------------------------------------*/
5839 /*-----------------------------------------------------------------*/
5840 static void FillFlow(pCodeFlow *pcflow)
5849 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5851 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5854 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5861 isBankInstruction(pc);
5863 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5867 fprintf(stderr, " FillFlow - Bad end of flow\n");
5869 fprintf(stderr, " FillFlow - Ending flow with\n ");
5870 pc->print(stderr,pc);
5873 fprintf(stderr, " FillFlow inCond: ");
5874 dumpCond(pcflow->inCond);
5875 fprintf(stderr, " FillFlow outCond: ");
5876 dumpCond(pcflow->outCond);
5880 /*-----------------------------------------------------------------*/
5881 /*-----------------------------------------------------------------*/
5882 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5884 pCodeFlowLink *fromLink, *toLink;
5886 if(!from || !to || !to->pcflow || !from->pcflow)
5889 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5890 toLink = pic16_newpCodeFlowLink(to->pcflow);
5892 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5893 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5897 /*-----------------------------------------------------------------*
5898 * void LinkFlow(pBlock *pb)
5900 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5901 * non-branching segments. In LinkFlow, we determine the execution
5902 * order of these segments. For example, if one of the segments ends
5903 * with a skip, then we know that there are two possible flow segments
5904 * to which control may be passed.
5905 *-----------------------------------------------------------------*/
5906 static void LinkFlow(pBlock *pb)
5912 //fprintf(stderr,"linkflow \n");
5914 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5916 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5919 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5921 //fprintf(stderr," link: ");
5922 //pcflow->print(stderr,pcflow);
5924 //FillFlow(PCFL(pcflow));
5926 pc = PCFL(pcflow)->end;
5928 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5929 if(isPCI_SKIP(pc)) {
5930 //fprintf(stderr, "ends with skip\n");
5931 //pc->print(stderr,pc);
5932 pct=pic16_findNextInstruction(pc->next);
5933 LinkFlow_pCode(PCI(pc),PCI(pct));
5934 pct=pic16_findNextInstruction(pct->next);
5935 LinkFlow_pCode(PCI(pc),PCI(pct));
5939 if(isPCI_BRANCH(pc)) {
5940 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5942 //fprintf(stderr, "ends with branch\n ");
5943 //pc->print(stderr,pc);
5945 if(!(pcol && isPCOLAB(pcol))) {
5946 if((PCI(pc)->op != POC_RETLW)
5947 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5949 /* continue if label is '$' which assembler knows how to parse */
5950 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5952 if(pic16_pcode_verbose) {
5953 pc->print(stderr,pc);
5954 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5960 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5961 LinkFlow_pCode(PCI(pc),PCI(pct));
5963 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5964 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5966 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
5972 //fprintf(stderr, "ends with non-branching instruction:\n");
5973 //pc->print(stderr,pc);
5975 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5981 //fprintf(stderr, "ends with unknown\n");
5982 //pc->print(stderr,pc);
5986 //fprintf(stderr, "ends with nothing: ERROR\n");
5990 /*-----------------------------------------------------------------*/
5991 /*-----------------------------------------------------------------*/
5993 /*-----------------------------------------------------------------*/
5994 /*-----------------------------------------------------------------*/
5995 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6001 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6004 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6014 /*-----------------------------------------------------------------*/
6015 /* insertBankSwitch - inserts a bank switch statement in the */
6016 /* assembly listing */
6018 /* position == 0: insert before */
6019 /* position == 1: insert after pc */
6020 /* position == 2: like 0 but previous was a skip instruction */
6021 /*-----------------------------------------------------------------*/
6022 pCodeOp *pic16_popGetLabel(unsigned int key);
6023 extern int pic16_labelOffset;
6025 static void insertBankSwitch(int position, pCode *pc)
6032 /* emit BANKSEL [symbol] */
6035 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6037 // position = 0; // position is always before (sanity check!)
6040 fprintf(stderr, "%s:%d: inserting bank switch\n", __FUNCTION__, __LINE__);
6041 pc->print(stderr, pc);
6046 /* insert the bank switch after this pc instruction */
6047 pCode *pcnext = pic16_findNextInstruction(pc);
6049 pic16_pCodeInsertAfter(pc, new_pc);
6050 if(pcnext)pc = pcnext;
6054 /* insert the bank switch BEFORE this pc instruction */
6055 pic16_pCodeInsertAfter(pc->prev, new_pc);
6060 pCode *pcnext, *pcprev, *npci;
6062 /* just like 0, but previous was a skip instruction,
6063 * so some care should be taken */
6065 pic16_labelOffset += 10000;
6066 tlbl = newiTempLabel(NULL);
6068 /* invert skip instruction */
6069 pcprev = pic16_findPrevInstruction(pc->prev);
6070 ipci = PCI(pcprev)->inverted_op;
6071 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6074 PCI(npci)->from = PCI(pcprev)->from;
6075 PCI(npci)->to = PCI(pcprev)->to;
6076 PCI(npci)->label = PCI(pcprev)->label;
6077 PCI(npci)->pcflow = PCI(pcprev)->pcflow;
6078 PCI(npci)->cline = PCI(pcprev)->cline;
6081 // memmove(PCI(pcprev), PCI(npci), sizeof(pCode) + sizeof(PIC_OPCODE) + sizeof(char const * const));
6084 pic16_pCodeInsertAfter(pcprev->prev, npci);
6085 /* unlink the pCode */
6086 pcprev->prev->next = pcprev->next;
6087 pcprev->next->prev = pcprev->prev;
6090 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6091 pic16_pCodeInsertAfter(pc->prev, pcnext);
6092 pic16_pCodeInsertAfter(pc->prev, new_pc);
6094 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6095 pic16_pCodeInsertAfter(pc, pcnext);
6100 /* Move the label, if there is one */
6101 if(PCI(pc)->label) {
6102 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6103 // __FILE__, __LINE__, pc, new_pc);
6104 PCAD(new_pc)->pci.label = PCI(pc)->label;
6105 PCI(pc)->label = NULL;
6110 /*-----------------------------------------------------------------*/
6111 /*int compareBankFlow - compare the banking requirements between */
6113 /*-----------------------------------------------------------------*/
6114 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6117 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6120 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6123 if(pcflow->firstBank == -1)
6127 if(pcflowLink->pcflow->firstBank == -1) {
6128 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6129 pcflowLink->pcflow->to :
6130 pcflowLink->pcflow->from);
6131 return compareBankFlow(pcflow, pctl, toORfrom);
6135 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6138 pcflowLink->bank_conflict++;
6139 pcflowLink->pcflow->FromConflicts++;
6140 pcflow->ToConflicts++;
6143 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6146 pcflowLink->bank_conflict++;
6147 pcflowLink->pcflow->ToConflicts++;
6148 pcflow->FromConflicts++;
6152 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6153 pcflowLink->pcflow->pc.seq,
6154 pcflowLink->pcflow->FromConflicts,
6155 pcflowLink->pcflow->ToConflicts);
6162 /*-----------------------------------------------------------------*/
6163 /*-----------------------------------------------------------------*/
6164 static void DumpFlow(pBlock *pb)
6168 pCodeFlowLink *pcfl;
6171 fprintf(stderr,"Dump flow \n");
6172 pb->pcHead->print(stderr, pb->pcHead);
6174 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6175 pcflow->print(stderr,pcflow);
6177 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6179 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6181 if(!isPCFL(pcflow)) {
6182 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6185 fprintf(stderr,"dumping: ");
6186 pcflow->print(stderr,pcflow);
6187 FlowStats(PCFL(pcflow));
6189 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6191 pc = PCODE(pcfl->pcflow);
6193 fprintf(stderr, " from seq %d:\n",pc->seq);
6195 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6196 pc->print(stderr,pc);
6201 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6203 pc = PCODE(pcfl->pcflow);
6205 fprintf(stderr, " to seq %d:\n",pc->seq);
6207 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6208 pc->print(stderr,pc);
6217 /*-----------------------------------------------------------------*/
6218 /*-----------------------------------------------------------------*/
6219 static int OptimizepBlock(pBlock *pb)
6224 if(!pb || !peepOptimizing)
6227 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6229 for(pc = pb->pcHead; pc; pc = pc->next)
6230 matches += pic16_pCodePeepMatchRule(pc);
6233 pc = pic16_findNextInstruction(pb->pcHead);
6241 if(pic16_pCodePeepMatchRule(pc)) {
6246 pc = pic16_findNextInstruction(pcprev->next);
6248 pc = pic16_findNextInstruction(pb->pcHead);
6250 pc = pic16_findNextInstruction(pc->next);
6254 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6259 /*-----------------------------------------------------------------*/
6260 /*-----------------------------------------------------------------*/
6261 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6265 for(pc = pcs; pc; pc = pc->next) {
6267 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6269 (PCI(pc)->pcop->type == PO_LABEL) &&
6270 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6278 /*-----------------------------------------------------------------*/
6279 /*-----------------------------------------------------------------*/
6280 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6287 (PCI(pc)->pcop->type == PO_LABEL)) {
6289 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6291 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6293 free(pcol->pcop.name);
6295 /* If the key is negative, then we (probably) have a label to
6296 * a function and the name is already defined */
6299 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6303 //sprintf(buffer,"_%05d_DS_",pcl->key);
6305 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6307 pcol->pcop.name = Safe_strdup(s);
6308 pcol->key = pcl->key;
6309 //pc->print(stderr,pc);
6316 /*-----------------------------------------------------------------*/
6317 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6318 /* pCode chain if they're not used. */
6319 /*-----------------------------------------------------------------*/
6320 static void pBlockRemoveUnusedLabels(pBlock *pb)
6322 pCode *pc; pCodeLabel *pcl;
6327 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6329 pBranch *pbr = PCI(pc)->label;
6330 if(pbr && pbr->next) {
6331 pCode *pcd = pb->pcHead;
6333 // fprintf(stderr, "multiple labels\n");
6334 // pc->print(stderr,pc);
6339 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6340 //fprintf(stderr,"Used by:\n");
6341 //pcd->print(stderr,pcd);
6343 exchangeLabels(PCL(pbr->pc),pcd);
6352 for(pc = pb->pcHead; pc; pc = pc->next) {
6354 if(isPCL(pc)) // pc->type == PC_LABEL)
6356 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6357 pcl = PCL(PCI(pc)->label->pc);
6360 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6362 /* This pCode is a label, so search the pBlock to see if anyone
6365 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6367 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6368 /* Couldn't find an instruction that refers to this label
6369 * So, unlink the pCode label from it's pCode chain
6370 * and destroy the label */
6371 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6373 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6374 if(pc->type == PC_LABEL) {
6375 pic16_unlinkpCode(pc);
6376 pCodeLabelDestruct(pc);
6378 unlinkpCodeFromBranch(pc, PCODE(pcl));
6379 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6390 /*-----------------------------------------------------------------*/
6391 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6392 /* chain and put them into pBranches that are */
6393 /* associated with the appropriate pCode */
6395 /*-----------------------------------------------------------------*/
6396 void pic16_pBlockMergeLabels(pBlock *pb)
6399 pCode *pc, *pcnext=NULL;
6404 /* First, Try to remove any unused labels */
6405 //pBlockRemoveUnusedLabels(pb);
6407 /* Now loop through the pBlock and merge the labels with the opcodes */
6410 // for(pc = pb->pcHead; pc; pc = pc->next) {
6413 pCode *pcn = pc->next;
6415 if(pc->type == PC_LABEL) {
6417 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6418 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6420 if((pcnext = pic16_findNextInstruction(pc) )) {
6422 // pcnext->print(stderr, pcnext);
6424 // Unlink the pCode label from it's pCode chain
6425 pic16_unlinkpCode(pc);
6427 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6428 // And link it into the instruction's pBranch labels. (Note, since
6429 // it's possible to have multiple labels associated with one instruction
6430 // we must provide a means to accomodate the additional labels. Thus
6431 // the labels are placed into the singly-linked list "label" as
6432 // opposed to being a single member of the pCodeInstruction.)
6434 //_ALLOC(pbr,sizeof(pBranch));
6436 pbr = Safe_calloc(1,sizeof(pBranch));
6440 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6443 if(pic16_pcode_verbose)
6444 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6446 } else if(pc->type == PC_CSOURCE) {
6448 /* merge the source line symbolic info into the next instruction */
6449 if((pcnext = pic16_findNextInstruction(pc) )) {
6451 // Unlink the pCode label from it's pCode chain
6452 pic16_unlinkpCode(pc);
6453 PCI(pcnext)->cline = PCCS(pc);
6454 //fprintf(stderr, "merging CSRC\n");
6455 //genericPrint(stderr,pcnext);
6461 pBlockRemoveUnusedLabels(pb);
6465 /*-----------------------------------------------------------------*/
6466 /*-----------------------------------------------------------------*/
6467 static int OptimizepCode(char dbName)
6469 #define MAX_PASSES 4
6478 DFPRINTF((stderr," Optimizing pCode\n"));
6482 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6483 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6484 matches += OptimizepBlock(pb);
6487 while(matches && ++passes < MAX_PASSES);
6494 const char *pic16_pCodeOpType(pCodeOp *pcop);
6495 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6498 /*-----------------------------------------------------------------*/
6499 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6500 /*-----------------------------------------------------------------*/
6502 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6506 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6507 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6509 if( !( (pcop->type == PO_LABEL) ||
6510 (pcop->type == PO_LITERAL) ||
6511 (pcop->type == PO_STR) ))
6512 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6513 PCOR(pcop)->r->wasUsed = 1;
6519 /*----------------------------------------------------------------------*
6520 * pic16_areRegsSame - check to see if the names of two registers match *
6521 *----------------------------------------------------------------------*/
6522 int pic16_areRegsSame(regs *r1, regs *r2)
6524 if(!strcmp(r1->name, r2->name))return 1;
6530 /*-----------------------------------------------------------------*/
6531 /*-----------------------------------------------------------------*/
6532 static void pic16_FixRegisterBanking(pBlock *pb)
6536 regs *reg, *prevreg;
6542 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6545 /* loop through all of the flow blocks with in one pblock */
6547 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6551 /* at this point, pc should point to a PC_FLOW object */
6552 /* for each flow block, determine the register banking
6555 if(!isPCI(pc))goto loop;
6557 if(PCI(pc)->is2MemOp)goto loop;
6559 reg = pic16_getRegFromInstruction(pc);
6562 pc->print(stderr, pc);
6563 fprintf(stderr, "reg = %p\n", reg);
6566 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6567 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6568 reg->address,reg->isBitField, reg->isFixed);
6572 /* now make some tests to make sure that instruction needs bank switch */
6574 /* if no register exists, and if not a bit opcode goto loop */
6576 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6579 if(isPCI_SKIP(pc)) {
6580 // fprintf(stderr, "instruction is SKIP instruction\n");
6582 if(reg && isACCESS_BANK(reg))goto loop;
6584 if(!isBankInstruction(pc))goto loop;
6586 if(isPCI_LIT(pc))goto loop;
6588 if(PCI(pc)->op == POC_CALL)goto loop;
6590 /* Examine the instruction before this one to make sure it is
6591 * not a skip type instruction */
6592 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6594 /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
6595 * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
6597 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6600 insertBankSwitch(flag, pc);
6603 // fprintf(stderr, "BANK SWITCH inserted\n");
6612 static void pBlockDestruct(pBlock *pb)
6623 /*-----------------------------------------------------------------*/
6624 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6625 /* name dbName and combine them */
6626 /* into one block */
6627 /*-----------------------------------------------------------------*/
6628 static void mergepBlocks(char dbName)
6631 pBlock *pb, *pbmerged = NULL,*pbn;
6633 pb = the_pFile->pbHead;
6635 //fprintf(stderr," merging blocks named %c\n",dbName);
6639 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6640 if( getpBlock_dbName(pb) == dbName) {
6642 //fprintf(stderr," merged block %c\n",dbName);
6647 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6648 /* pic16_addpCode2pBlock doesn't handle the tail: */
6649 pbmerged->pcTail = pb->pcTail;
6651 pb->prev->next = pbn;
6653 pbn->prev = pb->prev;
6658 //pic16_printpBlock(stderr, pbmerged);
6665 /*-----------------------------------------------------------------*/
6666 /* AnalyzeFlow - Examine the flow of the code and optimize */
6668 /* level 0 == minimal optimization */
6669 /* optimize registers that are used only by two instructions */
6670 /* level 1 == maximal optimization */
6671 /* optimize by looking at pairs of instructions that use the */
6673 /*-----------------------------------------------------------------*/
6675 static void AnalyzeFlow(int level)
6677 static int times_called=0;
6682 /* remove unused allocated registers before exiting */
6683 pic16_RemoveUnusedRegisters();
6689 /* if this is not the first time this function has been called,
6690 then clean up old flow information */
6691 if(times_called++) {
6692 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6695 pic16_RegsUnMapLiveRanges();
6700 /* Phase 2 - Flow Analysis - Register Banking
6702 * In this phase, the individual flow blocks are examined
6703 * and register banking is fixed.
6707 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6708 pic16_FixRegisterBanking(pb);
6711 /* Phase 2 - Flow Analysis
6713 * In this phase, the pCode is partition into pCodeFlow
6714 * blocks. The flow blocks mark the points where a continuous
6715 * stream of instructions changes flow (e.g. because of
6716 * a call or goto or whatever).
6719 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6720 pic16_BuildFlow(pb);
6723 /* Phase 2 - Flow Analysis - linking flow blocks
6725 * In this phase, the individual flow blocks are examined
6726 * to determine their order of excution.
6729 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6732 /* Phase 3 - Flow Analysis - Flow Tree
6734 * In this phase, the individual flow blocks are examined
6735 * to determine their order of execution.
6738 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6739 pic16_BuildFlowTree(pb);
6742 /* Phase x - Flow Analysis - Used Banks
6744 * In this phase, the individual flow blocks are examined
6745 * to determine the Register Banks they use
6749 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6754 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6755 pic16_pCodeRegMapLiveRanges(pb);
6757 pic16_RemoveUnusedRegisters();
6759 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6760 pic16_pCodeRegOptimizeRegUsage(level);
6768 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6773 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6775 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6776 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6777 pcflow = pcflow->next) {
6779 FillFlow(PCFL(pcflow));
6784 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6787 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6788 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6789 pcflow = pcflow->next) {
6791 FlowStats(PCFL(pcflow));
6797 /* VR -- no need to analyze banking in flow, but left here :
6798 * 1. because it may be used in the future for other purposes
6799 * 2. because if omitted we'll miss some optimization done here
6801 * Perhaps I should rename it to something else
6804 /*-----------------------------------------------------------------*/
6805 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6806 /* assigned to the registers. */
6808 /*-----------------------------------------------------------------*/
6810 void pic16_AnalyzeBanking(void)
6815 /* Phase x - Flow Analysis - Used Banks
6817 * In this phase, the individual flow blocks are examined
6818 * to determine the Register Banks they use
6824 if(!the_pFile)return;
6826 if(!pic16_options.no_banksel) {
6827 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6828 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6829 pic16_FixRegisterBanking(pb);
6835 /*-----------------------------------------------------------------*/
6836 /* buildCallTree - Look at the flow and extract all of the calls. */
6837 /*-----------------------------------------------------------------*/
6838 static set *register_usage(pBlock *pb);
6840 static void buildCallTree(void )
6852 /* Now build the call tree.
6853 First we examine all of the pCodes for functions.
6854 Keep in mind that the function boundaries coincide
6855 with pBlock boundaries.
6857 The algorithm goes something like this:
6858 We have two nested loops. The outer loop iterates
6859 through all of the pBlocks/functions. The inner
6860 loop iterates through all of the pCodes for
6861 a given pBlock. When we begin iterating through
6862 a pBlock, the variable pc_fstart, pCode of the start
6863 of a function, is cleared. We then search for pCodes
6864 of type PC_FUNCTION. When one is encountered, we
6865 initialize pc_fstart to this and at the same time
6866 associate a new pBranch object that signifies a
6867 branch entry. If a return is found, then this signifies
6868 a function exit point. We'll link the pCodes of these
6869 returns to the matching pc_fstart.
6871 When we're done, a doubly linked list of pBranches
6872 will exist. The head of this list is stored in
6873 `the_pFile', which is the meta structure for all
6874 of the pCode. Look at the pic16_printCallTree function
6875 on how the pBranches are linked together.
6878 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6879 pCode *pc_fstart=NULL;
6880 for(pc = pb->pcHead; pc; pc = pc->next) {
6882 if(isPCI(pc) && pc_fstart) {
6883 if(PCI(pc)->is2MemOp) {
6884 r = pic16_getRegFromInstruction2(pc);
6885 if(r && !strcmp(r->name, "POSTDEC1"))
6886 PCF(pc_fstart)->stackusage++;
6888 r = pic16_getRegFromInstruction(pc);
6889 if(r && !strcmp(r->name, "PREINC1"))
6890 PCF(pc_fstart)->stackusage--;
6895 if (PCF(pc)->fname) {
6897 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6898 //fprintf(stderr," found main \n");
6899 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6903 pbr = Safe_calloc(1,sizeof(pBranch));
6904 pbr->pc = pc_fstart = pc;
6907 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6909 // Here's a better way of doing the same:
6910 addSet(&pb->function_entries, pc);
6913 // Found an exit point in a function, e.g. return
6914 // (Note, there may be more than one return per function)
6916 pBranchLink(PCF(pc_fstart), PCF(pc));
6918 addSet(&pb->function_exits, pc);
6920 } else if(isCALL(pc)) {
6921 addSet(&pb->function_calls,pc);
6928 /* This is not needed because currently all register used
6929 * by a function are stored in stack -- VR */
6931 /* Re-allocate the registers so that there are no collisions
6932 * between local variables when one function call another */
6935 // pic16_deallocateAllRegs();
6937 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6945 /*-----------------------------------------------------------------*/
6946 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6947 /* all of the logical connections. */
6949 /* Essentially what's done here is that the pCode flow is */
6951 /*-----------------------------------------------------------------*/
6953 void pic16_AnalyzepCode(char dbName)
6964 /* Phase 1 - Register allocation and peep hole optimization
6966 * The first part of the analysis is to determine the registers
6967 * that are used in the pCode. Once that is done, the peep rules
6968 * are applied to the code. We continue to loop until no more
6969 * peep rule optimizations are found (or until we exceed the
6970 * MAX_PASSES threshold).
6972 * When done, the required registers will be determined.
6978 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6979 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6981 /* First, merge the labels with the instructions */
6982 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6983 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6985 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6986 //fprintf(stderr," analyze and merging block %c\n",dbName);
6987 pic16_pBlockMergeLabels(pb);
6990 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6995 changes = OptimizepCode(dbName);
6998 } while(changes && (i++ < MAX_PASSES));
7003 /*-----------------------------------------------------------------*/
7004 /* ispCodeFunction - returns true if *pc is the pCode of a */
7006 /*-----------------------------------------------------------------*/
7007 static bool ispCodeFunction(pCode *pc)
7010 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7016 /*-----------------------------------------------------------------*/
7017 /* findFunction - Search for a function by name (given the name) */
7018 /* in the set of all functions that are in a pBlock */
7019 /* (note - I expect this to change because I'm planning to limit */
7020 /* pBlock's to just one function declaration */
7021 /*-----------------------------------------------------------------*/
7022 static pCode *findFunction(char *fname)
7029 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7031 pc = setFirstItem(pb->function_entries);
7034 if((pc->type == PC_FUNCTION) &&
7036 (strcmp(fname, PCF(pc)->fname)==0))
7039 pc = setNextItem(pb->function_entries);
7047 static void MarkUsedRegisters(set *regset)
7052 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7053 // fprintf(stderr, "marking register = %s\t", r1->name);
7054 r2 = pic16_regWithIdx(r1->rIdx);
7055 // fprintf(stderr, "to register = %s\n", r2->name);
7061 static void pBlockStats(FILE *of, pBlock *pb)
7067 if(!pic16_pcode_verbose)return;
7069 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7071 // for now just print the first element of each set
7072 pc = setFirstItem(pb->function_entries);
7074 fprintf(of,";entry: ");
7077 pc = setFirstItem(pb->function_exits);
7079 fprintf(of,";has an exit\n");
7083 pc = setFirstItem(pb->function_calls);
7085 fprintf(of,";functions called:\n");
7088 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7089 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7091 pc = setNextItem(pb->function_calls);
7095 r = setFirstItem(pb->tregisters);
7097 int n = elementsInSet(pb->tregisters);
7099 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7102 fprintf(of,"; %s\n",r->name);
7103 r = setNextItem(pb->tregisters);
7107 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7110 /*-----------------------------------------------------------------*/
7111 /*-----------------------------------------------------------------*/
7113 static void sequencepCode(void)
7119 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7121 pb->seq = GpCodeSequenceNumber+1;
7123 for( pc = pb->pcHead; pc; pc = pc->next)
7124 pc->seq = ++GpCodeSequenceNumber;
7130 /*-----------------------------------------------------------------*/
7131 /*-----------------------------------------------------------------*/
7132 static set *register_usage(pBlock *pb)
7135 set *registers=NULL;
7136 set *registersInCallPath = NULL;
7138 /* check recursion */
7140 pc = setFirstItem(pb->function_entries);
7147 if(pc->type != PC_FUNCTION)
7148 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7150 pc = setFirstItem(pb->function_calls);
7151 for( ; pc; pc = setNextItem(pb->function_calls)) {
7153 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7154 char *dest = pic16_get_op_from_instruction(PCI(pc));
7156 pcn = findFunction(dest);
7158 registersInCallPath = register_usage(pcn->pb);
7160 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7165 pBlockStats(stderr,pb); // debug
7168 // Mark the registers in this block as used.
7170 MarkUsedRegisters(pb->tregisters);
7171 if(registersInCallPath) {
7172 /* registers were used in the functions this pBlock has called */
7173 /* so now, we need to see if these collide with the ones we are */
7176 regs *r1,*r2, *newreg;
7178 DFPRINTF((stderr,"comparing registers\n"));
7180 r1 = setFirstItem(registersInCallPath);
7183 r2 = setFirstItem(pb->tregisters);
7185 while(r2 && (r1->type != REG_STK)) {
7187 if(r2->rIdx == r1->rIdx) {
7188 newreg = pic16_findFreeReg(REG_GPR);
7192 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7196 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7197 r1->rIdx, newreg->rIdx));
7198 r2->rIdx = newreg->rIdx;
7199 //if(r2->name) free(r2->name);
7201 r2->name = Safe_strdup(newreg->name);
7205 newreg->wasUsed = 1;
7207 r2 = setNextItem(pb->tregisters);
7210 r1 = setNextItem(registersInCallPath);
7213 /* Collisions have been resolved. Now free the registers in the call path */
7214 r1 = setFirstItem(registersInCallPath);
7216 if(r1->type != REG_STK) {
7217 newreg = pic16_regWithIdx(r1->rIdx);
7220 r1 = setNextItem(registersInCallPath);
7224 // MarkUsedRegisters(pb->registers);
7226 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7229 DFPRINTF((stderr,"returning regs\n"));
7231 DFPRINTF((stderr,"not returning regs\n"));
7233 DFPRINTF((stderr,"pBlock after register optim.\n"));
7234 pBlockStats(stderr,pb); // debug
7240 /*-----------------------------------------------------------------*/
7241 /* pct2 - writes the call tree to a file */
7243 /*-----------------------------------------------------------------*/
7244 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7248 // set *registersInCallPath = NULL;
7254 fprintf(of, "recursive function\n");
7255 return; //recursion ?
7258 pc = setFirstItem(pb->function_entries);
7265 for(i=0;i<indent;i++) // Indentation
7269 if(pc->type == PC_FUNCTION) {
7270 usedstack += PCF(pc)->stackusage;
7271 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7272 } else return; // ???
7275 pc = setFirstItem(pb->function_calls);
7276 for( ; pc; pc = setNextItem(pb->function_calls)) {
7278 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7279 char *dest = pic16_get_op_from_instruction(PCI(pc));
7281 pcn = findFunction(dest);
7283 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7285 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7293 /*-----------------------------------------------------------------*/
7294 /* pic16_printCallTree - writes the call tree to a file */
7296 /*-----------------------------------------------------------------*/
7298 void pic16_printCallTree(FILE *of)
7310 fprintf(of, "\npBlock statistics\n");
7311 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7315 fprintf(of,"Call Tree\n");
7316 pbr = the_pFile->functions;
7320 if(!ispCodeFunction(pc))
7321 fprintf(of,"bug in call tree");
7324 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7326 while(pc->next && !ispCodeFunction(pc->next)) {
7328 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7329 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7337 fprintf(of,"\n**************\n\na better call tree\n");
7338 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7343 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7344 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7350 /*-----------------------------------------------------------------*/
7352 /*-----------------------------------------------------------------*/
7354 static void InlineFunction(pBlock *pb)
7362 pc = setFirstItem(pb->function_calls);
7364 for( ; pc; pc = setNextItem(pb->function_calls)) {
7367 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7373 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7375 //fprintf(stderr,"Cool can inline:\n");
7376 //pcn->print(stderr,pcn);
7378 //fprintf(stderr,"recursive call Inline\n");
7379 InlineFunction(pcn->pb);
7380 //fprintf(stderr,"return from recursive call Inline\n");
7383 At this point, *pc points to a CALL mnemonic, and
7384 *pcn points to the function that is being called.
7386 To in-line this call, we need to remove the CALL
7387 and RETURN(s), and link the function pCode in with
7393 /* Remove the CALL */
7397 /* remove callee pBlock from the pBlock linked list */
7398 removepBlock(pcn->pb);
7406 /* Remove the Function pCode */
7407 pct = pic16_findNextInstruction(pcn->next);
7409 /* Link the function with the callee */
7410 pc->next = pcn->next;
7411 pcn->next->prev = pc;
7413 /* Convert the function name into a label */
7415 pbr = Safe_calloc(1,sizeof(pBranch));
7416 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7418 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7419 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7421 /* turn all of the return's except the last into goto's */
7422 /* check case for 2 instruction pBlocks */
7423 pce = pic16_findNextInstruction(pcn->next);
7425 pCode *pce_next = pic16_findNextInstruction(pce->next);
7427 if(pce_next == NULL) {
7428 /* found the last return */
7429 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7431 //fprintf(stderr,"found last return\n");
7432 //pce->print(stderr,pce);
7433 pce->prev->next = pc_call->next;
7434 pc_call->next->prev = pce->prev;
7435 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7445 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7451 /*-----------------------------------------------------------------*/
7453 /*-----------------------------------------------------------------*/
7455 void pic16_InlinepCode(void)
7464 if(!functionInlining)
7467 /* Loop through all of the function definitions and count the
7468 * number of times each one is called */
7469 //fprintf(stderr,"inlining %d\n",__LINE__);
7471 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7473 pc = setFirstItem(pb->function_calls);
7475 for( ; pc; pc = setNextItem(pb->function_calls)) {
7478 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7479 if(pcn && isPCF(pcn)) {
7480 PCF(pcn)->ncalled++;
7483 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7488 //fprintf(stderr,"inlining %d\n",__LINE__);
7490 /* Now, Loop through the function definitions again, but this
7491 * time inline those functions that have only been called once. */
7493 InlineFunction(the_pFile->pbHead);
7494 //fprintf(stderr,"inlining %d\n",__LINE__);
7496 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7501 char *pic_optype_names[]={
7502 "PO_NONE", // No operand e.g. NOP
7503 "PO_W", // The working register (as a destination)
7504 "PO_WREG", // The working register (as a file register)
7505 "PO_STATUS", // The 'STATUS' register
7506 "PO_BSR", // The 'BSR' register
7507 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7509 "PO_INDF0", // The Indirect register
7510 "PO_INTCON", // Interrupt Control register
7511 "PO_GPR_REGISTER", // A general purpose register
7512 "PO_GPR_BIT", // A bit of a general purpose register
7513 "PO_GPR_TEMP", // A general purpose temporary register
7514 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7515 "PO_PCL", // Program counter Low register
7516 "PO_PCLATH", // Program counter Latch high register
7517 "PO_PCLATU", // Program counter Latch upper register
7518 "PO_PRODL", // Product Register Low
7519 "PO_PRODH", // Product Register High
7520 "PO_LITERAL", // A constant
7521 "PO_REL_ADDR", // A relative address
7522 "PO_IMMEDIATE", // (8051 legacy)
7523 "PO_DIR", // Direct memory (8051 legacy)
7524 "PO_CRY", // bit memory (8051 legacy)
7525 "PO_BIT", // bit operand.
7526 "PO_STR", // (8051 legacy)
7528 "PO_WILD" // Wild card operand in peep optimizer
7532 char *dumpPicOptype(PIC_OPTYPE type)
7534 return (pic_optype_names[ type ]);