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 pCodeOpReg pic16_pc_gptrreg = {{PO_GPR_REGISTER, "__GPTRREG"}, -1, NULL,0,NULL};
117 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
118 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
121 static int mnemonics_initialized = 0;
124 static hTab *pic16MnemonicsHash = NULL;
125 static hTab *pic16pCodePeepCommandsHash = NULL;
127 static pFile *the_pFile = NULL;
128 static pBlock *pb_dead_pcodes = NULL;
130 /* Hardcoded flags to change the behavior of the PIC port */
131 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
132 static int functionInlining = 1; /* inline functions if nonzero */
133 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
135 int pic16_pcode_verbose = 0;
137 //static int GpCodeSequenceNumber = 1;
138 static int GpcFlowSeq = 1;
140 extern void pic16_RemoveUnusedRegisters(void);
141 extern void pic16_RegsUnMapLiveRanges(void);
142 extern void pic16_BuildFlowTree(pBlock *pb);
143 extern void pic16_pCodeRegOptimizeRegUsage(int level);
144 extern int pic16_picIsInitialized(void);
145 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
146 extern int mnem2key(char const *mnem);
148 /****************************************************************/
149 /* Forward declarations */
150 /****************************************************************/
152 void pic16_unlinkpCode(pCode *pc);
154 static void genericAnalyze(pCode *pc);
155 static void AnalyzeGOTO(pCode *pc);
156 static void AnalyzeSKIP(pCode *pc);
157 static void AnalyzeRETURN(pCode *pc);
160 static void genericDestruct(pCode *pc);
161 static void genericPrint(FILE *of,pCode *pc);
163 static void pCodePrintLabel(FILE *of, pCode *pc);
164 static void pCodePrintFunction(FILE *of, pCode *pc);
165 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
166 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
167 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
168 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
169 int pic16_pCodePeepMatchRule(pCode *pc);
170 static void pBlockStats(FILE *of, pBlock *pb);
171 static pBlock *newpBlock(void);
172 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
173 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
174 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
175 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
177 char *dumpPicOptype(PIC_OPTYPE type);
179 /****************************************************************/
180 /* PIC Instructions */
181 /****************************************************************/
183 pCodeInstruction pic16_pciADDWF = {
184 {PC_OPCODE, NULL, NULL, 0, NULL,
197 1,0, // dest, bit instruction
199 0, // literal operand
201 0, // fast call/return mode select bit
202 0, // second memory operand
203 0, // second literal operand
205 (PCC_W | PCC_REGISTER), // inCond
206 (PCC_REGISTER | PCC_Z), // outCond
210 pCodeInstruction pic16_pciADDFW = {
211 {PC_OPCODE, NULL, NULL, 0, NULL,
224 0,0, // dest, bit instruction
226 0, // literal operand
228 0, // fast call/return mode select bit
229 0, // second memory operand
230 0, // second literal operand
232 (PCC_W | PCC_REGISTER), // inCond
233 (PCC_W | PCC_Z), // outCond
237 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
238 {PC_OPCODE, NULL, NULL, 0, NULL,
251 1,0, // dest, bit instruction
253 0, // literal operand
255 0, // fast call/return mode select bit
256 0, // second memory operand
257 0, // second literal operand
259 (PCC_W | PCC_REGISTER | PCC_C), // inCond
260 (PCC_REGISTER | PCC_Z), // outCond
264 pCodeInstruction pic16_pciADDFWC = {
265 {PC_OPCODE, NULL, NULL, 0, NULL,
278 0,0, // dest, bit instruction
280 0, // literal operand
282 0, // fast call/return mode select bit
283 0, // second memory operand
284 0, // second literal operand
286 (PCC_W | PCC_REGISTER | PCC_C), // inCond
287 (PCC_W | PCC_Z), // outCond
291 pCodeInstruction pic16_pciADDLW = {
292 {PC_OPCODE, NULL, NULL, 0, NULL,
305 0,0, // dest, bit instruction
307 1, // literal operand
309 0, // fast call/return mode select bit
310 0, // second memory operand
311 0, // second literal operand
313 (PCC_W | PCC_LITERAL), // inCond
314 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
318 pCodeInstruction pic16_pciANDLW = {
319 {PC_OPCODE, NULL, NULL, 0, NULL,
332 0,0, // dest, bit instruction
334 1, // literal operand
336 0, // fast call/return mode select bit
337 0, // second memory operand
338 0, // second literal operand
340 (PCC_W | PCC_LITERAL), // inCond
341 (PCC_W | PCC_Z | PCC_N), // outCond
345 pCodeInstruction pic16_pciANDWF = {
346 {PC_OPCODE, NULL, NULL, 0, NULL,
359 1,0, // dest, bit instruction
361 0, // literal operand
363 0, // fast call/return mode select bit
364 0, // second memory operand
365 0, // second literal operand
367 (PCC_W | PCC_REGISTER), // inCond
368 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
372 pCodeInstruction pic16_pciANDFW = {
373 {PC_OPCODE, NULL, NULL, 0, NULL,
386 0,0, // dest, bit instruction
388 0, // literal operand
390 0, // fast call/return mode select bit
391 0, // second memory operand
392 0, // second literal operand
394 (PCC_W | PCC_REGISTER), // inCond
395 (PCC_W | PCC_Z) // outCond
398 pCodeInstruction pic16_pciBC = { // mdubuc - New
399 {PC_OPCODE, NULL, NULL, 0, NULL,
412 0,0, // dest, bit instruction
414 0, // literal operand
416 0, // fast call/return mode select bit
417 0, // second memory operand
418 0, // second literal operand
420 (PCC_REL_ADDR | PCC_C), // inCond
425 pCodeInstruction pic16_pciBCF = {
426 {PC_OPCODE, NULL, NULL, 0, NULL,
439 1,1, // dest, bit instruction
441 0, // literal operand
443 0, // fast call/return mode select bit
444 0, // second memory operand
445 0, // second literal operand
447 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
448 PCC_REGISTER, // outCond
452 pCodeInstruction pic16_pciBN = { // mdubuc - New
453 {PC_OPCODE, NULL, NULL, 0, NULL,
466 0,0, // dest, bit instruction
468 0, // literal operand
470 0, // fast call/return mode select bit
471 0, // second memory operand
472 0, // second literal operand
474 (PCC_REL_ADDR | PCC_N), // inCond
475 PCC_NONE , // outCond
479 pCodeInstruction pic16_pciBNC = { // mdubuc - New
480 {PC_OPCODE, NULL, NULL, 0, NULL,
493 0,0, // dest, bit instruction
495 0, // literal operand
497 0, // fast call/return mode select bit
498 0, // second memory operand
499 0, // second literal operand
501 (PCC_REL_ADDR | PCC_C), // inCond
502 PCC_NONE , // outCond
506 pCodeInstruction pic16_pciBNN = { // mdubuc - New
507 {PC_OPCODE, NULL, NULL, 0, NULL,
520 0,0, // dest, bit instruction
522 0, // literal operand
524 0, // fast call/return mode select bit
525 0, // second memory operand
526 0, // second literal operand
528 (PCC_REL_ADDR | PCC_N), // inCond
529 PCC_NONE , // outCond
533 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
534 {PC_OPCODE, NULL, NULL, 0, NULL,
547 0,0, // dest, bit instruction
549 0, // literal operand
551 0, // fast call/return mode select bit
552 0, // second memory operand
553 0, // second literal operand
555 (PCC_REL_ADDR | PCC_OV), // inCond
556 PCC_NONE , // outCond
560 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
561 {PC_OPCODE, NULL, NULL, 0, NULL,
574 0,0, // dest, bit instruction
576 0, // literal operand
578 0, // fast call/return mode select bit
579 0, // second memory operand
580 0, // second literal operand
582 (PCC_REL_ADDR | PCC_Z), // inCond
583 PCC_NONE , // outCond
587 pCodeInstruction pic16_pciBOV = { // mdubuc - New
588 {PC_OPCODE, NULL, NULL, 0, NULL,
601 0,0, // dest, bit instruction
603 0, // literal operand
605 0, // fast call/return mode select bit
606 0, // second memory operand
607 0, // second literal operand
609 (PCC_REL_ADDR | PCC_OV), // inCond
610 PCC_NONE , // outCond
614 pCodeInstruction pic16_pciBRA = { // mdubuc - New
615 {PC_OPCODE, NULL, NULL, 0, NULL,
628 0,0, // dest, bit instruction
630 0, // literal operand
632 0, // fast call/return mode select bit
633 0, // second memory operand
634 0, // second literal operand
636 PCC_REL_ADDR, // inCond
637 PCC_NONE , // outCond
641 pCodeInstruction pic16_pciBSF = {
642 {PC_OPCODE, NULL, NULL, 0, NULL,
655 1,1, // dest, bit instruction
657 0, // literal operand
659 0, // fast call/return mode select bit
660 0, // second memory operand
661 0, // second literal operand
663 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
664 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
668 pCodeInstruction pic16_pciBTFSC = {
669 {PC_OPCODE, NULL, NULL, 0, NULL,
682 0,1, // dest, bit instruction
684 0, // literal operand
686 0, // fast call/return mode select bit
687 0, // second memory operand
688 0, // second literal operand
690 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
691 PCC_EXAMINE_PCOP, // outCond
695 pCodeInstruction pic16_pciBTFSS = {
696 {PC_OPCODE, NULL, NULL, 0, NULL,
709 0,1, // dest, bit instruction
711 0, // literal operand
713 0, // fast call/return mode select bit
714 0, // second memory operand
715 0, // second literal operand
717 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
718 PCC_EXAMINE_PCOP, // outCond
722 pCodeInstruction pic16_pciBTG = { // mdubuc - New
723 {PC_OPCODE, NULL, NULL, 0, NULL,
736 0,1, // dest, bit instruction
738 0, // literal operand
740 0, // fast call/return mode select bit
741 0, // second memory operand
742 0, // second literal operand
744 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
745 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
749 pCodeInstruction pic16_pciBZ = { // mdubuc - New
750 {PC_OPCODE, NULL, NULL, 0, NULL,
763 0,0, // dest, bit instruction
765 0, // literal operand
767 0, // fast call/return mode select bit
768 0, // second memory operand
769 0, // second literal operand
776 pCodeInstruction pic16_pciCALL = {
777 {PC_OPCODE, NULL, NULL, 0, NULL,
790 0,0, // dest, bit instruction
792 0, // literal operand
794 1, // fast call/return mode select bit
795 0, // second memory operand
796 0, // second literal operand
799 PCC_NONE , // outCond
803 pCodeInstruction pic16_pciCOMF = {
804 {PC_OPCODE, NULL, NULL, 0, NULL,
817 1,0, // dest, bit instruction
819 0, // literal operand
821 0, // fast call/return mode select bit
822 0, // second memory operand
823 0, // second literal operand
825 PCC_REGISTER, // inCond
826 PCC_REGISTER , // outCond
830 pCodeInstruction pic16_pciCOMFW = {
831 {PC_OPCODE, NULL, NULL, 0, NULL,
844 0,0, // dest, bit instruction
846 0, // literal operand
848 0, // fast call/return mode select bit
849 0, // second memory operand
850 0, // second literal operand
852 PCC_REGISTER, // inCond
857 pCodeInstruction pic16_pciCLRF = {
858 {PC_OPCODE, NULL, NULL, 0, NULL,
871 0,0, // dest, bit instruction
873 0, // literal operand
875 0, // fast call/return mode select bit
876 0, // second memory operand
877 0, // second literal operand
879 PCC_REGISTER, // inCond
880 PCC_REGISTER , // outCond
884 pCodeInstruction pic16_pciCLRWDT = {
885 {PC_OPCODE, NULL, NULL, 0, NULL,
898 0,0, // dest, bit instruction
900 0, // literal operand
902 0, // fast call/return mode select bit
903 0, // second memory operand
904 0, // second literal operand
907 PCC_NONE , // outCond
911 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
912 {PC_OPCODE, NULL, NULL, 0, NULL,
925 0,0, // dest, bit instruction
927 0, // literal operand
929 0, // fast call/return mode select bit
930 0, // second memory operand
931 0, // second literal operand
933 (PCC_W | PCC_REGISTER), // inCond
934 PCC_NONE , // outCond
938 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
939 {PC_OPCODE, NULL, NULL, 0, NULL,
952 0,0, // dest, bit instruction
954 0, // literal operand
956 0, // fast call/return mode select bit
957 0, // second memory operand
958 0, // second literal operand
960 (PCC_W | PCC_REGISTER), // inCond
961 PCC_NONE , // outCond
965 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
966 {PC_OPCODE, NULL, NULL, 0, NULL,
979 1,0, // dest, bit instruction
981 0, // literal operand
983 0, // fast call/return mode select bit
984 0, // second memory operand
985 0, // second literal operand
987 (PCC_W | PCC_REGISTER), // inCond
988 PCC_NONE , // outCond
992 pCodeInstruction pic16_pciDAW = {
993 {PC_OPCODE, NULL, NULL, 0, NULL,
1006 0,0, // dest, bit instruction
1007 0,0, // branch, skip
1008 0, // literal operand
1009 0, // RAM access bit
1010 0, // fast call/return mode select bit
1011 0, // second memory operand
1012 0, // second literal operand
1015 (PCC_W | PCC_C), // outCond
1019 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1020 {PC_OPCODE, NULL, NULL, 0, NULL,
1026 NULL, // from branch
1033 1,0, // dest, bit instruction
1034 1,1, // branch, skip
1035 0, // literal operand
1036 1, // RAM access bit
1037 0, // fast call/return mode select bit
1038 0, // second memory operand
1039 0, // second literal operand
1041 PCC_REGISTER, // inCond
1042 PCC_REGISTER , // outCond
1046 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1047 {PC_OPCODE, NULL, NULL, 0, NULL,
1053 NULL, // from branch
1060 0,0, // dest, bit instruction
1061 1,1, // branch, skip
1062 0, // literal operand
1063 1, // RAM access bit
1064 0, // fast call/return mode select bit
1065 0, // second memory operand
1066 0, // second literal operand
1068 PCC_REGISTER, // inCond
1073 pCodeInstruction pic16_pciDECF = {
1074 {PC_OPCODE, NULL, NULL, 0, NULL,
1080 NULL, // from branch
1087 1,0, // dest, bit instruction
1088 0,0, // branch, skip
1089 0, // literal operand
1090 1, // RAM access bit
1091 0, // fast call/return mode select bit
1092 0, // second memory operand
1093 0, // second literal operand
1095 PCC_REGISTER, // inCond
1096 PCC_REGISTER , // outCond
1100 pCodeInstruction pic16_pciDECFW = {
1101 {PC_OPCODE, NULL, NULL, 0, NULL,
1107 NULL, // from branch
1114 0,0, // dest, bit instruction
1115 0,0, // branch, skip
1116 0, // literal operand
1117 1, // RAM access bit
1118 0, // fast call/return mode select bit
1119 0, // second memory operand
1120 0, // second literal operand
1122 PCC_REGISTER, // inCond
1127 pCodeInstruction pic16_pciDECFSZ = {
1128 {PC_OPCODE, NULL, NULL, 0, NULL,
1134 NULL, // from branch
1141 1,0, // dest, bit instruction
1142 1,1, // branch, skip
1143 0, // literal operand
1144 1, // RAM access bit
1145 0, // fast call/return mode select bit
1146 0, // second memory operand
1147 0, // second literal operand
1149 PCC_REGISTER, // inCond
1150 PCC_REGISTER , // outCond
1154 pCodeInstruction pic16_pciDECFSZW = {
1155 {PC_OPCODE, NULL, NULL, 0, NULL,
1161 NULL, // from branch
1168 0,0, // dest, bit instruction
1169 1,1, // branch, skip
1170 0, // literal operand
1171 1, // RAM access bit
1172 0, // fast call/return mode select bit
1173 0, // second memory operand
1174 0, // second literal operand
1176 PCC_REGISTER, // inCond
1181 pCodeInstruction pic16_pciGOTO = {
1182 {PC_OPCODE, NULL, NULL, 0, NULL,
1188 NULL, // from branch
1195 0,0, // dest, bit instruction
1196 1,0, // branch, skip
1197 0, // literal operand
1198 0, // RAM access bit
1199 0, // fast call/return mode select bit
1200 0, // second memory operand
1201 0, // second literal operand
1203 PCC_REL_ADDR, // inCond
1204 PCC_NONE , // outCond
1208 pCodeInstruction pic16_pciINCF = {
1209 {PC_OPCODE, NULL, NULL, 0, NULL,
1215 NULL, // from branch
1222 1,0, // dest, bit instruction
1223 0,0, // branch, skip
1224 0, // literal operand
1225 1, // RAM access bit
1226 0, // fast call/return mode select bit
1227 0, // second memory operand
1228 0, // second literal operand
1230 PCC_REGISTER, // inCond
1231 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1235 pCodeInstruction pic16_pciINCFW = {
1236 {PC_OPCODE, NULL, NULL, 0, NULL,
1242 NULL, // from branch
1249 0,0, // dest, bit instruction
1250 0,0, // branch, skip
1251 0, // literal operand
1252 1, // RAM access bit
1253 0, // fast call/return mode select bit
1254 0, // second memory operand
1255 0, // second literal operand
1257 PCC_REGISTER, // inCond
1262 pCodeInstruction pic16_pciINCFSZ = {
1263 {PC_OPCODE, NULL, NULL, 0, NULL,
1269 NULL, // from branch
1276 1,0, // dest, bit instruction
1277 1,1, // branch, skip
1278 0, // literal operand
1279 1, // RAM access bit
1280 0, // fast call/return mode select bit
1281 0, // second memory operand
1282 0, // second literal operand
1284 PCC_REGISTER, // inCond
1285 PCC_REGISTER , // outCond
1289 pCodeInstruction pic16_pciINCFSZW = {
1290 {PC_OPCODE, NULL, NULL, 0, NULL,
1296 NULL, // from branch
1303 0,0, // dest, bit instruction
1304 1,1, // branch, skip
1305 0, // literal operand
1306 1, // RAM access bit
1307 0, // fast call/return mode select bit
1308 0, // second memory operand
1309 0, // second literal operand
1311 PCC_REGISTER, // inCond
1316 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1317 {PC_OPCODE, NULL, NULL, 0, NULL,
1323 NULL, // from branch
1330 1,0, // dest, bit instruction
1331 1,1, // branch, skip
1332 0, // literal operand
1333 1, // RAM access bit
1334 0, // fast call/return mode select bit
1335 0, // second memory operand
1336 0, // second literal operand
1338 PCC_REGISTER, // inCond
1339 PCC_REGISTER , // outCond
1343 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1344 {PC_OPCODE, NULL, NULL, 0, NULL,
1350 NULL, // from branch
1357 0,0, // dest, bit instruction
1358 1,1, // branch, skip
1359 0, // literal operand
1360 1, // RAM access bit
1361 0, // fast call/return mode select bit
1362 0, // second memory operand
1363 0, // second literal operand
1365 PCC_REGISTER, // inCond
1370 pCodeInstruction pic16_pciIORWF = {
1371 {PC_OPCODE, NULL, NULL, 0, NULL,
1377 NULL, // from branch
1384 1,0, // dest, bit instruction
1385 0,0, // branch, skip
1386 0, // literal operand
1387 1, // RAM access bit
1388 0, // fast call/return mode select bit
1389 0, // second memory operand
1390 0, // second literal operand
1392 (PCC_W | PCC_REGISTER), // inCond
1393 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1397 pCodeInstruction pic16_pciIORFW = {
1398 {PC_OPCODE, NULL, NULL, 0, NULL,
1404 NULL, // from branch
1411 0,0, // dest, bit instruction
1412 0,0, // branch, skip
1413 0, // literal operand
1414 1, // RAM access bit
1415 0, // fast call/return mode select bit
1416 0, // second memory operand
1417 0, // second literal operand
1419 (PCC_W | PCC_REGISTER), // inCond
1420 (PCC_W | PCC_Z | PCC_N), // outCond
1424 pCodeInstruction pic16_pciIORLW = {
1425 {PC_OPCODE, NULL, NULL, 0, NULL,
1431 NULL, // from branch
1438 0,0, // dest, bit instruction
1439 0,0, // branch, skip
1440 1, // literal operand
1441 0, // RAM access bit
1442 0, // fast call/return mode select bit
1443 0, // second memory operand
1444 0, // second literal operand
1446 (PCC_W | PCC_LITERAL), // inCond
1447 (PCC_W | PCC_Z | PCC_N), // outCond
1451 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1452 {PC_OPCODE, NULL, NULL, 0, NULL,
1458 NULL, // from branch
1465 0,0, // dest, bit instruction
1466 0,0, // branch, skip
1467 1, // literal operand
1468 0, // RAM access bit
1469 0, // fast call/return mode select bit
1470 0, // second memory operand
1471 1, // second literal operand
1473 (PCC_REGISTER | PCC_LITERAL),
1474 PCC_REGISTER, // outCond
1478 pCodeInstruction pic16_pciMOVF = {
1479 {PC_OPCODE, NULL, NULL, 0, NULL,
1485 NULL, // from branch
1492 1,0, // dest, bit instruction
1493 0,0, // branch, skip
1494 0, // literal operand
1495 1, // RAM access bit
1496 0, // fast call/return mode select bit
1497 0, // second memory operand
1498 0, // second literal operand
1500 PCC_REGISTER, // inCond
1501 (PCC_Z | PCC_N), // outCond
1505 pCodeInstruction pic16_pciMOVFW = {
1506 {PC_OPCODE, NULL, NULL, 0, NULL,
1512 NULL, // from branch
1519 0,0, // dest, bit instruction
1520 0,0, // branch, skip
1521 0, // literal operand
1522 1, // RAM access bit
1523 0, // fast call/return mode select bit
1524 0, // second memory operand
1525 0, // second literal operand
1527 PCC_REGISTER, // inCond
1528 (PCC_W | PCC_Z), // outCond
1532 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1533 {PC_OPCODE, NULL, NULL, 0, NULL,
1539 NULL, // from branch
1546 0,0, // dest, bit instruction
1547 0,0, // branch, skip
1548 0, // literal operand
1549 0, // RAM access bit
1550 0, // fast call/return mode select bit
1551 1, // second memory operand
1552 0, // second literal operand
1554 PCC_REGISTER, // inCond
1555 PCC_REGISTER, // outCond
1559 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1560 {PC_OPCODE, NULL, NULL, 0, NULL,
1565 NULL, // from branch
1572 0,0, // dest, bit instruction
1573 0,0, // branch, skip
1574 1, // literal operand
1575 0, // RAM access bit
1576 0, // fast call/return mode select bit
1577 0, // second memory operand
1578 0, // second literal operand
1580 (PCC_NONE | PCC_LITERAL), // inCond
1581 PCC_REGISTER, // outCond - BSR
1585 pCodeInstruction pic16_pciMOVLW = {
1586 {PC_OPCODE, NULL, NULL, 0, NULL,
1591 NULL, // from branch
1598 0,0, // dest, bit instruction
1599 0,0, // branch, skip
1600 1, // literal operand
1601 0, // RAM access bit
1602 0, // fast call/return mode select bit
1603 0, // second memory operand
1604 0, // second literal operand
1606 (PCC_NONE | PCC_LITERAL), // inCond
1611 pCodeInstruction pic16_pciMOVWF = {
1612 {PC_OPCODE, NULL, NULL, 0, NULL,
1618 NULL, // from branch
1625 0,0, // dest, bit instruction
1626 0,0, // branch, skip
1627 0, // literal operand
1628 1, // RAM access bit
1629 0, // fast call/return mode select bit
1630 0, // second memory operand
1631 0, // second literal operand
1633 PCC_REGISTER, // inCond
1638 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1639 {PC_OPCODE, NULL, NULL, 0, NULL,
1644 NULL, // from branch
1651 0,0, // dest, bit instruction
1652 0,0, // branch, skip
1653 1, // literal operand
1654 0, // RAM access bit
1655 0, // fast call/return mode select bit
1656 0, // second memory operand
1657 0, // second literal operand
1659 (PCC_W | PCC_LITERAL), // inCond
1660 PCC_REGISTER, // outCond - PROD
1664 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1665 {PC_OPCODE, NULL, NULL, 0, NULL,
1670 NULL, // from branch
1677 0,0, // dest, bit instruction
1678 0,0, // branch, skip
1679 0, // literal operand
1680 1, // RAM access bit
1681 0, // fast call/return mode select bit
1682 0, // second memory operand
1683 0, // second literal operand
1685 (PCC_W | PCC_REGISTER), // inCond
1686 PCC_REGISTER, // outCond - PROD
1690 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1691 {PC_OPCODE, NULL, NULL, 0, NULL,
1696 NULL, // from branch
1703 0,0, // dest, bit instruction
1704 0,0, // branch, skip
1705 0, // literal operand
1706 1, // RAM access bit
1707 0, // fast call/return mode select bit
1708 0, // second memory operand
1709 0, // second literal operand
1711 PCC_REGISTER, // inCond
1712 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1716 pCodeInstruction pic16_pciNOP = {
1717 {PC_OPCODE, NULL, NULL, 0, NULL,
1722 NULL, // from branch
1729 0,0, // dest, bit instruction
1730 0,0, // branch, skip
1731 0, // literal operand
1732 0, // RAM access bit
1733 0, // fast call/return mode select bit
1734 0, // second memory operand
1735 0, // second literal operand
1738 PCC_NONE, // outCond
1742 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1743 {PC_OPCODE, NULL, NULL, 0, NULL,
1748 NULL, // from branch
1755 0,0, // dest, bit instruction
1756 0,0, // branch, skip
1757 0, // literal operand
1758 0, // RAM access bit
1759 0, // fast call/return mode select bit
1760 0, // second memory operand
1761 0, // second literal operand
1764 PCC_NONE , // outCond
1768 pCodeInstruction pic16_pciPUSH = {
1769 {PC_OPCODE, NULL, NULL, 0, NULL,
1774 NULL, // from branch
1781 0,0, // dest, bit instruction
1782 0,0, // branch, skip
1783 0, // literal operand
1784 0, // RAM access bit
1785 0, // fast call/return mode select bit
1786 0, // second memory operand
1787 0, // second literal operand
1790 PCC_NONE , // outCond
1794 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1795 {PC_OPCODE, NULL, NULL, 0, NULL,
1800 NULL, // from branch
1807 0,0, // dest, bit instruction
1808 0,0, // branch, skip
1809 0, // literal operand
1810 0, // RAM access bit
1811 0, // fast call/return mode select bit
1812 0, // second memory operand
1813 0, // second literal operand
1815 PCC_REL_ADDR, // inCond
1816 PCC_NONE , // outCond
1820 pCodeInstruction pic16_pciRETFIE = {
1821 {PC_OPCODE, NULL, NULL, 0, NULL,
1827 NULL, // from branch
1834 0,0, // dest, bit instruction
1835 1,0, // branch, skip
1836 0, // literal operand
1837 0, // RAM access bit
1838 1, // fast call/return mode select bit
1839 0, // second memory operand
1840 0, // second literal operand
1843 PCC_NONE, // outCond (not true... affects the GIE bit too)
1847 pCodeInstruction pic16_pciRETLW = {
1848 {PC_OPCODE, NULL, NULL, 0, NULL,
1854 NULL, // from branch
1861 0,0, // dest, bit instruction
1862 1,0, // branch, skip
1863 1, // literal operand
1864 0, // RAM access bit
1865 0, // fast call/return mode select bit
1866 0, // second memory operand
1867 0, // second literal operand
1869 PCC_LITERAL, // inCond
1874 pCodeInstruction pic16_pciRETURN = {
1875 {PC_OPCODE, NULL, NULL, 0, NULL,
1881 NULL, // from branch
1888 0,0, // dest, bit instruction
1889 1,0, // branch, skip
1890 0, // literal operand
1891 0, // RAM access bit
1892 1, // fast call/return mode select bit
1893 0, // second memory operand
1894 0, // second literal operand
1897 PCC_NONE, // outCond
1900 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1901 {PC_OPCODE, NULL, NULL, 0, NULL,
1907 NULL, // from branch
1914 1,0, // dest, bit instruction
1915 0,0, // branch, skip
1916 0, // literal operand
1917 1, // RAM access bit
1918 0, // fast call/return mode select bit
1919 0, // second memory operand
1920 0, // second literal operand
1922 (PCC_C | PCC_REGISTER), // inCond
1923 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
1927 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1928 {PC_OPCODE, NULL, NULL, 0, NULL,
1934 NULL, // from branch
1941 0,0, // dest, bit instruction
1942 0,0, // branch, skip
1943 0, // literal operand
1944 1, // RAM access bit
1945 0, // fast call/return mode select bit
1946 0, // second memory operand
1947 0, // second literal operand
1949 (PCC_C | PCC_REGISTER), // inCond
1950 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
1954 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1955 {PC_OPCODE, NULL, NULL, 0, NULL,
1961 NULL, // from branch
1968 1,0, // dest, bit instruction
1969 0,0, // branch, skip
1970 0, // literal operand
1971 1, // RAM access bit
1972 0, // fast call/return mode select bit
1973 0, // second memory operand
1974 0, // second literal operand
1976 PCC_REGISTER, // inCond
1977 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1980 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1981 {PC_OPCODE, NULL, NULL, 0, NULL,
1987 NULL, // from branch
1994 0,0, // dest, bit instruction
1995 0,0, // branch, skip
1996 0, // literal operand
1997 1, // RAM access bit
1998 0, // fast call/return mode select bit
1999 0, // second memory operand
2000 0, // second literal operand
2002 PCC_REGISTER, // inCond
2003 (PCC_W | PCC_Z | PCC_N), // outCond
2006 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2007 {PC_OPCODE, NULL, NULL, 0, NULL,
2013 NULL, // from branch
2020 1,0, // dest, bit instruction
2021 0,0, // branch, skip
2022 0, // literal operand
2023 1, // RAM access bit
2024 0, // fast call/return mode select bit
2025 0, // second memory operand
2026 0, // second literal operand
2028 (PCC_C | PCC_REGISTER), // inCond
2029 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2032 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2033 {PC_OPCODE, NULL, NULL, 0, NULL,
2039 NULL, // from branch
2046 0,0, // dest, bit instruction
2047 0,0, // branch, skip
2048 0, // literal operand
2049 1, // RAM access bit
2050 0, // fast call/return mode select bit
2051 0, // second memory operand
2052 0, // second literal operand
2054 (PCC_C | PCC_REGISTER), // inCond
2055 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2058 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2059 {PC_OPCODE, NULL, NULL, 0, NULL,
2065 NULL, // from branch
2072 1,0, // dest, bit instruction
2073 0,0, // branch, skip
2074 0, // literal operand
2075 1, // RAM access bit
2076 0, // fast call/return mode select bit
2077 0, // second memory operand
2078 0, // second literal operand
2080 PCC_REGISTER, // inCond
2081 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2085 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2086 {PC_OPCODE, NULL, NULL, 0, NULL,
2092 NULL, // from branch
2099 0,0, // dest, bit instruction
2100 0,0, // branch, skip
2101 0, // literal operand
2102 1, // RAM access bit
2103 0, // fast call/return mode select bit
2104 0, // second memory operand
2105 0, // second literal operand
2107 PCC_REGISTER, // inCond
2108 (PCC_W | PCC_Z | PCC_N), // outCond
2112 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2113 {PC_OPCODE, NULL, NULL, 0, NULL,
2119 NULL, // from branch
2126 0,0, // dest, bit instruction
2127 0,0, // branch, skip
2128 0, // literal operand
2129 1, // RAM access bit
2130 0, // fast call/return mode select bit
2131 0, // second memory operand
2132 0, // second literal operand
2134 PCC_REGISTER, // inCond
2135 PCC_REGISTER , // outCond
2139 pCodeInstruction pic16_pciSUBLW = {
2140 {PC_OPCODE, NULL, NULL, 0, NULL,
2146 NULL, // from branch
2153 0,0, // dest, bit instruction
2154 0,0, // branch, skip
2155 1, // literal operand
2156 0, // RAM access bit
2157 0, // fast call/return mode select bit
2158 0, // second memory operand
2159 0, // second literal operand
2161 (PCC_W | PCC_LITERAL), // inCond
2162 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2166 pCodeInstruction pic16_pciSUBFWB = {
2167 {PC_OPCODE, NULL, NULL, 0, NULL,
2173 NULL, // from branch
2180 1,0, // dest, bit instruction
2181 0,0, // branch, skip
2182 0, // literal operand
2183 1, // RAM access bit
2184 0, // fast call/return mode select bit
2185 0, // second memory operand
2186 0, // second literal operand
2188 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2189 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2193 pCodeInstruction pic16_pciSUBWF = {
2194 {PC_OPCODE, NULL, NULL, 0, NULL,
2200 NULL, // from branch
2207 1,0, // dest, bit instruction
2208 0,0, // branch, skip
2209 0, // literal operand
2210 1, // RAM access bit
2211 0, // fast call/return mode select bit
2212 0, // second memory operand
2213 0, // second literal operand
2215 (PCC_W | PCC_REGISTER), // inCond
2216 (PCC_REGISTER | PCC_Z), // outCond
2220 pCodeInstruction pic16_pciSUBFW = {
2221 {PC_OPCODE, NULL, NULL, 0, NULL,
2227 NULL, // from branch
2234 0,0, // dest, bit instruction
2235 0,0, // branch, skip
2236 0, // literal operand
2237 1, // RAM access bit
2238 0, // fast call/return mode select bit
2239 0, // second memory operand
2240 0, // second literal operand
2242 (PCC_W | PCC_REGISTER), // inCond
2243 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2247 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2248 {PC_OPCODE, NULL, NULL, 0, NULL,
2254 NULL, // from branch
2261 1,0, // dest, bit instruction
2262 0,0, // branch, skip
2263 0, // literal operand
2264 1, // RAM access bit
2265 0, // fast call/return mode select bit
2266 0, // second memory operand
2267 0, // second literal operand
2269 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2270 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2274 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2275 {PC_OPCODE, NULL, NULL, 0, NULL,
2281 NULL, // from branch
2288 0,0, // dest, bit instruction
2289 0,0, // branch, skip
2290 0, // literal operand
2291 1, // RAM access bit
2292 0, // fast call/return mode select bit
2293 0, // second memory operand
2294 0, // second literal operand
2296 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2297 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2301 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2302 {PC_OPCODE, NULL, NULL, 0, NULL,
2308 NULL, // from branch
2315 1,0, // dest, bit instruction
2316 0,0, // branch, skip
2317 0, // literal operand
2318 1, // RAM access bit
2319 0, // fast call/return mode select bit
2320 0, // second memory operand
2321 0, // second literal operand
2323 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2324 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2328 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2329 {PC_OPCODE, NULL, NULL, 0, NULL,
2335 NULL, // from branch
2342 0,0, // dest, bit instruction
2343 0,0, // branch, skip
2344 0, // literal operand
2345 1, // RAM access bit
2346 0, // fast call/return mode select bit
2347 0, // second memory operand
2348 0, // second literal operand
2350 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2351 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2355 pCodeInstruction pic16_pciSWAPF = {
2356 {PC_OPCODE, NULL, NULL, 0, NULL,
2362 NULL, // from branch
2369 1,0, // dest, bit instruction
2370 0,0, // branch, skip
2371 0, // literal operand
2372 1, // RAM access bit
2373 0, // fast call/return mode select bit
2374 0, // second memory operand
2375 0, // second literal operand
2377 (PCC_REGISTER), // inCond
2378 (PCC_REGISTER), // outCond
2382 pCodeInstruction pic16_pciSWAPFW = {
2383 {PC_OPCODE, NULL, NULL, 0, NULL,
2389 NULL, // from branch
2396 0,0, // dest, bit instruction
2397 0,0, // branch, skip
2398 0, // literal operand
2399 1, // RAM access bit
2400 0, // fast call/return mode select bit
2401 0, // second memory operand
2402 0, // second literal operand
2404 (PCC_REGISTER), // inCond
2409 pCodeInstruction pic16_pciTBLRD = { // patch 15
2410 {PC_OPCODE, NULL, NULL, 0, NULL,
2415 NULL, // from branch
2422 0,0, // dest, bit instruction
2423 0,0, // branch, skip
2424 0, // literal operand
2425 0, // RAM access bit
2426 0, // fast call/return mode select bit
2427 0, // second memory operand
2428 0, // second literal operand
2431 PCC_NONE , // outCond
2435 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2436 {PC_OPCODE, NULL, NULL, 0, NULL,
2441 NULL, // from branch
2448 0,0, // dest, bit instruction
2449 0,0, // branch, skip
2450 0, // literal operand
2451 0, // RAM access bit
2452 0, // fast call/return mode select bit
2453 0, // second memory operand
2454 0, // second literal operand
2457 PCC_NONE , // outCond
2461 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2462 {PC_OPCODE, NULL, NULL, 0, NULL,
2467 NULL, // from branch
2474 0,0, // dest, bit instruction
2475 0,0, // branch, skip
2476 0, // literal operand
2477 0, // RAM access bit
2478 0, // fast call/return mode select bit
2479 0, // second memory operand
2480 0, // second literal operand
2483 PCC_NONE , // outCond
2487 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2488 {PC_OPCODE, NULL, NULL, 0, NULL,
2493 NULL, // from branch
2500 0,0, // dest, bit instruction
2501 0,0, // branch, skip
2502 0, // literal operand
2503 0, // RAM access bit
2504 0, // fast call/return mode select bit
2505 0, // second memory operand
2506 0, // second literal operand
2509 PCC_NONE , // outCond
2513 pCodeInstruction pic16_pciTBLWT = { // patch 15
2514 {PC_OPCODE, NULL, NULL, 0, NULL,
2519 NULL, // from branch
2526 0,0, // dest, bit instruction
2527 0,0, // branch, skip
2528 0, // literal operand
2529 0, // RAM access bit
2530 0, // fast call/return mode select bit
2531 0, // second memory operand
2532 0, // second literal operand
2535 PCC_NONE , // outCond
2539 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2540 {PC_OPCODE, NULL, NULL, 0, NULL,
2545 NULL, // from branch
2552 0,0, // dest, bit instruction
2553 0,0, // branch, skip
2554 0, // literal operand
2555 0, // RAM access bit
2556 0, // fast call/return mode select bit
2557 0, // second memory operand
2558 0, // second literal operand
2561 PCC_NONE , // outCond
2565 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2566 {PC_OPCODE, NULL, NULL, 0, NULL,
2571 NULL, // from branch
2578 0,0, // dest, bit instruction
2579 0,0, // branch, skip
2580 0, // literal operand
2581 0, // RAM access bit
2582 0, // fast call/return mode select bit
2583 0, // second memory operand
2584 0, // second literal operand
2587 PCC_NONE , // outCond
2591 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2592 {PC_OPCODE, NULL, NULL, 0, NULL,
2597 NULL, // from branch
2604 0,0, // dest, bit instruction
2605 0,0, // branch, skip
2606 0, // literal operand
2607 0, // RAM access bit
2608 0, // fast call/return mode select bit
2609 0, // second memory operand
2610 0, // second literal operand
2613 PCC_NONE , // outCond
2617 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2618 {PC_OPCODE, NULL, NULL, 0, NULL,
2624 NULL, // from branch
2631 0,0, // dest, bit instruction
2632 1,1, // branch, skip
2633 0, // literal operand
2634 1, // RAM access bit
2635 0, // fast call/return mode select bit
2636 0, // second memory operand
2637 0, // second literal operand
2639 PCC_REGISTER, // inCond
2640 PCC_NONE, // outCond
2644 pCodeInstruction pic16_pciXORWF = {
2645 {PC_OPCODE, NULL, NULL, 0, NULL,
2651 NULL, // from branch
2658 1,0, // dest, bit instruction
2659 0,0, // branch, skip
2660 0, // literal operand
2661 1, // RAM access bit
2662 0, // fast call/return mode select bit
2663 0, // second memory operand
2664 0, // second literal operand
2666 (PCC_W | PCC_REGISTER), // inCond
2667 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2671 pCodeInstruction pic16_pciXORFW = {
2672 {PC_OPCODE, NULL, NULL, 0, NULL,
2678 NULL, // from branch
2685 0,0, // dest, bit instruction
2686 0,0, // branch, skip
2687 0, // literal operand
2688 1, // RAM access bit
2689 0, // fast call/return mode select bit
2690 0, // second memory operand
2691 0, // second literal operand
2693 (PCC_W | PCC_REGISTER), // inCond
2694 (PCC_W | PCC_Z | PCC_N), // outCond
2698 pCodeInstruction pic16_pciXORLW = {
2699 {PC_OPCODE, NULL, NULL, 0, NULL,
2705 NULL, // from branch
2712 0,0, // dest, bit instruction
2713 0,0, // branch, skip
2714 1, // literal operand
2715 1, // RAM access bit
2716 0, // fast call/return mode select bit
2717 0, // second memory operand
2718 0, // second literal operand
2720 (PCC_W | PCC_LITERAL), // inCond
2721 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2726 pCodeInstruction pic16_pciBANKSEL = {
2727 {PC_OPCODE, NULL, NULL, 0, NULL,
2732 NULL, // from branch
2739 0,0, // dest, bit instruction
2740 0,0, // branch, skip
2741 0, // literal operand
2742 0, // RAM access bit
2743 0, // fast call/return mode select bit
2744 0, // second memory operand
2745 0, // second literal operand
2748 PCC_NONE, // outCond
2753 #define MAX_PIC16MNEMONICS 100
2754 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2756 //#define USE_VSNPRINTF
2759 #ifdef USE_VSNPRINTF
2760 // Alas, vsnprintf is not ANSI standard, and does not exist
2761 // on Solaris (and probably other non-Gnu flavored Unixes).
2763 /*-----------------------------------------------------------------*/
2764 /* SAFE_snprintf - like snprintf except the string pointer is */
2765 /* after the string has been printed to. This is */
2766 /* useful for printing to string as though if it */
2767 /* were a stream. */
2768 /*-----------------------------------------------------------------*/
2769 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2777 va_start(val, format);
2779 vsnprintf(*str, *size, format, val);
2785 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2786 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2795 // This version is *not* safe, despite the name.
2797 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2801 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2806 va_start(val, format);
2808 vsprintf(buffer, format, val);
2811 len = strlen(buffer);
2813 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2814 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2817 strcpy(*str, buffer);
2823 #endif // USE_VSNPRINTF
2826 extern set *externs;
2827 extern void pic16_initStack(int base_address, int size);
2828 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2829 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2830 extern void pic16_init_pic(char *);
2832 void pic16_pCodeInitRegisters(void)
2834 static int initialized=0;
2841 // pic16_initStack(0xfff, 8);
2842 pic16_init_pic(port->processor);
2844 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2845 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2846 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2847 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2848 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2849 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2850 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2852 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2853 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2854 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2856 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2857 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2858 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2859 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2861 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2862 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2863 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2864 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2865 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2866 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2868 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2869 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
2870 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
2871 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
2872 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
2874 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
2875 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
2876 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
2877 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
2878 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
2880 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
2881 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
2882 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
2883 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
2884 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
2886 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
2887 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
2890 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
2891 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
2892 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
2893 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
2896 pic16_pc_status.rIdx = IDX_STATUS;
2897 pic16_pc_intcon.rIdx = IDX_INTCON;
2898 pic16_pc_pcl.rIdx = IDX_PCL;
2899 pic16_pc_pclath.rIdx = IDX_PCLATH;
2900 pic16_pc_pclatu.rIdx = IDX_PCLATU;
2901 pic16_pc_wreg.rIdx = IDX_WREG;
2902 pic16_pc_bsr.rIdx = IDX_BSR;
2904 pic16_pc_tosl.rIdx = IDX_TOSL;
2905 pic16_pc_tosh.rIdx = IDX_TOSH;
2906 pic16_pc_tosu.rIdx = IDX_TOSU;
2908 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
2909 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
2910 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
2911 pic16_pc_tablat.rIdx = IDX_TABLAT;
2913 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
2914 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
2915 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
2916 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
2917 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
2918 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
2919 pic16_pc_indf0.rIdx = IDX_INDF0;
2920 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
2921 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
2922 pic16_pc_preinc0.rIdx = IDX_PREINC0;
2923 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
2924 pic16_pc_indf1.rIdx = IDX_INDF1;
2925 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
2926 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
2927 pic16_pc_preinc1.rIdx = IDX_PREINC1;
2928 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
2929 pic16_pc_indf2.rIdx = IDX_INDF2;
2930 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
2931 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
2932 pic16_pc_preinc2.rIdx = IDX_PREINC2;
2933 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
2934 pic16_pc_prodl.rIdx = IDX_PRODL;
2935 pic16_pc_prodh.rIdx = IDX_PRODH;
2937 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2938 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
2939 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2941 pic16_pc_kzero.rIdx = IDX_KZ;
2942 pic16_pc_wsave.rIdx = IDX_WSAVE;
2943 pic16_pc_ssave.rIdx = IDX_SSAVE;
2945 pic16_pc_eecon1.rIdx = IDX_EECON1;
2946 pic16_pc_eecon2.rIdx = IDX_EECON2;
2947 pic16_pc_eedata.rIdx = IDX_EEDATA;
2948 pic16_pc_eeadr.rIdx = IDX_EEADR;
2951 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
2952 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
2954 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
2955 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
2957 pic16_pc_gptrreg.r = newReg(REG_SFR, PO_GPR_REGISTER, 0, "__GPTRREG", 1, 0x40, NULL); //PO_GPR_REGISTER, 0x00);
2958 pic16_pc_gptrreg.rIdx = 0;
2960 /* probably should put this in a separate initialization routine */
2961 pb_dead_pcodes = newpBlock();
2966 /*-----------------------------------------------------------------*/
2967 /* mnem2key - convert a pic mnemonic into a hash key */
2968 /* (BTW - this spreads the mnemonics quite well) */
2970 /*-----------------------------------------------------------------*/
2972 int mnem2key(char const *mnem)
2981 key += toupper(*mnem++) +1;
2985 return (key & 0x1f);
2990 void pic16initMnemonics(void)
2995 pCodeInstruction *pci;
2997 if(mnemonics_initialized)
3000 // NULL out the array before making the assignments
3001 // since we check the array contents below this initialization.
3003 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3004 pic16Mnemonics[i] = NULL;
3007 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3008 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3009 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3010 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3011 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3012 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3013 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3014 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3015 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3016 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3017 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3018 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3019 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3020 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3021 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3022 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3023 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3024 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3025 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3026 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3027 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3028 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3029 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3030 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3031 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3032 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3033 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3034 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3035 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3036 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3037 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3038 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3039 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3040 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3041 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3042 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3043 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3044 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3045 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3046 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3047 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3048 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3049 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3050 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3051 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3052 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3053 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3054 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3055 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3056 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3057 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3058 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3059 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3060 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3061 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3062 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3063 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3064 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3065 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3066 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3067 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3068 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3069 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3070 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3071 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3072 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3073 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3074 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3075 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3076 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3077 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3078 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3079 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3080 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3081 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3082 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3083 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3084 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3085 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3086 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3087 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3088 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3089 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3090 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3091 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3092 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3093 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3094 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3095 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3096 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3097 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3098 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3099 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3100 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3102 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3103 if(pic16Mnemonics[i])
3104 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3105 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3108 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3109 pci = hTabNextItem(pic16MnemonicsHash, &key);
3112 mnemonics_initialized = 1;
3115 int pic16_getpCodePeepCommand(char *cmd);
3117 int pic16_getpCode(char *mnem,unsigned dest)
3120 pCodeInstruction *pci;
3121 int key = mnem2key(mnem);
3123 if(!mnemonics_initialized)
3124 pic16initMnemonics();
3126 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3130 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3131 if((pci->num_ops <= 1)
3132 || (pci->isModReg == dest)
3134 || (pci->num_ops <= 2 && pci->isAccess)
3135 || (pci->num_ops <= 2 && pci->isFastCall)
3136 || (pci->num_ops <= 2 && pci->is2MemOp)
3137 || (pci->num_ops <= 2 && pci->is2LitOp) )
3141 pci = hTabNextItemWK (pic16MnemonicsHash);
3148 /*-----------------------------------------------------------------*
3149 * pic16initpCodePeepCommands
3151 *-----------------------------------------------------------------*/
3152 void pic16initpCodePeepCommands(void)
3160 hTabAddItem(&pic16pCodePeepCommandsHash,
3161 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3163 } while (peepCommands[i].cmd);
3165 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3168 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3169 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3174 /*-----------------------------------------------------------------
3177 *-----------------------------------------------------------------*/
3179 int pic16_getpCodePeepCommand(char *cmd)
3183 int key = mnem2key(cmd);
3186 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3189 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3190 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3194 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3201 static char getpBlock_dbName(pBlock *pb)
3207 return pb->cmemmap->dbName;
3211 void pic16_pBlockConvert2ISR(pBlock *pb)
3215 if(pb->cmemmap)pb->cmemmap = NULL;
3219 if(pic16_pcode_verbose)
3220 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3223 void pic16_pBlockConvert2Absolute(pBlock *pb)
3226 if(pb->cmemmap)pb->cmemmap = NULL;
3230 if(pic16_pcode_verbose)
3231 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3234 /*-----------------------------------------------------------------*/
3235 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3236 /* instances to the front of the doubly linked */
3237 /* list of pBlocks */
3238 /*-----------------------------------------------------------------*/
3240 void pic16_movepBlock2Head(char dbName)
3245 /* this can happen in sources without code,
3246 * only variable definitions */
3247 if(!the_pFile)return;
3249 pb = the_pFile->pbHead;
3253 if(getpBlock_dbName(pb) == dbName) {
3254 pBlock *pbn = pb->next;
3255 pb->next = the_pFile->pbHead;
3256 the_pFile->pbHead->prev = pb;
3257 the_pFile->pbHead = pb;
3260 pb->prev->next = pbn;
3262 // If the pBlock that we just moved was the last
3263 // one in the link of all of the pBlocks, then we
3264 // need to point the tail to the block just before
3265 // the one we moved.
3266 // Note: if pb->next is NULL, then pb must have
3267 // been the last pBlock in the chain.
3270 pbn->prev = pb->prev;
3272 the_pFile->pbTail = pb->prev;
3283 void pic16_copypCode(FILE *of, char dbName)
3287 if(!of || !the_pFile)
3290 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3291 if(getpBlock_dbName(pb) == dbName) {
3292 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3294 pic16_printpBlock(of,pb);
3299 void pic16_pcode_test(void)
3302 DFPRINTF((stderr,"pcode is alive!\n"));
3312 /* create the file name */
3313 strcpy(buffer,dstFileName);
3314 strcat(buffer,".p");
3316 if( !(pFile = fopen(buffer, "w" ))) {
3317 werror(E_FILE_OPEN_ERR,buffer);
3321 fprintf(pFile,"pcode dump\n\n");
3323 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3324 fprintf(pFile,"\n\tNew pBlock\n\n");
3326 fprintf(pFile,"%s",pb->cmemmap->sname);
3328 fprintf(pFile,"internal pblock");
3330 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3331 pic16_printpBlock(pFile,pb);
3335 /*-----------------------------------------------------------------*/
3336 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3337 /* ister, RegCond will return the bit being referenced. */
3339 /* fixme - why not just OR in the pcop bit field */
3340 /*-----------------------------------------------------------------*/
3342 static int RegCond(pCodeOp *pcop)
3348 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3349 switch(PCORB(pcop)->bit) {
3363 /*-----------------------------------------------------------------*/
3364 /* pic16_newpCode - create and return a newly initialized pCode */
3366 /* fixme - rename this */
3368 /* The purpose of this routine is to create a new Instruction */
3369 /* pCode. This is called by gen.c while the assembly code is being */
3373 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3374 /* (note that the op is analogous to but not the */
3375 /* same thing as the opcode of the instruction.) */
3376 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3379 /* a pointer to the new malloc'd pCode is returned. */
3383 /*-----------------------------------------------------------------*/
3384 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3386 pCodeInstruction *pci ;
3388 if(!mnemonics_initialized)
3389 pic16initMnemonics();
3391 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3393 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3394 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3397 if(pci->inCond & PCC_EXAMINE_PCOP)
3398 pci->inCond |= RegCond(pcop);
3400 if(pci->outCond & PCC_EXAMINE_PCOP)
3401 pci->outCond |= RegCond(pcop);
3403 pci->pc.prev = pci->pc.next = NULL;
3404 return (pCode *)pci;
3407 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3413 /*-----------------------------------------------------------------*/
3414 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3416 /* Wild pcodes are used during the peep hole optimizer to serve */
3417 /* as place holders for any instruction. When a snippet of code is */
3418 /* compared to a peep hole rule, the wild card opcode will match */
3419 /* any instruction. However, the optional operand and label are */
3420 /* additional qualifiers that must also be matched before the */
3421 /* line (of assembly code) is declared matched. Note that the */
3422 /* operand may be wild too. */
3424 /* Note, a wild instruction is specified just like a wild var: */
3425 /* %4 ; A wild instruction, */
3426 /* See the peeph.def file for additional examples */
3428 /*-----------------------------------------------------------------*/
3430 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3435 pcw = Safe_calloc(1,sizeof(pCodeWild));
3437 pcw->pci.pc.type = PC_WILD;
3438 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3439 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3440 pcw->pci.pc.pb = NULL;
3442 // pcw->pci.pc.analyze = genericAnalyze;
3443 pcw->pci.pc.destruct = genericDestruct;
3444 pcw->pci.pc.print = genericPrint;
3446 pcw->id = pCodeID; // this is the 'n' in %n
3447 pcw->operand = optional_operand;
3448 pcw->label = optional_label;
3450 pcw->mustBeBitSkipInst = 0;
3451 pcw->mustNotBeBitSkipInst = 0;
3452 pcw->invertBitSkipInst = 0;
3454 return ( (pCode *)pcw);
3458 /*-----------------------------------------------------------------*/
3459 /* newPcodeInlineP - create a new pCode from a char string */
3460 /*-----------------------------------------------------------------*/
3463 pCode *pic16_newpCodeInlineP(char *cP)
3468 pcc = Safe_calloc(1,sizeof(pCodeComment));
3470 pcc->pc.type = PC_INLINE;
3471 pcc->pc.prev = pcc->pc.next = NULL;
3472 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3475 // pcc->pc.analyze = genericAnalyze;
3476 pcc->pc.destruct = genericDestruct;
3477 pcc->pc.print = genericPrint;
3480 pcc->comment = Safe_strdup(cP);
3482 pcc->comment = NULL;
3484 return ( (pCode *)pcc);
3488 /*-----------------------------------------------------------------*/
3489 /* newPcodeCharP - create a new pCode from a char string */
3490 /*-----------------------------------------------------------------*/
3492 pCode *pic16_newpCodeCharP(char *cP)
3497 pcc = Safe_calloc(1,sizeof(pCodeComment));
3499 pcc->pc.type = PC_COMMENT;
3500 pcc->pc.prev = pcc->pc.next = NULL;
3501 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3504 // pcc->pc.analyze = genericAnalyze;
3505 pcc->pc.destruct = genericDestruct;
3506 pcc->pc.print = genericPrint;
3509 pcc->comment = Safe_strdup(cP);
3511 pcc->comment = NULL;
3513 return ( (pCode *)pcc);
3517 /*-----------------------------------------------------------------*/
3518 /* pic16_newpCodeFunction - */
3519 /*-----------------------------------------------------------------*/
3522 pCode *pic16_newpCodeFunction(char *mod,char *f)
3526 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3528 pcf->pc.type = PC_FUNCTION;
3529 pcf->pc.prev = pcf->pc.next = NULL;
3530 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3533 // pcf->pc.analyze = genericAnalyze;
3534 pcf->pc.destruct = genericDestruct;
3535 pcf->pc.print = pCodePrintFunction;
3541 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3542 strcpy(pcf->modname,mod);
3544 pcf->modname = NULL;
3547 pcf->fname = Safe_calloc(1,strlen(f)+1);
3548 strcpy(pcf->fname,f);
3552 pcf->stackusage = 0;
3554 return ( (pCode *)pcf);
3557 /*-----------------------------------------------------------------*/
3558 /* pic16_newpCodeFlow */
3559 /*-----------------------------------------------------------------*/
3560 static void destructpCodeFlow(pCode *pc)
3562 if(!pc || !isPCFL(pc))
3569 pic16_unlinkpCode(pc);
3571 deleteSet(&PCFL(pc)->registers);
3572 deleteSet(&PCFL(pc)->from);
3573 deleteSet(&PCFL(pc)->to);
3575 /* Instead of deleting the memory used by this pCode, mark
3576 * the object as bad so that if there's a pointer to this pCode
3577 * dangling around somewhere then (hopefully) when the type is
3578 * checked we'll catch it.
3582 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3588 pCode *pic16_newpCodeFlow(void )
3592 //_ALLOC(pcflow,sizeof(pCodeFlow));
3593 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3595 pcflow->pc.type = PC_FLOW;
3596 pcflow->pc.prev = pcflow->pc.next = NULL;
3597 pcflow->pc.pb = NULL;
3599 // pcflow->pc.analyze = genericAnalyze;
3600 pcflow->pc.destruct = destructpCodeFlow;
3601 pcflow->pc.print = genericPrint;
3603 pcflow->pc.seq = GpcFlowSeq++;
3605 pcflow->from = pcflow->to = NULL;
3607 pcflow->inCond = PCC_NONE;
3608 pcflow->outCond = PCC_NONE;
3610 pcflow->firstBank = -1;
3611 pcflow->lastBank = -1;
3613 pcflow->FromConflicts = 0;
3614 pcflow->ToConflicts = 0;
3618 pcflow->registers = newSet();
3620 return ( (pCode *)pcflow);
3624 /*-----------------------------------------------------------------*/
3625 /*-----------------------------------------------------------------*/
3626 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3628 pCodeFlowLink *pcflowLink;
3630 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3632 pcflowLink->pcflow = pcflow;
3633 pcflowLink->bank_conflict = 0;
3638 /*-----------------------------------------------------------------*/
3639 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3640 /*-----------------------------------------------------------------*/
3642 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3647 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3649 pccs->pc.type = PC_CSOURCE;
3650 pccs->pc.prev = pccs->pc.next = NULL;
3653 pccs->pc.destruct = genericDestruct;
3654 pccs->pc.print = genericPrint;
3656 pccs->line_number = ln;
3658 pccs->line = Safe_strdup(l);
3663 pccs->file_name = Safe_strdup(f);
3665 pccs->file_name = NULL;
3667 return ( (pCode *)pccs);
3672 /*******************************************************************/
3673 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3674 /* added by VR 6-Jun-2003 */
3675 /*******************************************************************/
3677 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3684 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3685 pcad->pci.pc.type = PC_ASMDIR;
3686 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3687 pcad->pci.pc.pb = NULL;
3689 pcad->pci.pc.destruct = genericDestruct;
3690 pcad->pci.pc.print = genericPrint;
3692 if(asdir && *asdir) {
3694 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3696 pcad->directive = Safe_strdup( asdir );
3699 va_start(ap, argfmt);
3701 memset(buffer, 0, sizeof(buffer));
3702 if(argfmt && *argfmt)
3703 vsprintf(buffer, argfmt, ap);
3707 while(isspace(*lbp))lbp++;
3710 pcad->arg = Safe_strdup( lbp );
3712 return ((pCode *)pcad);
3715 /*-----------------------------------------------------------------*/
3716 /* pCodeLabelDestruct - free memory used by a label. */
3717 /*-----------------------------------------------------------------*/
3718 static void pCodeLabelDestruct(pCode *pc)
3724 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3725 // free(PCL(pc)->label);
3727 /* Instead of deleting the memory used by this pCode, mark
3728 * the object as bad so that if there's a pointer to this pCode
3729 * dangling around somewhere then (hopefully) when the type is
3730 * checked we'll catch it.
3734 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3740 pCode *pic16_newpCodeLabel(char *name, int key)
3746 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3748 pcl->pc.type = PC_LABEL;
3749 pcl->pc.prev = pcl->pc.next = NULL;
3750 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3753 // pcl->pc.analyze = genericAnalyze;
3754 pcl->pc.destruct = pCodeLabelDestruct;
3755 pcl->pc.print = pCodePrintLabel;
3762 sprintf(s,"_%05d_DS_",key);
3767 pcl->label = Safe_strdup(s);
3769 // if(pic16_pcode_verbose)
3770 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3773 return ( (pCode *)pcl);
3777 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3779 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3783 return ( (pCode *)pcl );
3787 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3794 /*-----------------------------------------------------------------*/
3795 /* newpBlock - create and return a pointer to a new pBlock */
3796 /*-----------------------------------------------------------------*/
3797 static pBlock *newpBlock(void)
3802 PpB = Safe_calloc(1,sizeof(pBlock) );
3803 PpB->next = PpB->prev = NULL;
3805 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3806 PpB->tregisters = NULL;
3808 PpB->FlowTree = NULL;
3814 /*-----------------------------------------------------------------*/
3815 /* pic16_newpCodeChain - create a new chain of pCodes */
3816 /*-----------------------------------------------------------------*
3818 * This function will create a new pBlock and the pointer to the
3819 * pCode that is passed in will be the first pCode in the block.
3820 *-----------------------------------------------------------------*/
3823 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3826 pBlock *pB = newpBlock();
3828 pB->pcHead = pB->pcTail = pc;
3837 /*-----------------------------------------------------------------*/
3838 /* pic16_newpCodeOpLabel - Create a new label given the key */
3839 /* Note, a negative key means that the label is part of wild card */
3840 /* (and hence a wild card label) used in the pCodePeep */
3841 /* optimizations). */
3842 /*-----------------------------------------------------------------*/
3844 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3847 static int label_key=-1;
3851 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3852 pcop->type = PO_LABEL;
3857 sprintf(s=buffer,"_%05d_DS_",key);
3859 s = name, key = label_key--;
3862 pcop->name = Safe_strdup(s);
3864 ((pCodeOpLabel *)pcop)->key = key;
3866 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3870 /*-----------------------------------------------------------------*/
3871 /*-----------------------------------------------------------------*/
3872 pCodeOp *pic16_newpCodeOpLit(int lit)
3878 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3879 pcop->type = PO_LITERAL;
3883 sprintf(s,"0x%02hhx",(char)(lit));
3885 // sprintf(s, "%i", lit);
3888 pcop->name = Safe_strdup(s);
3890 ((pCodeOpLit *)pcop)->lit = lit;
3895 /*-----------------------------------------------------------------*/
3896 /*-----------------------------------------------------------------*/
3897 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
3899 char *s = buffer, tbuf[256], *tb=tbuf;
3903 tb = pic16_get_op(arg2, NULL, 0);
3904 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
3905 pcop->type = PO_LITERAL;
3909 sprintf(s,"0x%02x, %s",lit, tb);
3911 pcop->name = Safe_strdup(s);
3914 ((pCodeOpLit2 *)pcop)->lit = lit;
3915 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
3920 /*-----------------------------------------------------------------*/
3921 /*-----------------------------------------------------------------*/
3922 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3926 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3927 pcop->type = PO_IMMEDIATE;
3929 regs *r = pic16_dirregWithName(name);
3930 pcop->name = Safe_strdup(name);
3934 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
3935 PCOI(pcop)->rIdx = r->rIdx;
3937 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
3938 PCOI(pcop)->rIdx = -1;
3940 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3945 PCOI(pcop)->index = index;
3946 PCOI(pcop)->offset = offset;
3947 PCOI(pcop)->_const = code_space;
3952 /*-----------------------------------------------------------------*/
3953 /*-----------------------------------------------------------------*/
3954 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3960 if(!pcwb || !subtype) {
3961 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3965 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3966 pcop->type = PO_WILD;
3967 sprintf(s,"%%%d",id);
3968 pcop->name = Safe_strdup(s);
3970 PCOW(pcop)->id = id;
3971 PCOW(pcop)->pcwb = pcwb;
3972 PCOW(pcop)->subtype = subtype;
3973 PCOW(pcop)->matched = NULL;
3975 PCOW(pcop)->pcop2 = NULL;
3980 /*-----------------------------------------------------------------*/
3981 /*-----------------------------------------------------------------*/
3982 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
3988 if(!pcwb || !subtype || !subtype2) {
3989 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3993 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3994 pcop->type = PO_WILD;
3995 sprintf(s,"%%%d",id);
3996 pcop->name = Safe_strdup(s);
3998 PCOW(pcop)->id = id;
3999 PCOW(pcop)->pcwb = pcwb;
4000 PCOW(pcop)->subtype = subtype;
4001 PCOW(pcop)->matched = NULL;
4003 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4005 if(!subtype2->name) {
4006 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4007 PCOW2(pcop)->pcop.type = PO_WILD;
4008 sprintf(s, "%%%d", id2);
4009 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4010 PCOW2(pcop)->id = id2;
4011 PCOW2(pcop)->subtype = subtype2;
4013 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4014 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4016 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4018 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4019 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4028 /*-----------------------------------------------------------------*/
4029 /*-----------------------------------------------------------------*/
4030 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4034 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4035 pcop->type = PO_GPR_BIT;
4037 pcop->name = Safe_strdup(s);
4041 PCORB(pcop)->bit = bit;
4042 PCORB(pcop)->inBitSpace = inBitSpace;
4043 PCORB(pcop)->subtype = subt;
4045 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4046 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4047 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4048 // PCOR(pcop)->rIdx = 0;
4053 /*-----------------------------------------------------------------*
4054 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4056 * If rIdx >=0 then a specific register from the set of registers
4057 * will be selected. If rIdx <0, then a new register will be searched
4059 *-----------------------------------------------------------------*/
4061 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4065 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4070 PCOR(pcop)->rIdx = rIdx;
4071 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4073 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4076 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4078 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4079 __FUNCTION__, __LINE__);
4084 pcop->type = PCOR(pcop)->r->pc_type;
4089 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4094 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4095 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4096 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4097 pcop->type = PCOR(pcop)->r->pc_type;
4098 pcop->name = PCOR(pcop)->r->name;
4100 // if(pic16_pcode_verbose) {
4101 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4102 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4108 /*-----------------------------------------------------------------*/
4109 /*-----------------------------------------------------------------*/
4110 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4114 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4117 pcop->key = Safe_strdup( key );
4119 return (PCOP(pcop));
4123 /*-----------------------------------------------------------------*/
4124 /*-----------------------------------------------------------------*/
4126 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4133 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4137 pcop = pic16_newpCodeOpLit(-1);
4141 pcop = pic16_newpCodeOpLabel(NULL,-1);
4144 pcop = pic16_newpCodeOpReg(-1);
4147 case PO_GPR_REGISTER:
4149 pcop = pic16_newpCodeOpRegFromStr(name);
4151 pcop = pic16_newpCodeOpReg(-1);
4155 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4158 pcop->name = Safe_strdup(name);
4166 #define DB_ITEMS_PER_LINE 8
4168 typedef struct DBdata
4175 static int DBd_init = -1;
4177 /*-----------------------------------------------------------------*/
4178 /* Initialiase "DB" data buffer */
4179 /*-----------------------------------------------------------------*/
4180 void pic16_initDB(void)
4186 /*-----------------------------------------------------------------*/
4187 /* Flush pending "DB" data to a pBlock */
4189 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4190 /*-----------------------------------------------------------------*/
4191 void pic16_flushDB(char ptype, void *p)
4195 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4198 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4201 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4205 DBd.buffer[0] = '\0';
4210 /*-----------------------------------------------------------------*/
4211 /* Add "DB" directives to a pBlock */
4212 /*-----------------------------------------------------------------*/
4213 void pic16_emitDB(char c, char ptype, void *p)
4218 // we need to initialize
4221 DBd.buffer[0] = '\0';
4224 l = strlen(DBd.buffer);
4225 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4227 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4230 if (DBd.count>= DB_ITEMS_PER_LINE)
4231 pic16_flushDB(ptype, p);
4234 void pic16_emitDS(char *s, char ptype, void *p)
4239 // we need to initialize
4242 DBd.buffer[0] = '\0';
4245 l = strlen(DBd.buffer);
4246 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4248 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4250 DBd.count++; //=strlen(s);
4252 pic16_flushDB(ptype, p);
4256 /*-----------------------------------------------------------------*/
4257 /*-----------------------------------------------------------------*/
4258 void pic16_pCodeConstString(char *name, char *value)
4262 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4267 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4269 pic16_addpBlock(pb);
4271 sprintf(buffer,"; %s = %s",name,value);
4273 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4274 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4277 pic16_emitDB(*value, 'p', (void *)pb);
4279 pic16_flushDB('p', (void *)pb);
4282 /*-----------------------------------------------------------------*/
4283 /*-----------------------------------------------------------------*/
4285 static void pCodeReadCodeTable(void)
4289 fprintf(stderr, " %s\n",__FUNCTION__);
4291 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4293 pic16_addpBlock(pb);
4295 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4296 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4297 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4298 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4300 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4301 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4302 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4303 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4308 /*-----------------------------------------------------------------*/
4309 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4310 /*-----------------------------------------------------------------*/
4311 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4318 /* If this is the first pcode to be added to a block that
4319 * was initialized with a NULL pcode, then go ahead and
4320 * make this pcode the head and tail */
4321 pb->pcHead = pb->pcTail = pc;
4324 pb->pcTail->next = pc;
4326 pc->prev = pb->pcTail;
4333 /*-----------------------------------------------------------------*/
4334 /* pic16_addpBlock - place a pBlock into the pFile */
4335 /*-----------------------------------------------------------------*/
4336 void pic16_addpBlock(pBlock *pb)
4338 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4341 /* First time called, we'll pass through here. */
4342 //_ALLOC(the_pFile,sizeof(pFile));
4343 the_pFile = Safe_calloc(1,sizeof(pFile));
4344 the_pFile->pbHead = the_pFile->pbTail = pb;
4345 the_pFile->functions = NULL;
4349 the_pFile->pbTail->next = pb;
4350 pb->prev = the_pFile->pbTail;
4352 the_pFile->pbTail = pb;
4355 /*-----------------------------------------------------------------*/
4356 /* removepBlock - remove a pBlock from the pFile */
4357 /*-----------------------------------------------------------------*/
4358 static void removepBlock(pBlock *pb)
4366 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4368 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4371 if(pbs == the_pFile->pbHead)
4372 the_pFile->pbHead = pbs->next;
4374 if (pbs == the_pFile->pbTail)
4375 the_pFile->pbTail = pbs->prev;
4378 pbs->next->prev = pbs->prev;
4381 pbs->prev->next = pbs->next;
4388 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4392 /*-----------------------------------------------------------------*/
4393 /* printpCode - write the contents of a pCode to a file */
4394 /*-----------------------------------------------------------------*/
4395 static void printpCode(FILE *of, pCode *pc)
4406 fprintf(of,"warning - unable to print pCode\n");
4409 /*-----------------------------------------------------------------*/
4410 /* pic16_printpBlock - write the contents of a pBlock to a file */
4411 /*-----------------------------------------------------------------*/
4412 void pic16_printpBlock(FILE *of, pBlock *pb)
4420 for(pc = pb->pcHead; pc; pc = pc->next) {
4421 if(isPCF(pc) && PCF(pc)->fname) {
4422 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4423 if(pb->dbName == 'A') {
4425 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4426 if(!strcmp(ab->name, PCF(pc)->fname)) {
4427 fprintf(of, "\t0X%06X", ab->address);
4438 /*-----------------------------------------------------------------*/
4440 /* pCode processing */
4444 /*-----------------------------------------------------------------*/
4446 void pic16_unlinkpCode(pCode *pc)
4452 fprintf(stderr,"Unlinking: ");
4453 printpCode(stderr, pc);
4456 pc->prev->next = pc->next;
4458 pc->next->prev = pc->prev;
4460 pc->prev = pc->next = NULL;
4464 /*-----------------------------------------------------------------*/
4465 /*-----------------------------------------------------------------*/
4467 static void genericDestruct(pCode *pc)
4470 pic16_unlinkpCode(pc);
4473 /* For instructions, tell the register (if there's one used)
4474 * that it's no longer needed */
4475 regs *reg = pic16_getRegFromInstruction(pc);
4477 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4479 if(PCI(pc)->is2MemOp) {
4480 reg = pic16_getRegFromInstruction2(pc);
4482 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4486 /* Instead of deleting the memory used by this pCode, mark
4487 * the object as bad so that if there's a pointer to this pCode
4488 * dangling around somewhere then (hopefully) when the type is
4489 * checked we'll catch it.
4493 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4499 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4500 /*-----------------------------------------------------------------*/
4501 /*-----------------------------------------------------------------*/
4502 /* modifiers for constant immediate */
4503 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4505 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4510 int use_buffer = 1; // copy the string to the passed buffer pointer
4515 use_buffer = 0; // Don't bother copying the string to the buffer.
4519 switch(pcop->type) {
4527 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4530 return PCOR(pcop)->r->name;
4533 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4535 SAFE_snprintf(&buffer,&size,"%s",r->name);
4542 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4543 if(PCOI(pcop)->index) {
4544 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4545 immdmod[ PCOI(pcop)->offset ],
4549 SAFE_snprintf(&s,&size,"%s(%s)",
4550 immdmod[ PCOI(pcop)->offset ],
4554 if(PCOI(pcop)->index) {
4555 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4560 SAFE_snprintf(&s,&size, "%s(%s)",
4567 case PO_GPR_REGISTER:
4570 // size = sizeof(buffer);
4571 if( PCOR(pcop)->instance) {
4572 SAFE_snprintf(&s,&size,"(%s + %d)",
4574 PCOR(pcop)->instance );
4576 SAFE_snprintf(&s,&size,"%s",pcop->name);
4583 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4592 return "NO operand1";
4595 /*-----------------------------------------------------------------*/
4596 /* pic16_get_op2 - variant to support two memory operand commands */
4597 /*-----------------------------------------------------------------*/
4598 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4603 int use_buffer = 1; // copy the string to the passed buffer pointer
4608 use_buffer = 0; // Don't bother copying the string to the buffer.
4612 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",
4613 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4614 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4618 switch(PCOR2(pcop)->pcop2->type) {
4626 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4629 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4632 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4635 SAFE_snprintf(&buffer,&size,"%s",r->name);
4646 if(PCOI(pcop)->_const) {
4647 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4648 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4651 8 * PCOI(pcop)->offset );
4653 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4655 if( PCOI(pcop)->index) {
4656 SAFE_snprintf(&s,&size,"(%s + %d)",
4658 PCOI(pcop)->index );
4660 if(PCOI(pcop)->offset)
4661 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4663 SAFE_snprintf(&s,&size,"%s",pcop->name);
4670 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4671 SAFE_snprintf(&s,&size,"(%s + %d)",
4672 PCOR(PCOR2(pcop)->pcop2)->r->name,
4673 PCOR(PCOR2(pcop)->pcop2)->instance );
4675 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4680 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4682 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4685 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4690 return "NO operand2";
4693 /*-----------------------------------------------------------------*/
4694 /*-----------------------------------------------------------------*/
4695 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4699 return pic16_get_op(pcc->pcop,NULL,0);
4701 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4702 * return ("ERROR Null: "__FUNCTION__);
4704 return ("ERROR Null: pic16_get_op_from_instruction");
4708 /*-----------------------------------------------------------------*/
4709 /*-----------------------------------------------------------------*/
4710 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4713 fprintf(of,"pcodeopprint- not implemented\n");
4716 /*-----------------------------------------------------------------*/
4717 /* pic16_pCode2str - convert a pCode instruction to string */
4718 /*-----------------------------------------------------------------*/
4719 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4725 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4726 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4727 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4735 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4737 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4739 if(PCI(pc)->is2MemOp) {
4740 SAFE_snprintf(&s,&size, "%s, %s",
4741 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4742 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4746 if(PCI(pc)->is2LitOp) {
4747 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4751 if(PCI(pc)->isBitInst) {
4752 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4753 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4754 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4755 PCI(pc)->pcop->name ,
4756 PCI(pc)->pcop->name );
4758 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4759 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4760 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4761 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4763 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4764 //PCI(pc)->pcop->t.bit );
4767 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4768 if( PCI(pc)->num_ops == 3)
4769 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4771 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4774 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4776 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4777 if(PCI(pc)->num_ops == 3)
4778 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4780 r = pic16_getRegFromInstruction(pc);
4781 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4782 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4784 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4793 /* assuming that comment ends with a \n */
4794 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4798 /* assuming that inline code ends with a \n */
4799 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4803 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4806 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4809 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4812 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4815 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4816 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4817 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4820 if(PCAD(pc)->directive) {
4821 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4824 /* special case to handle inline labels without a tab */
4825 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4830 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4834 SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4842 /*-----------------------------------------------------------------*/
4843 /* genericPrint - the contents of a pCode to a file */
4844 /*-----------------------------------------------------------------*/
4845 static void genericPrint(FILE *of, pCode *pc)
4853 fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4857 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4861 // If the opcode has a label, print that first
4863 pBranch *pbl = PCI(pc)->label;
4864 while(pbl && pbl->pc) {
4865 if(pbl->pc->type == PC_LABEL)
4866 pCodePrintLabel(of, pbl->pc);
4872 genericPrint(of,PCODE(PCI(pc)->cline));
4877 pic16_pCode2str(str, 256, pc);
4879 fprintf(of,"%s",str);
4881 if(pic16_debug_verbose) {
4882 fprintf(of, "\t;key=%03x",pc->seq);
4884 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4891 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4892 if(PCW(pc)->pci.label)
4893 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4895 if(PCW(pc)->operand) {
4896 fprintf(of,";\toperand ");
4897 pCodeOpPrint(of,PCW(pc)->operand );
4902 if(pic16_debug_verbose) {
4903 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4904 if(PCFL(pc)->ancestor)
4905 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4912 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4913 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4914 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4920 pBranch *pbl = PCAD(pc)->pci.label;
4921 while(pbl && pbl->pc) {
4922 if(pbl->pc->type == PC_LABEL)
4923 pCodePrintLabel(of, pbl->pc);
4927 if(PCAD(pc)->directive) {
4928 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4931 /* special case to handle inline labels without tab */
4932 fprintf(of, "%s\n", PCAD(pc)->arg);
4938 fprintf(of,"unknown pCode type %d\n",pc->type);
4943 /*-----------------------------------------------------------------*/
4944 /* pCodePrintFunction - prints function begin/end */
4945 /*-----------------------------------------------------------------*/
4947 static void pCodePrintFunction(FILE *of, pCode *pc)
4954 if( ((pCodeFunction *)pc)->modname)
4955 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4958 if(!PCF(pc)->absblock) {
4959 if(PCF(pc)->fname) {
4960 pBranch *exits = PCF(pc)->to;
4963 fprintf(of,"%s:", PCF(pc)->fname);
4965 if(pic16_pcode_verbose)
4966 fprintf(of, "\t;Function start");
4972 exits = exits->next;
4976 if(pic16_pcode_verbose)
4977 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4980 if((PCF(pc)->from &&
4981 PCF(pc)->from->pc->type == PC_FUNCTION &&
4982 PCF(PCF(pc)->from->pc)->fname) ) {
4984 if(pic16_pcode_verbose)
4985 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4987 if(pic16_pcode_verbose)
4988 fprintf(of,"; exit point [can't find entry point]\n");
4994 /*-----------------------------------------------------------------*/
4995 /* pCodePrintLabel - prints label */
4996 /*-----------------------------------------------------------------*/
4998 static void pCodePrintLabel(FILE *of, pCode *pc)
5005 fprintf(of,"%s:\n",PCL(pc)->label);
5006 else if (PCL(pc)->key >=0)
5007 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5009 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5012 /*-----------------------------------------------------------------*/
5013 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5014 /* remove it if it is found. */
5015 /*-----------------------------------------------------------------*/
5016 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5023 if(pcl->type == PC_OPCODE)
5024 b = PCI(pcl)->label;
5026 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5031 //fprintf (stderr, "%s \n",__FUNCTION__);
5032 //pcl->print(stderr,pcl);
5033 //pc->print(stderr,pc);
5036 //fprintf (stderr, "found label\n");
5037 //pc->print(stderr, pc);
5041 bprev->next = b->next; /* Not first pCode in chain */
5045 PCI(pcl)->label = b->next; /* First pCode in chain */
5048 return; /* A label can't occur more than once */
5056 /*-----------------------------------------------------------------*/
5057 /*-----------------------------------------------------------------*/
5058 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5077 /*-----------------------------------------------------------------*/
5078 /* pBranchLink - given two pcodes, this function will link them */
5079 /* together through their pBranches */
5080 /*-----------------------------------------------------------------*/
5081 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5085 // Declare a new branch object for the 'from' pCode.
5087 //_ALLOC(b,sizeof(pBranch));
5088 b = Safe_calloc(1,sizeof(pBranch));
5089 b->pc = PCODE(t); // The link to the 'to' pCode.
5092 f->to = pic16_pBranchAppend(f->to,b);
5094 // Now do the same for the 'to' pCode.
5096 //_ALLOC(b,sizeof(pBranch));
5097 b = Safe_calloc(1,sizeof(pBranch));
5101 t->from = pic16_pBranchAppend(t->from,b);
5106 /*-----------------------------------------------------------------*/
5107 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5109 /*-----------------------------------------------------------------*/
5110 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5123 /*-----------------------------------------------------------------*/
5124 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5125 /*-----------------------------------------------------------------*/
5126 void pic16_pCodeUnlink(pCode *pc)
5131 if(!pc->prev || !pc->next) {
5132 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5136 /* first remove the pCode from the chain */
5137 pc->prev->next = pc->next;
5138 pc->next->prev = pc->prev;
5140 /* Now for the hard part... */
5142 /* Remove the branches */
5144 pb1 = PCI(pc)->from;
5146 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5147 * one we're unlinking */
5149 /* search for the link back to this pCode (the one we're
5151 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5152 pb2->pc = PCI(pc)->to->pc; // make the replacement
5154 /* if the pCode we're unlinking contains multiple 'to'
5155 * branches (e.g. this a skip instruction) then we need
5156 * to copy these extra branches to the chain. */
5157 if(PCI(pc)->to->next)
5158 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5167 /*-----------------------------------------------------------------*/
5168 /*-----------------------------------------------------------------*/
5170 static void genericAnalyze(pCode *pc)
5180 // Go through the pCodes that are in pCode chain and link
5181 // them together through the pBranches. Note, the pCodes
5182 // are linked together as a contiguous stream like the
5183 // assembly source code lines. The linking here mimics this
5184 // except that comments are not linked in.
5186 pCode *npc = pc->next;
5188 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5189 pBranchLink(pc,npc);
5194 /* reached the end of the pcode chain without finding
5195 * an instruction we could link to. */
5199 fprintf(stderr,"analyze PC_FLOW\n");
5203 fprintf(stderr,,";A bad pCode is being used\n");
5209 /*-----------------------------------------------------------------*/
5210 /*-----------------------------------------------------------------*/
5211 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5215 if(pc->type == PC_LABEL) {
5216 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5219 if((pc->type == PC_OPCODE)
5220 || (pc->type == PC_ASMDIR)
5222 pbr = PCI(pc)->label;
5224 if(pbr->pc->type == PC_LABEL) {
5225 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5235 /*-----------------------------------------------------------------*/
5236 /*-----------------------------------------------------------------*/
5237 static int checkLabel(pCode *pc)
5241 if(pc && isPCI(pc)) {
5242 pbr = PCI(pc)->label;
5244 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5254 /*-----------------------------------------------------------------*/
5255 /* findLabelinpBlock - Search the pCode for a particular label */
5256 /*-----------------------------------------------------------------*/
5257 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5264 for(pc = pb->pcHead; pc; pc = pc->next)
5265 if(compareLabel(pc,pcop_label))
5271 /*-----------------------------------------------------------------*/
5272 /* findLabel - Search the pCode for a particular label */
5273 /*-----------------------------------------------------------------*/
5274 static pCode * findLabel(pCodeOpLabel *pcop_label)
5282 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5283 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5287 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5291 /*-----------------------------------------------------------------*/
5292 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5293 /* in the linked list */
5294 /*-----------------------------------------------------------------*/
5295 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5308 /*-----------------------------------------------------------------*/
5309 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5310 /* in the linked list */
5311 /*-----------------------------------------------------------------*/
5312 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5326 //#define PCODE_DEBUG
5327 /*-----------------------------------------------------------------*/
5328 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5329 /* in the linked list */
5330 /*-----------------------------------------------------------------*/
5331 pCode * pic16_findNextInstruction(pCode *pci)
5336 if((pc->type == PC_OPCODE)
5337 || (pc->type == PC_WILD)
5338 || (pc->type == PC_ASMDIR)
5343 fprintf(stderr,"pic16_findNextInstruction: ");
5344 printpCode(stderr, pc);
5349 //fprintf(stderr,"Couldn't find instruction\n");
5353 /*-----------------------------------------------------------------*/
5354 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5355 /* in the linked list */
5356 /*-----------------------------------------------------------------*/
5357 pCode * pic16_findPrevInstruction(pCode *pci)
5363 if((pc->type == PC_OPCODE)
5364 || (pc->type == PC_WILD)
5365 || (pc->type == PC_ASMDIR)
5371 fprintf(stderr,"pic16_findPrevInstruction: ");
5372 printpCode(stderr, pc);
5377 //fprintf(stderr,"Couldn't find instruction\n");
5384 /*-----------------------------------------------------------------*/
5385 /* findFunctionEnd - given a pCode find the end of the function */
5386 /* that contains it */
5387 /*-----------------------------------------------------------------*/
5388 static pCode * findFunctionEnd(pCode *pc)
5392 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5398 fprintf(stderr,"Couldn't find function end\n");
5403 /*-----------------------------------------------------------------*/
5404 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5405 /* instruction with which it is associated. */
5406 /*-----------------------------------------------------------------*/
5407 static void AnalyzeLabel(pCode *pc)
5410 pic16_pCodeUnlink(pc);
5416 static void AnalyzeGOTO(pCode *pc)
5419 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5423 static void AnalyzeSKIP(pCode *pc)
5426 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5427 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5431 static void AnalyzeRETURN(pCode *pc)
5434 // branch_link(pc,findFunctionEnd(pc->next));
5440 /*-----------------------------------------------------------------*/
5441 /*-----------------------------------------------------------------*/
5442 regs * pic16_getRegFromInstruction(pCode *pc)
5448 PCI(pc)->num_ops == 0 ||
5449 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5453 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5454 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5457 switch(PCI(pc)->pcop->type) {
5463 return PCOR(PCI(pc)->pcop)->r;
5467 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5468 return PCOR(PCI(pc)->pcop)->r;
5471 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5473 if(PCOI(PCI(pc)->pcop)->r)
5474 return (PCOI(PCI(pc)->pcop)->r);
5479 return PCOR(PCI(pc)->pcop)->r;
5481 case PO_GPR_REGISTER:
5483 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5484 return PCOR(PCI(pc)->pcop)->r;
5487 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5491 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5492 // genericPrint(stderr, pc);
5500 /*-------------------------------------------------------------------------------*/
5501 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5502 /*-------------------------------------------------------------------------------*/
5503 regs * pic16_getRegFromInstruction2(pCode *pc)
5509 PCI(pc)->num_ops == 0 ||
5510 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5515 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5516 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5520 * operands supported in MOVFF:
5527 switch(PCI(pc)->pcop->type) {
5533 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5535 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5539 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5540 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5544 // if(PCOI(PCI(pc)->pcop)->r)
5545 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5547 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5548 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5551 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5552 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5559 // return PCOR2(PCI(pc)->pcop)->r;
5561 case PO_GPR_REGISTER:
5563 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5564 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5568 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5571 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5572 //genericPrint(stderr, pc);
5580 /*-----------------------------------------------------------------*/
5581 /*-----------------------------------------------------------------*/
5583 static void AnalyzepBlock(pBlock *pb)
5590 /* Find all of the registers used in this pBlock
5591 * by looking at each instruction and examining it's
5594 for(pc = pb->pcHead; pc; pc = pc->next) {
5596 /* Is this an instruction with operands? */
5597 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5599 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5601 /* Loop through all of the registers declared so far in
5602 this block and see if we find this one there */
5604 regs *r = setFirstItem(pb->tregisters);
5607 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5608 PCOR(PCI(pc)->pcop)->r = r;
5611 r = setNextItem(pb->tregisters);
5615 /* register wasn't found */
5616 //r = Safe_calloc(1, sizeof(regs));
5617 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5618 //addSet(&pb->tregisters, r);
5619 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5620 //PCOR(PCI(pc)->pcop)->r = r;
5621 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5623 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5626 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5627 if(PCOR(PCI(pc)->pcop)->r) {
5628 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5629 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5631 if(PCI(pc)->pcop->name)
5632 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5634 fprintf(stderr,"ERROR: NULL register\n");
5643 /*-----------------------------------------------------------------*/
5645 /*-----------------------------------------------------------------*/
5646 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5648 static void InsertpFlow(pCode *pc, pCode **pflow)
5651 PCFL(*pflow)->end = pc;
5653 if(!pc || !pc->next)
5656 *pflow = pic16_newpCodeFlow();
5657 pic16_pCodeInsertAfter(pc, *pflow);
5660 /*-----------------------------------------------------------------*/
5661 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5662 /* the flow blocks. */
5664 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5665 * point the instruction flow changes.
5667 /*-----------------------------------------------------------------*/
5668 void pic16_BuildFlow(pBlock *pb)
5671 pCode *last_pci=NULL;
5678 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5679 /* Insert a pCodeFlow object at the beginning of a pBlock */
5681 InsertpFlow(pb->pcHead, &pflow);
5683 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5684 //pflow->next = pb->pcHead; /* Make the current head the next object */
5685 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5686 //pb->pcHead = pflow; /* Make the Flow object the head */
5689 for( pc = pic16_findNextInstruction(pb->pcHead);
5691 pc=pic16_findNextInstruction(pc)) {
5694 PCI(pc)->pcflow = PCFL(pflow);
5696 //fprintf(stderr," build: ");
5697 //pflow->print(stderr,pflow);
5699 if( PCI(pc)->isSkip) {
5701 /* The two instructions immediately following this one
5702 * mark the beginning of a new flow segment */
5704 while(pc && PCI(pc)->isSkip) {
5706 PCI(pc)->pcflow = PCFL(pflow);
5710 InsertpFlow(pc, &pflow);
5711 pc=pic16_findNextInstruction(pc->next);
5719 PCI(pc)->pcflow = PCFL(pflow);
5721 InsertpFlow(pc, &pflow);
5723 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5725 InsertpFlow(pc, &pflow);
5728 } else if (checkLabel(pc)) {
5730 /* This instruction marks the beginning of a
5731 * new flow segment */
5736 /* If the previous pCode is not a flow object, then
5737 * insert a new flow object. (This check prevents
5738 * two consecutive flow objects from being insert in
5739 * the case where a skip instruction preceeds an
5740 * instruction containing a label.) */
5742 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5743 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5745 PCI(pc)->pcflow = PCFL(pflow);
5752 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5754 PCFL(pflow)->end = pb->pcTail;
5757 /*-------------------------------------------------------------------*/
5758 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5759 /* the flow blocks. */
5761 * unBuildFlow removes pCodeFlow objects from a pCode chain
5763 /*-----------------------------------------------------------------*/
5764 static void unBuildFlow(pBlock *pb)
5779 if(PCI(pc)->pcflow) {
5780 //free(PCI(pc)->pcflow);
5781 PCI(pc)->pcflow = NULL;
5784 } else if(isPCFL(pc) )
5793 /*-----------------------------------------------------------------*/
5794 /*-----------------------------------------------------------------*/
5795 static void dumpCond(int cond)
5798 static char *pcc_str[] = {
5812 int ncond = sizeof(pcc_str) / sizeof(char *);
5815 fprintf(stderr, "0x%04X\n",cond);
5817 for(i=0,j=1; i<ncond; i++, j<<=1)
5819 fprintf(stderr, " %s\n",pcc_str[i]);
5825 /*-----------------------------------------------------------------*/
5826 /*-----------------------------------------------------------------*/
5827 static void FlowStats(pCodeFlow *pcflow)
5835 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5837 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5840 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5845 fprintf(stderr, " FlowStats inCond: ");
5846 dumpCond(pcflow->inCond);
5847 fprintf(stderr, " FlowStats outCond: ");
5848 dumpCond(pcflow->outCond);
5852 /*-----------------------------------------------------------------*
5853 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5854 * if it affects the banking bits.
5856 * return: -1 == Banking bits are unaffected by this pCode.
5858 * return: > 0 == Banking bits are affected.
5860 * If the banking bits are affected, then the returned value describes
5861 * which bits are affected and how they're affected. The lower half
5862 * of the integer maps to the bits that are affected, the upper half
5863 * to whether they're set or cleared.
5865 *-----------------------------------------------------------------*/
5867 static int isBankInstruction(pCode *pc)
5875 if( PCI(pc)->op == POC_MOVLB ||
5876 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5877 bank = PCOL(pc)->lit;
5884 /*-----------------------------------------------------------------*/
5885 /*-----------------------------------------------------------------*/
5886 static void FillFlow(pCodeFlow *pcflow)
5895 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5897 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
5900 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5907 isBankInstruction(pc);
5909 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5913 fprintf(stderr, " FillFlow - Bad end of flow\n");
5915 fprintf(stderr, " FillFlow - Ending flow with\n ");
5916 pc->print(stderr,pc);
5919 fprintf(stderr, " FillFlow inCond: ");
5920 dumpCond(pcflow->inCond);
5921 fprintf(stderr, " FillFlow outCond: ");
5922 dumpCond(pcflow->outCond);
5926 /*-----------------------------------------------------------------*/
5927 /*-----------------------------------------------------------------*/
5928 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5930 pCodeFlowLink *fromLink, *toLink;
5932 if(!from || !to || !to->pcflow || !from->pcflow)
5935 fromLink = pic16_newpCodeFlowLink(from->pcflow);
5936 toLink = pic16_newpCodeFlowLink(to->pcflow);
5938 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
5939 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5943 /*-----------------------------------------------------------------*
5944 * void LinkFlow(pBlock *pb)
5946 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5947 * non-branching segments. In LinkFlow, we determine the execution
5948 * order of these segments. For example, if one of the segments ends
5949 * with a skip, then we know that there are two possible flow segments
5950 * to which control may be passed.
5951 *-----------------------------------------------------------------*/
5952 static void LinkFlow(pBlock *pb)
5958 //fprintf(stderr,"linkflow \n");
5960 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5962 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5965 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5967 //fprintf(stderr," link: ");
5968 //pcflow->print(stderr,pcflow);
5970 //FillFlow(PCFL(pcflow));
5972 pc = PCFL(pcflow)->end;
5974 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5975 if(isPCI_SKIP(pc)) {
5976 //fprintf(stderr, "ends with skip\n");
5977 //pc->print(stderr,pc);
5978 pct=pic16_findNextInstruction(pc->next);
5979 LinkFlow_pCode(PCI(pc),PCI(pct));
5980 pct=pic16_findNextInstruction(pct->next);
5981 LinkFlow_pCode(PCI(pc),PCI(pct));
5985 if(isPCI_BRANCH(pc)) {
5986 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5988 //fprintf(stderr, "ends with branch\n ");
5989 //pc->print(stderr,pc);
5991 if(!(pcol && isPCOLAB(pcol))) {
5992 if((PCI(pc)->op != POC_RETLW)
5993 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5995 /* continue if label is '$' which assembler knows how to parse */
5996 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5998 if(pic16_pcode_verbose) {
5999 pc->print(stderr,pc);
6000 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6006 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6007 LinkFlow_pCode(PCI(pc),PCI(pct));
6009 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6010 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6012 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6018 //fprintf(stderr, "ends with non-branching instruction:\n");
6019 //pc->print(stderr,pc);
6021 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6027 //fprintf(stderr, "ends with unknown\n");
6028 //pc->print(stderr,pc);
6032 //fprintf(stderr, "ends with nothing: ERROR\n");
6036 /*-----------------------------------------------------------------*/
6037 /*-----------------------------------------------------------------*/
6039 /*-----------------------------------------------------------------*/
6040 /*-----------------------------------------------------------------*/
6041 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6047 if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6050 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6060 /*-----------------------------------------------------------------*/
6061 /* insertBankSwitch - inserts a bank switch statement in the */
6062 /* assembly listing */
6064 /* position == 0: insert before */
6065 /* position == 1: insert after pc */
6066 /* position == 2: like 0 but previous was a skip instruction */
6067 /*-----------------------------------------------------------------*/
6068 pCodeOp *pic16_popGetLabel(unsigned int key);
6069 extern int pic16_labelOffset;
6071 static void insertBankSwitch(unsigned char position, pCode *pc)
6078 /* emit BANKSEL [symbol] */
6081 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6083 // position = 0; // position is always before (sanity check!)
6086 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6087 pc->print(stderr, pc);
6092 /* insert the bank switch after this pc instruction */
6093 pCode *pcnext = pic16_findNextInstruction(pc);
6095 pic16_pCodeInsertAfter(pc, new_pc);
6096 if(pcnext)pc = pcnext;
6100 /* insert the bank switch BEFORE this pc instruction */
6101 pic16_pCodeInsertAfter(pc->prev, new_pc);
6106 pCode *pcnext, *pcprev, *npci, *ppc;
6108 int ofs1=0, ofs2=0, len=0;
6110 /* just like 0, but previous was a skip instruction,
6111 * so some care should be taken */
6113 pic16_labelOffset += 10000;
6114 tlbl = newiTempLabel(NULL);
6116 /* invert skip instruction */
6117 pcprev = pic16_findPrevInstruction(pc->prev);
6118 ipci = PCI(pcprev)->inverted_op;
6119 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6121 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6123 /* copy info from old pCode */
6124 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6125 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6126 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6127 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6128 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6129 PCI(npci)->op = PCI(pcprev)->inverted_op;
6131 /* unlink old pCode */
6133 ppc->next = pcprev->next;
6134 pcprev->next->prev = ppc;
6135 pic16_pCodeInsertAfter(ppc, npci);
6137 /* extra instructions to handle invertion */
6138 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6139 pic16_pCodeInsertAfter(npci, pcnext);
6140 pic16_pCodeInsertAfter(pc->prev, new_pc);
6142 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6143 pic16_pCodeInsertAfter(pc, pcnext);
6148 /* Move the label, if there is one */
6149 if(PCI(pc)->label) {
6150 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6151 // __FILE__, __LINE__, pc, new_pc);
6152 PCAD(new_pc)->pci.label = PCI(pc)->label;
6153 PCI(pc)->label = NULL;
6158 /*-----------------------------------------------------------------*/
6159 /*int compareBankFlow - compare the banking requirements between */
6161 /*-----------------------------------------------------------------*/
6162 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6165 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6168 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6171 if(pcflow->firstBank == -1)
6175 if(pcflowLink->pcflow->firstBank == -1) {
6176 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6177 pcflowLink->pcflow->to :
6178 pcflowLink->pcflow->from);
6179 return compareBankFlow(pcflow, pctl, toORfrom);
6183 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6186 pcflowLink->bank_conflict++;
6187 pcflowLink->pcflow->FromConflicts++;
6188 pcflow->ToConflicts++;
6191 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6194 pcflowLink->bank_conflict++;
6195 pcflowLink->pcflow->ToConflicts++;
6196 pcflow->FromConflicts++;
6200 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6201 pcflowLink->pcflow->pc.seq,
6202 pcflowLink->pcflow->FromConflicts,
6203 pcflowLink->pcflow->ToConflicts);
6210 /*-----------------------------------------------------------------*/
6211 /*-----------------------------------------------------------------*/
6212 static void DumpFlow(pBlock *pb)
6216 pCodeFlowLink *pcfl;
6219 fprintf(stderr,"Dump flow \n");
6220 pb->pcHead->print(stderr, pb->pcHead);
6222 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6223 pcflow->print(stderr,pcflow);
6225 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6227 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6229 if(!isPCFL(pcflow)) {
6230 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6233 fprintf(stderr,"dumping: ");
6234 pcflow->print(stderr,pcflow);
6235 FlowStats(PCFL(pcflow));
6237 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6239 pc = PCODE(pcfl->pcflow);
6241 fprintf(stderr, " from seq %d:\n",pc->seq);
6243 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6244 pc->print(stderr,pc);
6249 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6251 pc = PCODE(pcfl->pcflow);
6253 fprintf(stderr, " to seq %d:\n",pc->seq);
6255 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6256 pc->print(stderr,pc);
6265 /*-----------------------------------------------------------------*/
6266 /*-----------------------------------------------------------------*/
6267 static int OptimizepBlock(pBlock *pb)
6272 if(!pb || !peepOptimizing)
6275 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6277 for(pc = pb->pcHead; pc; pc = pc->next)
6278 matches += pic16_pCodePeepMatchRule(pc);
6281 pc = pic16_findNextInstruction(pb->pcHead);
6289 if(pic16_pCodePeepMatchRule(pc)) {
6294 pc = pic16_findNextInstruction(pcprev->next);
6296 pc = pic16_findNextInstruction(pb->pcHead);
6298 pc = pic16_findNextInstruction(pc->next);
6302 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6307 /*-----------------------------------------------------------------*/
6308 /*-----------------------------------------------------------------*/
6309 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6313 for(pc = pcs; pc; pc = pc->next) {
6315 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6317 (PCI(pc)->pcop->type == PO_LABEL) &&
6318 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6326 /*-----------------------------------------------------------------*/
6327 /*-----------------------------------------------------------------*/
6328 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6335 (PCI(pc)->pcop->type == PO_LABEL)) {
6337 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6339 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6340 // if(pcol->pcop.name)
6341 // free(pcol->pcop.name);
6343 /* If the key is negative, then we (probably) have a label to
6344 * a function and the name is already defined */
6347 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6351 //sprintf(buffer,"_%05d_DS_",pcl->key);
6353 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6355 pcol->pcop.name = Safe_strdup(s);
6356 pcol->key = pcl->key;
6357 //pc->print(stderr,pc);
6364 /*-----------------------------------------------------------------*/
6365 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6366 /* pCode chain if they're not used. */
6367 /*-----------------------------------------------------------------*/
6368 static void pBlockRemoveUnusedLabels(pBlock *pb)
6370 pCode *pc; pCodeLabel *pcl;
6375 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6377 pBranch *pbr = PCI(pc)->label;
6378 if(pbr && pbr->next) {
6379 pCode *pcd = pb->pcHead;
6381 // fprintf(stderr, "multiple labels\n");
6382 // pc->print(stderr,pc);
6387 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6388 //fprintf(stderr,"Used by:\n");
6389 //pcd->print(stderr,pcd);
6391 exchangeLabels(PCL(pbr->pc),pcd);
6400 for(pc = pb->pcHead; pc; pc = pc->next) {
6402 if(isPCL(pc)) // pc->type == PC_LABEL)
6404 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6405 pcl = PCL(PCI(pc)->label->pc);
6408 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6410 /* This pCode is a label, so search the pBlock to see if anyone
6413 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6415 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6416 /* Couldn't find an instruction that refers to this label
6417 * So, unlink the pCode label from it's pCode chain
6418 * and destroy the label */
6419 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6421 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6422 if(pc->type == PC_LABEL) {
6423 pic16_unlinkpCode(pc);
6424 pCodeLabelDestruct(pc);
6426 unlinkpCodeFromBranch(pc, PCODE(pcl));
6427 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6438 /*-----------------------------------------------------------------*/
6439 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6440 /* chain and put them into pBranches that are */
6441 /* associated with the appropriate pCode */
6443 /*-----------------------------------------------------------------*/
6444 void pic16_pBlockMergeLabels(pBlock *pb)
6447 pCode *pc, *pcnext=NULL;
6452 /* First, Try to remove any unused labels */
6453 //pBlockRemoveUnusedLabels(pb);
6455 /* Now loop through the pBlock and merge the labels with the opcodes */
6458 // for(pc = pb->pcHead; pc; pc = pc->next) {
6461 pCode *pcn = pc->next;
6463 if(pc->type == PC_LABEL) {
6465 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6466 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6468 if((pcnext = pic16_findNextInstruction(pc) )) {
6470 // pcnext->print(stderr, pcnext);
6472 // Unlink the pCode label from it's pCode chain
6473 pic16_unlinkpCode(pc);
6475 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6476 // And link it into the instruction's pBranch labels. (Note, since
6477 // it's possible to have multiple labels associated with one instruction
6478 // we must provide a means to accomodate the additional labels. Thus
6479 // the labels are placed into the singly-linked list "label" as
6480 // opposed to being a single member of the pCodeInstruction.)
6482 //_ALLOC(pbr,sizeof(pBranch));
6484 pbr = Safe_calloc(1,sizeof(pBranch));
6488 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6491 if(pic16_pcode_verbose)
6492 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6494 } else if(pc->type == PC_CSOURCE) {
6496 /* merge the source line symbolic info into the next instruction */
6497 if((pcnext = pic16_findNextInstruction(pc) )) {
6499 // Unlink the pCode label from it's pCode chain
6500 pic16_unlinkpCode(pc);
6501 PCI(pcnext)->cline = PCCS(pc);
6502 //fprintf(stderr, "merging CSRC\n");
6503 //genericPrint(stderr,pcnext);
6509 pBlockRemoveUnusedLabels(pb);
6513 /*-----------------------------------------------------------------*/
6514 /*-----------------------------------------------------------------*/
6515 static int OptimizepCode(char dbName)
6517 #define MAX_PASSES 4
6526 DFPRINTF((stderr," Optimizing pCode\n"));
6530 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6531 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6532 matches += OptimizepBlock(pb);
6535 while(matches && ++passes < MAX_PASSES);
6542 const char *pic16_pCodeOpType(pCodeOp *pcop);
6543 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6546 /*-----------------------------------------------------------------*/
6547 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6548 /*-----------------------------------------------------------------*/
6550 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6554 // fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6555 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6557 if( !( (pcop->type == PO_LABEL) ||
6558 (pcop->type == PO_LITERAL) ||
6559 (pcop->type == PO_STR) ))
6560 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6561 PCOR(pcop)->r->wasUsed = 1;
6567 /*----------------------------------------------------------------------*
6568 * pic16_areRegsSame - check to see if the names of two registers match *
6569 *----------------------------------------------------------------------*/
6570 int pic16_areRegsSame(regs *r1, regs *r2)
6572 if(!strcmp(r1->name, r2->name))return 1;
6578 /*-----------------------------------------------------------------*/
6579 /*-----------------------------------------------------------------*/
6580 static void pic16_FixRegisterBanking(pBlock *pb)
6584 regs *reg, *prevreg;
6585 unsigned char flag=0;
6590 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6593 /* loop through all of the flow blocks with in one pblock */
6595 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6599 /* at this point, pc should point to a PC_FLOW object */
6600 /* for each flow block, determine the register banking
6603 if(!isPCI(pc))goto loop;
6605 if(PCI(pc)->is2MemOp)goto loop;
6607 reg = pic16_getRegFromInstruction(pc);
6610 pc->print(stderr, pc);
6611 fprintf(stderr, "reg = %p\n", reg);
6614 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6615 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6616 reg->address,reg->isBitField, reg->isFixed);
6620 /* now make some tests to make sure that instruction needs bank switch */
6622 /* if no register exists, and if not a bit opcode goto loop */
6624 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6627 if(isPCI_SKIP(pc)) {
6628 // fprintf(stderr, "instruction is SKIP instruction\n");
6630 if(reg && isACCESS_BANK(reg))goto loop;
6632 if(!isBankInstruction(pc))goto loop;
6634 if(isPCI_LIT(pc))goto loop;
6636 if(PCI(pc)->op == POC_CALL)goto loop;
6638 /* Examine the instruction before this one to make sure it is
6639 * not a skip type instruction */
6640 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6642 flag = 0; /* add before this instruction */
6644 /* if previous instruction is a skip one, then set flag
6645 * to 2 and call insertBankSwitch */
6646 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6649 insertBankSwitch(flag, pc);
6652 // fprintf(stderr, "BANK SWITCH inserted\n");
6661 static void pBlockDestruct(pBlock *pb)
6672 /*-----------------------------------------------------------------*/
6673 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6674 /* name dbName and combine them */
6675 /* into one block */
6676 /*-----------------------------------------------------------------*/
6677 static void mergepBlocks(char dbName)
6680 pBlock *pb, *pbmerged = NULL,*pbn;
6682 pb = the_pFile->pbHead;
6684 //fprintf(stderr," merging blocks named %c\n",dbName);
6688 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6689 if( getpBlock_dbName(pb) == dbName) {
6691 //fprintf(stderr," merged block %c\n",dbName);
6696 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6697 /* pic16_addpCode2pBlock doesn't handle the tail: */
6698 pbmerged->pcTail = pb->pcTail;
6700 pb->prev->next = pbn;
6702 pbn->prev = pb->prev;
6707 //pic16_printpBlock(stderr, pbmerged);
6714 /*-----------------------------------------------------------------*/
6715 /* AnalyzeFlow - Examine the flow of the code and optimize */
6717 /* level 0 == minimal optimization */
6718 /* optimize registers that are used only by two instructions */
6719 /* level 1 == maximal optimization */
6720 /* optimize by looking at pairs of instructions that use the */
6722 /*-----------------------------------------------------------------*/
6724 static void AnalyzeFlow(int level)
6726 static int times_called=0;
6731 /* remove unused allocated registers before exiting */
6732 pic16_RemoveUnusedRegisters();
6738 /* if this is not the first time this function has been called,
6739 then clean up old flow information */
6740 if(times_called++) {
6741 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6744 pic16_RegsUnMapLiveRanges();
6749 /* Phase 2 - Flow Analysis - Register Banking
6751 * In this phase, the individual flow blocks are examined
6752 * and register banking is fixed.
6756 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6757 pic16_FixRegisterBanking(pb);
6760 /* Phase 2 - Flow Analysis
6762 * In this phase, the pCode is partition into pCodeFlow
6763 * blocks. The flow blocks mark the points where a continuous
6764 * stream of instructions changes flow (e.g. because of
6765 * a call or goto or whatever).
6768 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6769 pic16_BuildFlow(pb);
6772 /* Phase 2 - Flow Analysis - linking flow blocks
6774 * In this phase, the individual flow blocks are examined
6775 * to determine their order of excution.
6778 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6781 /* Phase 3 - Flow Analysis - Flow Tree
6783 * In this phase, the individual flow blocks are examined
6784 * to determine their order of execution.
6787 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6788 pic16_BuildFlowTree(pb);
6791 /* Phase x - Flow Analysis - Used Banks
6793 * In this phase, the individual flow blocks are examined
6794 * to determine the Register Banks they use
6798 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6803 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6804 pic16_pCodeRegMapLiveRanges(pb);
6806 pic16_RemoveUnusedRegisters();
6808 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
6809 pic16_pCodeRegOptimizeRegUsage(level);
6817 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6822 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6824 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6825 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6826 pcflow = pcflow->next) {
6828 FillFlow(PCFL(pcflow));
6833 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6836 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6837 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6838 pcflow = pcflow->next) {
6840 FlowStats(PCFL(pcflow));
6846 /* VR -- no need to analyze banking in flow, but left here :
6847 * 1. because it may be used in the future for other purposes
6848 * 2. because if omitted we'll miss some optimization done here
6850 * Perhaps I should rename it to something else
6853 /*-----------------------------------------------------------------*/
6854 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
6855 /* assigned to the registers. */
6857 /*-----------------------------------------------------------------*/
6859 void pic16_AnalyzeBanking(void)
6864 /* Phase x - Flow Analysis - Used Banks
6866 * In this phase, the individual flow blocks are examined
6867 * to determine the Register Banks they use
6873 if(!the_pFile)return;
6875 if(!pic16_options.no_banksel) {
6876 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6877 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6878 pic16_FixRegisterBanking(pb);
6884 /*-----------------------------------------------------------------*/
6885 /* buildCallTree - Look at the flow and extract all of the calls. */
6886 /*-----------------------------------------------------------------*/
6887 static set *register_usage(pBlock *pb);
6889 static void buildCallTree(void )
6901 /* Now build the call tree.
6902 First we examine all of the pCodes for functions.
6903 Keep in mind that the function boundaries coincide
6904 with pBlock boundaries.
6906 The algorithm goes something like this:
6907 We have two nested loops. The outer loop iterates
6908 through all of the pBlocks/functions. The inner
6909 loop iterates through all of the pCodes for
6910 a given pBlock. When we begin iterating through
6911 a pBlock, the variable pc_fstart, pCode of the start
6912 of a function, is cleared. We then search for pCodes
6913 of type PC_FUNCTION. When one is encountered, we
6914 initialize pc_fstart to this and at the same time
6915 associate a new pBranch object that signifies a
6916 branch entry. If a return is found, then this signifies
6917 a function exit point. We'll link the pCodes of these
6918 returns to the matching pc_fstart.
6920 When we're done, a doubly linked list of pBranches
6921 will exist. The head of this list is stored in
6922 `the_pFile', which is the meta structure for all
6923 of the pCode. Look at the pic16_printCallTree function
6924 on how the pBranches are linked together.
6927 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6928 pCode *pc_fstart=NULL;
6929 for(pc = pb->pcHead; pc; pc = pc->next) {
6931 if(isPCI(pc) && pc_fstart) {
6932 if(PCI(pc)->is2MemOp) {
6933 r = pic16_getRegFromInstruction2(pc);
6934 if(r && !strcmp(r->name, "POSTDEC1"))
6935 PCF(pc_fstart)->stackusage++;
6937 r = pic16_getRegFromInstruction(pc);
6938 if(r && !strcmp(r->name, "PREINC1"))
6939 PCF(pc_fstart)->stackusage--;
6944 if (PCF(pc)->fname) {
6946 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6947 //fprintf(stderr," found main \n");
6948 pb->cmemmap = NULL; /* FIXME do we need to free ? */
6952 pbr = Safe_calloc(1,sizeof(pBranch));
6953 pbr->pc = pc_fstart = pc;
6956 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6958 // Here's a better way of doing the same:
6959 addSet(&pb->function_entries, pc);
6962 // Found an exit point in a function, e.g. return
6963 // (Note, there may be more than one return per function)
6965 pBranchLink(PCF(pc_fstart), PCF(pc));
6967 addSet(&pb->function_exits, pc);
6969 } else if(isCALL(pc)) {
6970 addSet(&pb->function_calls,pc);
6977 /* This is not needed because currently all register used
6978 * by a function are stored in stack -- VR */
6980 /* Re-allocate the registers so that there are no collisions
6981 * between local variables when one function call another */
6984 // pic16_deallocateAllRegs();
6986 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6994 /*-----------------------------------------------------------------*/
6995 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6996 /* all of the logical connections. */
6998 /* Essentially what's done here is that the pCode flow is */
7000 /*-----------------------------------------------------------------*/
7002 void pic16_AnalyzepCode(char dbName)
7013 /* Phase 1 - Register allocation and peep hole optimization
7015 * The first part of the analysis is to determine the registers
7016 * that are used in the pCode. Once that is done, the peep rules
7017 * are applied to the code. We continue to loop until no more
7018 * peep rule optimizations are found (or until we exceed the
7019 * MAX_PASSES threshold).
7021 * When done, the required registers will be determined.
7027 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7028 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7030 /* First, merge the labels with the instructions */
7031 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7032 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7034 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7035 //fprintf(stderr," analyze and merging block %c\n",dbName);
7036 pic16_pBlockMergeLabels(pb);
7039 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7044 changes = OptimizepCode(dbName);
7047 } while(changes && (i++ < MAX_PASSES));
7052 /*-----------------------------------------------------------------*/
7053 /* ispCodeFunction - returns true if *pc is the pCode of a */
7055 /*-----------------------------------------------------------------*/
7056 static bool ispCodeFunction(pCode *pc)
7059 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7065 /*-----------------------------------------------------------------*/
7066 /* findFunction - Search for a function by name (given the name) */
7067 /* in the set of all functions that are in a pBlock */
7068 /* (note - I expect this to change because I'm planning to limit */
7069 /* pBlock's to just one function declaration */
7070 /*-----------------------------------------------------------------*/
7071 static pCode *findFunction(char *fname)
7078 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7080 pc = setFirstItem(pb->function_entries);
7083 if((pc->type == PC_FUNCTION) &&
7085 (strcmp(fname, PCF(pc)->fname)==0))
7088 pc = setNextItem(pb->function_entries);
7096 static void MarkUsedRegisters(set *regset)
7101 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7102 // fprintf(stderr, "marking register = %s\t", r1->name);
7103 r2 = pic16_regWithIdx(r1->rIdx);
7104 // fprintf(stderr, "to register = %s\n", r2->name);
7110 static void pBlockStats(FILE *of, pBlock *pb)
7116 if(!pic16_pcode_verbose)return;
7118 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7120 // for now just print the first element of each set
7121 pc = setFirstItem(pb->function_entries);
7123 fprintf(of,";entry: ");
7126 pc = setFirstItem(pb->function_exits);
7128 fprintf(of,";has an exit\n");
7132 pc = setFirstItem(pb->function_calls);
7134 fprintf(of,";functions called:\n");
7137 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7138 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
7140 pc = setNextItem(pb->function_calls);
7144 r = setFirstItem(pb->tregisters);
7146 int n = elementsInSet(pb->tregisters);
7148 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7151 fprintf(of,"; %s\n",r->name);
7152 r = setNextItem(pb->tregisters);
7156 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7159 /*-----------------------------------------------------------------*/
7160 /*-----------------------------------------------------------------*/
7162 static void sequencepCode(void)
7168 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7170 pb->seq = GpCodeSequenceNumber+1;
7172 for( pc = pb->pcHead; pc; pc = pc->next)
7173 pc->seq = ++GpCodeSequenceNumber;
7179 /*-----------------------------------------------------------------*/
7180 /*-----------------------------------------------------------------*/
7181 static set *register_usage(pBlock *pb)
7184 set *registers=NULL;
7185 set *registersInCallPath = NULL;
7187 /* check recursion */
7189 pc = setFirstItem(pb->function_entries);
7196 if(pc->type != PC_FUNCTION)
7197 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7199 pc = setFirstItem(pb->function_calls);
7200 for( ; pc; pc = setNextItem(pb->function_calls)) {
7202 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7203 char *dest = pic16_get_op_from_instruction(PCI(pc));
7205 pcn = findFunction(dest);
7207 registersInCallPath = register_usage(pcn->pb);
7209 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7214 pBlockStats(stderr,pb); // debug
7217 // Mark the registers in this block as used.
7219 MarkUsedRegisters(pb->tregisters);
7220 if(registersInCallPath) {
7221 /* registers were used in the functions this pBlock has called */
7222 /* so now, we need to see if these collide with the ones we are */
7225 regs *r1,*r2, *newreg;
7227 DFPRINTF((stderr,"comparing registers\n"));
7229 r1 = setFirstItem(registersInCallPath);
7232 r2 = setFirstItem(pb->tregisters);
7234 while(r2 && (r1->type != REG_STK)) {
7236 if(r2->rIdx == r1->rIdx) {
7237 newreg = pic16_findFreeReg(REG_GPR);
7241 DFPRINTF((stderr,"Bummer, no more registers.\n"));
7245 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7246 r1->rIdx, newreg->rIdx));
7247 r2->rIdx = newreg->rIdx;
7248 //if(r2->name) free(r2->name);
7250 r2->name = Safe_strdup(newreg->name);
7254 newreg->wasUsed = 1;
7256 r2 = setNextItem(pb->tregisters);
7259 r1 = setNextItem(registersInCallPath);
7262 /* Collisions have been resolved. Now free the registers in the call path */
7263 r1 = setFirstItem(registersInCallPath);
7265 if(r1->type != REG_STK) {
7266 newreg = pic16_regWithIdx(r1->rIdx);
7269 r1 = setNextItem(registersInCallPath);
7273 // MarkUsedRegisters(pb->registers);
7275 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7278 DFPRINTF((stderr,"returning regs\n"));
7280 DFPRINTF((stderr,"not returning regs\n"));
7282 DFPRINTF((stderr,"pBlock after register optim.\n"));
7283 pBlockStats(stderr,pb); // debug
7289 /*-----------------------------------------------------------------*/
7290 /* pct2 - writes the call tree to a file */
7292 /*-----------------------------------------------------------------*/
7293 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7297 // set *registersInCallPath = NULL;
7303 fprintf(of, "recursive function\n");
7304 return; //recursion ?
7307 pc = setFirstItem(pb->function_entries);
7314 for(i=0;i<indent;i++) // Indentation
7318 if(pc->type == PC_FUNCTION) {
7319 usedstack += PCF(pc)->stackusage;
7320 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7321 } else return; // ???
7324 pc = setFirstItem(pb->function_calls);
7325 for( ; pc; pc = setNextItem(pb->function_calls)) {
7327 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7328 char *dest = pic16_get_op_from_instruction(PCI(pc));
7330 pcn = findFunction(dest);
7332 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
7334 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7342 /*-----------------------------------------------------------------*/
7343 /* pic16_printCallTree - writes the call tree to a file */
7345 /*-----------------------------------------------------------------*/
7347 void pic16_printCallTree(FILE *of)
7359 fprintf(of, "\npBlock statistics\n");
7360 for(pb = the_pFile->pbHead; pb; pb = pb->next )
7364 fprintf(of,"Call Tree\n");
7365 pbr = the_pFile->functions;
7369 if(!ispCodeFunction(pc))
7370 fprintf(of,"bug in call tree");
7373 fprintf(of,"Function: %s\n", PCF(pc)->fname);
7375 while(pc->next && !ispCodeFunction(pc->next)) {
7377 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7378 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7386 fprintf(of,"\n**************\n\na better call tree\n");
7387 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7392 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7393 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7399 /*-----------------------------------------------------------------*/
7401 /*-----------------------------------------------------------------*/
7403 static void InlineFunction(pBlock *pb)
7411 pc = setFirstItem(pb->function_calls);
7413 for( ; pc; pc = setNextItem(pb->function_calls)) {
7416 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7422 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
7424 //fprintf(stderr,"Cool can inline:\n");
7425 //pcn->print(stderr,pcn);
7427 //fprintf(stderr,"recursive call Inline\n");
7428 InlineFunction(pcn->pb);
7429 //fprintf(stderr,"return from recursive call Inline\n");
7432 At this point, *pc points to a CALL mnemonic, and
7433 *pcn points to the function that is being called.
7435 To in-line this call, we need to remove the CALL
7436 and RETURN(s), and link the function pCode in with
7442 /* Remove the CALL */
7446 /* remove callee pBlock from the pBlock linked list */
7447 removepBlock(pcn->pb);
7455 /* Remove the Function pCode */
7456 pct = pic16_findNextInstruction(pcn->next);
7458 /* Link the function with the callee */
7459 pc->next = pcn->next;
7460 pcn->next->prev = pc;
7462 /* Convert the function name into a label */
7464 pbr = Safe_calloc(1,sizeof(pBranch));
7465 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7467 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7468 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7470 /* turn all of the return's except the last into goto's */
7471 /* check case for 2 instruction pBlocks */
7472 pce = pic16_findNextInstruction(pcn->next);
7474 pCode *pce_next = pic16_findNextInstruction(pce->next);
7476 if(pce_next == NULL) {
7477 /* found the last return */
7478 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
7480 //fprintf(stderr,"found last return\n");
7481 //pce->print(stderr,pce);
7482 pce->prev->next = pc_call->next;
7483 pc_call->next->prev = pce->prev;
7484 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7494 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7500 /*-----------------------------------------------------------------*/
7502 /*-----------------------------------------------------------------*/
7504 void pic16_InlinepCode(void)
7513 if(!functionInlining)
7516 /* Loop through all of the function definitions and count the
7517 * number of times each one is called */
7518 //fprintf(stderr,"inlining %d\n",__LINE__);
7520 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7522 pc = setFirstItem(pb->function_calls);
7524 for( ; pc; pc = setNextItem(pb->function_calls)) {
7527 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7528 if(pcn && isPCF(pcn)) {
7529 PCF(pcn)->ncalled++;
7532 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7537 //fprintf(stderr,"inlining %d\n",__LINE__);
7539 /* Now, Loop through the function definitions again, but this
7540 * time inline those functions that have only been called once. */
7542 InlineFunction(the_pFile->pbHead);
7543 //fprintf(stderr,"inlining %d\n",__LINE__);
7545 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7550 char *pic_optype_names[]={
7551 "PO_NONE", // No operand e.g. NOP
7552 "PO_W", // The working register (as a destination)
7553 "PO_WREG", // The working register (as a file register)
7554 "PO_STATUS", // The 'STATUS' register
7555 "PO_BSR", // The 'BSR' register
7556 "PO_FSR0", // The "file select register" (in PIC18 family it's one
7558 "PO_INDF0", // The Indirect register
7559 "PO_INTCON", // Interrupt Control register
7560 "PO_GPR_REGISTER", // A general purpose register
7561 "PO_GPR_BIT", // A bit of a general purpose register
7562 "PO_GPR_TEMP", // A general purpose temporary register
7563 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
7564 "PO_PCL", // Program counter Low register
7565 "PO_PCLATH", // Program counter Latch high register
7566 "PO_PCLATU", // Program counter Latch upper register
7567 "PO_PRODL", // Product Register Low
7568 "PO_PRODH", // Product Register High
7569 "PO_LITERAL", // A constant
7570 "PO_REL_ADDR", // A relative address
7571 "PO_IMMEDIATE", // (8051 legacy)
7572 "PO_DIR", // Direct memory (8051 legacy)
7573 "PO_CRY", // bit memory (8051 legacy)
7574 "PO_BIT", // bit operand.
7575 "PO_STR", // (8051 legacy)
7577 "PO_WILD" // Wild card operand in peep optimizer
7581 char *dumpPicOptype(PIC_OPTYPE type)
7583 return (pic_optype_names[ type ]);