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};
109 pCodeOpReg pic16_pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL};
110 pCodeOpReg pic16_pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL};
111 pCodeOpReg pic16_pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg *pic16_stackpnt_lo;
114 pCodeOpReg *pic16_stackpnt_hi;
115 pCodeOpReg *pic16_stack_postinc;
116 pCodeOpReg *pic16_stack_postdec;
117 pCodeOpReg *pic16_stack_preinc;
118 pCodeOpReg *pic16_stack_plusw;
120 pCodeOpReg *pic16_framepnt_lo;
121 pCodeOpReg *pic16_framepnt_hi;
122 pCodeOpReg *pic16_frame_postinc;
123 pCodeOpReg *pic16_frame_postdec;
124 pCodeOpReg *pic16_frame_preinc;
125 pCodeOpReg *pic16_frame_plusw;
127 pCodeOpReg pic16_pc_gpsimio = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
128 pCodeOpReg pic16_pc_gpsimio2 = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
130 char *OPT_TYPE_STR[] = { "begin", "end" };
131 char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
134 static int mnemonics_initialized = 0;
137 static hTab *pic16MnemonicsHash = NULL;
138 static hTab *pic16pCodePeepCommandsHash = NULL;
140 static pFile *the_pFile = NULL;
141 static pBlock *pb_dead_pcodes = NULL;
143 /* Hardcoded flags to change the behavior of the PIC port */
144 static int peepOptimizing = 1; /* run the peephole optimizer if nonzero */
145 static int functionInlining = 1; /* inline functions if nonzero */
146 int pic16_debug_verbose = 0; /* Set true to inundate .asm file */
148 int pic16_pcode_verbose = 0;
150 //static int GpCodeSequenceNumber = 1;
151 static int GpcFlowSeq = 1;
153 extern void pic16_RemoveUnusedRegisters(void);
154 extern void pic16_RegsUnMapLiveRanges(void);
155 extern void pic16_BuildFlowTree(pBlock *pb);
156 extern void pic16_pCodeRegOptimizeRegUsage(int level);
157 extern int pic16_picIsInitialized(void);
158 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
159 extern int mnem2key(char const *mnem);
161 /****************************************************************/
162 /* Forward declarations */
163 /****************************************************************/
165 void pic16_unlinkpCode(pCode *pc);
167 static void genericAnalyze(pCode *pc);
168 static void AnalyzeGOTO(pCode *pc);
169 static void AnalyzeSKIP(pCode *pc);
170 static void AnalyzeRETURN(pCode *pc);
173 static void genericDestruct(pCode *pc);
174 static void genericPrint(FILE *of,pCode *pc);
176 static void pCodePrintLabel(FILE *of, pCode *pc);
177 static void pCodePrintFunction(FILE *of, pCode *pc);
178 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
179 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
180 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
181 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
182 int pic16_pCodePeepMatchRule(pCode *pc);
183 static void pBlockStats(FILE *of, pBlock *pb);
184 static pBlock *newpBlock(void);
185 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
186 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
187 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
188 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
189 void OptimizeLocalRegs(void);
190 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
192 char *dumpPicOptype(PIC_OPTYPE type);
194 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
195 pCodeOp *pic16_popGetLit(int);
196 pCodeOp *pic16_popGetWithString(char *);
197 extern int inWparamList(char *s);
200 /****************************************************************/
201 /* PIC Instructions */
202 /****************************************************************/
204 pCodeInstruction pic16_pciADDWF = {
205 {PC_OPCODE, NULL, NULL, 0, NULL,
219 1,0, // dest, bit instruction
221 0, // literal operand
223 0, // fast call/return mode select bit
224 0, // second memory operand
225 0, // second literal operand
227 (PCC_W | PCC_REGISTER), // inCond
228 (PCC_REGISTER | PCC_Z), // outCond
232 pCodeInstruction pic16_pciADDFW = {
233 {PC_OPCODE, NULL, NULL, 0, NULL,
247 0,0, // dest, bit instruction
249 0, // literal operand
251 0, // fast call/return mode select bit
252 0, // second memory operand
253 0, // second literal operand
255 (PCC_W | PCC_REGISTER), // inCond
256 (PCC_W | PCC_Z), // outCond
260 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
261 {PC_OPCODE, NULL, NULL, 0, NULL,
275 1,0, // dest, bit instruction
277 0, // literal operand
279 0, // fast call/return mode select bit
280 0, // second memory operand
281 0, // second literal operand
283 (PCC_W | PCC_REGISTER | PCC_C), // inCond
284 (PCC_REGISTER | PCC_Z), // outCond
288 pCodeInstruction pic16_pciADDFWC = {
289 {PC_OPCODE, NULL, NULL, 0, NULL,
303 0,0, // dest, bit instruction
305 0, // literal operand
307 0, // fast call/return mode select bit
308 0, // second memory operand
309 0, // second literal operand
311 (PCC_W | PCC_REGISTER | PCC_C), // inCond
312 (PCC_W | PCC_Z), // outCond
316 pCodeInstruction pic16_pciADDLW = {
317 {PC_OPCODE, NULL, NULL, 0, NULL,
331 0,0, // dest, bit instruction
333 1, // literal operand
335 0, // fast call/return mode select bit
336 0, // second memory operand
337 0, // second literal operand
339 (PCC_W | PCC_LITERAL), // inCond
340 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
344 pCodeInstruction pic16_pciANDLW = {
345 {PC_OPCODE, NULL, NULL, 0, NULL,
359 0,0, // dest, bit instruction
361 1, // literal operand
363 0, // fast call/return mode select bit
364 0, // second memory operand
365 0, // second literal operand
367 (PCC_W | PCC_LITERAL), // inCond
368 (PCC_W | PCC_Z | PCC_N), // outCond
372 pCodeInstruction pic16_pciANDWF = {
373 {PC_OPCODE, NULL, NULL, 0, NULL,
387 1,0, // dest, bit instruction
389 0, // literal operand
391 0, // fast call/return mode select bit
392 0, // second memory operand
393 0, // second literal operand
395 (PCC_W | PCC_REGISTER), // inCond
396 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
400 pCodeInstruction pic16_pciANDFW = {
401 {PC_OPCODE, NULL, NULL, 0, NULL,
415 0,0, // dest, bit instruction
417 0, // literal operand
419 0, // fast call/return mode select bit
420 0, // second memory operand
421 0, // second literal operand
423 (PCC_W | PCC_REGISTER), // inCond
424 (PCC_W | PCC_Z) // outCond
427 pCodeInstruction pic16_pciBC = { // mdubuc - New
428 {PC_OPCODE, NULL, NULL, 0, NULL,
442 0,0, // dest, bit instruction
444 0, // literal operand
446 0, // fast call/return mode select bit
447 0, // second memory operand
448 0, // second literal operand
450 (PCC_REL_ADDR | PCC_C), // inCond
455 pCodeInstruction pic16_pciBCF = {
456 {PC_OPCODE, NULL, NULL, 0, NULL,
470 1,1, // dest, bit instruction
472 0, // literal operand
474 0, // fast call/return mode select bit
475 0, // second memory operand
476 0, // second literal operand
478 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
479 PCC_REGISTER, // outCond
483 pCodeInstruction pic16_pciBN = { // mdubuc - New
484 {PC_OPCODE, NULL, NULL, 0, NULL,
498 0,0, // dest, bit instruction
500 0, // literal operand
502 0, // fast call/return mode select bit
503 0, // second memory operand
504 0, // second literal operand
506 (PCC_REL_ADDR | PCC_N), // inCond
507 PCC_NONE , // outCond
511 pCodeInstruction pic16_pciBNC = { // mdubuc - New
512 {PC_OPCODE, NULL, NULL, 0, NULL,
526 0,0, // dest, bit instruction
528 0, // literal operand
530 0, // fast call/return mode select bit
531 0, // second memory operand
532 0, // second literal operand
534 (PCC_REL_ADDR | PCC_C), // inCond
535 PCC_NONE , // outCond
539 pCodeInstruction pic16_pciBNN = { // mdubuc - New
540 {PC_OPCODE, NULL, NULL, 0, NULL,
554 0,0, // dest, bit instruction
556 0, // literal operand
558 0, // fast call/return mode select bit
559 0, // second memory operand
560 0, // second literal operand
562 (PCC_REL_ADDR | PCC_N), // inCond
563 PCC_NONE , // outCond
567 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
568 {PC_OPCODE, NULL, NULL, 0, NULL,
582 0,0, // dest, bit instruction
584 0, // literal operand
586 0, // fast call/return mode select bit
587 0, // second memory operand
588 0, // second literal operand
590 (PCC_REL_ADDR | PCC_OV), // inCond
591 PCC_NONE , // outCond
595 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
596 {PC_OPCODE, NULL, NULL, 0, NULL,
610 0,0, // dest, bit instruction
612 0, // literal operand
614 0, // fast call/return mode select bit
615 0, // second memory operand
616 0, // second literal operand
618 (PCC_REL_ADDR | PCC_Z), // inCond
619 PCC_NONE , // outCond
623 pCodeInstruction pic16_pciBOV = { // mdubuc - New
624 {PC_OPCODE, NULL, NULL, 0, NULL,
638 0,0, // dest, bit instruction
640 0, // literal operand
642 0, // fast call/return mode select bit
643 0, // second memory operand
644 0, // second literal operand
646 (PCC_REL_ADDR | PCC_OV), // inCond
647 PCC_NONE , // outCond
651 pCodeInstruction pic16_pciBRA = { // mdubuc - New
652 {PC_OPCODE, NULL, NULL, 0, NULL,
666 0,0, // dest, bit instruction
668 0, // literal operand
670 0, // fast call/return mode select bit
671 0, // second memory operand
672 0, // second literal operand
674 PCC_REL_ADDR, // inCond
675 PCC_NONE , // outCond
679 pCodeInstruction pic16_pciBSF = {
680 {PC_OPCODE, NULL, NULL, 0, NULL,
694 1,1, // dest, bit instruction
696 0, // literal operand
698 0, // fast call/return mode select bit
699 0, // second memory operand
700 0, // second literal operand
702 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
703 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
707 pCodeInstruction pic16_pciBTFSC = {
708 {PC_OPCODE, NULL, NULL, 0, NULL,
722 0,1, // dest, bit instruction
724 0, // literal operand
726 0, // fast call/return mode select bit
727 0, // second memory operand
728 0, // second literal operand
730 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
731 PCC_EXAMINE_PCOP, // outCond
735 pCodeInstruction pic16_pciBTFSS = {
736 {PC_OPCODE, NULL, NULL, 0, NULL,
750 0,1, // dest, bit instruction
752 0, // literal operand
754 0, // fast call/return mode select bit
755 0, // second memory operand
756 0, // second literal operand
758 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
759 PCC_EXAMINE_PCOP, // outCond
763 pCodeInstruction pic16_pciBTG = { // mdubuc - New
764 {PC_OPCODE, NULL, NULL, 0, NULL,
778 0,1, // dest, bit instruction
780 0, // literal operand
782 0, // fast call/return mode select bit
783 0, // second memory operand
784 0, // second literal operand
786 (PCC_REGISTER | PCC_EXAMINE_PCOP), // inCond
787 (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
791 pCodeInstruction pic16_pciBZ = { // mdubuc - New
792 {PC_OPCODE, NULL, NULL, 0, NULL,
806 0,0, // dest, bit instruction
808 0, // literal operand
810 0, // fast call/return mode select bit
811 0, // second memory operand
812 0, // second literal operand
819 pCodeInstruction pic16_pciCALL = {
820 {PC_OPCODE, NULL, NULL, 0, NULL,
834 0,0, // dest, bit instruction
836 0, // literal operand
838 1, // fast call/return mode select bit
839 0, // second memory operand
840 0, // second literal operand
847 pCodeInstruction pic16_pciCOMF = {
848 {PC_OPCODE, NULL, NULL, 0, NULL,
862 1,0, // dest, bit instruction
864 0, // literal operand
866 0, // fast call/return mode select bit
867 0, // second memory operand
868 0, // second literal operand
870 PCC_REGISTER, // inCond
871 PCC_REGISTER , // outCond
875 pCodeInstruction pic16_pciCOMFW = {
876 {PC_OPCODE, NULL, NULL, 0, NULL,
890 0,0, // dest, bit instruction
892 0, // literal operand
894 0, // fast call/return mode select bit
895 0, // second memory operand
896 0, // second literal operand
898 PCC_REGISTER, // inCond
903 pCodeInstruction pic16_pciCLRF = {
904 {PC_OPCODE, NULL, NULL, 0, NULL,
918 0,0, // dest, bit instruction
920 0, // literal operand
922 0, // fast call/return mode select bit
923 0, // second memory operand
924 0, // second literal operand
926 PCC_REGISTER, // inCond
927 PCC_REGISTER , // outCond
931 pCodeInstruction pic16_pciCLRWDT = {
932 {PC_OPCODE, NULL, NULL, 0, NULL,
946 0,0, // dest, bit instruction
948 0, // literal operand
950 0, // fast call/return mode select bit
951 0, // second memory operand
952 0, // second literal operand
955 PCC_NONE , // outCond
959 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
960 {PC_OPCODE, NULL, NULL, 0, NULL,
974 0,0, // dest, bit instruction
976 0, // literal operand
978 0, // fast call/return mode select bit
979 0, // second memory operand
980 0, // second literal operand
982 (PCC_W | PCC_REGISTER), // inCond
983 PCC_NONE , // outCond
987 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
988 {PC_OPCODE, NULL, NULL, 0, NULL,
1002 0,0, // dest, bit instruction
1003 1,1, // branch, skip
1004 0, // literal operand
1005 1, // RAM access bit
1006 0, // fast call/return mode select bit
1007 0, // second memory operand
1008 0, // second literal operand
1010 (PCC_W | PCC_REGISTER), // inCond
1011 PCC_NONE , // outCond
1015 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
1016 {PC_OPCODE, NULL, NULL, 0, NULL,
1023 NULL, // from branch
1030 1,0, // dest, bit instruction
1031 1,1, // branch, skip
1032 0, // literal operand
1033 1, // RAM access bit
1034 0, // fast call/return mode select bit
1035 0, // second memory operand
1036 0, // second literal operand
1038 (PCC_W | PCC_REGISTER), // inCond
1039 PCC_NONE , // outCond
1043 pCodeInstruction pic16_pciDAW = {
1044 {PC_OPCODE, NULL, NULL, 0, NULL,
1051 NULL, // from branch
1058 0,0, // dest, bit instruction
1059 0,0, // branch, skip
1060 0, // literal operand
1061 0, // RAM access bit
1062 0, // fast call/return mode select bit
1063 0, // second memory operand
1064 0, // second literal operand
1067 (PCC_W | PCC_C), // outCond
1071 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1072 {PC_OPCODE, NULL, NULL, 0, NULL,
1079 NULL, // from branch
1086 1,0, // dest, bit instruction
1087 1,1, // branch, skip
1088 0, // literal operand
1089 1, // RAM access bit
1090 0, // fast call/return mode select bit
1091 0, // second memory operand
1092 0, // second literal operand
1094 PCC_REGISTER, // inCond
1095 PCC_REGISTER , // outCond
1099 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1100 {PC_OPCODE, NULL, NULL, 0, NULL,
1107 NULL, // from branch
1114 0,0, // dest, bit instruction
1115 1,1, // 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_pciDECF = {
1128 {PC_OPCODE, NULL, NULL, 0, NULL,
1135 NULL, // from branch
1142 1,0, // dest, bit instruction
1143 0,0, // branch, skip
1144 0, // literal operand
1145 1, // RAM access bit
1146 0, // fast call/return mode select bit
1147 0, // second memory operand
1148 0, // second literal operand
1150 PCC_REGISTER, // inCond
1151 PCC_REGISTER , // outCond
1155 pCodeInstruction pic16_pciDECFW = {
1156 {PC_OPCODE, NULL, NULL, 0, NULL,
1163 NULL, // from branch
1170 0,0, // dest, bit instruction
1171 0,0, // branch, skip
1172 0, // literal operand
1173 1, // RAM access bit
1174 0, // fast call/return mode select bit
1175 0, // second memory operand
1176 0, // second literal operand
1178 PCC_REGISTER, // inCond
1183 pCodeInstruction pic16_pciDECFSZ = {
1184 {PC_OPCODE, NULL, NULL, 0, NULL,
1191 NULL, // from branch
1198 1,0, // dest, bit instruction
1199 1,1, // branch, skip
1200 0, // literal operand
1201 1, // RAM access bit
1202 0, // fast call/return mode select bit
1203 0, // second memory operand
1204 0, // second literal operand
1206 PCC_REGISTER, // inCond
1207 PCC_REGISTER , // outCond
1211 pCodeInstruction pic16_pciDECFSZW = {
1212 {PC_OPCODE, NULL, NULL, 0, NULL,
1219 NULL, // from branch
1226 0,0, // dest, bit instruction
1227 1,1, // branch, skip
1228 0, // literal operand
1229 1, // RAM access bit
1230 0, // fast call/return mode select bit
1231 0, // second memory operand
1232 0, // second literal operand
1234 PCC_REGISTER, // inCond
1239 pCodeInstruction pic16_pciGOTO = {
1240 {PC_OPCODE, NULL, NULL, 0, NULL,
1247 NULL, // from branch
1254 0,0, // dest, bit instruction
1255 1,0, // branch, skip
1256 0, // literal operand
1257 0, // RAM access bit
1258 0, // fast call/return mode select bit
1259 0, // second memory operand
1260 0, // second literal operand
1262 PCC_REL_ADDR, // inCond
1263 PCC_NONE , // outCond
1267 pCodeInstruction pic16_pciINCF = {
1268 {PC_OPCODE, NULL, NULL, 0, NULL,
1275 NULL, // from branch
1282 1,0, // dest, bit instruction
1283 0,0, // branch, skip
1284 0, // literal operand
1285 1, // RAM access bit
1286 0, // fast call/return mode select bit
1287 0, // second memory operand
1288 0, // second literal operand
1290 PCC_REGISTER, // inCond
1291 (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
1295 pCodeInstruction pic16_pciINCFW = {
1296 {PC_OPCODE, NULL, NULL, 0, NULL,
1303 NULL, // from branch
1310 0,0, // dest, bit instruction
1311 0,0, // branch, skip
1312 0, // literal operand
1313 1, // RAM access bit
1314 0, // fast call/return mode select bit
1315 0, // second memory operand
1316 0, // second literal operand
1318 PCC_REGISTER, // inCond
1323 pCodeInstruction pic16_pciINCFSZ = {
1324 {PC_OPCODE, NULL, NULL, 0, NULL,
1331 NULL, // from branch
1338 1,0, // dest, bit instruction
1339 1,1, // branch, skip
1340 0, // literal operand
1341 1, // RAM access bit
1342 0, // fast call/return mode select bit
1343 0, // second memory operand
1344 0, // second literal operand
1346 PCC_REGISTER, // inCond
1347 PCC_REGISTER , // outCond
1351 pCodeInstruction pic16_pciINCFSZW = {
1352 {PC_OPCODE, NULL, NULL, 0, NULL,
1359 NULL, // from branch
1366 0,0, // dest, bit instruction
1367 1,1, // branch, skip
1368 0, // literal operand
1369 1, // RAM access bit
1370 0, // fast call/return mode select bit
1371 0, // second memory operand
1372 0, // second literal operand
1374 PCC_REGISTER, // inCond
1379 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1380 {PC_OPCODE, NULL, NULL, 0, NULL,
1387 NULL, // from branch
1394 1,0, // dest, bit instruction
1395 1,1, // branch, skip
1396 0, // literal operand
1397 1, // RAM access bit
1398 0, // fast call/return mode select bit
1399 0, // second memory operand
1400 0, // second literal operand
1402 PCC_REGISTER, // inCond
1403 PCC_REGISTER , // outCond
1407 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1408 {PC_OPCODE, NULL, NULL, 0, NULL,
1415 NULL, // from branch
1422 0,0, // dest, bit instruction
1423 1,1, // branch, skip
1424 0, // literal operand
1425 1, // RAM access bit
1426 0, // fast call/return mode select bit
1427 0, // second memory operand
1428 0, // second literal operand
1430 PCC_REGISTER, // inCond
1435 pCodeInstruction pic16_pciIORWF = {
1436 {PC_OPCODE, NULL, NULL, 0, NULL,
1443 NULL, // from branch
1450 1,0, // dest, bit instruction
1451 0,0, // branch, skip
1452 0, // literal operand
1453 1, // RAM access bit
1454 0, // fast call/return mode select bit
1455 0, // second memory operand
1456 0, // second literal operand
1458 (PCC_W | PCC_REGISTER), // inCond
1459 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1463 pCodeInstruction pic16_pciIORFW = {
1464 {PC_OPCODE, NULL, NULL, 0, NULL,
1471 NULL, // from branch
1478 0,0, // dest, bit instruction
1479 0,0, // branch, skip
1480 0, // literal operand
1481 1, // RAM access bit
1482 0, // fast call/return mode select bit
1483 0, // second memory operand
1484 0, // second literal operand
1486 (PCC_W | PCC_REGISTER), // inCond
1487 (PCC_W | PCC_Z | PCC_N), // outCond
1491 pCodeInstruction pic16_pciIORLW = {
1492 {PC_OPCODE, NULL, NULL, 0, NULL,
1499 NULL, // from branch
1506 0,0, // dest, bit instruction
1507 0,0, // branch, skip
1508 1, // literal operand
1509 0, // RAM access bit
1510 0, // fast call/return mode select bit
1511 0, // second memory operand
1512 0, // second literal operand
1514 (PCC_W | PCC_LITERAL), // inCond
1515 (PCC_W | PCC_Z | PCC_N), // outCond
1519 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1520 {PC_OPCODE, NULL, NULL, 0, NULL,
1527 NULL, // from branch
1534 0,0, // dest, bit instruction
1535 0,0, // branch, skip
1536 1, // literal operand
1537 0, // RAM access bit
1538 0, // fast call/return mode select bit
1539 0, // second memory operand
1540 1, // second literal operand
1542 (PCC_REGISTER | PCC_LITERAL),
1543 PCC_REGISTER, // outCond
1547 pCodeInstruction pic16_pciMOVF = {
1548 {PC_OPCODE, NULL, NULL, 0, NULL,
1555 NULL, // from branch
1562 1,0, // dest, bit instruction
1563 0,0, // branch, skip
1564 0, // literal operand
1565 1, // RAM access bit
1566 0, // fast call/return mode select bit
1567 0, // second memory operand
1568 0, // second literal operand
1570 PCC_REGISTER, // inCond
1571 (PCC_Z | PCC_N), // outCond
1575 pCodeInstruction pic16_pciMOVFW = {
1576 {PC_OPCODE, NULL, NULL, 0, NULL,
1583 NULL, // from branch
1590 0,0, // dest, bit instruction
1591 0,0, // branch, skip
1592 0, // literal operand
1593 1, // RAM access bit
1594 0, // fast call/return mode select bit
1595 0, // second memory operand
1596 0, // second literal operand
1598 PCC_REGISTER, // inCond
1599 (PCC_W | PCC_Z), // outCond
1603 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1604 {PC_OPCODE, NULL, NULL, 0, NULL,
1611 NULL, // from branch
1618 0,0, // dest, bit instruction
1619 0,0, // branch, skip
1620 0, // literal operand
1621 0, // RAM access bit
1622 0, // fast call/return mode select bit
1623 1, // second memory operand
1624 0, // second literal operand
1626 PCC_REGISTER, // inCond
1627 PCC_REGISTER, // outCond
1631 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1632 {PC_OPCODE, NULL, NULL, 0, NULL,
1638 NULL, // from branch
1645 0,0, // dest, bit instruction
1646 0,0, // branch, skip
1647 1, // literal operand
1648 0, // RAM access bit
1649 0, // fast call/return mode select bit
1650 0, // second memory operand
1651 0, // second literal operand
1653 (PCC_NONE | PCC_LITERAL), // inCond
1654 PCC_REGISTER, // outCond - BSR
1658 pCodeInstruction pic16_pciMOVLW = {
1659 {PC_OPCODE, NULL, NULL, 0, NULL,
1665 NULL, // from branch
1672 0,0, // dest, bit instruction
1673 0,0, // branch, skip
1674 1, // literal operand
1675 0, // RAM access bit
1676 0, // fast call/return mode select bit
1677 0, // second memory operand
1678 0, // second literal operand
1680 (PCC_NONE | PCC_LITERAL), // inCond
1685 pCodeInstruction pic16_pciMOVWF = {
1686 {PC_OPCODE, NULL, NULL, 0, NULL,
1693 NULL, // from branch
1700 0,0, // dest, bit instruction
1701 0,0, // branch, skip
1702 0, // literal operand
1703 1, // RAM access bit
1704 0, // fast call/return mode select bit
1705 0, // second memory operand
1706 0, // second literal operand
1708 PCC_REGISTER, // inCond
1713 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1714 {PC_OPCODE, NULL, NULL, 0, NULL,
1720 NULL, // from branch
1727 0,0, // dest, bit instruction
1728 0,0, // branch, skip
1729 1, // literal operand
1730 0, // RAM access bit
1731 0, // fast call/return mode select bit
1732 0, // second memory operand
1733 0, // second literal operand
1735 (PCC_W | PCC_LITERAL), // inCond
1736 PCC_REGISTER, // outCond - PROD
1740 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1741 {PC_OPCODE, NULL, NULL, 0, NULL,
1747 NULL, // from branch
1754 0,0, // dest, bit instruction
1755 0,0, // branch, skip
1756 0, // literal operand
1757 1, // RAM access bit
1758 0, // fast call/return mode select bit
1759 0, // second memory operand
1760 0, // second literal operand
1762 (PCC_W | PCC_REGISTER), // inCond
1763 PCC_REGISTER, // outCond - PROD
1767 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1768 {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 1, // RAM access bit
1785 0, // fast call/return mode select bit
1786 0, // second memory operand
1787 0, // second literal operand
1789 PCC_REGISTER, // inCond
1790 (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
1794 pCodeInstruction pic16_pciNOP = {
1795 {PC_OPCODE, NULL, NULL, 0, NULL,
1801 NULL, // from branch
1808 0,0, // dest, bit instruction
1809 0,0, // branch, skip
1810 0, // literal operand
1811 0, // RAM access bit
1812 0, // fast call/return mode select bit
1813 0, // second memory operand
1814 0, // second literal operand
1817 PCC_NONE, // outCond
1821 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1822 {PC_OPCODE, NULL, NULL, 0, NULL,
1828 NULL, // from branch
1835 0,0, // dest, bit instruction
1836 0,0, // branch, skip
1837 0, // literal operand
1838 0, // RAM access bit
1839 0, // fast call/return mode select bit
1840 0, // second memory operand
1841 0, // second literal operand
1844 PCC_NONE , // outCond
1848 pCodeInstruction pic16_pciPUSH = {
1849 {PC_OPCODE, NULL, NULL, 0, NULL,
1855 NULL, // from branch
1862 0,0, // dest, bit instruction
1863 0,0, // branch, skip
1864 0, // literal operand
1865 0, // RAM access bit
1866 0, // fast call/return mode select bit
1867 0, // second memory operand
1868 0, // second literal operand
1871 PCC_NONE , // outCond
1875 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1876 {PC_OPCODE, NULL, NULL, 0, NULL,
1882 NULL, // from branch
1889 0,0, // dest, bit instruction
1890 0,0, // branch, skip
1891 0, // literal operand
1892 0, // RAM access bit
1893 0, // fast call/return mode select bit
1894 0, // second memory operand
1895 0, // second literal operand
1897 PCC_REL_ADDR, // inCond
1898 PCC_NONE , // outCond
1902 pCodeInstruction pic16_pciRETFIE = {
1903 {PC_OPCODE, NULL, NULL, 0, NULL,
1910 NULL, // from branch
1917 0,0, // dest, bit instruction
1918 1,0, // branch, skip
1919 0, // literal operand
1920 0, // RAM access bit
1921 1, // fast call/return mode select bit
1922 0, // second memory operand
1923 0, // second literal operand
1926 PCC_NONE, // outCond (not true... affects the GIE bit too)
1930 pCodeInstruction pic16_pciRETLW = {
1931 {PC_OPCODE, NULL, NULL, 0, NULL,
1938 NULL, // from branch
1945 0,0, // dest, bit instruction
1946 1,0, // branch, skip
1947 1, // literal operand
1948 0, // RAM access bit
1949 0, // fast call/return mode select bit
1950 0, // second memory operand
1951 0, // second literal operand
1953 PCC_LITERAL, // inCond
1958 pCodeInstruction pic16_pciRETURN = {
1959 {PC_OPCODE, NULL, NULL, 0, NULL,
1966 NULL, // from branch
1973 0,0, // dest, bit instruction
1974 1,0, // branch, skip
1975 0, // literal operand
1976 0, // RAM access bit
1977 1, // fast call/return mode select bit
1978 0, // second memory operand
1979 0, // second literal operand
1982 PCC_NONE, // outCond
1985 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1986 {PC_OPCODE, NULL, NULL, 0, NULL,
1993 NULL, // from branch
2000 1,0, // dest, bit instruction
2001 0,0, // branch, skip
2002 0, // literal operand
2003 1, // RAM access bit
2004 0, // fast call/return mode select bit
2005 0, // second memory operand
2006 0, // second literal operand
2008 (PCC_C | PCC_REGISTER), // inCond
2009 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2013 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
2014 {PC_OPCODE, NULL, NULL, 0, NULL,
2021 NULL, // from branch
2028 0,0, // dest, bit instruction
2029 0,0, // branch, skip
2030 0, // literal operand
2031 1, // RAM access bit
2032 0, // fast call/return mode select bit
2033 0, // second memory operand
2034 0, // second literal operand
2036 (PCC_C | PCC_REGISTER), // inCond
2037 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2041 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
2042 {PC_OPCODE, NULL, NULL, 0, NULL,
2049 NULL, // from branch
2056 1,0, // dest, bit instruction
2057 0,0, // branch, skip
2058 0, // literal operand
2059 1, // RAM access bit
2060 0, // fast call/return mode select bit
2061 0, // second memory operand
2062 0, // second literal operand
2064 PCC_REGISTER, // inCond
2065 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2068 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
2069 {PC_OPCODE, NULL, NULL, 0, NULL,
2076 NULL, // from branch
2083 0,0, // dest, bit instruction
2084 0,0, // branch, skip
2085 0, // literal operand
2086 1, // RAM access bit
2087 0, // fast call/return mode select bit
2088 0, // second memory operand
2089 0, // second literal operand
2091 PCC_REGISTER, // inCond
2092 (PCC_W | PCC_Z | PCC_N), // outCond
2095 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2096 {PC_OPCODE, NULL, NULL, 0, NULL,
2103 NULL, // from branch
2110 1,0, // dest, bit instruction
2111 0,0, // branch, skip
2112 0, // literal operand
2113 1, // RAM access bit
2114 0, // fast call/return mode select bit
2115 0, // second memory operand
2116 0, // second literal operand
2118 (PCC_C | PCC_REGISTER), // inCond
2119 (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2122 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2123 {PC_OPCODE, NULL, NULL, 0, NULL,
2130 NULL, // from branch
2137 0,0, // dest, bit instruction
2138 0,0, // branch, skip
2139 0, // literal operand
2140 1, // RAM access bit
2141 0, // fast call/return mode select bit
2142 0, // second memory operand
2143 0, // second literal operand
2145 (PCC_C | PCC_REGISTER), // inCond
2146 (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2149 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2150 {PC_OPCODE, NULL, NULL, 0, NULL,
2157 NULL, // from branch
2164 1,0, // dest, bit instruction
2165 0,0, // branch, skip
2166 0, // literal operand
2167 1, // RAM access bit
2168 0, // fast call/return mode select bit
2169 0, // second memory operand
2170 0, // second literal operand
2172 PCC_REGISTER, // inCond
2173 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2177 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2178 {PC_OPCODE, NULL, NULL, 0, NULL,
2185 NULL, // from branch
2192 0,0, // dest, bit instruction
2193 0,0, // branch, skip
2194 0, // literal operand
2195 1, // RAM access bit
2196 0, // fast call/return mode select bit
2197 0, // second memory operand
2198 0, // second literal operand
2200 PCC_REGISTER, // inCond
2201 (PCC_W | PCC_Z | PCC_N), // outCond
2205 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2206 {PC_OPCODE, NULL, NULL, 0, NULL,
2213 NULL, // from branch
2220 0,0, // dest, bit instruction
2221 0,0, // branch, skip
2222 0, // literal operand
2223 1, // RAM access bit
2224 0, // fast call/return mode select bit
2225 0, // second memory operand
2226 0, // second literal operand
2228 PCC_REGISTER, // inCond
2229 PCC_REGISTER , // outCond
2233 pCodeInstruction pic16_pciSUBLW = {
2234 {PC_OPCODE, NULL, NULL, 0, NULL,
2241 NULL, // from branch
2248 0,0, // dest, bit instruction
2249 0,0, // branch, skip
2250 1, // literal operand
2251 0, // RAM access bit
2252 0, // fast call/return mode select bit
2253 0, // second memory operand
2254 0, // second literal operand
2256 (PCC_W | PCC_LITERAL), // inCond
2257 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2261 pCodeInstruction pic16_pciSUBFWB = {
2262 {PC_OPCODE, NULL, NULL, 0, NULL,
2269 NULL, // from branch
2276 1,0, // dest, bit instruction
2277 0,0, // branch, skip
2278 0, // literal operand
2279 1, // RAM access bit
2280 0, // fast call/return mode select bit
2281 0, // second memory operand
2282 0, // second literal operand
2284 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2285 (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N), // outCond
2289 pCodeInstruction pic16_pciSUBWF = {
2290 {PC_OPCODE, NULL, NULL, 0, NULL,
2297 NULL, // from branch
2304 1,0, // dest, bit instruction
2305 0,0, // branch, skip
2306 0, // literal operand
2307 1, // RAM access bit
2308 0, // fast call/return mode select bit
2309 0, // second memory operand
2310 0, // second literal operand
2312 (PCC_W | PCC_REGISTER), // inCond
2313 (PCC_REGISTER | PCC_Z), // outCond
2317 pCodeInstruction pic16_pciSUBFW = {
2318 {PC_OPCODE, NULL, NULL, 0, NULL,
2325 NULL, // from branch
2332 0,0, // dest, bit instruction
2333 0,0, // branch, skip
2334 0, // literal operand
2335 1, // RAM access bit
2336 0, // fast call/return mode select bit
2337 0, // second memory operand
2338 0, // second literal operand
2340 (PCC_W | PCC_REGISTER), // inCond
2341 (PCC_W | PCC_Z | PCC_OV | PCC_N), // outCond
2345 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2346 {PC_OPCODE, NULL, NULL, 0, NULL,
2353 NULL, // from branch
2360 1,0, // dest, bit instruction
2361 0,0, // branch, skip
2362 0, // literal operand
2363 1, // RAM access bit
2364 0, // fast call/return mode select bit
2365 0, // second memory operand
2366 0, // second literal operand
2368 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2369 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2373 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2374 {PC_OPCODE, NULL, NULL, 0, NULL,
2381 NULL, // from branch
2388 0,0, // dest, bit instruction
2389 0,0, // branch, skip
2390 0, // literal operand
2391 1, // RAM access bit
2392 0, // fast call/return mode select bit
2393 0, // second memory operand
2394 0, // second literal operand
2396 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2397 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2401 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2402 {PC_OPCODE, NULL, NULL, 0, NULL,
2409 NULL, // from branch
2416 1,0, // dest, bit instruction
2417 0,0, // branch, skip
2418 0, // literal operand
2419 1, // RAM access bit
2420 0, // fast call/return mode select bit
2421 0, // second memory operand
2422 0, // second literal operand
2424 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2425 (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2429 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2430 {PC_OPCODE, NULL, NULL, 0, NULL,
2437 NULL, // from branch
2444 0,0, // dest, bit instruction
2445 0,0, // branch, skip
2446 0, // literal operand
2447 1, // RAM access bit
2448 0, // fast call/return mode select bit
2449 0, // second memory operand
2450 0, // second literal operand
2452 (PCC_W | PCC_REGISTER | PCC_C), // inCond
2453 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N), // outCond
2457 pCodeInstruction pic16_pciSWAPF = {
2458 {PC_OPCODE, NULL, NULL, 0, NULL,
2465 NULL, // from branch
2472 1,0, // dest, bit instruction
2473 0,0, // branch, skip
2474 0, // literal operand
2475 1, // RAM access bit
2476 0, // fast call/return mode select bit
2477 0, // second memory operand
2478 0, // second literal operand
2480 (PCC_REGISTER), // inCond
2481 (PCC_REGISTER), // outCond
2485 pCodeInstruction pic16_pciSWAPFW = {
2486 {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 1, // RAM access bit
2504 0, // fast call/return mode select bit
2505 0, // second memory operand
2506 0, // second literal operand
2508 (PCC_REGISTER), // inCond
2513 pCodeInstruction pic16_pciTBLRD = { // patch 15
2514 {PC_OPCODE, NULL, NULL, 0, NULL,
2520 NULL, // from branch
2527 0,0, // dest, bit instruction
2528 0,0, // branch, skip
2529 0, // literal operand
2530 0, // RAM access bit
2531 0, // fast call/return mode select bit
2532 0, // second memory operand
2533 0, // second literal operand
2536 PCC_NONE , // outCond
2540 pCodeInstruction pic16_pciTBLRD_POSTINC = { // patch 15
2541 {PC_OPCODE, NULL, NULL, 0, NULL,
2547 NULL, // from branch
2554 0,0, // dest, bit instruction
2555 0,0, // branch, skip
2556 0, // literal operand
2557 0, // RAM access bit
2558 0, // fast call/return mode select bit
2559 0, // second memory operand
2560 0, // second literal operand
2563 PCC_NONE , // outCond
2567 pCodeInstruction pic16_pciTBLRD_POSTDEC = { // patch 15
2568 {PC_OPCODE, NULL, NULL, 0, NULL,
2574 NULL, // from branch
2581 0,0, // dest, bit instruction
2582 0,0, // branch, skip
2583 0, // literal operand
2584 0, // RAM access bit
2585 0, // fast call/return mode select bit
2586 0, // second memory operand
2587 0, // second literal operand
2590 PCC_NONE , // outCond
2594 pCodeInstruction pic16_pciTBLRD_PREINC = { // patch 15
2595 {PC_OPCODE, NULL, NULL, 0, NULL,
2601 NULL, // from branch
2608 0,0, // dest, bit instruction
2609 0,0, // branch, skip
2610 0, // literal operand
2611 0, // RAM access bit
2612 0, // fast call/return mode select bit
2613 0, // second memory operand
2614 0, // second literal operand
2617 PCC_NONE , // outCond
2621 pCodeInstruction pic16_pciTBLWT = { // patch 15
2622 {PC_OPCODE, NULL, NULL, 0, NULL,
2628 NULL, // from branch
2635 0,0, // dest, bit instruction
2636 0,0, // branch, skip
2637 0, // literal operand
2638 0, // RAM access bit
2639 0, // fast call/return mode select bit
2640 0, // second memory operand
2641 0, // second literal operand
2644 PCC_NONE , // outCond
2648 pCodeInstruction pic16_pciTBLWT_POSTINC = { // patch 15
2649 {PC_OPCODE, NULL, NULL, 0, NULL,
2655 NULL, // from branch
2662 0,0, // dest, bit instruction
2663 0,0, // branch, skip
2664 0, // literal operand
2665 0, // RAM access bit
2666 0, // fast call/return mode select bit
2667 0, // second memory operand
2668 0, // second literal operand
2671 PCC_NONE , // outCond
2675 pCodeInstruction pic16_pciTBLWT_POSTDEC = { // patch 15
2676 {PC_OPCODE, NULL, NULL, 0, NULL,
2682 NULL, // from branch
2689 0,0, // dest, bit instruction
2690 0,0, // branch, skip
2691 0, // literal operand
2692 0, // RAM access bit
2693 0, // fast call/return mode select bit
2694 0, // second memory operand
2695 0, // second literal operand
2698 PCC_NONE , // outCond
2702 pCodeInstruction pic16_pciTBLWT_PREINC = { // patch 15
2703 {PC_OPCODE, NULL, NULL, 0, NULL,
2709 NULL, // from branch
2716 0,0, // dest, bit instruction
2717 0,0, // branch, skip
2718 0, // literal operand
2719 0, // RAM access bit
2720 0, // fast call/return mode select bit
2721 0, // second memory operand
2722 0, // second literal operand
2725 PCC_NONE , // outCond
2729 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2730 {PC_OPCODE, NULL, NULL, 0, NULL,
2737 NULL, // from branch
2744 0,0, // dest, bit instruction
2745 1,1, // branch, skip
2746 0, // literal operand
2747 1, // RAM access bit
2748 0, // fast call/return mode select bit
2749 0, // second memory operand
2750 0, // second literal operand
2752 PCC_REGISTER, // inCond
2753 PCC_NONE, // outCond
2757 pCodeInstruction pic16_pciXORWF = {
2758 {PC_OPCODE, NULL, NULL, 0, NULL,
2765 NULL, // from branch
2772 1,0, // dest, bit instruction
2773 0,0, // branch, skip
2774 0, // literal operand
2775 1, // RAM access bit
2776 0, // fast call/return mode select bit
2777 0, // second memory operand
2778 0, // second literal operand
2780 (PCC_W | PCC_REGISTER), // inCond
2781 (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2785 pCodeInstruction pic16_pciXORFW = {
2786 {PC_OPCODE, NULL, NULL, 0, NULL,
2793 NULL, // from branch
2800 0,0, // dest, bit instruction
2801 0,0, // branch, skip
2802 0, // literal operand
2803 1, // RAM access bit
2804 0, // fast call/return mode select bit
2805 0, // second memory operand
2806 0, // second literal operand
2808 (PCC_W | PCC_REGISTER), // inCond
2809 (PCC_W | PCC_Z | PCC_N), // outCond
2813 pCodeInstruction pic16_pciXORLW = {
2814 {PC_OPCODE, NULL, NULL, 0, NULL,
2821 NULL, // from branch
2828 0,0, // dest, bit instruction
2829 0,0, // branch, skip
2830 1, // literal operand
2831 1, // RAM access bit
2832 0, // fast call/return mode select bit
2833 0, // second memory operand
2834 0, // second literal operand
2836 (PCC_W | PCC_LITERAL), // inCond
2837 (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N), // outCond
2842 pCodeInstruction pic16_pciBANKSEL = {
2843 {PC_OPCODE, NULL, NULL, 0, NULL,
2849 NULL, // from branch
2856 0,0, // dest, bit instruction
2857 0,0, // branch, skip
2858 0, // literal operand
2859 0, // RAM access bit
2860 0, // fast call/return mode select bit
2861 0, // second memory operand
2862 0, // second literal operand
2865 PCC_NONE, // outCond
2870 #define MAX_PIC16MNEMONICS 100
2871 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2873 //#define USE_VSNPRINTF
2876 #ifdef USE_VSNPRINTF
2877 // Alas, vsnprintf is not ANSI standard, and does not exist
2878 // on Solaris (and probably other non-Gnu flavored Unixes).
2880 /*-----------------------------------------------------------------*/
2881 /* SAFE_snprintf - like snprintf except the string pointer is */
2882 /* after the string has been printed to. This is */
2883 /* useful for printing to string as though if it */
2884 /* were a stream. */
2885 /*-----------------------------------------------------------------*/
2886 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2894 va_start(val, format);
2896 vsnprintf(*str, *size, format, val);
2902 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2903 fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2912 // This version is *not* safe, despite the name.
2914 void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
2918 static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2923 va_start(val, format);
2925 vsprintf(buffer, format, val);
2928 len = strlen(buffer);
2930 fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2931 fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2934 strcpy(*str, buffer);
2940 #endif // USE_VSNPRINTF
2943 extern set *externs;
2944 extern void pic16_initStack(int base_address, int size);
2945 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2946 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2947 extern void pic16_init_pic(char *);
2949 void pic16_pCodeInitRegisters(void)
2951 static int initialized=0;
2958 // pic16_initStack(0xfff, 8);
2959 pic16_init_pic(port->processor);
2961 pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2962 pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2963 pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2964 pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2965 pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2966 pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2967 pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2969 pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2970 pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2971 pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2973 pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2974 pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2975 pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2976 pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2978 pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2979 pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2980 pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2981 pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2982 pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2983 pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2985 pic16_stackpnt_lo = &pic16_pc_fsr1l;
2986 pic16_stackpnt_hi = &pic16_pc_fsr1h;
2987 pic16_stack_postdec = &pic16_pc_postdec1;
2988 pic16_stack_postinc = &pic16_pc_postinc1;
2989 pic16_stack_preinc = &pic16_pc_preinc1;
2990 pic16_stack_plusw = &pic16_pc_plusw1;
2992 pic16_framepnt_lo = &pic16_pc_fsr2l;
2993 pic16_framepnt_hi = &pic16_pc_fsr2h;
2994 pic16_frame_postdec = &pic16_pc_postdec2;
2995 pic16_frame_postinc = &pic16_pc_postinc2;
2996 pic16_frame_preinc = &pic16_pc_preinc2;
2997 pic16_frame_plusw = &pic16_pc_plusw2;
2999 pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
3000 pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
3001 pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
3002 pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
3003 pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
3005 pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
3006 pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
3007 pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
3008 pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
3009 pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
3011 pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
3012 pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
3013 pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
3014 pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
3015 pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
3017 pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
3018 pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
3021 pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
3022 pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
3023 pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
3024 pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
3027 pic16_pc_status.rIdx = IDX_STATUS;
3028 pic16_pc_intcon.rIdx = IDX_INTCON;
3029 pic16_pc_pcl.rIdx = IDX_PCL;
3030 pic16_pc_pclath.rIdx = IDX_PCLATH;
3031 pic16_pc_pclatu.rIdx = IDX_PCLATU;
3032 pic16_pc_wreg.rIdx = IDX_WREG;
3033 pic16_pc_bsr.rIdx = IDX_BSR;
3035 pic16_pc_tosl.rIdx = IDX_TOSL;
3036 pic16_pc_tosh.rIdx = IDX_TOSH;
3037 pic16_pc_tosu.rIdx = IDX_TOSU;
3039 pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
3040 pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
3041 pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
3042 pic16_pc_tablat.rIdx = IDX_TABLAT;
3044 pic16_pc_fsr0l.rIdx = IDX_FSR0L;
3045 pic16_pc_fsr0h.rIdx = IDX_FSR0H;
3046 pic16_pc_fsr1l.rIdx = IDX_FSR1L;
3047 pic16_pc_fsr1h.rIdx = IDX_FSR1H;
3048 pic16_pc_fsr2l.rIdx = IDX_FSR2L;
3049 pic16_pc_fsr2h.rIdx = IDX_FSR2H;
3050 pic16_pc_indf0.rIdx = IDX_INDF0;
3051 pic16_pc_postinc0.rIdx = IDX_POSTINC0;
3052 pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
3053 pic16_pc_preinc0.rIdx = IDX_PREINC0;
3054 pic16_pc_plusw0.rIdx = IDX_PLUSW0;
3055 pic16_pc_indf1.rIdx = IDX_INDF1;
3056 pic16_pc_postinc1.rIdx = IDX_POSTINC1;
3057 pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
3058 pic16_pc_preinc1.rIdx = IDX_PREINC1;
3059 pic16_pc_plusw1.rIdx = IDX_PLUSW1;
3060 pic16_pc_indf2.rIdx = IDX_INDF2;
3061 pic16_pc_postinc2.rIdx = IDX_POSTINC2;
3062 pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
3063 pic16_pc_preinc2.rIdx = IDX_PREINC2;
3064 pic16_pc_plusw2.rIdx = IDX_PLUSW2;
3065 pic16_pc_prodl.rIdx = IDX_PRODL;
3066 pic16_pc_prodh.rIdx = IDX_PRODH;
3068 pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
3069 pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
3070 pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
3072 pic16_pc_kzero.rIdx = IDX_KZ;
3073 pic16_pc_wsave.rIdx = IDX_WSAVE;
3074 pic16_pc_ssave.rIdx = IDX_SSAVE;
3076 pic16_pc_eecon1.rIdx = IDX_EECON1;
3077 pic16_pc_eecon2.rIdx = IDX_EECON2;
3078 pic16_pc_eedata.rIdx = IDX_EEDATA;
3079 pic16_pc_eeadr.rIdx = IDX_EEADR;
3082 pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
3083 pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
3085 pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
3086 pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
3088 /* probably should put this in a separate initialization routine */
3089 pb_dead_pcodes = newpBlock();
3094 /*-----------------------------------------------------------------*/
3095 /* mnem2key - convert a pic mnemonic into a hash key */
3096 /* (BTW - this spreads the mnemonics quite well) */
3098 /*-----------------------------------------------------------------*/
3100 int mnem2key(char const *mnem)
3109 key += toupper(*mnem++) +1;
3113 return (key & 0x1f);
3118 void pic16initMnemonics(void)
3123 pCodeInstruction *pci;
3125 if(mnemonics_initialized)
3128 // NULL out the array before making the assignments
3129 // since we check the array contents below this initialization.
3131 for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3132 pic16Mnemonics[i] = NULL;
3135 pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3136 pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3137 pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3138 pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3139 pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3140 pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3141 pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3142 pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3143 pic16Mnemonics[POC_BC] = &pic16_pciBC;
3144 pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3145 pic16Mnemonics[POC_BN] = &pic16_pciBN;
3146 pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3147 pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3148 pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3149 pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3150 pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3151 pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3152 pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3153 pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3154 pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3155 pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3156 pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3157 pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3158 pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3159 pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3160 pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3161 pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3162 pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3163 pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3164 pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3165 pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3166 pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3167 pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3168 pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3169 pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3170 pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3171 pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3172 pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3173 pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3174 pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3175 pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3176 pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3177 pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3178 pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3179 pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3180 pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3181 pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3182 pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3183 pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3184 pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3185 pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3186 pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3187 pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3188 pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3189 pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3190 pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3191 pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3192 pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3193 pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3194 pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3195 pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3196 pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3197 pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3198 pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3199 pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3200 pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3201 pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3202 pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3203 pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3204 pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3205 pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3206 pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3207 pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3208 pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3209 pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3210 pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3211 pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3212 pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3213 pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3214 pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3215 pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3216 pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3217 pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3218 pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3219 pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3220 pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3221 pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3222 pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3223 pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3224 pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3225 pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3226 pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3227 pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3228 pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3230 for(i=0; i<MAX_PIC16MNEMONICS; i++)
3231 if(pic16Mnemonics[i])
3232 hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3233 pci = hTabFirstItem(pic16MnemonicsHash, &key);
3236 DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3237 pci = hTabNextItem(pic16MnemonicsHash, &key);
3240 mnemonics_initialized = 1;
3243 int pic16_getpCodePeepCommand(char *cmd);
3245 int pic16_getpCode(char *mnem,unsigned dest)
3248 pCodeInstruction *pci;
3249 int key = mnem2key(mnem);
3251 if(!mnemonics_initialized)
3252 pic16initMnemonics();
3254 pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3258 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3259 if((pci->num_ops <= 1)
3260 || (pci->isModReg == dest)
3262 || (pci->num_ops <= 2 && pci->isAccess)
3263 || (pci->num_ops <= 2 && pci->isFastCall)
3264 || (pci->num_ops <= 2 && pci->is2MemOp)
3265 || (pci->num_ops <= 2 && pci->is2LitOp) )
3269 pci = hTabNextItemWK (pic16MnemonicsHash);
3276 /*-----------------------------------------------------------------*
3277 * pic16initpCodePeepCommands
3279 *-----------------------------------------------------------------*/
3280 void pic16initpCodePeepCommands(void)
3288 hTabAddItem(&pic16pCodePeepCommandsHash,
3289 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
3291 } while (peepCommands[i].cmd);
3293 pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3296 //fprintf(stderr, "peep command %s key %d\n",pcmd->cmd,pcmd->id);
3297 pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3302 /*-----------------------------------------------------------------
3305 *-----------------------------------------------------------------*/
3307 int pic16_getpCodePeepCommand(char *cmd)
3311 int key = mnem2key(cmd);
3314 pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3317 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3318 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3322 pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3329 static char getpBlock_dbName(pBlock *pb)
3335 return pb->cmemmap->dbName;
3339 void pic16_pBlockConvert2ISR(pBlock *pb)
3343 if(pb->cmemmap)pb->cmemmap = NULL;
3347 if(pic16_pcode_verbose)
3348 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3351 void pic16_pBlockConvert2Absolute(pBlock *pb)
3354 if(pb->cmemmap)pb->cmemmap = NULL;
3358 if(pic16_pcode_verbose)
3359 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3362 /*-----------------------------------------------------------------*/
3363 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all */
3364 /* instances to the front of the doubly linked */
3365 /* list of pBlocks */
3366 /*-----------------------------------------------------------------*/
3368 void pic16_movepBlock2Head(char dbName)
3373 /* this can happen in sources without code,
3374 * only variable definitions */
3375 if(!the_pFile)return;
3377 pb = the_pFile->pbHead;
3381 if(getpBlock_dbName(pb) == dbName) {
3382 pBlock *pbn = pb->next;
3383 pb->next = the_pFile->pbHead;
3384 the_pFile->pbHead->prev = pb;
3385 the_pFile->pbHead = pb;
3388 pb->prev->next = pbn;
3390 // If the pBlock that we just moved was the last
3391 // one in the link of all of the pBlocks, then we
3392 // need to point the tail to the block just before
3393 // the one we moved.
3394 // Note: if pb->next is NULL, then pb must have
3395 // been the last pBlock in the chain.
3398 pbn->prev = pb->prev;
3400 the_pFile->pbTail = pb->prev;
3411 void pic16_copypCode(FILE *of, char dbName)
3415 if(!of || !the_pFile)
3418 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3419 if(getpBlock_dbName(pb) == dbName) {
3420 // fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3422 pic16_printpBlock(of,pb);
3427 void pic16_pcode_test(void)
3430 DFPRINTF((stderr,"pcode is alive!\n"));
3440 /* create the file name */
3441 strcpy(buffer,dstFileName);
3442 strcat(buffer,".p");
3444 if( !(pFile = fopen(buffer, "w" ))) {
3445 werror(E_FILE_OPEN_ERR,buffer);
3449 fprintf(pFile,"pcode dump\n\n");
3451 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3452 fprintf(pFile,"\n\tNew pBlock\n\n");
3454 fprintf(pFile,"%s",pb->cmemmap->sname);
3456 fprintf(pFile,"internal pblock");
3458 fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3459 pic16_printpBlock(pFile,pb);
3465 unsigned long pic16_countInstructions(void)
3469 unsigned long isize=0;
3471 if(!the_pFile)return -1;
3473 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3474 for(pc = pb->pcHead; pc; pc = pc->next) {
3475 if(isPCI(pc) || isPCAD(pc))isize += PCI(pc)->isize;
3482 /*-----------------------------------------------------------------*/
3483 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg- */
3484 /* ister, RegCond will return the bit being referenced. */
3486 /* fixme - why not just OR in the pcop bit field */
3487 /*-----------------------------------------------------------------*/
3489 static int RegCond(pCodeOp *pcop)
3495 if(!pcop->name)return 0;
3497 if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3498 switch(PCORB(pcop)->bit) {
3512 /*-----------------------------------------------------------------*/
3513 /* pic16_newpCode - create and return a newly initialized pCode */
3515 /* fixme - rename this */
3517 /* The purpose of this routine is to create a new Instruction */
3518 /* pCode. This is called by gen.c while the assembly code is being */
3522 /* PIC_OPCODE op - the assembly instruction we wish to create. */
3523 /* (note that the op is analogous to but not the */
3524 /* same thing as the opcode of the instruction.) */
3525 /* pCdoeOp *pcop - pointer to the operand of the instruction. */
3528 /* a pointer to the new malloc'd pCode is returned. */
3532 /*-----------------------------------------------------------------*/
3533 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3535 pCodeInstruction *pci ;
3537 if(!mnemonics_initialized)
3538 pic16initMnemonics();
3540 pci = Safe_calloc(1, sizeof(pCodeInstruction));
3542 if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3543 memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3546 if(pci->inCond & PCC_EXAMINE_PCOP)
3547 pci->inCond |= RegCond(pcop);
3549 if(pci->outCond & PCC_EXAMINE_PCOP)
3550 pci->outCond |= RegCond(pcop);
3552 pci->pc.prev = pci->pc.next = NULL;
3553 return (pCode *)pci;
3556 fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3562 /*-----------------------------------------------------------------*/
3563 /* pic16_newpCodeWild - create a "wild" as in wild card pCode */
3565 /* Wild pcodes are used during the peep hole optimizer to serve */
3566 /* as place holders for any instruction. When a snippet of code is */
3567 /* compared to a peep hole rule, the wild card opcode will match */
3568 /* any instruction. However, the optional operand and label are */
3569 /* additional qualifiers that must also be matched before the */
3570 /* line (of assembly code) is declared matched. Note that the */
3571 /* operand may be wild too. */
3573 /* Note, a wild instruction is specified just like a wild var: */
3574 /* %4 ; A wild instruction, */
3575 /* See the peeph.def file for additional examples */
3577 /*-----------------------------------------------------------------*/
3579 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3584 pcw = Safe_calloc(1,sizeof(pCodeWild));
3586 pcw->pci.pc.type = PC_WILD;
3587 pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3588 pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3589 pcw->pci.pc.pb = NULL;
3591 // pcw->pci.pc.analyze = genericAnalyze;
3592 pcw->pci.pc.destruct = genericDestruct;
3593 pcw->pci.pc.print = genericPrint;
3595 pcw->id = pCodeID; // this is the 'n' in %n
3596 pcw->operand = optional_operand;
3597 pcw->label = optional_label;
3599 pcw->mustBeBitSkipInst = 0;
3600 pcw->mustNotBeBitSkipInst = 0;
3601 pcw->invertBitSkipInst = 0;
3603 return ( (pCode *)pcw);
3607 /*-----------------------------------------------------------------*/
3608 /* newPcodeInlineP - create a new pCode from a char string */
3609 /*-----------------------------------------------------------------*/
3612 pCode *pic16_newpCodeInlineP(char *cP)
3617 pcc = Safe_calloc(1,sizeof(pCodeComment));
3619 pcc->pc.type = PC_INLINE;
3620 pcc->pc.prev = pcc->pc.next = NULL;
3621 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3624 // pcc->pc.analyze = genericAnalyze;
3625 pcc->pc.destruct = genericDestruct;
3626 pcc->pc.print = genericPrint;
3629 pcc->comment = Safe_strdup(cP);
3631 pcc->comment = NULL;
3633 return ( (pCode *)pcc);
3637 /*-----------------------------------------------------------------*/
3638 /* newPcodeCharP - create a new pCode from a char string */
3639 /*-----------------------------------------------------------------*/
3641 pCode *pic16_newpCodeCharP(char *cP)
3646 pcc = Safe_calloc(1,sizeof(pCodeComment));
3648 pcc->pc.type = PC_COMMENT;
3649 pcc->pc.prev = pcc->pc.next = NULL;
3650 //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3653 // pcc->pc.analyze = genericAnalyze;
3654 pcc->pc.destruct = genericDestruct;
3655 pcc->pc.print = genericPrint;
3658 pcc->comment = Safe_strdup(cP);
3660 pcc->comment = NULL;
3662 return ( (pCode *)pcc);
3666 /*-----------------------------------------------------------------*/
3667 /* pic16_newpCodeFunction - */
3668 /*-----------------------------------------------------------------*/
3671 pCode *pic16_newpCodeFunction(char *mod,char *f)
3675 pcf = Safe_calloc(1,sizeof(pCodeFunction));
3677 pcf->pc.type = PC_FUNCTION;
3678 pcf->pc.prev = pcf->pc.next = NULL;
3679 //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3682 // pcf->pc.analyze = genericAnalyze;
3683 pcf->pc.destruct = genericDestruct;
3684 pcf->pc.print = pCodePrintFunction;
3690 pcf->modname = Safe_calloc(1,strlen(mod)+1);
3691 strcpy(pcf->modname,mod);
3693 pcf->modname = NULL;
3696 pcf->fname = Safe_calloc(1,strlen(f)+1);
3697 strcpy(pcf->fname,f);
3701 pcf->stackusage = 0;
3703 return ( (pCode *)pcf);
3706 /*-----------------------------------------------------------------*/
3707 /* pic16_newpCodeFlow */
3708 /*-----------------------------------------------------------------*/
3709 static void destructpCodeFlow(pCode *pc)
3711 if(!pc || !isPCFL(pc))
3718 pic16_unlinkpCode(pc);
3720 deleteSet(&PCFL(pc)->registers);
3721 deleteSet(&PCFL(pc)->from);
3722 deleteSet(&PCFL(pc)->to);
3724 /* Instead of deleting the memory used by this pCode, mark
3725 * the object as bad so that if there's a pointer to this pCode
3726 * dangling around somewhere then (hopefully) when the type is
3727 * checked we'll catch it.
3731 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3737 pCode *pic16_newpCodeFlow(void )
3741 //_ALLOC(pcflow,sizeof(pCodeFlow));
3742 pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3744 pcflow->pc.type = PC_FLOW;
3745 pcflow->pc.prev = pcflow->pc.next = NULL;
3746 pcflow->pc.pb = NULL;
3748 // pcflow->pc.analyze = genericAnalyze;
3749 pcflow->pc.destruct = destructpCodeFlow;
3750 pcflow->pc.print = genericPrint;
3752 pcflow->pc.seq = GpcFlowSeq++;
3754 pcflow->from = pcflow->to = NULL;
3756 pcflow->inCond = PCC_NONE;
3757 pcflow->outCond = PCC_NONE;
3759 pcflow->firstBank = -1;
3760 pcflow->lastBank = -1;
3762 pcflow->FromConflicts = 0;
3763 pcflow->ToConflicts = 0;
3767 pcflow->registers = newSet();
3769 return ( (pCode *)pcflow);
3773 /*-----------------------------------------------------------------*/
3774 /*-----------------------------------------------------------------*/
3775 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3777 pCodeFlowLink *pcflowLink;
3779 pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3781 pcflowLink->pcflow = pcflow;
3782 pcflowLink->bank_conflict = 0;
3787 /*-----------------------------------------------------------------*/
3788 /* pic16_newpCodeCSource - create a new pCode Source Symbol */
3789 /*-----------------------------------------------------------------*/
3791 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3796 pccs = Safe_calloc(1,sizeof(pCodeCSource));
3798 pccs->pc.type = PC_CSOURCE;
3799 pccs->pc.prev = pccs->pc.next = NULL;
3802 pccs->pc.destruct = genericDestruct;
3803 pccs->pc.print = genericPrint;
3805 pccs->line_number = ln;
3807 pccs->line = Safe_strdup(l);
3812 pccs->file_name = Safe_strdup(f);
3814 pccs->file_name = NULL;
3816 return ( (pCode *)pccs);
3821 /*******************************************************************/
3822 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive */
3823 /* added by VR 6-Jun-2003 */
3824 /*******************************************************************/
3826 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3833 pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3834 pcad->pci.pc.type = PC_ASMDIR;
3835 pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3836 pcad->pci.pc.pb = NULL;
3837 pcad->pci.isize = 2;
3838 pcad->pci.pc.destruct = genericDestruct;
3839 pcad->pci.pc.print = genericPrint;
3841 if(asdir && *asdir) {
3843 while(isspace(*asdir))asdir++; // strip any white space from the beginning
3845 pcad->directive = Safe_strdup( asdir );
3848 va_start(ap, argfmt);
3850 memset(buffer, 0, sizeof(buffer));
3851 if(argfmt && *argfmt)
3852 vsprintf(buffer, argfmt, ap);
3856 while(isspace(*lbp))lbp++;
3859 pcad->arg = Safe_strdup( lbp );
3861 return ((pCode *)pcad);
3864 /*-----------------------------------------------------------------*/
3865 /* pCodeLabelDestruct - free memory used by a label. */
3866 /*-----------------------------------------------------------------*/
3867 static void pCodeLabelDestruct(pCode *pc)
3873 // if((pc->type == PC_LABEL) && PCL(pc)->label)
3874 // free(PCL(pc)->label);
3876 /* Instead of deleting the memory used by this pCode, mark
3877 * the object as bad so that if there's a pointer to this pCode
3878 * dangling around somewhere then (hopefully) when the type is
3879 * checked we'll catch it.
3883 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3889 pCode *pic16_newpCodeLabel(char *name, int key)
3895 pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3897 pcl->pc.type = PC_LABEL;
3898 pcl->pc.prev = pcl->pc.next = NULL;
3899 //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3902 // pcl->pc.analyze = genericAnalyze;
3903 pcl->pc.destruct = pCodeLabelDestruct;
3904 pcl->pc.print = pCodePrintLabel;
3911 sprintf(s,"_%05d_DS_",key);
3916 pcl->label = Safe_strdup(s);
3918 // if(pic16_pcode_verbose)
3919 // fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3922 return ( (pCode *)pcl);
3926 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3928 pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3932 return ( (pCode *)pcl );
3935 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3939 pci = Safe_calloc(1, sizeof(pCodeInfo));
3940 pci->pci.pc.type = PC_INFO;
3941 pci->pci.pc.prev = pci->pci.pc.next = NULL;
3942 pci->pci.pc.pb = NULL;
3943 pci->pci.label = NULL;
3945 pci->pci.pc.destruct = genericDestruct;
3946 pci->pci.pc.print = genericPrint;
3951 return ((pCode *)pci);
3955 /*-----------------------------------------------------------------*/
3956 /* newpBlock - create and return a pointer to a new pBlock */
3957 /*-----------------------------------------------------------------*/
3958 static pBlock *newpBlock(void)
3963 PpB = Safe_calloc(1,sizeof(pBlock) );
3964 PpB->next = PpB->prev = NULL;
3966 PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3967 PpB->tregisters = NULL;
3969 PpB->FlowTree = NULL;
3975 /*-----------------------------------------------------------------*/
3976 /* pic16_newpCodeChain - create a new chain of pCodes */
3977 /*-----------------------------------------------------------------*
3979 * This function will create a new pBlock and the pointer to the
3980 * pCode that is passed in will be the first pCode in the block.
3981 *-----------------------------------------------------------------*/
3984 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3987 pBlock *pB = newpBlock();
3989 pB->pcHead = pB->pcTail = pc;
3998 /*-----------------------------------------------------------------*/
3999 /* pic16_newpCodeOpLabel - Create a new label given the key */
4000 /* Note, a negative key means that the label is part of wild card */
4001 /* (and hence a wild card label) used in the pCodePeep */
4002 /* optimizations). */
4003 /*-----------------------------------------------------------------*/
4005 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
4008 static int label_key=-1;
4012 pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
4013 pcop->type = PO_LABEL;
4018 sprintf(s=buffer,"_%05d_DS_",key);
4020 s = name, key = label_key--;
4023 pcop->name = Safe_strdup(s);
4025 ((pCodeOpLabel *)pcop)->key = key;
4027 //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4031 /*-----------------------------------------------------------------*/
4032 /*-----------------------------------------------------------------*/
4033 pCodeOp *pic16_newpCodeOpLit(int lit)
4039 pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4040 pcop->type = PO_LITERAL;
4044 sprintf(s,"0x%02hhx", (unsigned char)lit);
4046 // sprintf(s, "%i", lit);
4049 pcop->name = Safe_strdup(s);
4051 ((pCodeOpLit *)pcop)->lit = lit;
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4060 char *s = buffer, tbuf[256], *tb=tbuf;
4064 tb = pic16_get_op(arg2, NULL, 0);
4065 pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4066 pcop->type = PO_LITERAL;
4070 sprintf(s,"0x%02x, %s", (unsigned char)lit, tb);
4072 pcop->name = Safe_strdup(s);
4075 ((pCodeOpLit2 *)pcop)->lit = lit;
4076 ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4081 /*-----------------------------------------------------------------*/
4082 /*-----------------------------------------------------------------*/
4083 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4087 pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4088 pcop->type = PO_IMMEDIATE;
4090 regs *r = pic16_dirregWithName(name);
4091 pcop->name = Safe_strdup(name);
4095 // fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4096 PCOI(pcop)->rIdx = r->rIdx;
4098 // fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4099 PCOI(pcop)->rIdx = -1;
4101 // fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4106 PCOI(pcop)->index = index;
4107 PCOI(pcop)->offset = offset;
4108 PCOI(pcop)->_const = code_space;
4113 /*-----------------------------------------------------------------*/
4114 /*-----------------------------------------------------------------*/
4115 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4121 if(!pcwb || !subtype) {
4122 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4126 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4127 pcop->type = PO_WILD;
4128 sprintf(s,"%%%d",id);
4129 pcop->name = Safe_strdup(s);
4131 PCOW(pcop)->id = id;
4132 PCOW(pcop)->pcwb = pcwb;
4133 PCOW(pcop)->subtype = subtype;
4134 PCOW(pcop)->matched = NULL;
4136 PCOW(pcop)->pcop2 = NULL;
4141 /*-----------------------------------------------------------------*/
4142 /*-----------------------------------------------------------------*/
4143 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4149 if(!pcwb || !subtype || !subtype2) {
4150 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4154 pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4155 pcop->type = PO_WILD;
4156 sprintf(s,"%%%d",id);
4157 pcop->name = Safe_strdup(s);
4159 PCOW(pcop)->id = id;
4160 PCOW(pcop)->pcwb = pcwb;
4161 PCOW(pcop)->subtype = subtype;
4162 PCOW(pcop)->matched = NULL;
4164 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4166 if(!subtype2->name) {
4167 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4168 PCOW2(pcop)->pcop.type = PO_WILD;
4169 sprintf(s, "%%%d", id2);
4170 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4171 PCOW2(pcop)->id = id2;
4172 PCOW2(pcop)->subtype = subtype2;
4174 // fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4175 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4177 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4179 // fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4180 // pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4189 /*-----------------------------------------------------------------*/
4190 /*-----------------------------------------------------------------*/
4191 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4195 pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4196 pcop->type = PO_GPR_BIT;
4198 pcop->name = Safe_strdup(s);
4202 PCORB(pcop)->bit = bit;
4203 PCORB(pcop)->inBitSpace = inBitSpace;
4204 PCORB(pcop)->subtype = subt;
4206 /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4207 PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4208 // fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4209 // PCOR(pcop)->rIdx = 0;
4214 /*-----------------------------------------------------------------*
4215 * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4217 * If rIdx >=0 then a specific register from the set of registers
4218 * will be selected. If rIdx <0, then a new register will be searched
4220 *-----------------------------------------------------------------*/
4222 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4226 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4231 PCOR(pcop)->rIdx = rIdx;
4232 PCOR(pcop)->r = pic16_regWithIdx(rIdx);
4234 PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
4237 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4239 fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4240 __FUNCTION__, __LINE__);
4245 pcop->type = PCOR(pcop)->r->pc_type;
4250 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4255 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4256 PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4257 PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4258 pcop->type = PCOR(pcop)->r->pc_type;
4259 pcop->name = PCOR(pcop)->r->name;
4261 // if(pic16_pcode_verbose) {
4262 // fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4263 // __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4269 /*-----------------------------------------------------------------*/
4270 /*-----------------------------------------------------------------*/
4271 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4275 pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4278 pcop->key = Safe_strdup( key );
4280 return (PCOP(pcop));
4283 /*-----------------------------------------------------------------*/
4284 /*-----------------------------------------------------------------*/
4285 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4287 pCodeOpLocalReg *pcop;
4289 pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4293 return (PCOP(pcop));
4297 /*-----------------------------------------------------------------*/
4298 /*-----------------------------------------------------------------*/
4300 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4307 pcop = pic16_newpCodeOpBit(name, -1,0, type);
4311 pcop = pic16_newpCodeOpLit(-1);
4315 pcop = pic16_newpCodeOpLabel(NULL,-1);
4318 pcop = pic16_newpCodeOpReg(-1);
4321 case PO_GPR_REGISTER:
4323 pcop = pic16_newpCodeOpRegFromStr(name);
4325 pcop = pic16_newpCodeOpReg(-1);
4329 pcop = Safe_calloc(1,sizeof(pCodeOp) );
4332 pcop->name = Safe_strdup(name);
4340 #define DB_ITEMS_PER_LINE 8
4342 typedef struct DBdata
4349 static int DBd_init = -1;
4351 /*-----------------------------------------------------------------*/
4352 /* Initialiase "DB" data buffer */
4353 /*-----------------------------------------------------------------*/
4354 void pic16_initDB(void)
4360 /*-----------------------------------------------------------------*/
4361 /* Flush pending "DB" data to a pBlock */
4363 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4364 /*-----------------------------------------------------------------*/
4365 void pic16_flushDB(char ptype, void *p)
4369 pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4372 fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4375 fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4379 DBd.buffer[0] = '\0';
4384 /*-----------------------------------------------------------------*/
4385 /* Add "DB" directives to a pBlock */
4386 /*-----------------------------------------------------------------*/
4387 void pic16_emitDB(char c, char ptype, void *p)
4392 // we need to initialize
4395 DBd.buffer[0] = '\0';
4398 l = strlen(DBd.buffer);
4399 sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4401 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4404 if (DBd.count>= DB_ITEMS_PER_LINE)
4405 pic16_flushDB(ptype, p);
4408 void pic16_emitDS(char *s, char ptype, void *p)
4413 // we need to initialize
4416 DBd.buffer[0] = '\0';
4419 l = strlen(DBd.buffer);
4420 sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4422 // fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4424 DBd.count++; //=strlen(s);
4426 pic16_flushDB(ptype, p);
4430 /*-----------------------------------------------------------------*/
4431 /*-----------------------------------------------------------------*/
4432 void pic16_pCodeConstString(char *name, char *value)
4436 // fprintf(stderr, " %s %s %s\n",__FUNCTION__,name,value);
4441 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4443 pic16_addpBlock(pb);
4445 // sprintf(buffer,"; %s = ", name);
4446 // strcat(buffer, value);
4447 // fputs(buffer, stderr);
4449 // pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4450 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4453 pic16_emitDB(*value, 'p', (void *)pb);
4455 pic16_flushDB('p', (void *)pb);
4458 /*-----------------------------------------------------------------*/
4459 /*-----------------------------------------------------------------*/
4461 static void pCodeReadCodeTable(void)
4465 fprintf(stderr, " %s\n",__FUNCTION__);
4467 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4469 pic16_addpBlock(pb);
4471 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4472 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4473 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4474 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4476 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4477 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4478 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4479 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4484 /*-----------------------------------------------------------------*/
4485 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list */
4486 /*-----------------------------------------------------------------*/
4487 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4494 /* If this is the first pcode to be added to a block that
4495 * was initialized with a NULL pcode, then go ahead and
4496 * make this pcode the head and tail */
4497 pb->pcHead = pb->pcTail = pc;
4500 pb->pcTail->next = pc;
4502 pc->prev = pb->pcTail;
4509 /*-----------------------------------------------------------------*/
4510 /* pic16_addpBlock - place a pBlock into the pFile */
4511 /*-----------------------------------------------------------------*/
4512 void pic16_addpBlock(pBlock *pb)
4514 // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4517 /* First time called, we'll pass through here. */
4518 //_ALLOC(the_pFile,sizeof(pFile));
4519 the_pFile = Safe_calloc(1,sizeof(pFile));
4520 the_pFile->pbHead = the_pFile->pbTail = pb;
4521 the_pFile->functions = NULL;
4525 the_pFile->pbTail->next = pb;
4526 pb->prev = the_pFile->pbTail;
4528 the_pFile->pbTail = pb;
4531 /*-----------------------------------------------------------------*/
4532 /* removepBlock - remove a pBlock from the pFile */
4533 /*-----------------------------------------------------------------*/
4534 static void removepBlock(pBlock *pb)
4542 //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4544 for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4547 if(pbs == the_pFile->pbHead)
4548 the_pFile->pbHead = pbs->next;
4550 if (pbs == the_pFile->pbTail)
4551 the_pFile->pbTail = pbs->prev;
4554 pbs->next->prev = pbs->prev;
4557 pbs->prev->next = pbs->next;
4564 fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4568 /*-----------------------------------------------------------------*/
4569 /* printpCode - write the contents of a pCode to a file */
4570 /*-----------------------------------------------------------------*/
4571 static void printpCode(FILE *of, pCode *pc)
4582 fprintf(of,"warning - unable to print pCode\n");
4585 /*-----------------------------------------------------------------*/
4586 /* pic16_printpBlock - write the contents of a pBlock to a file */
4587 /*-----------------------------------------------------------------*/
4588 void pic16_printpBlock(FILE *of, pBlock *pb)
4596 for(pc = pb->pcHead; pc; pc = pc->next) {
4597 if(isPCF(pc) && PCF(pc)->fname) {
4598 fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4599 if(pb->dbName == 'A') {
4601 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4602 // fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4603 if(!strcmp(ab->name, PCF(pc)->fname)) {
4604 // fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4605 fprintf(of, "\t0X%06X", ab->address);
4616 /*-----------------------------------------------------------------*/
4618 /* pCode processing */
4622 /*-----------------------------------------------------------------*/
4624 void pic16_unlinkpCode(pCode *pc)
4630 fprintf(stderr,"Unlinking: ");
4631 printpCode(stderr, pc);
4634 pc->prev->next = pc->next;
4636 pc->next->prev = pc->prev;
4638 pc->prev = pc->next = NULL;
4642 /*-----------------------------------------------------------------*/
4643 /*-----------------------------------------------------------------*/
4645 static void genericDestruct(pCode *pc)
4648 pic16_unlinkpCode(pc);
4651 /* For instructions, tell the register (if there's one used)
4652 * that it's no longer needed */
4653 regs *reg = pic16_getRegFromInstruction(pc);
4655 deleteSetItem (&(reg->reglives.usedpCodes),pc);
4657 if(PCI(pc)->is2MemOp) {
4658 reg = pic16_getRegFromInstruction2(pc);
4660 deleteSetItem(&(reg->reglives.usedpCodes), pc);
4664 /* Instead of deleting the memory used by this pCode, mark
4665 * the object as bad so that if there's a pointer to this pCode
4666 * dangling around somewhere then (hopefully) when the type is
4667 * checked we'll catch it.
4671 pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4677 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4678 /*-----------------------------------------------------------------*/
4679 /*-----------------------------------------------------------------*/
4680 /* modifiers for constant immediate */
4681 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4683 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4688 int use_buffer = 1; // copy the string to the passed buffer pointer
4693 use_buffer = 0; // Don't bother copying the string to the buffer.
4697 switch(pcop->type) {
4705 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4708 return PCOR(pcop)->r->name;
4711 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4713 SAFE_snprintf(&buffer,&size,"%s",r->name);
4720 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4721 if(PCOI(pcop)->index) {
4722 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4723 immdmod[ PCOI(pcop)->offset ],
4727 SAFE_snprintf(&s,&size,"%s(%s)",
4728 immdmod[ PCOI(pcop)->offset ],
4732 if(PCOI(pcop)->index) {
4733 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4738 SAFE_snprintf(&s,&size, "%s(%s)",
4745 case PO_GPR_REGISTER:
4748 // size = sizeof(buffer);
4749 if( PCOR(pcop)->instance) {
4750 SAFE_snprintf(&s,&size,"(%s + %d)",
4752 PCOR(pcop)->instance );
4754 SAFE_snprintf(&s,&size,"%s",pcop->name);
4759 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4760 SAFE_snprintf(&s, &size, "%s", pcop->name);
4762 if(PCORB(pcop)->pcor.instance)
4763 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4765 SAFE_snprintf(&s, &size, "%s", pcop->name);
4772 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4781 return "NO operand1";
4784 /*-----------------------------------------------------------------*/
4785 /* pic16_get_op2 - variant to support two memory operand commands */
4786 /*-----------------------------------------------------------------*/
4787 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4792 int use_buffer = 1; // copy the string to the passed buffer pointer
4797 use_buffer = 0; // Don't bother copying the string to the buffer.
4801 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",
4802 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4803 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4807 switch(PCOR2(pcop)->pcop2->type) {
4815 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4818 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4821 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4824 SAFE_snprintf(&buffer,&size,"%s",r->name);
4835 if(PCOI(pcop)->_const) {
4836 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4837 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4840 8 * PCOI(pcop)->offset );
4842 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4844 if( PCOI(pcop)->index) {
4845 SAFE_snprintf(&s,&size,"(%s + %d)",
4847 PCOI(pcop)->index );
4849 if(PCOI(pcop)->offset)
4850 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4852 SAFE_snprintf(&s,&size,"%s",pcop->name);
4859 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4860 SAFE_snprintf(&s,&size,"(%s + %d)",
4861 PCOR(PCOR2(pcop)->pcop2)->r->name,
4862 PCOR(PCOR2(pcop)->pcop2)->instance );
4864 SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4869 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4871 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4874 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4879 return "NO operand2";
4882 /*-----------------------------------------------------------------*/
4883 /*-----------------------------------------------------------------*/
4884 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4888 return pic16_get_op(pcc->pcop,NULL,0);
4890 /* gcc 3.2: warning: concatenation of string literals with __FUNCTION__ is deprecated
4891 * return ("ERROR Null: "__FUNCTION__);
4893 return ("ERROR Null: pic16_get_op_from_instruction");
4897 /*-----------------------------------------------------------------*/
4898 /*-----------------------------------------------------------------*/
4899 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4902 fprintf(of,"pcodeopprint- not implemented\n");
4905 /*-----------------------------------------------------------------*/
4906 /* pic16_pCode2str - convert a pCode instruction to string */
4907 /*-----------------------------------------------------------------*/
4908 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4914 if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4915 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4916 __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4924 SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4926 if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4928 if(PCI(pc)->is2MemOp) {
4929 SAFE_snprintf(&s,&size, "%s, %s",
4930 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4931 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4935 if(PCI(pc)->is2LitOp) {
4936 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4940 if(PCI(pc)->isBitInst) {
4941 if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4942 if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4943 SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)",
4944 PCI(pc)->pcop->name ,
4945 PCI(pc)->pcop->name );
4947 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4948 // (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4949 (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4951 } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4952 SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4954 SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4955 //PCI(pc)->pcop->t.bit );
4958 if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4959 if( PCI(pc)->num_ops == 3)
4960 SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4962 SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4965 SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4967 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4968 if(PCI(pc)->num_ops == 3)
4969 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4971 r = pic16_getRegFromInstruction(pc);
4972 // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4973 // __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4975 if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4984 /* assuming that comment ends with a \n */
4985 SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4989 SAFE_snprintf(&s,&size,"; info ==>");
4990 switch(((pCodeInfo *)pc)->type) {
4991 case INF_OPTIMIZATION:
4992 SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4995 SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5000 /* assuming that inline code ends with a \n */
5001 SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
5005 SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
5008 SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
5011 SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
5014 SAFE_snprintf(&s,&size,";\t--FLOW change\n");
5017 // SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5018 SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5019 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5022 if(PCAD(pc)->directive) {
5023 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5026 /* special case to handle inline labels without a tab */
5027 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5032 SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5040 /*-----------------------------------------------------------------*/
5041 /* genericPrint - the contents of a pCode to a file */
5042 /*-----------------------------------------------------------------*/
5043 static void genericPrint(FILE *of, pCode *pc)
5051 // fputs(((pCodeComment *)pc)->comment, of);
5052 fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5057 pBranch *pbl = PCI(pc)->label;
5058 while(pbl && pbl->pc) {
5059 if(pbl->pc->type == PC_LABEL)
5060 pCodePrintLabel(of, pbl->pc);
5065 if(pic16_pcode_verbose) {
5066 fprintf(of, "; info ==>");
5067 switch(((pCodeInfo *)pc)->type) {
5068 case INF_OPTIMIZATION:
5069 fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5072 fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5080 fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5084 // If the opcode has a label, print that first
5086 pBranch *pbl = PCI(pc)->label;
5087 while(pbl && pbl->pc) {
5088 if(pbl->pc->type == PC_LABEL)
5089 pCodePrintLabel(of, pbl->pc);
5095 genericPrint(of,PCODE(PCI(pc)->cline));
5100 pic16_pCode2str(str, 256, pc);
5102 fprintf(of,"%s",str);
5104 if(pic16_debug_verbose) {
5105 fprintf(of, "\t;key=%03x",pc->seq);
5107 fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5114 fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5115 if(PCW(pc)->pci.label)
5116 pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5118 if(PCW(pc)->operand) {
5119 fprintf(of,";\toperand ");
5120 pCodeOpPrint(of,PCW(pc)->operand );
5125 if(pic16_debug_verbose) {
5126 fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5127 if(PCFL(pc)->ancestor)
5128 fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5135 // fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5136 fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5137 PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5143 pBranch *pbl = PCAD(pc)->pci.label;
5144 while(pbl && pbl->pc) {
5145 if(pbl->pc->type == PC_LABEL)
5146 pCodePrintLabel(of, pbl->pc);
5150 if(PCAD(pc)->directive) {
5151 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5154 /* special case to handle inline labels without tab */
5155 fprintf(of, "%s\n", PCAD(pc)->arg);
5161 fprintf(of,"unknown pCode type %d\n",pc->type);
5166 /*-----------------------------------------------------------------*/
5167 /* pCodePrintFunction - prints function begin/end */
5168 /*-----------------------------------------------------------------*/
5170 static void pCodePrintFunction(FILE *of, pCode *pc)
5177 if( ((pCodeFunction *)pc)->modname)
5178 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5181 if(!PCF(pc)->absblock) {
5182 if(PCF(pc)->fname) {
5183 pBranch *exits = PCF(pc)->to;
5186 fprintf(of,"%s:", PCF(pc)->fname);
5188 if(pic16_pcode_verbose)
5189 fprintf(of, "\t;Function start");
5195 exits = exits->next;
5199 if(pic16_pcode_verbose)
5200 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5203 if((PCF(pc)->from &&
5204 PCF(pc)->from->pc->type == PC_FUNCTION &&
5205 PCF(PCF(pc)->from->pc)->fname) ) {
5207 if(pic16_pcode_verbose)
5208 fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5210 if(pic16_pcode_verbose)
5211 fprintf(of,"; exit point [can't find entry point]\n");
5217 /*-----------------------------------------------------------------*/
5218 /* pCodePrintLabel - prints label */
5219 /*-----------------------------------------------------------------*/
5221 static void pCodePrintLabel(FILE *of, pCode *pc)
5228 fprintf(of,"%s:\n",PCL(pc)->label);
5229 else if (PCL(pc)->key >=0)
5230 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5232 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5235 /*-----------------------------------------------------------------*/
5236 /* unlinkpCodeFromBranch - Search for a label in a pBranch and */
5237 /* remove it if it is found. */
5238 /*-----------------------------------------------------------------*/
5239 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5246 if(pcl->type == PC_OPCODE)
5247 b = PCI(pcl)->label;
5249 fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5254 //fprintf (stderr, "%s \n",__FUNCTION__);
5255 //pcl->print(stderr,pcl);
5256 //pc->print(stderr,pc);
5259 //fprintf (stderr, "found label\n");
5260 //pc->print(stderr, pc);
5264 bprev->next = b->next; /* Not first pCode in chain */
5268 PCI(pcl)->label = b->next; /* First pCode in chain */
5271 return; /* A label can't occur more than once */
5279 /*-----------------------------------------------------------------*/
5280 /*-----------------------------------------------------------------*/
5281 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5300 /*-----------------------------------------------------------------*/
5301 /* pBranchLink - given two pcodes, this function will link them */
5302 /* together through their pBranches */
5303 /*-----------------------------------------------------------------*/
5304 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5308 // Declare a new branch object for the 'from' pCode.
5310 //_ALLOC(b,sizeof(pBranch));
5311 b = Safe_calloc(1,sizeof(pBranch));
5312 b->pc = PCODE(t); // The link to the 'to' pCode.
5315 f->to = pic16_pBranchAppend(f->to,b);
5317 // Now do the same for the 'to' pCode.
5319 //_ALLOC(b,sizeof(pBranch));
5320 b = Safe_calloc(1,sizeof(pBranch));
5324 t->from = pic16_pBranchAppend(t->from,b);
5329 /*-----------------------------------------------------------------*/
5330 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5332 /*-----------------------------------------------------------------*/
5333 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5346 /*-----------------------------------------------------------------*/
5347 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain. */
5348 /*-----------------------------------------------------------------*/
5349 void pic16_pCodeUnlink(pCode *pc)
5354 if(!pc->prev || !pc->next) {
5355 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5359 /* first remove the pCode from the chain */
5360 pc->prev->next = pc->next;
5361 pc->next->prev = pc->prev;
5363 /* Now for the hard part... */
5365 /* Remove the branches */
5367 pb1 = PCI(pc)->from;
5369 PCI(pc1) = pb1->pc; /* Get the pCode that branches to the
5370 * one we're unlinking */
5372 /* search for the link back to this pCode (the one we're
5374 if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5375 pb2->pc = PCI(pc)->to->pc; // make the replacement
5377 /* if the pCode we're unlinking contains multiple 'to'
5378 * branches (e.g. this a skip instruction) then we need
5379 * to copy these extra branches to the chain. */
5380 if(PCI(pc)->to->next)
5381 pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5390 /*-----------------------------------------------------------------*/
5391 /*-----------------------------------------------------------------*/
5393 static void genericAnalyze(pCode *pc)
5403 // Go through the pCodes that are in pCode chain and link
5404 // them together through the pBranches. Note, the pCodes
5405 // are linked together as a contiguous stream like the
5406 // assembly source code lines. The linking here mimics this
5407 // except that comments are not linked in.
5409 pCode *npc = pc->next;
5411 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5412 pBranchLink(pc,npc);
5417 /* reached the end of the pcode chain without finding
5418 * an instruction we could link to. */
5422 fprintf(stderr,"analyze PC_FLOW\n");
5426 fprintf(stderr,,";A bad pCode is being used\n");
5432 /*-----------------------------------------------------------------*/
5433 /*-----------------------------------------------------------------*/
5434 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5438 if(pc->type == PC_LABEL) {
5439 if( ((pCodeLabel *)pc)->key == pcop_label->key)
5442 if((pc->type == PC_OPCODE)
5443 || (pc->type == PC_ASMDIR)
5445 pbr = PCI(pc)->label;
5447 if(pbr->pc->type == PC_LABEL) {
5448 if( ((pCodeLabel *)(pbr->pc))->key == pcop_label->key)
5458 /*-----------------------------------------------------------------*/
5459 /*-----------------------------------------------------------------*/
5460 static int checkLabel(pCode *pc)
5464 if(pc && isPCI(pc)) {
5465 pbr = PCI(pc)->label;
5467 if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5477 /*-----------------------------------------------------------------*/
5478 /* findLabelinpBlock - Search the pCode for a particular label */
5479 /*-----------------------------------------------------------------*/
5480 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5487 for(pc = pb->pcHead; pc; pc = pc->next)
5488 if(compareLabel(pc,pcop_label))
5494 /*-----------------------------------------------------------------*/
5495 /* findLabel - Search the pCode for a particular label */
5496 /*-----------------------------------------------------------------*/
5497 static pCode * findLabel(pCodeOpLabel *pcop_label)
5505 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5506 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5510 fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5514 /*-----------------------------------------------------------------*/
5515 /* pic16_findNextpCode - given a pCode, find the next of type 'pct' */
5516 /* in the linked list */
5517 /*-----------------------------------------------------------------*/
5518 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5531 /*-----------------------------------------------------------------*/
5532 /* findPrevpCode - given a pCode, find the previous of type 'pct' */
5533 /* in the linked list */
5534 /*-----------------------------------------------------------------*/
5535 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5549 //#define PCODE_DEBUG
5550 /*-----------------------------------------------------------------*/
5551 /* pic16_findNextInstruction - given a pCode, find the next instruction */
5552 /* in the linked list */
5553 /*-----------------------------------------------------------------*/
5554 pCode * pic16_findNextInstruction(pCode *pci)
5559 if((pc->type == PC_OPCODE)
5560 || (pc->type == PC_WILD)
5561 || (pc->type == PC_ASMDIR)
5566 fprintf(stderr,"pic16_findNextInstruction: ");
5567 printpCode(stderr, pc);
5572 //fprintf(stderr,"Couldn't find instruction\n");
5576 /*-----------------------------------------------------------------*/
5577 /* pic16_findPrevInstruction - given a pCode, find the next instruction */
5578 /* in the linked list */
5579 /*-----------------------------------------------------------------*/
5580 pCode * pic16_findPrevInstruction(pCode *pci)
5586 if((pc->type == PC_OPCODE)
5587 || (pc->type == PC_WILD)
5588 || (pc->type == PC_ASMDIR)
5594 fprintf(stderr,"pic16_findPrevInstruction: ");
5595 printpCode(stderr, pc);
5600 //fprintf(stderr,"Couldn't find instruction\n");
5607 /*-----------------------------------------------------------------*/
5608 /* findFunctionEnd - given a pCode find the end of the function */
5609 /* that contains it */
5610 /*-----------------------------------------------------------------*/
5611 static pCode * findFunctionEnd(pCode *pc)
5615 if(pc->type == PC_FUNCTION && !(PCF(pc)->fname))
5621 fprintf(stderr,"Couldn't find function end\n");
5626 /*-----------------------------------------------------------------*/
5627 /* AnalyzeLabel - if the pCode is a label, then merge it with the */
5628 /* instruction with which it is associated. */
5629 /*-----------------------------------------------------------------*/
5630 static void AnalyzeLabel(pCode *pc)
5633 pic16_pCodeUnlink(pc);
5639 static void AnalyzeGOTO(pCode *pc)
5642 pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5646 static void AnalyzeSKIP(pCode *pc)
5649 pBranchLink(pc,pic16_findNextInstruction(pc->next));
5650 pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5654 static void AnalyzeRETURN(pCode *pc)
5657 // branch_link(pc,findFunctionEnd(pc->next));
5663 /*-----------------------------------------------------------------*/
5664 /*-----------------------------------------------------------------*/
5665 regs * pic16_getRegFromInstruction(pCode *pc)
5671 PCI(pc)->num_ops == 0 ||
5672 (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5676 fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5677 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5680 switch(PCI(pc)->pcop->type) {
5686 return PCOR(PCI(pc)->pcop)->r;
5690 // fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5691 return PCOR(PCI(pc)->pcop)->r;
5694 // return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5696 if(PCOI(PCI(pc)->pcop)->r)
5697 return (PCOI(PCI(pc)->pcop)->r);
5702 return PCOR(PCI(pc)->pcop)->r;
5704 case PO_GPR_REGISTER:
5706 // fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5707 return PCOR(PCI(pc)->pcop)->r;
5710 //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5714 // fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5715 // genericPrint(stderr, pc);
5723 /*-------------------------------------------------------------------------------*/
5724 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5725 /*-------------------------------------------------------------------------------*/
5726 regs * pic16_getRegFromInstruction2(pCode *pc)
5732 PCI(pc)->num_ops == 0 ||
5733 (PCI(pc)->num_ops == 1)) // accept only 2 operand commands
5738 fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5739 dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5743 * operands supported in MOVFF:
5750 switch(PCI(pc)->pcop->type) {
5756 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5758 // return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5762 //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5763 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5767 // if(PCOI(PCI(pc)->pcop)->r)
5768 // return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5770 //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5771 return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5774 if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5775 return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5782 // return PCOR2(PCI(pc)->pcop)->r;
5784 case PO_GPR_REGISTER:
5786 //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5787 return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5791 //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5794 //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5795 //genericPrint(stderr, pc);
5803 /*-----------------------------------------------------------------*/
5804 /*-----------------------------------------------------------------*/
5806 static void AnalyzepBlock(pBlock *pb)
5813 /* Find all of the registers used in this pBlock
5814 * by looking at each instruction and examining it's
5817 for(pc = pb->pcHead; pc; pc = pc->next) {
5819 /* Is this an instruction with operands? */
5820 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5822 if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5824 /* Loop through all of the registers declared so far in
5825 this block and see if we find this one there */
5827 regs *r = setFirstItem(pb->tregisters);
5830 if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5831 PCOR(PCI(pc)->pcop)->r = r;
5834 r = setNextItem(pb->tregisters);
5838 /* register wasn't found */
5839 //r = Safe_calloc(1, sizeof(regs));
5840 //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5841 //addSet(&pb->tregisters, r);
5842 addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5843 //PCOR(PCI(pc)->pcop)->r = r;
5844 //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5846 fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5849 if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5850 if(PCOR(PCI(pc)->pcop)->r) {
5851 pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5852 DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5854 if(PCI(pc)->pcop->name)
5855 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5857 fprintf(stderr,"ERROR: NULL register\n");
5866 /*-----------------------------------------------------------------*/
5868 /*-----------------------------------------------------------------*/
5869 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5871 static void InsertpFlow(pCode *pc, pCode **pflow)
5874 PCFL(*pflow)->end = pc;
5876 if(!pc || !pc->next)
5879 *pflow = pic16_newpCodeFlow();
5880 pic16_pCodeInsertAfter(pc, *pflow);
5883 /*-----------------------------------------------------------------*/
5884 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5885 /* the flow blocks. */
5887 * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5888 * point the instruction flow changes.
5890 /*-----------------------------------------------------------------*/
5891 void pic16_BuildFlow(pBlock *pb)
5894 pCode *last_pci=NULL;
5901 //fprintf (stderr,"build flow start seq %d ",GpcFlowSeq);
5902 /* Insert a pCodeFlow object at the beginning of a pBlock */
5904 InsertpFlow(pb->pcHead, &pflow);
5906 //pflow = pic16_newpCodeFlow(); /* Create a new Flow object */
5907 //pflow->next = pb->pcHead; /* Make the current head the next object */
5908 //pb->pcHead->prev = pflow; /* let the current head point back to the flow object */
5909 //pb->pcHead = pflow; /* Make the Flow object the head */
5912 for( pc = pic16_findNextInstruction(pb->pcHead);
5914 pc=pic16_findNextInstruction(pc)) {
5917 PCI(pc)->pcflow = PCFL(pflow);
5919 //fprintf(stderr," build: ");
5920 //pflow->print(stderr,pflow);
5922 if( PCI(pc)->isSkip) {
5924 /* The two instructions immediately following this one
5925 * mark the beginning of a new flow segment */
5927 while(pc && PCI(pc)->isSkip) {
5929 PCI(pc)->pcflow = PCFL(pflow);
5933 InsertpFlow(pc, &pflow);
5934 pc=pic16_findNextInstruction(pc->next);
5942 PCI(pc)->pcflow = PCFL(pflow);
5944 InsertpFlow(pc, &pflow);
5946 } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next))) {
5948 InsertpFlow(pc, &pflow);
5951 } else if (checkLabel(pc)) {
5953 /* This instruction marks the beginning of a
5954 * new flow segment */
5959 /* If the previous pCode is not a flow object, then
5960 * insert a new flow object. (This check prevents
5961 * two consecutive flow objects from being insert in
5962 * the case where a skip instruction preceeds an
5963 * instruction containing a label.) */
5965 if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5966 InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5968 PCI(pc)->pcflow = PCFL(pflow);
5975 //fprintf (stderr,",end seq %d",GpcFlowSeq);
5977 PCFL(pflow)->end = pb->pcTail;
5980 /*-------------------------------------------------------------------*/
5981 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build */
5982 /* the flow blocks. */
5984 * unBuildFlow removes pCodeFlow objects from a pCode chain
5986 /*-----------------------------------------------------------------*/
5987 static void unBuildFlow(pBlock *pb)
6002 if(PCI(pc)->pcflow) {
6003 //free(PCI(pc)->pcflow);
6004 PCI(pc)->pcflow = NULL;
6007 } else if(isPCFL(pc) )
6016 /*-----------------------------------------------------------------*/
6017 /*-----------------------------------------------------------------*/
6018 static void dumpCond(int cond)
6021 static char *pcc_str[] = {
6035 int ncond = sizeof(pcc_str) / sizeof(char *);
6038 fprintf(stderr, "0x%04X\n",cond);
6040 for(i=0,j=1; i<ncond; i++, j<<=1)
6042 fprintf(stderr, " %s\n",pcc_str[i]);
6048 /*-----------------------------------------------------------------*/
6049 /*-----------------------------------------------------------------*/
6050 static void FlowStats(pCodeFlow *pcflow)
6058 fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6060 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6063 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6068 fprintf(stderr, " FlowStats inCond: ");
6069 dumpCond(pcflow->inCond);
6070 fprintf(stderr, " FlowStats outCond: ");
6071 dumpCond(pcflow->outCond);
6075 /*-----------------------------------------------------------------*
6076 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6077 * if it affects the banking bits.
6079 * return: -1 == Banking bits are unaffected by this pCode.
6081 * return: > 0 == Banking bits are affected.
6083 * If the banking bits are affected, then the returned value describes
6084 * which bits are affected and how they're affected. The lower half
6085 * of the integer maps to the bits that are affected, the upper half
6086 * to whether they're set or cleared.
6088 *-----------------------------------------------------------------*/
6090 static int isBankInstruction(pCode *pc)
6098 if( PCI(pc)->op == POC_MOVLB ||
6099 (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6100 bank = PCOL(pc)->lit;
6107 /*-----------------------------------------------------------------*/
6108 /*-----------------------------------------------------------------*/
6109 static void FillFlow(pCodeFlow *pcflow)
6118 // fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6120 pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE);
6123 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6130 isBankInstruction(pc);
6132 } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6136 fprintf(stderr, " FillFlow - Bad end of flow\n");
6138 fprintf(stderr, " FillFlow - Ending flow with\n ");
6139 pc->print(stderr,pc);
6142 fprintf(stderr, " FillFlow inCond: ");
6143 dumpCond(pcflow->inCond);
6144 fprintf(stderr, " FillFlow outCond: ");
6145 dumpCond(pcflow->outCond);
6149 /*-----------------------------------------------------------------*/
6150 /*-----------------------------------------------------------------*/
6151 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6153 pCodeFlowLink *fromLink, *toLink;
6155 if(!from || !to || !to->pcflow || !from->pcflow)
6158 fromLink = pic16_newpCodeFlowLink(from->pcflow);
6159 toLink = pic16_newpCodeFlowLink(to->pcflow);
6161 addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow);
6162 addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6166 /*-----------------------------------------------------------------*
6167 * void LinkFlow(pBlock *pb)
6169 * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6170 * non-branching segments. In LinkFlow, we determine the execution
6171 * order of these segments. For example, if one of the segments ends
6172 * with a skip, then we know that there are two possible flow segments
6173 * to which control may be passed.
6174 *-----------------------------------------------------------------*/
6175 static void LinkFlow(pBlock *pb)
6181 //fprintf(stderr,"linkflow \n");
6183 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6185 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6188 fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6190 //fprintf(stderr," link: ");
6191 //pcflow->print(stderr,pcflow);
6193 //FillFlow(PCFL(pcflow));
6195 pc = PCFL(pcflow)->end;
6197 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6198 if(isPCI_SKIP(pc)) {
6199 //fprintf(stderr, "ends with skip\n");
6200 //pc->print(stderr,pc);
6201 pct=pic16_findNextInstruction(pc->next);
6202 LinkFlow_pCode(PCI(pc),PCI(pct));
6203 pct=pic16_findNextInstruction(pct->next);
6204 LinkFlow_pCode(PCI(pc),PCI(pct));
6208 if(isPCI_BRANCH(pc)) {
6209 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6211 //fprintf(stderr, "ends with branch\n ");
6212 //pc->print(stderr,pc);
6214 if(!(pcol && isPCOLAB(pcol))) {
6215 if((PCI(pc)->op != POC_RETLW)
6216 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6218 /* continue if label is '$' which assembler knows how to parse */
6219 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6221 if(pic16_pcode_verbose) {
6222 pc->print(stderr,pc);
6223 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6229 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6230 LinkFlow_pCode(PCI(pc),PCI(pct));
6232 fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6233 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6235 // fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6241 //fprintf(stderr, "ends with non-branching instruction:\n");
6242 //pc->print(stderr,pc);
6244 LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6250 //fprintf(stderr, "ends with unknown\n");
6251 //pc->print(stderr,pc);
6255 //fprintf(stderr, "ends with nothing: ERROR\n");
6259 /*-----------------------------------------------------------------*/
6260 /*-----------------------------------------------------------------*/
6262 /*-----------------------------------------------------------------*/
6263 /*-----------------------------------------------------------------*/
6264 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6270 if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6273 if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6283 /*-----------------------------------------------------------------*/
6284 /* insertBankSwitch - inserts a bank switch statement in the */
6285 /* assembly listing */
6287 /* position == 0: insert before */
6288 /* position == 1: insert after pc */
6289 /* position == 2: like 0 but previous was a skip instruction */
6290 /*-----------------------------------------------------------------*/
6291 pCodeOp *pic16_popGetLabel(unsigned int key);
6292 extern int pic16_labelOffset;
6294 static void insertBankSwitch(unsigned char position, pCode *pc)
6301 /* emit BANKSEL [symbol] */
6304 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6306 // position = 0; // position is always before (sanity check!)
6309 fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6310 pc->print(stderr, pc);
6315 /* insert the bank switch after this pc instruction */
6316 pCode *pcnext = pic16_findNextInstruction(pc);
6318 pic16_pCodeInsertAfter(pc, new_pc);
6319 if(pcnext)pc = pcnext;
6323 /* insert the bank switch BEFORE this pc instruction */
6324 pic16_pCodeInsertAfter(pc->prev, new_pc);
6329 pCode *pcnext, *pcprev, *npci, *ppc;
6331 int ofs1=0, ofs2=0, len=0;
6333 /* just like 0, but previous was a skip instruction,
6334 * so some care should be taken */
6336 pic16_labelOffset += 10000;
6337 tlbl = newiTempLabel(NULL);
6339 /* invert skip instruction */
6340 pcprev = pic16_findPrevInstruction(pc->prev);
6341 ipci = PCI(pcprev)->inverted_op;
6342 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6344 // fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6346 /* copy info from old pCode */
6347 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6348 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6349 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6350 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6351 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6352 PCI(npci)->op = PCI(pcprev)->inverted_op;
6354 /* unlink old pCode */
6356 ppc->next = pcprev->next;
6357 pcprev->next->prev = ppc;
6358 pic16_pCodeInsertAfter(ppc, npci);
6360 /* extra instructions to handle invertion */
6361 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6362 pic16_pCodeInsertAfter(npci, pcnext);
6363 pic16_pCodeInsertAfter(pc->prev, new_pc);
6365 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6366 pic16_pCodeInsertAfter(pc, pcnext);
6371 /* Move the label, if there is one */
6372 if(PCI(pc)->label) {
6373 // fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6374 // __FILE__, __LINE__, pc, new_pc);
6375 PCAD(new_pc)->pci.label = PCI(pc)->label;
6376 PCI(pc)->label = NULL;
6381 /*-----------------------------------------------------------------*/
6382 /*int compareBankFlow - compare the banking requirements between */
6384 /*-----------------------------------------------------------------*/
6385 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6388 if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6391 if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6394 if(pcflow->firstBank == -1)
6398 if(pcflowLink->pcflow->firstBank == -1) {
6399 pCodeFlowLink *pctl = setFirstItem( toORfrom ?
6400 pcflowLink->pcflow->to :
6401 pcflowLink->pcflow->from);
6402 return compareBankFlow(pcflow, pctl, toORfrom);
6406 if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6409 pcflowLink->bank_conflict++;
6410 pcflowLink->pcflow->FromConflicts++;
6411 pcflow->ToConflicts++;
6414 if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6417 pcflowLink->bank_conflict++;
6418 pcflowLink->pcflow->ToConflicts++;
6419 pcflow->FromConflicts++;
6423 fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6424 pcflowLink->pcflow->pc.seq,
6425 pcflowLink->pcflow->FromConflicts,
6426 pcflowLink->pcflow->ToConflicts);
6433 /*-----------------------------------------------------------------*/
6434 /*-----------------------------------------------------------------*/
6435 static void DumpFlow(pBlock *pb)
6439 pCodeFlowLink *pcfl;
6442 fprintf(stderr,"Dump flow \n");
6443 pb->pcHead->print(stderr, pb->pcHead);
6445 pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6446 pcflow->print(stderr,pcflow);
6448 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6450 pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6452 if(!isPCFL(pcflow)) {
6453 fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6456 fprintf(stderr,"dumping: ");
6457 pcflow->print(stderr,pcflow);
6458 FlowStats(PCFL(pcflow));
6460 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6462 pc = PCODE(pcfl->pcflow);
6464 fprintf(stderr, " from seq %d:\n",pc->seq);
6466 fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6467 pc->print(stderr,pc);
6472 for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6474 pc = PCODE(pcfl->pcflow);
6476 fprintf(stderr, " to seq %d:\n",pc->seq);
6478 fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6479 pc->print(stderr,pc);
6488 /*-----------------------------------------------------------------*/
6489 /*-----------------------------------------------------------------*/
6490 static int OptimizepBlock(pBlock *pb)
6495 if(!pb || !peepOptimizing)
6498 DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6500 for(pc = pb->pcHead; pc; pc = pc->next)
6501 matches += pic16_pCodePeepMatchRule(pc);
6504 pc = pic16_findNextInstruction(pb->pcHead);
6512 if(pic16_pCodePeepMatchRule(pc)) {
6517 pc = pic16_findNextInstruction(pcprev->next);
6519 pc = pic16_findNextInstruction(pb->pcHead);
6521 pc = pic16_findNextInstruction(pc->next);
6525 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6530 /*-----------------------------------------------------------------*/
6531 /*-----------------------------------------------------------------*/
6532 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6536 for(pc = pcs; pc; pc = pc->next) {
6538 if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) &&
6540 (PCI(pc)->pcop->type == PO_LABEL) &&
6541 (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6549 /*-----------------------------------------------------------------*/
6550 /*-----------------------------------------------------------------*/
6551 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6558 (PCI(pc)->pcop->type == PO_LABEL)) {
6560 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6562 // fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6563 // if(pcol->pcop.name)
6564 // free(pcol->pcop.name);
6566 /* If the key is negative, then we (probably) have a label to
6567 * a function and the name is already defined */
6570 sprintf(s=buffer,"_%05d_DS_",pcl->key);
6574 //sprintf(buffer,"_%05d_DS_",pcl->key);
6576 fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6578 pcol->pcop.name = Safe_strdup(s);
6579 pcol->key = pcl->key;
6580 //pc->print(stderr,pc);
6587 /*-----------------------------------------------------------------*/
6588 /* pBlockRemoveUnusedLabels - remove the pCode labels from the */
6589 /* pCode chain if they're not used. */
6590 /*-----------------------------------------------------------------*/
6591 static void pBlockRemoveUnusedLabels(pBlock *pb)
6593 pCode *pc; pCodeLabel *pcl;
6598 for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6600 pBranch *pbr = PCI(pc)->label;
6601 if(pbr && pbr->next) {
6602 pCode *pcd = pb->pcHead;
6604 // fprintf(stderr, "multiple labels\n");
6605 // pc->print(stderr,pc);
6610 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6611 //fprintf(stderr,"Used by:\n");
6612 //pcd->print(stderr,pcd);
6614 exchangeLabels(PCL(pbr->pc),pcd);
6623 for(pc = pb->pcHead; pc; pc = pc->next) {
6625 if(isPCL(pc)) // pc->type == PC_LABEL)
6627 else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6628 pcl = PCL(PCI(pc)->label->pc);
6631 // fprintf(stderr," found A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6633 /* This pCode is a label, so search the pBlock to see if anyone
6636 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6638 //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6639 /* Couldn't find an instruction that refers to this label
6640 * So, unlink the pCode label from it's pCode chain
6641 * and destroy the label */
6642 // fprintf(stderr," removed A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6644 DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6645 if(pc->type == PC_LABEL) {
6646 pic16_unlinkpCode(pc);
6647 pCodeLabelDestruct(pc);
6649 unlinkpCodeFromBranch(pc, PCODE(pcl));
6650 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6661 /*-----------------------------------------------------------------*/
6662 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode */
6663 /* chain and put them into pBranches that are */
6664 /* associated with the appropriate pCode */
6666 /*-----------------------------------------------------------------*/
6667 void pic16_pBlockMergeLabels(pBlock *pb)
6670 pCode *pc, *pcnext=NULL;
6675 /* First, Try to remove any unused labels */
6676 //pBlockRemoveUnusedLabels(pb);
6678 /* Now loop through the pBlock and merge the labels with the opcodes */
6681 // for(pc = pb->pcHead; pc; pc = pc->next) {
6684 pCode *pcn = pc->next;
6686 if(pc->type == PC_LABEL) {
6688 // fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6689 // fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6691 if((pcnext = pic16_findNextInstruction(pc) )) {
6693 // pcnext->print(stderr, pcnext);
6695 // Unlink the pCode label from it's pCode chain
6696 pic16_unlinkpCode(pc);
6698 // fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6699 // And link it into the instruction's pBranch labels. (Note, since
6700 // it's possible to have multiple labels associated with one instruction
6701 // we must provide a means to accomodate the additional labels. Thus
6702 // the labels are placed into the singly-linked list "label" as
6703 // opposed to being a single member of the pCodeInstruction.)
6705 //_ALLOC(pbr,sizeof(pBranch));
6707 pbr = Safe_calloc(1,sizeof(pBranch));
6711 PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6714 if(pic16_pcode_verbose)
6715 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6717 } else if(pc->type == PC_CSOURCE) {
6719 /* merge the source line symbolic info into the next instruction */
6720 if((pcnext = pic16_findNextInstruction(pc) )) {
6722 // Unlink the pCode label from it's pCode chain
6723 pic16_unlinkpCode(pc);
6724 PCI(pcnext)->cline = PCCS(pc);
6725 //fprintf(stderr, "merging CSRC\n");
6726 //genericPrint(stderr,pcnext);
6732 pBlockRemoveUnusedLabels(pb);
6736 /*-----------------------------------------------------------------*/
6737 /*-----------------------------------------------------------------*/
6738 static int OptimizepCode(char dbName)
6740 #define MAX_PASSES 4
6749 DFPRINTF((stderr," Optimizing pCode\n"));
6753 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6754 if('*' == dbName || getpBlock_dbName(pb) == dbName)
6755 matches += OptimizepBlock(pb);
6758 while(matches && ++passes < MAX_PASSES);
6765 const char *pic16_pCodeOpType(pCodeOp *pcop);
6766 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6769 /*-----------------------------------------------------------------*/
6770 /* pic16_popCopyGPR2Bit - copy a pcode operator */
6771 /*-----------------------------------------------------------------*/
6773 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6777 // fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6780 pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6782 if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6785 assert(pcop != NULL);
6787 if( !( (pcop->type == PO_LABEL) ||
6788 (pcop->type == PO_LITERAL) ||
6789 (pcop->type == PO_STR) ))
6790 PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
6791 PCOR(pcop)->r->wasUsed = 1;
6792 PCOR(pcop)->instance = PCOR(pc)->instance;
6798 /*----------------------------------------------------------------------*
6799 * pic16_areRegsSame - check to see if the names of two registers match *
6800 *----------------------------------------------------------------------*/
6801 int pic16_areRegsSame(regs *r1, regs *r2)
6803 if(!strcmp(r1->name, r2->name))return 1;
6809 /*-----------------------------------------------------------------*/
6810 /*-----------------------------------------------------------------*/
6811 static void pic16_FixRegisterBanking(pBlock *pb)
6815 regs *reg, *prevreg;
6816 unsigned char flag=0;
6821 pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6824 /* loop through all of the flow blocks with in one pblock */
6826 // fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6830 /* at this point, pc should point to a PC_FLOW object */
6831 /* for each flow block, determine the register banking
6835 /* if label, then might come from other point, force banksel */
6836 if(isPCL(pc))prevreg = NULL;
6838 if(!isPCI(pc))goto loop;
6840 if(PCI(pc)->label)prevreg = NULL;
6842 if(PCI(pc)->is2MemOp)goto loop;
6844 /* if goto, then force banksel */
6845 // if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6847 reg = pic16_getRegFromInstruction(pc);
6850 pc->print(stderr, pc);
6851 fprintf(stderr, "reg = %p\n", reg);
6854 fprintf(stderr, "%s:%d: %s %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6855 fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6856 reg->address,reg->isBitField, reg->isFixed);
6860 /* now make some tests to make sure that instruction needs bank switch */
6862 /* if no register exists, and if not a bit opcode goto loop */
6864 if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6867 if(isPCI_SKIP(pc)) {
6868 // fprintf(stderr, "instruction is SKIP instruction\n");
6871 if(reg && isACCESS_BANK(reg))goto loop;
6873 if(!isBankInstruction(pc))goto loop;
6875 if(isPCI_LIT(pc))goto loop;
6877 if(PCI(pc)->op == POC_CALL)goto loop;
6879 /* Examine the instruction before this one to make sure it is
6880 * not a skip type instruction */
6881 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6883 flag = 0; /* add before this instruction */
6885 /* if previous instruction is a skip one, then set flag
6886 * to 2 and call insertBankSwitch */
6887 if(pcprev && isPCI_SKIP(pcprev)) {
6892 if(pic16_options.opt_banksel>0) {
6893 char op1[128], op2[128];
6896 strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6897 strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6898 if(!strcmp(op1, op2))goto loop;
6902 insertBankSwitch(flag, pc);
6904 // fprintf(stderr, "BANK SWITCH inserted\n");
6912 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6914 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6915 int instrSize (pCode *pc)
6920 if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6921 return 4; // assumes only regular instructions using <= 4 bytes
6924 if (isPCI(pc)) return PCI(pc)->isize;
6929 /* Returns 1 if pc is referenced by the given label (either
6930 * pc is the label itself or is an instruction with an attached
6932 * Returns 0 if pc is not preceeded by the specified label.
6934 int isLabel (pCode *pc, char *label)
6938 // label attached to the pCode?
6939 if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6940 pBranch *lab = NULL;
6941 lab = PCI(pc)->label;
6944 if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6951 // is inline assembly label?
6952 if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6953 // do not compare trailing ':'
6954 if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6961 if (strcmp(PCL(pc)->label,label) == 0) {
6966 // no label/no label attached/wrong label(s)
6970 /* Returns the distance to the given label in terms of words.
6971 * Labels are searched only within -max .. max words from pc.
6972 * Returns max if the label could not be found or
6973 * its distance from pc in (-max..+max).
6975 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
6976 int dist = instrSize(pc);
6980 while (dist < max && curr && !isLabel (curr, label)) {
6982 dist += instrSize(curr); // sizeof (instruction)
6984 if (curr && dist < max) {
6985 if (target != NULL) *target = curr;
6990 curr = pic16_findNextInstruction (pc->next);
6992 while (dist < max && curr && !isLabel (curr, label)) {
6993 dist += instrSize(curr); // sizeof (instruction)
6996 if (curr && dist < max) {
6997 if (target != NULL) *target = curr;
7001 if (target != NULL) *target = NULL;
7005 /* Returns -1 if pc does NOT denote an instruction like
7007 * Otherwise we return
7008 * (a) 0x10 + i for BTFSS
7009 * (b) 0x00 + i for BTFSC
7011 int isSkipOnStatus (pCode *pc)
7015 if (!pc || !isPCI(pc)) return -1;
7016 if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7017 else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7020 pcop = PCI(pc)->pcop;
7022 if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7023 return res + ((pCodeOpRegBit *)pcop)->bit;
7029 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7030 * returns 0 otherwise. */
7031 int isConditionalBranch (pCode *pc)
7033 if (!pc || !isPCI_BRANCH(pc)) return 0;
7035 switch (PCI(pc)->op) {
7053 /* Returns 1 if pc has a label attached to it.
7054 * This can be either a label stored in the pCode itself (.label)
7055 * or a label making up its own pCode preceding this pc.
7056 * Returns 0 if pc cannot be reached directly via a label.
7058 int hasNoLabel (pCode *pc)
7063 // are there any label pCodes between pc and the previous instruction?
7064 prev = pic16_findPrevInstruction (pc->prev);
7065 while (pc && pc != prev) {
7066 // pCode with attached label?
7067 if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7068 && PCI(pc)->label) {
7071 // is inline assembly label?
7072 if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7073 if (isPCW(pc) && PCW(pc)->label) return 0;
7076 if (isPCL(pc)) return 0;
7085 /* Replaces the old pCode with the new one, moving the labels,
7086 * C source line and probably flow information to the new pCode.
7088 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7089 if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7092 /* first move all labels from old to new */
7093 PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7094 PCI(oldPC)->label = NULL;
7096 /* move C source line (if possible) */
7097 if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7098 PCI(newPC)->cline = PCI(oldPC)->cline;
7100 /* insert new pCode into pBlock */
7101 pic16_pCodeInsertAfter (oldPC, newPC);
7102 pic16_unlinkpCode (oldPC);
7104 /* TODO: update flow (newPC->from, newPC->to) */
7105 PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7107 /* destruct replaced pCode */
7108 oldPC->destruct (oldPC);
7111 /* Returns the inverted conditional branch (if any) or NULL.
7112 * pcop must be set to the new jump target.
7114 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7118 if (!bcc || !isPCI(bcc)) return NULL;
7120 switch (PCI(bcc)->op) {
7121 case POC_BC: newBcc = pic16_newpCode (POC_BNC , pcop); break;
7122 case POC_BZ: newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7123 case POC_BOV: newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7124 case POC_BN: newBcc = pic16_newpCode (POC_BNN , pcop); break;
7125 case POC_BNC: newBcc = pic16_newpCode (POC_BC , pcop); break;
7126 case POC_BNZ: newBcc = pic16_newpCode (POC_BZ , pcop); break;
7127 case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7128 case POC_BNN: newBcc = pic16_newpCode (POC_BN , pcop); break;
7135 #define MAX_DIST_GOTO 0x7FFFFFFF
7136 #define MAX_DIST_BRA 1020 // maximum offset (in bytes) possible with BRA
7137 #define MAX_DIST_BCC 120 // maximum offset (in bytes) possible with Bcc
7138 #define MAX_JUMPCHAIN_DEPTH 16 // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7139 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7141 /* Follows GOTO/BRA instructions to their target instructions, stores the
7142 * final destination (not a GOTO or BRA instruction) in target and returns
7143 * the distance from the original pc to *target.
7145 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7148 pCodeOp *lastPCOP = NULL;
7152 //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7154 /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7155 while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7156 && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7158 lastPCOP = PCI(curr)->pcop;
7159 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7160 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7163 if (target) *target = last;
7164 if (pcop) *pcop = lastPCOP;
7168 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7169 * Otherwise the first pCode after the jumptable (after
7170 * the OPT_JUMPTABLE_END tag) is returned.
7172 pCode *skipJumptables (pCode *pc, int *isJumptable)
7175 if (!pc) return NULL;
7177 while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7179 //fprintf (stderr, "SKIPPING jumptable\n");
7181 //pc->print(stderr, pc);
7183 } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7184 || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7185 //fprintf (stderr, "<<JUMPTAB:\n");
7186 // skip OPT_END as well
7187 if (pc) pc = pc->next;
7193 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7197 while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7198 // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7199 pc = skipJumptables (pc, &isJumptab);
7201 // pc is the first pCode after the jumptable
7204 // pc has not been changed by skipJumptables()
7212 /* Turn GOTOs into BRAs if distance between GOTO and label
7213 * is less than 1024 bytes.
7215 * This method is especially useful if GOTOs after BTFS[SC]
7216 * can be turned into BRAs as GOTO would cost another NOP
7219 void pic16_OptimizeJumps ()
7222 pCode *pc_prev = NULL;
7223 pCode *pc_next = NULL;
7226 int change, iteration, isJumptab;
7229 int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7231 if (!the_pFile) return;
7233 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7235 for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7236 int matchedInvertRule = 1;
7239 //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7241 pc = pic16_findNextInstruction (pb->pcHead);
7244 pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7246 // skip jumptable, i.e. start over with no pc_prev!
7252 /* (1) resolve chained jumps
7253 * Do not perform this until pattern (4) is no longer present! Otherwise we will
7254 * (a) leave dead code in and
7255 * (b) skip over the dead code with an (unneccessary) jump.
7257 if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7258 pCodeOp *lastTargetOp = NULL;
7259 int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7260 int maxDist = MAX_DIST_BCC;
7261 if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7262 if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7264 /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7265 if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7266 && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7267 //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7268 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7269 PCI(pc)->pcop->name = lastTargetOp->name;
7278 int condBraType = isSkipOnStatus(pc_prev);
7279 label = PCI(pc)->pcop->name;
7280 dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7281 if (dist < 0) dist = -dist;
7282 //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7286 /* (2) remove "GOTO label; label:" */
7287 if (isLabel (pc_next, label)) {
7288 //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7289 // first remove all preceeding SKIP instructions
7290 while (pc_prev && isPCI_SKIP(pc_prev)) {
7291 // attach labels on this instruction to pc_next
7292 //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7293 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7294 PCI(pc_prev)->label = NULL;
7295 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7296 pic16_unlinkpCode (pc_prev);
7297 pc_prev = pic16_findPrevInstruction (pc);
7299 // now remove the redundant goto itself
7300 PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7301 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7302 pic16_unlinkpCode (pc);
7303 pc = pic16_findPrevInstruction(pc_next->prev);
7304 isHandled = 1; // do not perform further optimizations
7310 /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7311 if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7312 if (dist < MAX_DIST_BCC) {
7314 switch (condBraType) {
7315 case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7316 // no BDC on DIGIT CARRY available
7317 case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7318 case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7319 case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7320 case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7321 // no BNDC on DIGIT CARRY available
7322 case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7323 case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7324 case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7326 // no replacement possible
7331 // ATTENTION: keep labels attached to BTFSx!
7332 // HINT: GOTO is label free (checked above)
7333 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7334 isHandled = 1; // do not perform further optimizations
7335 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7336 pic16_pCodeReplace (pc_prev, bcc);
7343 //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7349 // (4) eliminate the following (common) tripel:
7351 // labels1: Bcc label2;
7352 // GOTO somewhere; ; <-- instruction referenced by pc
7354 // and replace it by
7355 // labels1: B#(cc) somewhere; ; #(cc) is the negated condition cc
7357 // ATTENTION: all labels pointing to "Bcc label2" must be attached
7358 // to <cont.> instead
7359 // ATTENTION: This optimization is only valid if <pred.> is
7360 // not a skip operation!
7361 // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7362 // ATTENTION: no label may be attached to the GOTO instruction!
7363 if (isConditionalBranch(pc_prev)
7364 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7365 && (dist < MAX_DIST_BCC)
7366 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7367 && hasNoLabel(pc)) {
7368 pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7371 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7372 isHandled = 1; // do not perform further optimizations
7373 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7374 pic16_pCodeReplace (pc_prev, newBcc);
7379 matchedInvertRule++;
7384 /* (5) now just turn GOTO into BRA */
7385 if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7386 if (dist < MAX_DIST_BRA) {
7387 pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7388 //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7389 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7390 pic16_pCodeReplace (pc, newBra);
7395 //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7398 } // if (!isHandled)
7405 pBlockRemoveUnusedLabels (pb);
7407 // This line enables goto chain resolution!
7408 if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7411 } while (change); /* fixpoint iteration per pBlock */
7414 // emit some statistics concerning goto-optimization
7416 if (pic16_debug_verbose || pic16_pcode_verbose) {
7417 fprintf (stderr, "optimize-goto:\n"
7418 "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7419 "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7420 "\t%5d conditional \"skipping\" jumps inverted\n"
7421 "\t%5d GOTOs to next instruction removed\n"
7422 "\t%5d chained GOTOs resolved\n",
7423 opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7426 //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7430 #undef MAX_JUMPCHAIN_DEPTH
7431 #undef MAX_DIST_GOTO
7435 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7437 static void pBlockDestruct(pBlock *pb)
7448 /*-----------------------------------------------------------------*/
7449 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7450 /* name dbName and combine them */
7451 /* into one block */
7452 /*-----------------------------------------------------------------*/
7453 static void mergepBlocks(char dbName)
7456 pBlock *pb, *pbmerged = NULL,*pbn;
7458 pb = the_pFile->pbHead;
7460 //fprintf(stderr," merging blocks named %c\n",dbName);
7464 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7465 if( getpBlock_dbName(pb) == dbName) {
7467 //fprintf(stderr," merged block %c\n",dbName);
7472 pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7473 /* pic16_addpCode2pBlock doesn't handle the tail: */
7474 pbmerged->pcTail = pb->pcTail;
7476 pb->prev->next = pbn;
7478 pbn->prev = pb->prev;
7483 //pic16_printpBlock(stderr, pbmerged);
7490 /*-----------------------------------------------------------------*/
7491 /* AnalyzeFlow - Examine the flow of the code and optimize */
7493 /* level 0 == minimal optimization */
7494 /* optimize registers that are used only by two instructions */
7495 /* level 1 == maximal optimization */
7496 /* optimize by looking at pairs of instructions that use the */
7498 /*-----------------------------------------------------------------*/
7500 static void AnalyzeFlow(int level)
7502 static int times_called=0;
7507 /* remove unused allocated registers before exiting */
7508 pic16_RemoveUnusedRegisters();
7514 /* if this is not the first time this function has been called,
7515 then clean up old flow information */
7516 if(times_called++) {
7517 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7520 pic16_RegsUnMapLiveRanges();
7525 /* Phase 2 - Flow Analysis - Register Banking
7527 * In this phase, the individual flow blocks are examined
7528 * and register banking is fixed.
7532 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7533 pic16_FixRegisterBanking(pb);
7536 /* Phase 2 - Flow Analysis
7538 * In this phase, the pCode is partition into pCodeFlow
7539 * blocks. The flow blocks mark the points where a continuous
7540 * stream of instructions changes flow (e.g. because of
7541 * a call or goto or whatever).
7544 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7545 pic16_BuildFlow(pb);
7548 /* Phase 2 - Flow Analysis - linking flow blocks
7550 * In this phase, the individual flow blocks are examined
7551 * to determine their order of excution.
7554 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7557 /* Phase 3 - Flow Analysis - Flow Tree
7559 * In this phase, the individual flow blocks are examined
7560 * to determine their order of execution.
7563 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7564 pic16_BuildFlowTree(pb);
7567 /* Phase x - Flow Analysis - Used Banks
7569 * In this phase, the individual flow blocks are examined
7570 * to determine the Register Banks they use
7574 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7579 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7580 pic16_pCodeRegMapLiveRanges(pb);
7582 pic16_RemoveUnusedRegisters();
7584 // for(pb = the_pFile->pbHead; pb; pb = pb->next)
7585 pic16_pCodeRegOptimizeRegUsage(level);
7593 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7598 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7600 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7601 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7602 pcflow = pcflow->next) {
7604 FillFlow(PCFL(pcflow));
7609 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7612 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
7613 (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7614 pcflow = pcflow->next) {
7616 FlowStats(PCFL(pcflow));
7622 /* VR -- no need to analyze banking in flow, but left here :
7623 * 1. because it may be used in the future for other purposes
7624 * 2. because if omitted we'll miss some optimization done here
7626 * Perhaps I should rename it to something else
7629 /*-----------------------------------------------------------------*/
7630 /* pic16_AnalyzeBanking - Called after the memory addresses have been */
7631 /* assigned to the registers. */
7633 /*-----------------------------------------------------------------*/
7635 void pic16_AnalyzeBanking(void)
7640 /* Phase x - Flow Analysis - Used Banks
7642 * In this phase, the individual flow blocks are examined
7643 * to determine the Register Banks they use
7649 if(!the_pFile)return;
7651 if(!pic16_options.no_banksel) {
7652 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7653 // fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7654 pic16_FixRegisterBanking(pb);
7660 /*-----------------------------------------------------------------*/
7661 /* buildCallTree - Look at the flow and extract all of the calls. */
7662 /*-----------------------------------------------------------------*/
7663 static set *register_usage(pBlock *pb);
7665 static void buildCallTree(void )
7677 /* Now build the call tree.
7678 First we examine all of the pCodes for functions.
7679 Keep in mind that the function boundaries coincide
7680 with pBlock boundaries.
7682 The algorithm goes something like this:
7683 We have two nested loops. The outer loop iterates
7684 through all of the pBlocks/functions. The inner
7685 loop iterates through all of the pCodes for
7686 a given pBlock. When we begin iterating through
7687 a pBlock, the variable pc_fstart, pCode of the start
7688 of a function, is cleared. We then search for pCodes
7689 of type PC_FUNCTION. When one is encountered, we
7690 initialize pc_fstart to this and at the same time
7691 associate a new pBranch object that signifies a
7692 branch entry. If a return is found, then this signifies
7693 a function exit point. We'll link the pCodes of these
7694 returns to the matching pc_fstart.
7696 When we're done, a doubly linked list of pBranches
7697 will exist. The head of this list is stored in
7698 `the_pFile', which is the meta structure for all
7699 of the pCode. Look at the pic16_printCallTree function
7700 on how the pBranches are linked together.
7703 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7704 pCode *pc_fstart=NULL;
7705 for(pc = pb->pcHead; pc; pc = pc->next) {
7707 if(isPCI(pc) && pc_fstart) {
7708 if(PCI(pc)->is2MemOp) {
7709 r = pic16_getRegFromInstruction2(pc);
7710 if(r && !strcmp(r->name, "POSTDEC1"))
7711 PCF(pc_fstart)->stackusage++;
7713 r = pic16_getRegFromInstruction(pc);
7714 if(r && !strcmp(r->name, "PREINC1"))
7715 PCF(pc_fstart)->stackusage--;
7720 if (PCF(pc)->fname) {
7722 if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7723 //fprintf(stderr," found main \n");
7724 pb->cmemmap = NULL; /* FIXME do we need to free ? */
7728 pbr = Safe_calloc(1,sizeof(pBranch));
7729 pbr->pc = pc_fstart = pc;
7732 the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7734 // Here's a better way of doing the same:
7735 addSet(&pb->function_entries, pc);
7738 // Found an exit point in a function, e.g. return
7739 // (Note, there may be more than one return per function)
7741 pBranchLink(PCF(pc_fstart), PCF(pc));
7743 addSet(&pb->function_exits, pc);
7745 } else if(isCALL(pc)) {
7746 addSet(&pb->function_calls,pc);
7753 /* This is not needed because currently all register used
7754 * by a function are stored in stack -- VR */
7756 /* Re-allocate the registers so that there are no collisions
7757 * between local variables when one function call another */
7760 // pic16_deallocateAllRegs();
7762 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7770 /*-----------------------------------------------------------------*/
7771 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7772 /* all of the logical connections. */
7774 /* Essentially what's done here is that the pCode flow is */
7776 /*-----------------------------------------------------------------*/
7778 void pic16_AnalyzepCode(char dbName)
7789 /* Phase 1 - Register allocation and peep hole optimization
7791 * The first part of the analysis is to determine the registers
7792 * that are used in the pCode. Once that is done, the peep rules
7793 * are applied to the code. We continue to loop until no more
7794 * peep rule optimizations are found (or until we exceed the
7795 * MAX_PASSES threshold).
7797 * When done, the required registers will be determined.
7803 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7804 //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7806 /* First, merge the labels with the instructions */
7807 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7808 if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7810 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7811 //fprintf(stderr," analyze and merging block %c\n",dbName);
7812 pic16_pBlockMergeLabels(pb);
7815 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7820 changes = OptimizepCode(dbName);
7823 } while(changes && (i++ < MAX_PASSES));
7830 /* convert a series of movff's of local regs to stack, with a single call to
7831 * a support functions which does the same thing via loop */
7832 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7836 char *fname[]={"__lr_store", "__lr_restore"};
7838 // pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7840 pct = pic16_findNextInstruction(pcstart->next);
7843 pct = pc->next; //pic16_findNextInstruction(pc->next);
7844 // pc->print(stderr, pc);
7845 if(isPCI(pc) && PCI(pc)->label) {
7846 pbr = PCI(pc)->label;
7847 while(pbr && pbr->pc) {
7848 PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7852 // pc->print(stderr, pc);
7854 pc->prev->next = pct;
7855 pct->prev = pc->prev;
7859 } while ((pc) && (pc != pcend));
7861 /* unlink movff instructions */
7862 pcstart->next = pcend;
7863 pcend->prev = pcstart;
7867 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7868 // pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7871 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7872 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7873 pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7876 // pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7877 // pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7884 sym = newSymbol( fname[ entry?0:1 ], 0 );
7885 strcpy(sym->rname, fname[ entry?0:1 ]);
7886 checkAddSym(&externs, sym);
7888 // fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7893 /*-----------------------------------------------------------------*/
7894 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for */
7895 /* local registers to a support function call */
7896 /*-----------------------------------------------------------------*/
7897 void pic16_OptimizeLocalRegs(void)
7902 pCodeOpLocalReg *pclr;
7905 regs *r, *lastr=NULL, *firstr=NULL;
7906 pCode *pcstart=NULL, *pcend=NULL;
7911 * local_regs begin mark
7912 * MOVFF r0x01, POSTDEC1
7913 * MOVFF r0x02, POSTDEC1
7916 * MOVFF r0x0n, POSTDEC1
7917 * local_regs end mark
7919 * convert the above to the below:
7920 * MOVLW starting_register_index
7922 * MOVLW register_count
7923 * call __save_registers_in_stack
7929 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7930 inRegCount = regCount = 0;
7931 firstr = lastr = NULL;
7932 for(pc = pb->pcHead; pc; pc = pc->next) {
7934 /* hold current function name */
7935 if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7937 if(pc && (pc->type == PC_INFO)) {
7940 if(pci->type == INF_LOCALREGS) {
7941 pclr = PCOLR(pci->oper1);
7943 if((pclr->type == LR_ENTRY_BEGIN)
7944 || (pclr->type == LR_ENTRY_END))inEntry = 1;
7947 switch(pclr->type) {
7948 case LR_ENTRY_BEGIN:
7950 inRegCount = 1; regCount = 0;
7951 pcstart = pc; //pic16_findNextInstruction(pc->next);
7952 firstr = lastr = NULL;
7958 pcend = pc; //pic16_findPrevInstruction(pc->prev);
7961 if(curFunc && inWparamList(curFunc+1)) {
7962 fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7966 pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7971 firstr = lastr = NULL;
7975 if(inRegCount == -1) {
7976 // fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7982 if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7984 r = pic16_getRegFromInstruction(pc);
7986 r = pic16_getRegFromInstruction2(pc);
7987 if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7988 if(!firstr)firstr = r;
7990 // fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
8002 /*-----------------------------------------------------------------*/
8003 /* ispCodeFunction - returns true if *pc is the pCode of a */
8005 /*-----------------------------------------------------------------*/
8006 static bool ispCodeFunction(pCode *pc)
8009 if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8015 /*-----------------------------------------------------------------*/
8016 /* findFunction - Search for a function by name (given the name) */
8017 /* in the set of all functions that are in a pBlock */
8018 /* (note - I expect this to change because I'm planning to limit */
8019 /* pBlock's to just one function declaration */
8020 /*-----------------------------------------------------------------*/
8021 static pCode *findFunction(char *fname)
8028 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8030 pc = setFirstItem(pb->function_entries);
8033 if((pc->type == PC_FUNCTION) &&
8035 (strcmp(fname, PCF(pc)->fname)==0))
8038 pc = setNextItem(pb->function_entries);
8046 static void MarkUsedRegisters(set *regset)
8051 for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8052 // fprintf(stderr, "marking register = %s\t", r1->name);
8053 r2 = pic16_regWithIdx(r1->rIdx);
8054 // fprintf(stderr, "to register = %s\n", r2->name);
8060 static void pBlockStats(FILE *of, pBlock *pb)
8066 if(!pic16_pcode_verbose)return;
8068 fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8070 // for now just print the first element of each set
8071 pc = setFirstItem(pb->function_entries);
8073 fprintf(of,";entry: ");
8076 pc = setFirstItem(pb->function_exits);
8078 fprintf(of,";has an exit\n");
8082 pc = setFirstItem(pb->function_calls);
8084 fprintf(of,";functions called:\n");
8087 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8088 fprintf(of,"; %s\n",pic16_get_op_from_instruction(PCI(pc)));
8090 pc = setNextItem(pb->function_calls);
8094 r = setFirstItem(pb->tregisters);
8096 int n = elementsInSet(pb->tregisters);
8098 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8101 fprintf(of,"; %s\n",r->name);
8102 r = setNextItem(pb->tregisters);
8106 fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8109 /*-----------------------------------------------------------------*/
8110 /*-----------------------------------------------------------------*/
8112 static void sequencepCode(void)
8118 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8120 pb->seq = GpCodeSequenceNumber+1;
8122 for( pc = pb->pcHead; pc; pc = pc->next)
8123 pc->seq = ++GpCodeSequenceNumber;
8129 /*-----------------------------------------------------------------*/
8130 /*-----------------------------------------------------------------*/
8131 static set *register_usage(pBlock *pb)
8134 set *registers=NULL;
8135 set *registersInCallPath = NULL;
8137 /* check recursion */
8139 pc = setFirstItem(pb->function_entries);
8146 if(pc->type != PC_FUNCTION)
8147 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8149 pc = setFirstItem(pb->function_calls);
8150 for( ; pc; pc = setNextItem(pb->function_calls)) {
8152 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8153 char *dest = pic16_get_op_from_instruction(PCI(pc));
8155 pcn = findFunction(dest);
8157 registersInCallPath = register_usage(pcn->pb);
8159 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8164 pBlockStats(stderr,pb); // debug
8167 // Mark the registers in this block as used.
8169 MarkUsedRegisters(pb->tregisters);
8170 if(registersInCallPath) {
8171 /* registers were used in the functions this pBlock has called */
8172 /* so now, we need to see if these collide with the ones we are */
8175 regs *r1,*r2, *newreg;
8177 DFPRINTF((stderr,"comparing registers\n"));
8179 r1 = setFirstItem(registersInCallPath);
8182 r2 = setFirstItem(pb->tregisters);
8184 while(r2 && (r1->type != REG_STK)) {
8186 if(r2->rIdx == r1->rIdx) {
8187 newreg = pic16_findFreeReg(REG_GPR);
8191 DFPRINTF((stderr,"Bummer, no more registers.\n"));
8195 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8196 r1->rIdx, newreg->rIdx));
8197 r2->rIdx = newreg->rIdx;
8198 //if(r2->name) free(r2->name);
8200 r2->name = Safe_strdup(newreg->name);
8204 newreg->wasUsed = 1;
8206 r2 = setNextItem(pb->tregisters);
8209 r1 = setNextItem(registersInCallPath);
8212 /* Collisions have been resolved. Now free the registers in the call path */
8213 r1 = setFirstItem(registersInCallPath);
8215 if(r1->type != REG_STK) {
8216 newreg = pic16_regWithIdx(r1->rIdx);
8219 r1 = setNextItem(registersInCallPath);
8223 // MarkUsedRegisters(pb->registers);
8225 registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8228 DFPRINTF((stderr,"returning regs\n"));
8230 DFPRINTF((stderr,"not returning regs\n"));
8232 DFPRINTF((stderr,"pBlock after register optim.\n"));
8233 pBlockStats(stderr,pb); // debug
8239 /*-----------------------------------------------------------------*/
8240 /* pct2 - writes the call tree to a file */
8242 /*-----------------------------------------------------------------*/
8243 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8247 // set *registersInCallPath = NULL;
8253 fprintf(of, "recursive function\n");
8254 return; //recursion ?
8257 pc = setFirstItem(pb->function_entries);
8264 for(i=0;i<indent;i++) // Indentation
8268 if(pc->type == PC_FUNCTION) {
8269 usedstack += PCF(pc)->stackusage;
8270 fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8271 } else return; // ???
8274 pc = setFirstItem(pb->function_calls);
8275 for( ; pc; pc = setNextItem(pb->function_calls)) {
8277 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8278 char *dest = pic16_get_op_from_instruction(PCI(pc));
8280 pcn = findFunction(dest);
8282 pct2(of,pcn->pb,indent+1, usedstack); // + PCF(pcn)->stackusage);
8284 fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8292 /*-----------------------------------------------------------------*/
8293 /* pic16_printCallTree - writes the call tree to a file */
8295 /*-----------------------------------------------------------------*/
8297 void pic16_printCallTree(FILE *of)
8309 fprintf(of, "\npBlock statistics\n");
8310 for(pb = the_pFile->pbHead; pb; pb = pb->next )
8314 fprintf(of,"Call Tree\n");
8315 pbr = the_pFile->functions;
8319 if(!ispCodeFunction(pc))
8320 fprintf(of,"bug in call tree");
8323 fprintf(of,"Function: %s\n", PCF(pc)->fname);
8325 while(pc->next && !ispCodeFunction(pc->next)) {
8327 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8328 fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8336 fprintf(of,"\n**************\n\na better call tree\n");
8337 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8342 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8343 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8349 /*-----------------------------------------------------------------*/
8351 /*-----------------------------------------------------------------*/
8353 static void InlineFunction(pBlock *pb)
8361 pc = setFirstItem(pb->function_calls);
8363 for( ; pc; pc = setNextItem(pb->function_calls)) {
8366 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8372 if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) { /* change 0 to 1 to enable inlining */
8374 //fprintf(stderr,"Cool can inline:\n");
8375 //pcn->print(stderr,pcn);
8377 //fprintf(stderr,"recursive call Inline\n");
8378 InlineFunction(pcn->pb);
8379 //fprintf(stderr,"return from recursive call Inline\n");
8382 At this point, *pc points to a CALL mnemonic, and
8383 *pcn points to the function that is being called.
8385 To in-line this call, we need to remove the CALL
8386 and RETURN(s), and link the function pCode in with
8392 /* Remove the CALL */
8396 /* remove callee pBlock from the pBlock linked list */
8397 removepBlock(pcn->pb);
8405 /* Remove the Function pCode */
8406 pct = pic16_findNextInstruction(pcn->next);
8408 /* Link the function with the callee */
8409 pc->next = pcn->next;
8410 pcn->next->prev = pc;
8412 /* Convert the function name into a label */
8414 pbr = Safe_calloc(1,sizeof(pBranch));
8415 pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8417 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8418 PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8420 /* turn all of the return's except the last into goto's */
8421 /* check case for 2 instruction pBlocks */
8422 pce = pic16_findNextInstruction(pcn->next);
8424 pCode *pce_next = pic16_findNextInstruction(pce->next);
8426 if(pce_next == NULL) {
8427 /* found the last return */
8428 pCode *pc_call_next = pic16_findNextInstruction(pc_call->next);
8430 //fprintf(stderr,"found last return\n");
8431 //pce->print(stderr,pce);
8432 pce->prev->next = pc_call->next;
8433 pc_call->next->prev = pce->prev;
8434 PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8444 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8450 /*-----------------------------------------------------------------*/
8452 /*-----------------------------------------------------------------*/
8454 void pic16_InlinepCode(void)
8463 if(!functionInlining)
8466 /* Loop through all of the function definitions and count the
8467 * number of times each one is called */
8468 //fprintf(stderr,"inlining %d\n",__LINE__);
8470 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8472 pc = setFirstItem(pb->function_calls);
8474 for( ; pc; pc = setNextItem(pb->function_calls)) {
8477 pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8478 if(pcn && isPCF(pcn)) {
8479 PCF(pcn)->ncalled++;
8482 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8487 //fprintf(stderr,"inlining %d\n",__LINE__);
8489 /* Now, Loop through the function definitions again, but this
8490 * time inline those functions that have only been called once. */
8492 InlineFunction(the_pFile->pbHead);
8493 //fprintf(stderr,"inlining %d\n",__LINE__);
8495 for(pb = the_pFile->pbHead; pb; pb = pb->next)
8500 char *pic_optype_names[]={
8501 "PO_NONE", // No operand e.g. NOP
8502 "PO_W", // The working register (as a destination)
8503 "PO_WREG", // The working register (as a file register)
8504 "PO_STATUS", // The 'STATUS' register
8505 "PO_BSR", // The 'BSR' register
8506 "PO_FSR0", // The "file select register" (in PIC18 family it's one
8508 "PO_INDF0", // The Indirect register
8509 "PO_INTCON", // Interrupt Control register
8510 "PO_GPR_REGISTER", // A general purpose register
8511 "PO_GPR_BIT", // A bit of a general purpose register
8512 "PO_GPR_TEMP", // A general purpose temporary register
8513 "PO_SFR_REGISTER", // A special function register (e.g. PORTA)
8514 "PO_PCL", // Program counter Low register
8515 "PO_PCLATH", // Program counter Latch high register
8516 "PO_PCLATU", // Program counter Latch upper register
8517 "PO_PRODL", // Product Register Low
8518 "PO_PRODH", // Product Register High
8519 "PO_LITERAL", // A constant
8520 "PO_REL_ADDR", // A relative address
8521 "PO_IMMEDIATE", // (8051 legacy)
8522 "PO_DIR", // Direct memory (8051 legacy)
8523 "PO_CRY", // bit memory (8051 legacy)
8524 "PO_BIT", // bit operand.
8525 "PO_STR", // (8051 legacy)
8527 "PO_WILD" // Wild card operand in peep optimizer
8531 char *dumpPicOptype(PIC_OPTYPE type)
8533 return (pic_optype_names[ type ]);