12fed71666aeaa101d5e83b80d260164623f87c5
[fw/sdcc] / src / pic16 / pcode.c
1 /*-------------------------------------------------------------------------
2
3    pcode.c - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5    Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
6
7    This program is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published by the
9    Free Software Foundation; either version 2, or (at your option) any
10    later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
21
22
23 #include <stdio.h>
24
25 #include "common.h"   // Include everything in the SDCC src directory
26 #include "newalloc.h"
27
28
29 #include "pcode.h"
30 #include "pcodeflow.h"
31 #include "ralloc.h"
32 #include "device.h"
33
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
36 #else
37 #define STRCASECMP strcasecmp
38 #endif
39
40 /****************************************************************/
41 /****************************************************************/
42
43 static peepCommand peepCommands[] = {
44
45   {NOTBITSKIP, "_NOTBITSKIP_"},
46   {BITSKIP, "_BITSKIP_"},
47   {INVERTBITSKIP, "_INVERTBITSKIP_"},
48
49   {-1, NULL}
50 };
51
52
53
54 // Eventually this will go into device dependent files:
55 pCodeOpReg pic16_pc_status    = {{PO_STATUS,  "_STATUS"}, -1, NULL,0,NULL};
56 pCodeOpReg pic16_pc_indf0     = {{PO_INDF0,   "INDF0"}, -1, NULL,0,NULL};
57 pCodeOpReg pic16_pc_fsr0      = {{PO_FSR0,    "FSR0"}, -1, NULL,0,NULL};
58 pCodeOpReg pic16_pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pclath    = {{PO_PCLATH,  "_PCLATH"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_wreg      = {{PO_WREG,    "WREG"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_bsr       = {{PO_BSR,     "BSR"}, -1, NULL,0,NULL};
63
64 pCodeOpReg pic16_pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
65 pCodeOpReg pic16_pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pic16_pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
67
68 static int mnemonics_initialized = 0;
69
70
71 static hTab *pic16MnemonicsHash = NULL;
72 static hTab *pic16pCodePeepCommandsHash = NULL;
73
74
75
76 static pFile *the_pFile = NULL;
77 static pBlock *pb_dead_pcodes = NULL;
78
79 /* Hardcoded flags to change the behavior of the PIC port */
80 static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
81 static int functionInlining = 1;      /* inline functions if nonzero */
82 int pic16_debug_verbose = 0;                /* Set true to inundate .asm file */
83
84 static int GpCodeSequenceNumber = 1;
85 static int GpcFlowSeq = 1;
86
87 extern void pic16_RemoveUnusedRegisters(void);
88 extern void pic16_RegsUnMapLiveRanges(void);
89 extern void pic16_BuildFlowTree(pBlock *pb);
90 extern void pic16_pCodeRegOptimizeRegUsage(int level);
91 extern int pic16_picIsInitialized(void);
92 #if !OPT_DISABLE_PIC
93 // From pic/pcode.c:
94 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
95 extern int mnem2key(char const *mnem);
96 #endif // OPT_DISABLE_PIC
97
98 /****************************************************************/
99 /*                      Forward declarations                    */
100 /****************************************************************/
101
102 void pic16_unlinkpCode(pCode *pc);
103 #if 0
104 static void genericAnalyze(pCode *pc);
105 static void AnalyzeGOTO(pCode *pc);
106 static void AnalyzeSKIP(pCode *pc);
107 static void AnalyzeRETURN(pCode *pc);
108 #endif
109
110 static void genericDestruct(pCode *pc);
111 static void genericPrint(FILE *of,pCode *pc);
112
113 static void pCodePrintLabel(FILE *of, pCode *pc);
114 static void pCodePrintFunction(FILE *of, pCode *pc);
115 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
116 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
117 char *pic16_get_op( pCodeOp *pcop,char *buff,int buf_size);
118 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
119 int pic16_pCodePeepMatchRule(pCode *pc);
120 static void pBlockStats(FILE *of, pBlock *pb);
121 static pBlock *newpBlock(void);
122 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
123 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
124 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
125 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
126
127
128 /****************************************************************/
129 /*                    PIC Instructions                          */
130 /****************************************************************/
131
132 pCodeInstruction pic16_pciADDWF = {
133   {PC_OPCODE, NULL, NULL, 0, NULL, 
134    //   genericAnalyze,
135    genericDestruct,
136    genericPrint},
137   POC_ADDWF,
138   "ADDWF",
139   NULL, // from branch
140   NULL, // to branch
141   NULL, // label
142   NULL, // operand
143   NULL, // flow block
144   NULL, // C source 
145   3,    // num ops
146   1,0,  // dest, bit instruction
147   0,0,  // branch, skip
148   0,    // literal operand
149   1,    // RAM access bit
150   0,    // fast call/return mode select bit
151   POC_NOP,
152   (PCC_W | PCC_REGISTER),   // inCond
153   (PCC_REGISTER | PCC_Z) // outCond
154 };
155
156 pCodeInstruction pic16_pciADDFW = {
157   {PC_OPCODE, NULL, NULL, 0, NULL, 
158    //   genericAnalyze,
159    genericDestruct,
160    genericPrint},
161   POC_ADDFW,
162   "ADDWF",
163   NULL, // from branch
164   NULL, // to branch
165   NULL, // label
166   NULL, // operand
167   NULL, // flow block
168   NULL, // C source 
169   3,    // num ops
170   0,0,  // dest, bit instruction
171   0,0,  // branch, skip
172   0,    // literal operand
173   1,    // RAM access bit
174   0,    // fast call/return mode select bit
175   POC_NOP,
176   (PCC_W | PCC_REGISTER),   // inCond
177   (PCC_W | PCC_Z) // outCond
178 };
179
180 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
181   {PC_OPCODE, NULL, NULL, 0, NULL, 
182    //   genericAnalyze,
183    genericDestruct,
184    genericPrint},
185   POC_ADDWFC,
186   "ADDWFC",
187   NULL, // from branch
188   NULL, // to branch
189   NULL, // label
190   NULL, // operand
191   NULL, // flow block
192   NULL, // C source 
193   3,    // num ops
194   1,0,  // dest, bit instruction
195   0,0,  // branch, skip
196   0,    // literal operand
197   1,    // RAM access bit
198   0,    // fast call/return mode select bit
199   POC_NOP,
200   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
201   (PCC_REGISTER | PCC_Z) // outCond
202 };
203
204 pCodeInstruction pic16_pciADDFWC = {
205   {PC_OPCODE, NULL, NULL, 0, NULL, 
206    //   genericAnalyze,
207    genericDestruct,
208    genericPrint},
209   POC_ADDFWC,
210   "ADDWFC",
211   NULL, // from branch
212   NULL, // to branch
213   NULL, // label
214   NULL, // operand
215   NULL, // flow block
216   NULL, // C source 
217   3,    // num ops
218   0,0,  // dest, bit instruction
219   0,0,  // branch, skip
220   0,    // literal operand
221   1,    // RAM access bit
222   0,    // fast call/return mode select bit
223   POC_NOP,
224   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
225   (PCC_W | PCC_Z) // outCond
226 };
227
228 pCodeInstruction pic16_pciADDLW = {
229   {PC_OPCODE, NULL, NULL, 0, NULL, 
230    //   genericAnalyze,
231    genericDestruct,
232    genericPrint},
233   POC_ADDLW,
234   "ADDLW",
235   NULL, // from branch
236   NULL, // to branch
237   NULL, // label
238   NULL, // operand
239   NULL, // flow block
240   NULL, // C source 
241   1,    // num ops
242   0,0,  // dest, bit instruction
243   0,0,  // branch, skip
244   1,    // literal operand
245   0,    // RAM access bit
246   0,    // fast call/return mode select bit
247   POC_NOP,
248   (PCC_W | PCC_LITERAL),   // inCond
249   (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
250 };
251
252 pCodeInstruction pic16_pciANDLW = {
253   {PC_OPCODE, NULL, NULL, 0, NULL, 
254    //   genericAnalyze,
255    genericDestruct,
256    genericPrint},
257   POC_ANDLW,
258   "ANDLW",
259   NULL, // from branch
260   NULL, // to branch
261   NULL, // label
262   NULL, // operand
263   NULL, // flow block
264   NULL, // C source 
265   1,    // num ops
266   0,0,  // dest, bit instruction
267   0,0,  // branch, skip
268   1,    // literal operand
269   0,    // RAM access bit
270   0,    // fast call/return mode select bit
271   POC_NOP,
272   (PCC_W | PCC_LITERAL),   // inCond
273   (PCC_W | PCC_Z | PCC_N) // outCond
274 };
275
276 pCodeInstruction pic16_pciANDWF = {
277   {PC_OPCODE, NULL, NULL, 0, NULL, 
278    //   genericAnalyze,
279    genericDestruct,
280    genericPrint},
281   POC_ANDWF,
282   "ANDWF",
283   NULL, // from branch
284   NULL, // to branch
285   NULL, // label
286   NULL, // operand
287   NULL, // flow block
288   NULL, // C source 
289   3,    // num ops
290   1,0,  // dest, bit instruction
291   0,0,  // branch, skip
292   0,    // literal operand
293   1,    // RAM access bit
294   0,    // fast call/return mode select bit
295   POC_NOP,
296   (PCC_W | PCC_REGISTER),   // inCond
297   (PCC_REGISTER | PCC_Z | PCC_N) // outCond
298 };
299
300 pCodeInstruction pic16_pciANDFW = {
301   {PC_OPCODE, NULL, NULL, 0, NULL, 
302    //   genericAnalyze,
303    genericDestruct,
304    genericPrint},
305   POC_ANDFW,
306   "ANDWF",
307   NULL, // from branch
308   NULL, // to branch
309   NULL, // label
310   NULL, // operand
311   NULL, // flow block
312   NULL, // C source 
313   3,    // num ops
314   0,0,  // dest, bit instruction
315   0,0,  // branch, skip
316   0,    // literal operand
317   1,    // RAM access bit
318   0,    // fast call/return mode select bit
319   POC_NOP,
320   (PCC_W | PCC_REGISTER),   // inCond
321   (PCC_W | PCC_Z) // outCond
322 };
323
324 pCodeInstruction pic16_pciBC = { // mdubuc - New
325   {PC_OPCODE, NULL, NULL, 0, NULL, 
326    //   genericAnalyze,
327    genericDestruct,
328    genericPrint},
329   POC_BC,
330   "BC",
331   NULL, // from branch
332   NULL, // to branch
333   NULL, // label
334   NULL, // operand
335   NULL, // flow block
336   NULL, // C source 
337   1,    // num ops
338   0,0,  // dest, bit instruction
339   1,0,  // branch, skip
340   0,    // literal operand
341   0,    // RAM access bit
342   0,    // fast call/return mode select bit
343   POC_NOP,
344   (PCC_REL_ADDR | PCC_C),   // inCond
345   PCC_NONE    // outCond
346 };
347
348 pCodeInstruction pic16_pciBCF = {
349   {PC_OPCODE, NULL, NULL, 0, NULL, 
350    //   genericAnalyze,
351    genericDestruct,
352    genericPrint},
353   POC_BCF,
354   "BCF",
355   NULL, // from branch
356   NULL, // to branch
357   NULL, // label
358   NULL, // operand
359   NULL, // flow block
360   NULL, // C source 
361   3,    // num ops
362   1,1,  // dest, bit instruction
363   0,0,  // branch, skip
364   0,    // literal operand
365   1,    // RAM access bit
366   0,    // fast call/return mode select bit
367   POC_BSF,
368   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
369   PCC_REGISTER // outCond
370 };
371
372 pCodeInstruction pic16_pciBN = { // mdubuc - New
373   {PC_OPCODE, NULL, NULL, 0, NULL, 
374    //   genericAnalyze,
375    genericDestruct,
376    genericPrint},
377   POC_BN,
378   "BN",
379   NULL, // from branch
380   NULL, // to branch
381   NULL, // label
382   NULL, // operand
383   NULL, // flow block
384   NULL, // C source 
385   1,    // num ops
386   0,0,  // dest, bit instruction
387   1,0,  // branch, skip
388   0,    // literal operand
389   0,    // RAM access bit
390   0,    // fast call/return mode select bit
391   POC_NOP,
392   (PCC_REL_ADDR | PCC_N),   // inCond
393   PCC_NONE    // outCond
394 };
395
396 pCodeInstruction pic16_pciBNC = { // mdubuc - New
397   {PC_OPCODE, NULL, NULL, 0, NULL, 
398    //   genericAnalyze,
399    genericDestruct,
400    genericPrint},
401   POC_BNC,
402   "BNC",
403   NULL, // from branch
404   NULL, // to branch
405   NULL, // label
406   NULL, // operand
407   NULL, // flow block
408   NULL, // C source 
409   1,    // num ops
410   0,0,  // dest, bit instruction
411   1,0,  // branch, skip
412   0,    // literal operand
413   0,    // RAM access bit
414   0,    // fast call/return mode select bit
415   POC_NOP,
416   (PCC_REL_ADDR | PCC_C),   // inCond
417   PCC_NONE    // outCond
418 };
419
420 pCodeInstruction pic16_pciBNN = { // mdubuc - New
421   {PC_OPCODE, NULL, NULL, 0, NULL, 
422    //   genericAnalyze,
423    genericDestruct,
424    genericPrint},
425   POC_BNN,
426   "BNN",
427   NULL, // from branch
428   NULL, // to branch
429   NULL, // label
430   NULL, // operand
431   NULL, // flow block
432   NULL, // C source 
433   1,    // num ops
434   0,0,  // dest, bit instruction
435   1,0,  // branch, skip
436   0,    // literal operand
437   0,    // RAM access bit
438   0,    // fast call/return mode select bit
439   POC_NOP,
440   (PCC_REL_ADDR | PCC_N),   // inCond
441   PCC_NONE    // outCond
442 };
443
444 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
445   {PC_OPCODE, NULL, NULL, 0, NULL, 
446    //   genericAnalyze,
447    genericDestruct,
448    genericPrint},
449   POC_BNOV,
450   "BNOV",
451   NULL, // from branch
452   NULL, // to branch
453   NULL, // label
454   NULL, // operand
455   NULL, // flow block
456   NULL, // C source 
457   1,    // num ops
458   0,0,  // dest, bit instruction
459   1,0,  // branch, skip
460   0,    // literal operand
461   0,    // RAM access bit
462   0,    // fast call/return mode select bit
463   POC_NOP,
464   (PCC_REL_ADDR | PCC_OV),   // inCond
465   PCC_NONE    // outCond
466 };
467
468 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
469   {PC_OPCODE, NULL, NULL, 0, NULL, 
470    //   genericAnalyze,
471    genericDestruct,
472    genericPrint},
473   POC_BNZ,
474   "BNZ",
475   NULL, // from branch
476   NULL, // to branch
477   NULL, // label
478   NULL, // operand
479   NULL, // flow block
480   NULL, // C source 
481   1,    // num ops
482   0,0,  // dest, bit instruction
483   1,0,  // branch, skip
484   0,    // literal operand
485   0,    // RAM access bit
486   0,    // fast call/return mode select bit
487   POC_NOP,
488   (PCC_REL_ADDR | PCC_Z),   // inCond
489   PCC_NONE    // outCond
490 };
491
492 pCodeInstruction pic16_pciBOV = { // mdubuc - New
493   {PC_OPCODE, NULL, NULL, 0, NULL, 
494    //   genericAnalyze,
495    genericDestruct,
496    genericPrint},
497   POC_BOV,
498   "BOV",
499   NULL, // from branch
500   NULL, // to branch
501   NULL, // label
502   NULL, // operand
503   NULL, // flow block
504   NULL, // C source 
505   1,    // num ops
506   0,0,  // dest, bit instruction
507   1,0,  // branch, skip
508   0,    // literal operand
509   0,    // RAM access bit
510   0,    // fast call/return mode select bit
511   POC_NOP,
512   (PCC_REL_ADDR | PCC_OV),   // inCond
513   PCC_NONE  // outCond
514 };
515
516 pCodeInstruction pic16_pciBRA = { // mdubuc - New
517   {PC_OPCODE, NULL, NULL, 0, NULL, 
518    //   genericAnalyze,
519    genericDestruct,
520    genericPrint},
521   POC_BRA,
522   "BRA",
523   NULL, // from branch
524   NULL, // to branch
525   NULL, // label
526   NULL, // operand
527   NULL, // flow block
528   NULL, // C source 
529   1,    // num ops
530   0,0,  // dest, bit instruction
531   1,0,  // branch, skip
532   0,    // literal operand
533   0,    // RAM access bit
534   0,    // fast call/return mode select bit
535   POC_NOP,
536   PCC_REL_ADDR,   // inCond
537   PCC_NONE    // outCond
538 };
539
540 pCodeInstruction pic16_pciBSF = {
541   {PC_OPCODE, NULL, NULL, 0, NULL, 
542    //   genericAnalyze,
543    genericDestruct,
544    genericPrint},
545   POC_BSF,
546   "BSF",
547   NULL, // from branch
548   NULL, // to branch
549   NULL, // label
550   NULL, // operand
551   NULL, // flow block
552   NULL, // C source 
553   3,    // num ops
554   1,1,  // dest, bit instruction
555   0,0,  // branch, skip
556   0,    // literal operand
557   1,    // RAM access bit
558   0,    // fast call/return mode select bit
559   POC_BCF,
560   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
561   (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
562 };
563
564 pCodeInstruction pic16_pciBTFSC = {
565   {PC_OPCODE, NULL, NULL, 0, NULL, 
566    //   AnalyzeSKIP,
567    genericDestruct,
568    genericPrint},
569   POC_BTFSC,
570   "BTFSC",
571   NULL, // from branch
572   NULL, // to branch
573   NULL, // label
574   NULL, // operand
575   NULL, // flow block
576   NULL, // C source 
577   3,    // num ops
578   0,1,  // dest, bit instruction
579   1,1,  // branch, skip
580   0,    // literal operand
581   1,    // RAM access bit
582   0,    // fast call/return mode select bit
583   POC_BTFSS,
584   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
585   PCC_EXAMINE_PCOP // outCond
586 };
587
588 pCodeInstruction pic16_pciBTFSS = {
589   {PC_OPCODE, NULL, NULL, 0, NULL, 
590    //   AnalyzeSKIP,
591    genericDestruct,
592    genericPrint},
593   POC_BTFSS,
594   "BTFSS",
595   NULL, // from branch
596   NULL, // to branch
597   NULL, // label
598   NULL, // operand
599   NULL, // flow block
600   NULL, // C source 
601   3,    // num ops
602   0,1,  // dest, bit instruction
603   1,1,  // branch, skip
604   0,    // literal operand
605   1,    // RAM access bit
606   0,    // fast call/return mode select bit
607   POC_BTFSC,
608   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
609   PCC_EXAMINE_PCOP // outCond
610 };
611
612 pCodeInstruction pic16_pciBTG = { // mdubuc - New
613   {PC_OPCODE, NULL, NULL, 0, NULL, 
614    //   genericAnalyze,
615    genericDestruct,
616    genericPrint},
617   POC_BTG,
618   "BTG",
619   NULL, // from branch
620   NULL, // to branch
621   NULL, // label
622   NULL, // operand
623   NULL, // flow block
624   NULL, // C source 
625   3,    // num ops
626   0,1,  // dest, bit instruction
627   0,0,  // branch, skip
628   0,    // literal operand
629   1,    // RAM access bit
630   0,    // fast call/return mode select bit
631   POC_NOP,
632   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
633   (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
634 };
635
636 pCodeInstruction pic16_pciBZ = { // mdubuc - New
637   {PC_OPCODE, NULL, NULL, 0, NULL, 
638    //   genericAnalyze,
639    genericDestruct,
640    genericPrint},
641   POC_BZ,
642   "BZ",
643   NULL, // from branch
644   NULL, // to branch
645   NULL, // label
646   NULL, // operand
647   NULL, // flow block
648   NULL, // C source 
649   1,    // num ops
650   0,0,  // dest, bit instruction
651   1,0,  // branch, skip
652   0,    // literal operand
653   0,    // RAM access bit
654   0,    // fast call/return mode select bit
655   POC_NOP,
656   PCC_Z,   // inCond
657   PCC_NONE // outCond
658 };
659
660 pCodeInstruction pic16_pciCALL = {
661   {PC_OPCODE, NULL, NULL, 0, NULL, 
662    //   genericAnalyze,
663    genericDestruct,
664    genericPrint},
665   POC_CALL,
666   "CALL",
667   NULL, // from branch
668   NULL, // to branch
669   NULL, // label
670   NULL, // operand
671   NULL, // flow block
672   NULL, // C source 
673   2,    // num ops
674   0,0,  // dest, bit instruction
675   1,0,  // branch, skip
676   0,    // literal operand
677   0,    // RAM access bit
678   1,    // fast call/return mode select bit
679   POC_NOP,
680   PCC_NONE, // inCond
681   PCC_NONE  // outCond
682 };
683
684 pCodeInstruction pic16_pciCOMF = {
685   {PC_OPCODE, NULL, NULL, 0, NULL, 
686    //   genericAnalyze,
687    genericDestruct,
688    genericPrint},
689   POC_COMF,
690   "COMF",
691   NULL, // from branch
692   NULL, // to branch
693   NULL, // label
694   NULL, // operand
695   NULL, // flow block
696   NULL, // C source 
697   3,    // num ops
698   1,0,  // dest, bit instruction
699   0,0,  // branch, skip
700   0,    // literal operand
701   1,    // RAM access bit
702   0,    // fast call/return mode select bit
703   POC_NOP,
704   PCC_REGISTER,  // inCond
705   PCC_REGISTER   // outCond
706 };
707
708 pCodeInstruction pic16_pciCOMFW = {
709   {PC_OPCODE, NULL, NULL, 0, NULL, 
710    //   genericAnalyze,
711    genericDestruct,
712    genericPrint},
713   POC_COMFW,
714   "COMF",
715   NULL, // from branch
716   NULL, // to branch
717   NULL, // label
718   NULL, // operand
719   NULL, // flow block
720   NULL, // C source 
721   3,    // num ops
722   0,0,  // dest, bit instruction
723   0,0,  // branch, skip
724   0,    // literal operand
725   1,    // RAM access bit
726   0,    // fast call/return mode select bit
727   POC_NOP,
728   PCC_REGISTER,  // inCond
729   PCC_W   // outCond
730 };
731
732 pCodeInstruction pic16_pciCLRF = {
733   {PC_OPCODE, NULL, NULL, 0, NULL, 
734    //   genericAnalyze,
735    genericDestruct,
736    genericPrint},
737   POC_CLRF,
738   "CLRF",
739   NULL, // from branch
740   NULL, // to branch
741   NULL, // label
742   NULL, // operand
743   NULL, // flow block
744   NULL, // C source 
745   2,    // num ops
746   0,0,  // dest, bit instruction
747   0,0,  // branch, skip
748   0,    // literal operand
749   1,    // RAM access bit
750   0,    // fast call/return mode select bit
751   POC_NOP,
752   PCC_REGISTER, // inCond
753   PCC_REGISTER  // outCond
754 };
755
756 pCodeInstruction pic16_pciCLRWDT = {
757   {PC_OPCODE, NULL, NULL, 0, NULL, 
758    //   genericAnalyze,
759    genericDestruct,
760    genericPrint},
761   POC_CLRWDT,
762   "CLRWDT",
763   NULL, // from branch
764   NULL, // to branch
765   NULL, // label
766   NULL, // operand
767   NULL, // flow block
768   NULL, // C source 
769   0,    // num ops
770   0,0,  // dest, bit instruction
771   0,0,  // branch, skip
772   0,    // literal operand
773   0,    // RAM access bit
774   0,    // fast call/return mode select bit
775   POC_NOP,
776   PCC_NONE, // inCond
777   PCC_NONE  // outCond
778 };
779
780 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
781   {PC_OPCODE, NULL, NULL, 0, NULL, 
782    //   genericAnalyze,
783    genericDestruct,
784    genericPrint},
785   POC_CPFSEQ,
786   "CPFSEQ",
787   NULL, // from branch
788   NULL, // to branch
789   NULL, // label
790   NULL, // operand
791   NULL, // flow block
792   NULL, // C source 
793   2,    // num ops
794   0,0,  // dest, bit instruction
795   1,1,  // branch, skip
796   0,    // literal operand
797   1,    // RAM access bit
798   0,    // fast call/return mode select bit
799   POC_NOP,
800   (PCC_W | PCC_REGISTER), // inCond
801   PCC_NONE  // outCond
802 };
803
804 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
805   {PC_OPCODE, NULL, NULL, 0, NULL, 
806    //   genericAnalyze,
807    genericDestruct,
808    genericPrint},
809   POC_CPFSGT,
810   "CPFSGT",
811   NULL, // from branch
812   NULL, // to branch
813   NULL, // label
814   NULL, // operand
815   NULL, // flow block
816   NULL, // C source 
817   2,    // num ops
818   0,0,  // dest, bit instruction
819   1,1,  // branch, skip
820   0,    // literal operand
821   1,    // RAM access bit
822   0,    // fast call/return mode select bit
823   POC_NOP,
824   (PCC_W | PCC_REGISTER), // inCond
825   PCC_NONE  // outCond
826 };
827
828 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
829   {PC_OPCODE, NULL, NULL, 0, NULL, 
830    //   genericAnalyze,
831    genericDestruct,
832    genericPrint},
833   POC_CPFSLT,
834   "CPFSLT",
835   NULL, // from branch
836   NULL, // to branch
837   NULL, // label
838   NULL, // operand
839   NULL, // flow block
840   NULL, // C source 
841   2,    // num ops
842   1,0,  // dest, bit instruction
843   1,1,  // branch, skip
844   0,    // literal operand
845   1,    // RAM access bit
846   0,    // fast call/return mode select bit
847   POC_NOP,
848   (PCC_W | PCC_REGISTER), // inCond
849   PCC_NONE  // outCond
850 };
851
852 pCodeInstruction pic16_pciDAW = {
853   {PC_OPCODE, NULL, NULL, 0, NULL, 
854    //   genericAnalyze,
855    genericDestruct,
856    genericPrint},
857   POC_DAW,
858   "DAW",
859   NULL, // from branch
860   NULL, // to branch
861   NULL, // label
862   NULL, // operand
863   NULL, // flow block
864   NULL, // C source 
865   0,    // num ops
866   0,0,  // dest, bit instruction
867   0,0,  // branch, skip
868   0,    // literal operand
869   0,    // RAM access bit
870   0,    // fast call/return mode select bit
871   POC_NOP,
872   PCC_W, // inCond
873   (PCC_W | PCC_C) // outCond
874 };
875
876 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
877   {PC_OPCODE, NULL, NULL, 0, NULL, 
878    //   genericAnalyze,
879    genericDestruct,
880    genericPrint},
881   POC_DCFSNZ,
882   "DCFSNZ",
883   NULL, // from branch
884   NULL, // to branch
885   NULL, // label
886   NULL, // operand
887   NULL, // flow block
888   NULL, // C source 
889   3,    // num ops
890   1,0,  // dest, bit instruction
891   1,1,  // branch, skip
892   0,    // literal operand
893   1,    // RAM access bit
894   0,    // fast call/return mode select bit
895   POC_NOP,
896   PCC_REGISTER, // inCond
897   PCC_REGISTER  // outCond
898 };
899
900 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
901   {PC_OPCODE, NULL, NULL, 0, NULL, 
902    //   genericAnalyze,
903    genericDestruct,
904    genericPrint},
905   POC_DCFSNZW,
906   "DCFSNZ",
907   NULL, // from branch
908   NULL, // to branch
909   NULL, // label
910   NULL, // operand
911   NULL, // flow block
912   NULL, // C source 
913   3,    // num ops
914   0,0,  // dest, bit instruction
915   1,1,  // branch, skip
916   0,    // literal operand
917   1,    // RAM access bit
918   0,    // fast call/return mode select bit
919   POC_NOP,
920   PCC_REGISTER, // inCond
921   PCC_W  // outCond
922 };
923
924 pCodeInstruction pic16_pciDECF = {
925   {PC_OPCODE, NULL, NULL, 0, NULL, 
926    //   genericAnalyze,
927    genericDestruct,
928    genericPrint},
929   POC_DECF,
930   "DECF",
931   NULL, // from branch
932   NULL, // to branch
933   NULL, // label
934   NULL, // operand
935   NULL, // flow block
936   NULL, // C source 
937   3,    // num ops
938   1,0,  // dest, bit instruction
939   0,0,  // branch, skip
940   0,    // literal operand
941   1,    // RAM access bit
942   0,    // fast call/return mode select bit
943   POC_NOP,
944   PCC_REGISTER,   // inCond
945   PCC_REGISTER    // outCond
946 };
947
948 pCodeInstruction pic16_pciDECFW = {
949   {PC_OPCODE, NULL, NULL, 0, NULL, 
950    //   genericAnalyze,
951    genericDestruct,
952    genericPrint},
953   POC_DECFW,
954   "DECF",
955   NULL, // from branch
956   NULL, // to branch
957   NULL, // label
958   NULL, // operand
959   NULL, // flow block
960   NULL, // C source 
961   3,    // num ops
962   0,0,  // dest, bit instruction
963   0,0,  // branch, skip
964   0,    // literal operand
965   1,    // RAM access bit
966   0,    // fast call/return mode select bit
967   POC_NOP,
968   PCC_REGISTER,   // inCond
969   PCC_W    // outCond
970 };
971
972 pCodeInstruction pic16_pciDECFSZ = {
973   {PC_OPCODE, NULL, NULL, 0, NULL, 
974    //   AnalyzeSKIP,
975    genericDestruct,
976    genericPrint},
977   POC_DECFSZ,
978   "DECFSZ",
979   NULL, // from branch
980   NULL, // to branch
981   NULL, // label
982   NULL, // operand
983   NULL, // flow block
984   NULL, // C source 
985   3,    // num ops
986   1,0,  // dest, bit instruction
987   1,1,  // branch, skip
988   0,    // literal operand
989   1,    // RAM access bit
990   0,    // fast call/return mode select bit
991   POC_NOP,
992   PCC_REGISTER,   // inCond
993   PCC_REGISTER    // outCond
994 };
995
996 pCodeInstruction pic16_pciDECFSZW = {
997   {PC_OPCODE, NULL, NULL, 0, NULL, 
998    //   AnalyzeSKIP,
999    genericDestruct,
1000    genericPrint},
1001   POC_DECFSZW,
1002   "DECFSZ",
1003   NULL, // from branch
1004   NULL, // to branch
1005   NULL, // label
1006   NULL, // operand
1007   NULL, // flow block
1008   NULL, // C source 
1009   3,    // num ops
1010   0,0,  // dest, bit instruction
1011   1,1,  // branch, skip
1012   0,    // literal operand
1013   1,    // RAM access bit
1014   0,    // fast call/return mode select bit
1015   POC_NOP,
1016   PCC_REGISTER,   // inCond
1017   PCC_W           // outCond
1018 };
1019
1020 pCodeInstruction pic16_pciGOTO = {
1021   {PC_OPCODE, NULL, NULL, 0, NULL, 
1022    //   AnalyzeGOTO,
1023    genericDestruct,
1024    genericPrint},
1025   POC_GOTO,
1026   "GOTO",
1027   NULL, // from branch
1028   NULL, // to branch
1029   NULL, // label
1030   NULL, // operand
1031   NULL, // flow block
1032   NULL, // C source 
1033   1,    // num ops
1034   0,0,  // dest, bit instruction
1035   1,0,  // branch, skip
1036   0,    // literal operand
1037   0,    // RAM access bit
1038   0,    // fast call/return mode select bit
1039   POC_NOP,
1040   PCC_REL_ADDR,   // inCond
1041   PCC_NONE    // outCond
1042 };
1043
1044 pCodeInstruction pic16_pciINCF = {
1045   {PC_OPCODE, NULL, NULL, 0, NULL, 
1046    //   genericAnalyze,
1047    genericDestruct,
1048    genericPrint},
1049   POC_INCF,
1050   "INCF",
1051   NULL, // from branch
1052   NULL, // to branch
1053   NULL, // label
1054   NULL, // operand
1055   NULL, // flow block
1056   NULL, // C source 
1057   3,    // num ops
1058   1,0,  // dest, bit instruction
1059   0,0,  // branch, skip
1060   0,    // literal operand
1061   1,    // RAM access bit
1062   0,    // fast call/return mode select bit
1063   POC_NOP,
1064   PCC_REGISTER,   // inCond
1065   (PCC_REGISTER | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1066 };
1067
1068 pCodeInstruction pic16_pciINCFW = {
1069   {PC_OPCODE, NULL, NULL, 0, NULL, 
1070    //   genericAnalyze,
1071    genericDestruct,
1072    genericPrint},
1073   POC_INCFW,
1074   "INCF",
1075   NULL, // from branch
1076   NULL, // to branch
1077   NULL, // label
1078   NULL, // operand
1079   NULL, // flow block
1080   NULL, // C source 
1081   3,    // num ops
1082   0,0,  // dest, bit instruction
1083   0,0,  // branch, skip
1084   0,    // literal operand
1085   1,    // RAM access bit
1086   0,    // fast call/return mode select bit
1087   POC_NOP,
1088   PCC_REGISTER,   // inCond
1089   PCC_W    // outCond
1090 };
1091
1092 pCodeInstruction pic16_pciINCFSZ = {
1093   {PC_OPCODE, NULL, NULL, 0, NULL, 
1094    //   AnalyzeSKIP,
1095    genericDestruct,
1096    genericPrint},
1097   POC_INCFSZ,
1098   "INCFSZ",
1099   NULL, // from branch
1100   NULL, // to branch
1101   NULL, // label
1102   NULL, // operand
1103   NULL, // flow block
1104   NULL, // C source 
1105   3,    // num ops
1106   1,0,  // dest, bit instruction
1107   1,1,  // branch, skip
1108   0,    // literal operand
1109   1,    // RAM access bit
1110   0,    // fast call/return mode select bit
1111   POC_NOP,
1112   PCC_REGISTER,   // inCond
1113   PCC_REGISTER    // outCond
1114 };
1115
1116 pCodeInstruction pic16_pciINCFSZW = {
1117   {PC_OPCODE, NULL, NULL, 0, NULL, 
1118    //   AnalyzeSKIP,
1119    genericDestruct,
1120    genericPrint},
1121   POC_INCFSZW,
1122   "INCFSZ",
1123   NULL, // from branch
1124   NULL, // to branch
1125   NULL, // label
1126   NULL, // operand
1127   NULL, // flow block
1128   NULL, // C source 
1129   3,    // num ops
1130   0,0,  // dest, bit instruction
1131   1,1,  // branch, skip
1132   0,    // literal operand
1133   1,    // RAM access bit
1134   0,    // fast call/return mode select bit
1135   POC_NOP,
1136   PCC_REGISTER,   // inCond
1137   PCC_W           // outCond
1138 };
1139
1140 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1141   {PC_OPCODE, NULL, NULL, 0, NULL, 
1142    //   AnalyzeSKIP,
1143    genericDestruct,
1144    genericPrint},
1145   POC_INFSNZ,
1146   "INCFSNZ",
1147   NULL, // from branch
1148   NULL, // to branch
1149   NULL, // label
1150   NULL, // operand
1151   NULL, // flow block
1152   NULL, // C source 
1153   3,    // num ops
1154   1,0,  // dest, bit instruction
1155   1,1,  // branch, skip
1156   0,    // literal operand
1157   1,    // RAM access bit
1158   0,    // fast call/return mode select bit
1159   POC_NOP,
1160   PCC_REGISTER,   // inCond
1161   PCC_REGISTER    // outCond
1162 };
1163
1164 pCodeInstruction pic16_pciIORWF = {
1165   {PC_OPCODE, NULL, NULL, 0, NULL, 
1166    //   genericAnalyze,
1167    genericDestruct,
1168    genericPrint},
1169   POC_IORWF,
1170   "IORWF",
1171   NULL, // from branch
1172   NULL, // to branch
1173   NULL, // label
1174   NULL, // operand
1175   NULL, // flow block
1176   NULL, // C source 
1177   3,    // num ops
1178   1,0,  // dest, bit instruction
1179   0,0,  // branch, skip
1180   0,    // literal operand
1181   1,    // RAM access bit
1182   0,    // fast call/return mode select bit
1183   POC_NOP,
1184   (PCC_W | PCC_REGISTER),   // inCond
1185   (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1186 };
1187
1188 pCodeInstruction pic16_pciIORFW = {
1189   {PC_OPCODE, NULL, NULL, 0, NULL, 
1190    //   genericAnalyze,
1191    genericDestruct,
1192    genericPrint},
1193   POC_IORFW,
1194   "IORWF",
1195   NULL, // from branch
1196   NULL, // to branch
1197   NULL, // label
1198   NULL, // operand
1199   NULL, // flow block
1200   NULL, // C source 
1201   3,    // num ops
1202   0,0,  // dest, bit instruction
1203   0,0,  // branch, skip
1204   0,    // literal operand
1205   1,    // RAM access bit
1206   0,    // fast call/return mode select bit
1207   POC_NOP,
1208   (PCC_W | PCC_REGISTER),   // inCond
1209   (PCC_W | PCC_Z | PCC_N) // outCond
1210 };
1211
1212 pCodeInstruction pic16_pciIORLW = {
1213   {PC_OPCODE, NULL, NULL, 0, NULL, 
1214    //   genericAnalyze,
1215    genericDestruct,
1216    genericPrint},
1217   POC_IORLW,
1218   "IORLW",
1219   NULL, // from branch
1220   NULL, // to branch
1221   NULL, // label
1222   NULL, // operand
1223   NULL, // flow block
1224   NULL, // C source 
1225   1,    // num ops
1226   0,0,  // dest, bit instruction
1227   0,0,  // branch, skip
1228   1,    // literal operand
1229   0,    // RAM access bit
1230   0,    // fast call/return mode select bit
1231   POC_NOP,
1232   (PCC_W | PCC_LITERAL),   // inCond
1233   (PCC_W | PCC_Z | PCC_N) // outCond
1234 };
1235
1236 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1237   {PC_OPCODE, NULL, NULL, 0, NULL, 
1238    //   genericAnalyze,
1239    genericDestruct,
1240    genericPrint},
1241   POC_LFSR,
1242   "LFSR",
1243   NULL, // from branch
1244   NULL, // to branch
1245   NULL, // label
1246   NULL, // operand
1247   NULL, // flow block
1248   NULL, // C source 
1249   2,    // num ops
1250   0,0,  // dest, bit instruction
1251   0,0,  // branch, skip
1252   1,    // literal operand
1253   0,    // RAM access bit
1254   0,    // fast call/return mode select bit
1255   POC_NOP,
1256   (PCC_REGISTER | PCC_LITERAL), // mdubuc - Should we use a special syntax for
1257                                 // f (identifies FSRx)?
1258   PCC_REGISTER // outCond
1259 };
1260
1261 pCodeInstruction pic16_pciMOVF = {
1262   {PC_OPCODE, NULL, NULL, 0, NULL, 
1263    //   genericAnalyze,
1264    genericDestruct,
1265    genericPrint},
1266   POC_MOVF,
1267   "MOVF",
1268   NULL, // from branch
1269   NULL, // to branch
1270   NULL, // label
1271   NULL, // operand
1272   NULL, // flow block
1273   NULL, // C source 
1274   3,    // num ops
1275   1,0,  // dest, bit instruction
1276   0,0,  // branch, skip
1277   0,    // literal operand
1278   1,    // RAM access bit
1279   0,    // fast call/return mode select bit
1280   POC_NOP,
1281   PCC_REGISTER,   // inCond
1282   (PCC_Z | PCC_N) // outCond
1283 };
1284
1285 pCodeInstruction pic16_pciMOVFW = {
1286   {PC_OPCODE, NULL, NULL, 0, NULL, 
1287    //   genericAnalyze,
1288    genericDestruct,
1289    genericPrint},
1290   POC_MOVFW,
1291   "MOVF",
1292   NULL, // from branch
1293   NULL, // to branch
1294   NULL, // label
1295   NULL, // operand
1296   NULL, // flow block
1297   NULL, // C source 
1298   3,    // num ops
1299   0,0,  // dest, bit instruction
1300   0,0,  // branch, skip
1301   0,    // literal operand
1302   1,    // RAM access bit
1303   0,    // fast call/return mode select bit
1304   POC_NOP,
1305   PCC_REGISTER,   // inCond
1306   (PCC_W | PCC_Z) // outCond
1307 };
1308
1309 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1310   {PC_OPCODE, NULL, NULL, 0, NULL, 
1311    //   genericAnalyze,
1312    genericDestruct,
1313    genericPrint},
1314   POC_MOVFF,
1315   "MOVFF",
1316   NULL, // from branch
1317   NULL, // to branch
1318   NULL, // label
1319   NULL, // operand
1320   NULL, // flow block
1321   NULL, // C source 
1322   2,    // num ops
1323   0,0,  // dest, bit instruction
1324   0,0,  // branch, skip
1325   0,    // literal operand
1326   0,    // RAM access bit
1327   0,    // fast call/return mode select bit
1328   POC_NOP,
1329   PCC_REGISTER,   // inCond
1330   PCC_REGISTER2 // outCond
1331 };
1332
1333 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1334   {PC_OPCODE, NULL, NULL, 0, NULL, 
1335    genericDestruct,
1336    genericPrint},
1337   POC_MOVLB,
1338   "MOVLB",
1339   NULL, // from branch
1340   NULL, // to branch
1341   NULL, // label
1342   NULL, // operand
1343   NULL, // flow block
1344   NULL, // C source 
1345   1,    // num ops
1346   0,0,  // dest, bit instruction
1347   0,0,  // branch, skip
1348   1,    // literal operand
1349   0,    // RAM access bit
1350   0,    // fast call/return mode select bit
1351   POC_NOP,
1352   (PCC_NONE | PCC_LITERAL),   // inCond
1353   PCC_REGISTER // outCond - BSR
1354 };
1355
1356 pCodeInstruction pic16_pciMOVLW = {
1357   {PC_OPCODE, NULL, NULL, 0, NULL, 
1358    genericDestruct,
1359    genericPrint},
1360   POC_MOVLW,
1361   "MOVLW",
1362   NULL, // from branch
1363   NULL, // to branch
1364   NULL, // label
1365   NULL, // operand
1366   NULL, // flow block
1367   NULL, // C source 
1368   1,    // num ops
1369   0,0,  // dest, bit instruction
1370   0,0,  // branch, skip
1371   1,    // literal operand
1372   0,    // RAM access bit
1373   0,    // fast call/return mode select bit
1374   POC_NOP,
1375   (PCC_NONE | PCC_LITERAL),   // inCond
1376   PCC_W // outCond
1377 };
1378
1379 pCodeInstruction pic16_pciMOVWF = {
1380   {PC_OPCODE, NULL, NULL, 0, NULL, 
1381    //   genericAnalyze,
1382    genericDestruct,
1383    genericPrint},
1384   POC_MOVWF,
1385   "MOVWF",
1386   NULL, // from branch
1387   NULL, // to branch
1388   NULL, // label
1389   NULL, // operand
1390   NULL, // flow block
1391   NULL, // C source 
1392   2,    // num ops
1393   0,0,  // dest, bit instruction
1394   0,0,  // branch, skip
1395   0,    // literal operand
1396   1,    // RAM access bit
1397   0,    // fast call/return mode select bit
1398   POC_NOP,
1399   PCC_REGISTER,   // inCond
1400   PCC_W // outCond
1401 };
1402
1403 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1404   {PC_OPCODE, NULL, NULL, 0, NULL, 
1405    genericDestruct,
1406    genericPrint},
1407   POC_MULLW,
1408   "MULLW",
1409   NULL, // from branch
1410   NULL, // to branch
1411   NULL, // label
1412   NULL, // operand
1413   NULL, // flow block
1414   NULL, // C source 
1415   1,    // num ops
1416   0,0,  // dest, bit instruction
1417   0,0,  // branch, skip
1418   1,    // literal operand
1419   0,    // RAM access bit
1420   0,    // fast call/return mode select bit
1421   POC_NOP,
1422   (PCC_W | PCC_LITERAL),   // inCond
1423   PCC_REGISTER // outCond - PROD
1424 };
1425
1426 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1427   {PC_OPCODE, NULL, NULL, 0, NULL, 
1428    genericDestruct,
1429    genericPrint},
1430   POC_MULWF,
1431   "MULWF",
1432   NULL, // from branch
1433   NULL, // to branch
1434   NULL, // label
1435   NULL, // operand
1436   NULL, // flow block
1437   NULL, // C source 
1438   2,    // num ops
1439   0,0,  // dest, bit instruction
1440   0,0,  // branch, skip
1441   0,    // literal operand
1442   1,    // RAM access bit
1443   0,    // fast call/return mode select bit
1444   POC_NOP,
1445   (PCC_W | PCC_REGISTER),   // inCond
1446   PCC_REGISTER // outCond - PROD
1447 };
1448
1449 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1450   {PC_OPCODE, NULL, NULL, 0, NULL, 
1451    genericDestruct,
1452    genericPrint},
1453   POC_NEGF,
1454   "NEGF",
1455   NULL, // from branch
1456   NULL, // to branch
1457   NULL, // label
1458   NULL, // operand
1459   NULL, // flow block
1460   NULL, // C source 
1461   2,    // num ops
1462   0,0,  // dest, bit instruction
1463   0,0,  // branch, skip
1464   0,    // literal operand
1465   1,    // RAM access bit
1466   0,    // fast call/return mode select bit
1467   POC_NOP,
1468   PCC_REGISTER, // inCond
1469   (PCC_REGISTER | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1470 };
1471
1472 pCodeInstruction pic16_pciNOP = {
1473   {PC_OPCODE, NULL, NULL, 0, NULL, 
1474    genericDestruct,
1475    genericPrint},
1476   POC_NOP,
1477   "NOP",
1478   NULL, // from branch
1479   NULL, // to branch
1480   NULL, // label
1481   NULL, // operand
1482   NULL, // flow block
1483   NULL, // C source 
1484   0,    // num ops
1485   0,0,  // dest, bit instruction
1486   0,0,  // branch, skip
1487   0,    // literal operand
1488   0,    // RAM access bit
1489   0,    // fast call/return mode select bit
1490   POC_NOP,
1491   PCC_NONE,   // inCond
1492   PCC_NONE // outCond
1493 };
1494
1495 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1496   {PC_OPCODE, NULL, NULL, 0, NULL, 
1497    genericDestruct,
1498    genericPrint},
1499   POC_POP,
1500   "POP",
1501   NULL, // from branch
1502   NULL, // to branch
1503   NULL, // label
1504   NULL, // operand
1505   NULL, // flow block
1506   NULL, // C source 
1507   0,    // num ops
1508   0,0,  // dest, bit instruction
1509   0,0,  // branch, skip
1510   0,    // literal operand
1511   0,    // RAM access bit
1512   0,    // fast call/return mode select bit
1513   POC_NOP,
1514   PCC_NONE,  // inCond
1515   PCC_NONE   // outCond
1516 };
1517
1518 pCodeInstruction pic16_pciPUSH = {
1519   {PC_OPCODE, NULL, NULL, 0, NULL, 
1520    genericDestruct,
1521    genericPrint},
1522   POC_PUSH,
1523   "PUSH",
1524   NULL, // from branch
1525   NULL, // to branch
1526   NULL, // label
1527   NULL, // operand
1528   NULL, // flow block
1529   NULL, // C source 
1530   0,    // num ops
1531   0,0,  // dest, bit instruction
1532   0,0,  // branch, skip
1533   0,    // literal operand
1534   0,    // RAM access bit
1535   0,    // fast call/return mode select bit
1536   POC_NOP,
1537   PCC_NONE,  // inCond
1538   PCC_NONE   // outCond
1539 };
1540
1541 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1542   {PC_OPCODE, NULL, NULL, 0, NULL, 
1543    genericDestruct,
1544    genericPrint},
1545   POC_RCALL,
1546   "RCALL",
1547   NULL, // from branch
1548   NULL, // to branch
1549   NULL, // label
1550   NULL, // operand
1551   NULL, // flow block
1552   NULL, // C source 
1553   1,    // num ops
1554   0,0,  // dest, bit instruction
1555   0,0,  // branch, skip
1556   0,    // literal operand
1557   0,    // RAM access bit
1558   0,    // fast call/return mode select bit
1559   POC_NOP,
1560   PCC_REL_ADDR,  // inCond
1561   PCC_NONE   // outCond
1562 };
1563
1564 pCodeInstruction pic16_pciRETFIE = {
1565   {PC_OPCODE, NULL, NULL, 0, NULL, 
1566    //   AnalyzeRETURN,
1567    genericDestruct,
1568    genericPrint},
1569   POC_RETFIE,
1570   "RETFIE",
1571   NULL, // from branch
1572   NULL, // to branch
1573   NULL, // label
1574   NULL, // operand
1575   NULL, // flow block
1576   NULL, // C source 
1577   1,    // num ops
1578   0,0,  // dest, bit instruction
1579   1,0,  // branch, skip
1580   0,    // literal operand
1581   0,    // RAM access bit
1582   1,    // fast call/return mode select bit
1583   POC_NOP,
1584   PCC_NONE,   // inCond
1585   PCC_NONE    // outCond (not true... affects the GIE bit too)
1586 };
1587
1588 pCodeInstruction pic16_pciRETLW = {
1589   {PC_OPCODE, NULL, NULL, 0, NULL, 
1590    //   AnalyzeRETURN,
1591    genericDestruct,
1592    genericPrint},
1593   POC_RETLW,
1594   "RETLW",
1595   NULL, // from branch
1596   NULL, // to branch
1597   NULL, // label
1598   NULL, // operand
1599   NULL, // flow block
1600   NULL, // C source 
1601   1,    // num ops
1602   0,0,  // dest, bit instruction
1603   1,0,  // branch, skip
1604   1,    // literal operand
1605   0,    // RAM access bit
1606   0,    // fast call/return mode select bit
1607   POC_NOP,
1608   PCC_LITERAL,   // inCond
1609   PCC_W // outCond
1610 };
1611
1612 pCodeInstruction pic16_pciRETURN = {
1613   {PC_OPCODE, NULL, NULL, 0, NULL, 
1614    //   AnalyzeRETURN,
1615    genericDestruct,
1616    genericPrint},
1617   POC_RETURN,
1618   "RETURN",
1619   NULL, // from branch
1620   NULL, // to branch
1621   NULL, // label
1622   NULL, // operand
1623   NULL, // flow block
1624   NULL, // C source 
1625   1,    // num ops
1626   0,0,  // dest, bit instruction
1627   1,0,  // branch, skip
1628   0,    // literal operand
1629   0,    // RAM access bit
1630   1,    // fast call/return mode select bit
1631   POC_NOP,
1632   PCC_NONE,   // inCond
1633   PCC_NONE // outCond
1634 };
1635 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1636   {PC_OPCODE, NULL, NULL, 0, NULL, 
1637    //   genericAnalyze,
1638    genericDestruct,
1639    genericPrint},
1640   POC_RLCF,
1641   "RLCF",
1642   NULL, // from branch
1643   NULL, // to branch
1644   NULL, // label
1645   NULL, // operand
1646   NULL, // flow block
1647   NULL, // C source 
1648   3,    // num ops
1649   1,0,  // dest, bit instruction
1650   0,0,  // branch, skip
1651   0,    // literal operand
1652   1,    // RAM access bit
1653   0,    // fast call/return mode select bit
1654   POC_NOP,
1655   (PCC_C | PCC_REGISTER),   // inCond
1656   (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1657 };
1658
1659 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
1660   {PC_OPCODE, NULL, NULL, 0, NULL, 
1661    //   genericAnalyze,
1662    genericDestruct,
1663    genericPrint},
1664   POC_RLCFW,
1665   "RLCF",
1666   NULL, // from branch
1667   NULL, // to branch
1668   NULL, // label
1669   NULL, // operand
1670   NULL, // flow block
1671   NULL, // C source 
1672   3,    // num ops
1673   0,0,  // dest, bit instruction
1674   0,0,  // branch, skip
1675   0,    // literal operand
1676   1,    // RAM access bit
1677   0,    // fast call/return mode select bit
1678   POC_NOP,
1679   (PCC_C | PCC_REGISTER),   // inCond
1680   (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1681 };
1682
1683 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
1684   {PC_OPCODE, NULL, NULL, 0, NULL, 
1685    //   genericAnalyze,
1686    genericDestruct,
1687    genericPrint},
1688   POC_RLNCF,
1689   "RLNCF",
1690   NULL, // from branch
1691   NULL, // to branch
1692   NULL, // label
1693   NULL, // operand
1694   NULL, // flow block
1695   NULL, // C source 
1696   3,    // num ops
1697   1,0,  // dest, bit instruction
1698   0,0,  // branch, skip
1699   0,    // literal operand
1700   1,    // RAM access bit
1701   0,    // fast call/return mode select bit
1702   POC_NOP,
1703   PCC_REGISTER,   // inCond
1704   (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1705 };
1706 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
1707   {PC_OPCODE, NULL, NULL, 0, NULL, 
1708    //   genericAnalyze,
1709    genericDestruct,
1710    genericPrint},
1711   POC_RLNCFW,
1712   "RLNCF",
1713   NULL, // from branch
1714   NULL, // to branch
1715   NULL, // label
1716   NULL, // operand
1717   NULL, // flow block
1718   NULL, // C source 
1719   3,    // num ops
1720   0,0,  // dest, bit instruction
1721   0,0,  // branch, skip
1722   0,    // literal operand
1723   1,    // RAM access bit
1724   0,    // fast call/return mode select bit
1725   POC_NOP,
1726   PCC_REGISTER,   // inCond
1727   (PCC_W | PCC_Z | PCC_N) // outCond
1728 };
1729 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
1730   {PC_OPCODE, NULL, NULL, 0, NULL, 
1731    //   genericAnalyze,
1732    genericDestruct,
1733    genericPrint},
1734   POC_RRCF,
1735   "RRCF",
1736   NULL, // from branch
1737   NULL, // to branch
1738   NULL, // label
1739   NULL, // operand
1740   NULL, // flow block
1741   NULL, // C source 
1742   3,    // num ops
1743   1,0,  // dest, bit instruction
1744   0,0,  // branch, skip
1745   0,    // literal operand
1746   1,    // RAM access bit
1747   0,    // fast call/return mode select bit
1748   POC_NOP,
1749   (PCC_C | PCC_REGISTER),   // inCond
1750   (PCC_REGISTER | PCC_C | PCC_Z | PCC_N) // outCond
1751 };
1752 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
1753   {PC_OPCODE, NULL, NULL, 0, NULL, 
1754    //   genericAnalyze,
1755    genericDestruct,
1756    genericPrint},
1757   POC_RRCFW,
1758   "RRCF",
1759   NULL, // from branch
1760   NULL, // to branch
1761   NULL, // label
1762   NULL, // operand
1763   NULL, // flow block
1764   NULL, // C source 
1765   3,    // num ops
1766   0,0,  // dest, bit instruction
1767   0,0,  // branch, skip
1768   0,    // literal operand
1769   1,    // RAM access bit
1770   0,    // fast call/return mode select bit
1771   POC_NOP,
1772   (PCC_C | PCC_REGISTER),   // inCond
1773   (PCC_W | PCC_C | PCC_Z | PCC_N) // outCond
1774 };
1775 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
1776   {PC_OPCODE, NULL, NULL, 0, NULL, 
1777    //   genericAnalyze,
1778    genericDestruct,
1779    genericPrint},
1780   POC_RRNCF,
1781   "RRNCF",
1782   NULL, // from branch
1783   NULL, // to branch
1784   NULL, // label
1785   NULL, // operand
1786   NULL, // flow block
1787   NULL, // C source 
1788   3,    // num ops
1789   1,0,  // dest, bit instruction
1790   0,0,  // branch, skip
1791   0,    // literal operand
1792   1,    // RAM access bit
1793   0,    // fast call/return mode select bit
1794   POC_NOP,
1795   PCC_REGISTER,   // inCond
1796   (PCC_REGISTER | PCC_Z | PCC_N) // outCond
1797 };
1798
1799 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
1800   {PC_OPCODE, NULL, NULL, 0, NULL, 
1801    //   genericAnalyze,
1802    genericDestruct,
1803    genericPrint},
1804   POC_RRNCFW,
1805   "RRNCF",
1806   NULL, // from branch
1807   NULL, // to branch
1808   NULL, // label
1809   NULL, // operand
1810   NULL, // flow block
1811   NULL, // C source 
1812   3,    // num ops
1813   0,0,  // dest, bit instruction
1814   0,0,  // branch, skip
1815   0,    // literal operand
1816   1,    // RAM access bit
1817   0,    // fast call/return mode select bit
1818   POC_NOP,
1819   PCC_REGISTER,   // inCond
1820   (PCC_W | PCC_Z | PCC_N) // outCond
1821 };
1822
1823 pCodeInstruction pic16_pciSETF = { // mdubuc - New
1824   {PC_OPCODE, NULL, NULL, 0, NULL, 
1825    //   genericAnalyze,
1826    genericDestruct,
1827    genericPrint},
1828   POC_SETF,
1829   "SETF",
1830   NULL, // from branch
1831   NULL, // to branch
1832   NULL, // label
1833   NULL, // operand
1834   NULL, // flow block
1835   NULL, // C source 
1836   2,    // num ops
1837   0,0,  // dest, bit instruction
1838   0,0,  // branch, skip
1839   0,    // literal operand
1840   1,    // RAM access bit
1841   0,    // fast call/return mode select bit
1842   POC_NOP,
1843   PCC_REGISTER,  // inCond
1844   PCC_REGISTER   // outCond
1845 };
1846
1847 pCodeInstruction pic16_pciSUBLW = {
1848   {PC_OPCODE, NULL, NULL, 0, NULL, 
1849    //   genericAnalyze,
1850    genericDestruct,
1851    genericPrint},
1852   POC_SUBLW,
1853   "SUBLW",
1854   NULL, // from branch
1855   NULL, // to branch
1856   NULL, // label
1857   NULL, // operand
1858   NULL, // flow block
1859   NULL, // C source 
1860   1,    // num ops
1861   0,0,  // dest, bit instruction
1862   0,0,  // branch, skip
1863   1,    // literal operand
1864   0,    // RAM access bit
1865   0,    // fast call/return mode select bit
1866   POC_NOP,
1867   (PCC_W | PCC_LITERAL),   // inCond
1868   (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1869 };
1870
1871 pCodeInstruction pic16_pciSUBFWB = {
1872   {PC_OPCODE, NULL, NULL, 0, NULL, 
1873    //   genericAnalyze,
1874    genericDestruct,
1875    genericPrint},
1876   POC_SUBFWB,
1877   "SUBFWB",
1878   NULL, // from branch
1879   NULL, // to branch
1880   NULL, // label
1881   NULL, // operand
1882   NULL, // flow block
1883   NULL, // C source 
1884   3,    // num ops
1885   1,0,  // dest, bit instruction
1886   0,0,  // branch, skip
1887   0,    // literal operand
1888   1,    // RAM access bit
1889   0,    // fast call/return mode select bit
1890   POC_NOP,
1891   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
1892   (PCC_W | PCC_C | PCC_DC | PCC_Z | PCC_OV | PCC_N) // outCond
1893 };
1894
1895 pCodeInstruction pic16_pciSUBWF = {
1896   {PC_OPCODE, NULL, NULL, 0, NULL, 
1897    //   genericAnalyze,
1898    genericDestruct,
1899    genericPrint},
1900   POC_SUBWF,
1901   "SUBWF",
1902   NULL, // from branch
1903   NULL, // to branch
1904   NULL, // label
1905   NULL, // operand
1906   NULL, // flow block
1907   NULL, // C source 
1908   3,    // num ops
1909   1,0,  // dest, bit instruction
1910   0,0,  // branch, skip
1911   0,    // literal operand
1912   1,    // RAM access bit
1913   0,    // fast call/return mode select bit
1914   POC_NOP,
1915   (PCC_W | PCC_REGISTER),   // inCond
1916   (PCC_REGISTER | PCC_Z) // outCond
1917 };
1918
1919 pCodeInstruction pic16_pciSUBFW = {
1920   {PC_OPCODE, NULL, NULL, 0, NULL, 
1921    //   genericAnalyze,
1922    genericDestruct,
1923    genericPrint},
1924   POC_SUBFW,
1925   "SUBWF",
1926   NULL, // from branch
1927   NULL, // to branch
1928   NULL, // label
1929   NULL, // operand
1930   NULL, // flow block
1931   NULL, // C source 
1932   3,    // num ops
1933   0,0,  // dest, bit instruction
1934   0,0,  // branch, skip
1935   0,    // literal operand
1936   1,    // RAM access bit
1937   0,    // fast call/return mode select bit
1938   POC_NOP,
1939   (PCC_W | PCC_REGISTER),   // inCond
1940   (PCC_W | PCC_Z | PCC_OV | PCC_N) // outCond
1941 };
1942
1943 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
1944   {PC_OPCODE, NULL, NULL, 0, NULL, 
1945    //   genericAnalyze,
1946    genericDestruct,
1947    genericPrint},
1948   POC_SUBFWB_D1,
1949   "SUBFWB",
1950   NULL, // from branch
1951   NULL, // to branch
1952   NULL, // label
1953   NULL, // operand
1954   NULL, // flow block
1955   NULL, // C source 
1956   3,    // num ops
1957   1,0,  // dest, bit instruction
1958   0,0,  // branch, skip
1959   0,    // literal operand
1960   1,    // RAM access bit
1961   0,    // fast call/return mode select bit
1962   POC_NOP,
1963   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
1964   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1965 };
1966
1967 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
1968   {PC_OPCODE, NULL, NULL, 0, NULL, 
1969    //   genericAnalyze,
1970    genericDestruct,
1971    genericPrint},
1972   POC_SUBFWB_D0,
1973   "SUBFWB",
1974   NULL, // from branch
1975   NULL, // to branch
1976   NULL, // label
1977   NULL, // operand
1978   NULL, // flow block
1979   NULL, // C source 
1980   3,    // num ops
1981   0,0,  // dest, bit instruction
1982   0,0,  // branch, skip
1983   0,    // literal operand
1984   1,    // RAM access bit
1985   0,    // fast call/return mode select bit
1986   POC_NOP,
1987   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
1988   (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
1989 };
1990
1991 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
1992   {PC_OPCODE, NULL, NULL, 0, NULL, 
1993    //   genericAnalyze,
1994    genericDestruct,
1995    genericPrint},
1996   POC_SUBWFB_D1,
1997   "SUBWFB",
1998   NULL, // from branch
1999   NULL, // to branch
2000   NULL, // label
2001   NULL, // operand
2002   NULL, // flow block
2003   NULL, // C source 
2004   3,    // num ops
2005   1,0,  // dest, bit instruction
2006   0,0,  // branch, skip
2007   0,    // literal operand
2008   1,    // RAM access bit
2009   0,    // fast call/return mode select bit
2010   POC_NOP,
2011   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2012   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2013 };
2014
2015 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2016   {PC_OPCODE, NULL, NULL, 0, NULL, 
2017    //   genericAnalyze,
2018    genericDestruct,
2019    genericPrint},
2020   POC_SUBWFB_D0,
2021   "SUBWFB",
2022   NULL, // from branch
2023   NULL, // to branch
2024   NULL, // label
2025   NULL, // operand
2026   NULL, // flow block
2027   NULL, // C source 
2028   3,    // num ops
2029   0,0,  // dest, bit instruction
2030   0,0,  // branch, skip
2031   0,    // literal operand
2032   1,    // RAM access bit
2033   0,    // fast call/return mode select bit
2034   POC_NOP,
2035   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2036   (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_OV | PCC_N) // outCond
2037 };
2038
2039 pCodeInstruction pic16_pciSWAPF = {
2040   {PC_OPCODE, NULL, NULL, 0, NULL, 
2041    //   genericAnalyze,
2042    genericDestruct,
2043    genericPrint},
2044   POC_SWAPF,
2045   "SWAPF",
2046   NULL, // from branch
2047   NULL, // to branch
2048   NULL, // label
2049   NULL, // operand
2050   NULL, // flow block
2051   NULL, // C source 
2052   3,    // num ops
2053   1,0,  // dest, bit instruction
2054   0,0,  // branch, skip
2055   0,    // literal operand
2056   1,    // RAM access bit
2057   0,    // fast call/return mode select bit
2058   POC_NOP,
2059   (PCC_REGISTER),   // inCond
2060   (PCC_REGISTER) // outCond
2061 };
2062
2063 pCodeInstruction pic16_pciSWAPFW = {
2064   {PC_OPCODE, NULL, NULL, 0, NULL, 
2065    //   genericAnalyze,
2066    genericDestruct,
2067    genericPrint},
2068   POC_SWAPFW,
2069   "SWAPF",
2070   NULL, // from branch
2071   NULL, // to branch
2072   NULL, // label
2073   NULL, // operand
2074   NULL, // flow block
2075   NULL, // C source 
2076   3,    // num ops
2077   0,0,  // dest, bit instruction
2078   0,0,  // branch, skip
2079   0,    // literal operand
2080   1,    // RAM access bit
2081   0,    // fast call/return mode select bit
2082   POC_NOP,
2083   (PCC_REGISTER),   // inCond
2084   (PCC_W) // outCond
2085 };
2086
2087 // mdubuc - Remove TRIS
2088
2089 pCodeInstruction pic16_pciTRIS = {
2090   {PC_OPCODE, NULL, NULL, 0, NULL, 
2091    //   genericAnalyze,
2092    genericDestruct,
2093    genericPrint},
2094   POC_TRIS,
2095   "TRIS",
2096   NULL, // from branch
2097   NULL, // to branch
2098   NULL, // label
2099   NULL, // operand
2100   NULL, // flow block
2101   NULL, // C source 
2102   1,    // num ops
2103   0,0,  // dest, bit instruction
2104   0,0,  // branch, skip
2105   0,    // literal operand
2106   POC_NOP,
2107   PCC_NONE,   // inCond
2108   PCC_REGISTER // outCond
2109 };
2110
2111 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2112   {PC_OPCODE, NULL, NULL, 0, NULL, 
2113    //   genericAnalyze,
2114    genericDestruct,
2115    genericPrint},
2116   POC_TSTFSZ,
2117   "TSTFSZ",
2118   NULL, // from branch
2119   NULL, // to branch
2120   NULL, // label
2121   NULL, // operand
2122   NULL, // flow block
2123   NULL, // C source 
2124   2,    // num ops
2125   0,0,  // dest, bit instruction
2126   1,1,  // branch, skip
2127   0,    // literal operand
2128   1,    // RAM access bit
2129   0,    // fast call/return mode select bit
2130   POC_NOP,
2131   PCC_REGISTER,   // inCond
2132   PCC_NONE // outCond
2133 };
2134
2135 pCodeInstruction pic16_pciXORWF = {
2136   {PC_OPCODE, NULL, NULL, 0, NULL, 
2137    //   genericAnalyze,
2138    genericDestruct,
2139    genericPrint},
2140   POC_XORWF,
2141   "XORWF",
2142   NULL, // from branch
2143   NULL, // to branch
2144   NULL, // label
2145   NULL, // operand
2146   NULL, // flow block
2147   NULL, // C source 
2148   3,    // num ops
2149   1,0,  // dest, bit instruction
2150   0,0,  // branch, skip
2151   0,    // literal operand
2152   1,    // RAM access bit
2153   0,    // fast call/return mode select bit
2154   POC_NOP,
2155   (PCC_W | PCC_REGISTER),   // inCond
2156   (PCC_REGISTER | PCC_Z | PCC_N) // outCond
2157 };
2158
2159 pCodeInstruction pic16_pciXORFW = {
2160   {PC_OPCODE, NULL, NULL, 0, NULL, 
2161    //   genericAnalyze,
2162    genericDestruct,
2163    genericPrint},
2164   POC_XORFW,
2165   "XORWF",
2166   NULL, // from branch
2167   NULL, // to branch
2168   NULL, // label
2169   NULL, // operand
2170   NULL, // flow block
2171   NULL, // C source 
2172   3,    // num ops
2173   0,0,  // dest, bit instruction
2174   0,0,  // branch, skip
2175   0,    // literal operand
2176   1,    // RAM access bit
2177   0,    // fast call/return mode select bit
2178   POC_NOP,
2179   (PCC_W | PCC_REGISTER),   // inCond
2180   (PCC_W | PCC_Z | PCC_N) // outCond
2181 };
2182
2183 pCodeInstruction pic16_pciXORLW = {
2184   {PC_OPCODE, NULL, NULL, 0, NULL, 
2185    //   genericAnalyze,
2186    genericDestruct,
2187    genericPrint},
2188   POC_XORLW,
2189   "XORLW",
2190   NULL, // from branch
2191   NULL, // to branch
2192   NULL, // label
2193   NULL, // operand
2194   NULL, // flow block
2195   NULL, // C source 
2196   1,    // num ops
2197   0,0,  // dest, bit instruction
2198   0,0,  // branch, skip
2199   1,    // literal operand
2200   1,    // RAM access bit
2201   0,    // fast call/return mode select bit
2202   POC_NOP,
2203   (PCC_W | PCC_LITERAL),   // inCond
2204   (PCC_W | PCC_Z | PCC_C | PCC_DC | PCC_N) // outCond
2205 };
2206
2207
2208 #define MAX_PIC16MNEMONICS 100
2209 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2210
2211 #if OPT_DISABLE_PIC
2212 /* This definition needs to be part of configure.in */
2213 // #define USE_VSNPRINTF
2214
2215 #ifdef USE_VSNPRINTF
2216   // Alas, vsnprintf is not ANSI standard, and does not exist
2217   // on Solaris (and probably other non-Gnu flavored Unixes).
2218
2219 /*-----------------------------------------------------------------*/
2220 /* SAFE_snprintf - like snprintf except the string pointer is      */
2221 /*                 after the string has been printed to. This is   */
2222 /*                 useful for printing to string as though if it   */
2223 /*                 were a stream.                                  */
2224 /*-----------------------------------------------------------------*/
2225 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
2226 {
2227   va_list val;
2228   int len;
2229
2230   if(!str || !*str)
2231     return;
2232
2233   va_start(val, format);
2234
2235   vsnprintf(*str, *size, format, val);
2236
2237   va_end (val);
2238
2239   len = strlen(*str);
2240   if(len > *size) {
2241     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2242     fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2243   }
2244
2245   *str += len;
2246   *size -= len;
2247
2248 }
2249
2250 #else  //  USE_VSNPRINTF
2251
2252 // This version is *not* safe, despite the name.
2253
2254 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
2255 {
2256   va_list val;
2257   int len;
2258   static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2259
2260   if(!str || !*str)
2261     return;
2262
2263   va_start(val, format);
2264
2265   vsprintf(buffer, format, val);
2266   va_end (val);
2267
2268   len = strlen(buffer);
2269   if(len > *size) {
2270     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2271     fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2272   }
2273
2274   strcpy(*str, buffer);
2275   *str += len;
2276   *size -= len;
2277
2278 }
2279
2280 #endif    //  USE_VSNPRINTF
2281     
2282 #endif // OPT_DISABLE_PIC
2283
2284
2285 extern  void pic16_initStack(int base_address, int size);
2286 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2287 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2288 extern void pic16_init_pic(char *);
2289
2290 void  pic16_pCodeInitRegisters(void)
2291 {
2292   static int initialized=0;
2293
2294   if(initialized)
2295     return;
2296   initialized = 1;
2297
2298   pic16_initStack(0xfff, 8);
2299   pic16_init_pic(port->processor);
2300
2301   pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"_STATUS", PO_STATUS, 0x80);
2302   pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2303   pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"_PCLATH", PO_PCLATH, 0x80);
2304   pic16_pc_fsr0.r = pic16_allocProcessorRegister(IDX_FSR0,"FSR0", PO_FSR0, 0x80);
2305   pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
2306   pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2307   pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2308
2309   pic16_pc_status.rIdx = IDX_STATUS;
2310   pic16_pc_fsr0.rIdx = IDX_FSR0;
2311   pic16_pc_indf0.rIdx = IDX_INDF0;
2312   pic16_pc_intcon.rIdx = IDX_INTCON;
2313   pic16_pc_pcl.rIdx = IDX_PCL;
2314   pic16_pc_pclath.rIdx = IDX_PCLATH;
2315   pic16_pc_wreg.rIdx = IDX_WREG;
2316
2317   pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
2318   pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
2319   pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
2320
2321   pic16_pc_kzero.rIdx = IDX_KZ;
2322   pic16_pc_wsave.rIdx = IDX_WSAVE;
2323   pic16_pc_ssave.rIdx = IDX_SSAVE;
2324
2325   /* probably should put this in a separate initialization routine */
2326   pb_dead_pcodes = newpBlock();
2327
2328 }
2329
2330 #if OPT_DISABLE_PIC
2331 /*-----------------------------------------------------------------*/
2332 /*  mnem2key - convert a pic mnemonic into a hash key              */
2333 /*   (BTW - this spreads the mnemonics quite well)                 */
2334 /*                                                                 */
2335 /*-----------------------------------------------------------------*/
2336
2337 int mnem2key(char const *mnem)
2338 {
2339   int key = 0;
2340
2341   if(!mnem)
2342     return 0;
2343
2344   while(*mnem) {
2345
2346     key += toupper(*mnem++) +1;
2347
2348   }
2349
2350   return (key & 0x1f);
2351
2352 }
2353 #endif // OPT_DISABLE_PIC
2354
2355 void pic16initMnemonics(void)
2356 {
2357   int i = 0;
2358   int key;
2359   //  char *str;
2360   pCodeInstruction *pci;
2361
2362   if(mnemonics_initialized)
2363     return;
2364
2365   // NULL out the array before making the assignments
2366   // since we check the array contents below this initialization.
2367
2368   for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
2369     pic16Mnemonics[i] = NULL;
2370   }
2371
2372   pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
2373   pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
2374   pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
2375   pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
2376   pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
2377   pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
2378   pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
2379   pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
2380   pic16Mnemonics[POC_BC] = &pic16_pciBC;
2381   pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
2382   pic16Mnemonics[POC_BN] = &pic16_pciBN;
2383   pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
2384   pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
2385   pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
2386   pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
2387   pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
2388   pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
2389   pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
2390   pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
2391   pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
2392   pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
2393   pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
2394   pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
2395   pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
2396   pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
2397   pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
2398   pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
2399   pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
2400   pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
2401   pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
2402   pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
2403   pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
2404   pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
2405   pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
2406   pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
2407   pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
2408   pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
2409   pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
2410   pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
2411   pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
2412   pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
2413   pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
2414   pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
2415   pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
2416   pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
2417   pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
2418   pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
2419   pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
2420   pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
2421   pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
2422   pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
2423   pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
2424   pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
2425   pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
2426   pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
2427   pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
2428   pic16Mnemonics[POC_POP] = &pic16_pciPOP;
2429   pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
2430   pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
2431   pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
2432   pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
2433   pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
2434   pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
2435   pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
2436   pic16Mnemonics[POC_RLCF] = &pic16_pciRLNCF;
2437   pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
2438   pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
2439   pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
2440   pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
2441   pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
2442   pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
2443   pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
2444   pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
2445   pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
2446   pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
2447   pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
2448   pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
2449   pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
2450   pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
2451   pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
2452   pic16Mnemonics[POC_TRIS] = &pic16_pciTRIS;
2453   pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
2454   pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
2455   pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
2456   pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
2457
2458   for(i=0; i<MAX_PIC16MNEMONICS; i++)
2459     if(pic16Mnemonics[i])
2460       hTabAddItem(&pic16MnemonicsHash, mnem2key(pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
2461   pci = hTabFirstItem(pic16MnemonicsHash, &key);
2462
2463   while(pci) {
2464     DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
2465     pci = hTabNextItem(pic16MnemonicsHash, &key);
2466   }
2467
2468   mnemonics_initialized = 1;
2469 }
2470
2471 int pic16_getpCodePeepCommand(char *cmd);
2472
2473 int pic16_getpCode(char *mnem,unsigned dest)
2474 {
2475
2476   pCodeInstruction *pci;
2477   int key = mnem2key(mnem);
2478
2479   if(!mnemonics_initialized)
2480     pic16initMnemonics();
2481
2482   pci = hTabFirstItemWK(pic16MnemonicsHash, key);
2483
2484   while(pci) {
2485
2486     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
2487       if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst) ||
2488          (pci->num_ops <= 2 && pci->isAccess) ||
2489          (pci->num_ops <= 2 && pci->isFastCall))
2490         return(pci->op);
2491     }
2492
2493     pci = hTabNextItemWK (pic16MnemonicsHash);
2494   
2495   }
2496
2497   return -1;
2498 }
2499
2500 /*-----------------------------------------------------------------*
2501  * pic16initpCodePeepCommands
2502  *
2503  *-----------------------------------------------------------------*/
2504 void pic16initpCodePeepCommands(void)
2505 {
2506
2507   int key, i;
2508   peepCommand *pcmd;
2509
2510   i = 0;
2511   do {
2512     hTabAddItem(&pic16pCodePeepCommandsHash, 
2513                 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
2514     i++;
2515   } while (peepCommands[i].cmd);
2516
2517   pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
2518
2519   while(pcmd) {
2520     //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
2521     pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
2522   }
2523
2524 }
2525
2526 /*-----------------------------------------------------------------
2527  *
2528  *
2529  *-----------------------------------------------------------------*/
2530
2531 int pic16_getpCodePeepCommand(char *cmd)
2532 {
2533
2534   peepCommand *pcmd;
2535   int key = mnem2key(cmd);
2536
2537
2538   pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
2539
2540   while(pcmd) {
2541     // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
2542     if(STRCASECMP(pcmd->cmd, cmd) == 0) {
2543       return pcmd->id;
2544     }
2545
2546     pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
2547   
2548   }
2549
2550   return -1;
2551 }
2552
2553 static char getpBlock_dbName(pBlock *pb)
2554 {
2555   if(!pb)
2556     return 0;
2557
2558   if(pb->cmemmap)
2559     return pb->cmemmap->dbName;
2560
2561   return pb->dbName;
2562 }
2563 void pic16_pBlockConvert2ISR(pBlock *pb)
2564 {
2565   if(!pb)
2566     return;
2567
2568   if(pb->cmemmap)
2569     pb->cmemmap = NULL;
2570
2571   pb->dbName = 'I';
2572 }
2573
2574 /*-----------------------------------------------------------------*/
2575 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all  */
2576 /*                   instances to the front of the doubly linked   */
2577 /*                   list of pBlocks                               */
2578 /*-----------------------------------------------------------------*/
2579
2580 void pic16_movepBlock2Head(char dbName)
2581 {
2582   pBlock *pb;
2583
2584   pb = the_pFile->pbHead;
2585
2586   while(pb) {
2587
2588     if(getpBlock_dbName(pb) == dbName) {
2589       pBlock *pbn = pb->next;
2590       pb->next = the_pFile->pbHead;
2591       the_pFile->pbHead->prev = pb;
2592       the_pFile->pbHead = pb;
2593
2594       if(pb->prev)
2595         pb->prev->next = pbn;
2596
2597       // If the pBlock that we just moved was the last
2598       // one in the link of all of the pBlocks, then we
2599       // need to point the tail to the block just before
2600       // the one we moved.
2601       // Note: if pb->next is NULL, then pb must have 
2602       // been the last pBlock in the chain.
2603
2604       if(pbn)
2605         pbn->prev = pb->prev;
2606       else
2607         the_pFile->pbTail = pb->prev;
2608
2609       pb = pbn;
2610
2611     } else
2612       pb = pb->next;
2613
2614   }
2615
2616 }
2617
2618 void pic16_copypCode(FILE *of, char dbName)
2619 {
2620   pBlock *pb;
2621
2622   if(!of || !the_pFile)
2623     return;
2624
2625   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2626     if(getpBlock_dbName(pb) == dbName) {
2627       pBlockStats(of,pb);
2628       pic16_printpBlock(of,pb);
2629     }
2630   }
2631
2632 }
2633 void pic16_pcode_test(void)
2634 {
2635
2636   DFPRINTF((stderr,"pcode is alive!\n"));
2637
2638   //initMnemonics();
2639
2640   if(the_pFile) {
2641
2642     pBlock *pb;
2643     FILE *pFile;
2644     char buffer[100];
2645
2646     /* create the file name */
2647     strcpy(buffer,srcFileName);
2648     strcat(buffer,".p");
2649
2650     if( !(pFile = fopen(buffer, "w" ))) {
2651       werror(E_FILE_OPEN_ERR,buffer);
2652       exit(1);
2653     }
2654
2655     fprintf(pFile,"pcode dump\n\n");
2656
2657     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2658       fprintf(pFile,"\n\tNew pBlock\n\n");
2659       if(pb->cmemmap)
2660         fprintf(pFile,"%s",pb->cmemmap->sname);
2661       else
2662         fprintf(pFile,"internal pblock");
2663
2664       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
2665       pic16_printpBlock(pFile,pb);
2666     }
2667   }
2668 }
2669 /*-----------------------------------------------------------------*/
2670 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
2671 /*      ister, RegCond will return the bit being referenced.       */
2672 /*                                                                 */
2673 /* fixme - why not just OR in the pcop bit field                   */
2674 /*-----------------------------------------------------------------*/
2675
2676 static int RegCond(pCodeOp *pcop)
2677 {
2678
2679   if(!pcop)
2680     return 0;
2681
2682   if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
2683     switch(PCORB(pcop)->bit) {
2684     case PIC_C_BIT:
2685       return PCC_C;
2686     case PIC_DC_BIT:
2687         return PCC_DC;
2688     case PIC_Z_BIT:
2689       return PCC_Z;
2690     }
2691
2692   }
2693
2694   return 0;
2695 }
2696
2697 /*-----------------------------------------------------------------*/
2698 /* pic16_newpCode - create and return a newly initialized pCode          */
2699 /*                                                                 */
2700 /*  fixme - rename this                                            */
2701 /*                                                                 */
2702 /* The purpose of this routine is to create a new Instruction      */
2703 /* pCode. This is called by gen.c while the assembly code is being */
2704 /* generated.                                                      */
2705 /*                                                                 */
2706 /* Inouts:                                                         */
2707 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
2708 /*                  (note that the op is analogous to but not the  */
2709 /*                  same thing as the opcode of the instruction.)  */
2710 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
2711 /*                                                                 */
2712 /* Outputs:                                                        */
2713 /*  a pointer to the new malloc'd pCode is returned.               */
2714 /*                                                                 */
2715 /*                                                                 */
2716 /*                                                                 */
2717 /*-----------------------------------------------------------------*/
2718 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
2719 {
2720   pCodeInstruction *pci ;
2721
2722   if(!mnemonics_initialized)
2723     pic16initMnemonics();
2724     
2725   pci = Safe_calloc(1, sizeof(pCodeInstruction));
2726
2727   if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
2728     memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
2729     pci->pcop = pcop;
2730
2731     if(pci->inCond & PCC_EXAMINE_PCOP)
2732       pci->inCond  |= RegCond(pcop);
2733
2734     if(pci->outCond & PCC_EXAMINE_PCOP)
2735       pci->outCond  |= RegCond(pcop);
2736
2737     pci->pc.prev = pci->pc.next = NULL;
2738     return (pCode *)pci;
2739   }
2740
2741   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
2742   exit(1);
2743
2744   return NULL;
2745 }       
2746
2747 /*-----------------------------------------------------------------*/
2748 /* pic16_newpCodeWild - create a "wild" as in wild card pCode            */
2749 /*                                                                 */
2750 /* Wild pcodes are used during the peep hole optimizer to serve    */
2751 /* as place holders for any instruction. When a snippet of code is */
2752 /* compared to a peep hole rule, the wild card opcode will match   */
2753 /* any instruction. However, the optional operand and label are    */
2754 /* additional qualifiers that must also be matched before the      */
2755 /* line (of assembly code) is declared matched. Note that the      */
2756 /* operand may be wild too.                                        */
2757 /*                                                                 */
2758 /*   Note, a wild instruction is specified just like a wild var:   */
2759 /*      %4     ; A wild instruction,                               */
2760 /*  See the peeph.def file for additional examples                 */
2761 /*                                                                 */
2762 /*-----------------------------------------------------------------*/
2763
2764 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
2765 {
2766
2767   pCodeWild *pcw;
2768     
2769   pcw = Safe_calloc(1,sizeof(pCodeWild));
2770
2771   pcw->pci.pc.type = PC_WILD;
2772   pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
2773   pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
2774   pcw->pci.pc.pb = NULL;
2775
2776   //  pcw->pci.pc.analyze = genericAnalyze;
2777   pcw->pci.pc.destruct = genericDestruct;
2778   pcw->pci.pc.print = genericPrint;
2779
2780   pcw->id = pCodeID;              // this is the 'n' in %n
2781   pcw->operand = optional_operand;
2782   pcw->label   = optional_label;
2783
2784   pcw->mustBeBitSkipInst = 0;
2785   pcw->mustNotBeBitSkipInst = 0;
2786   pcw->invertBitSkipInst = 0;
2787
2788   return ( (pCode *)pcw);
2789   
2790 }
2791
2792  /*-----------------------------------------------------------------*/
2793 /* newPcodeInlineP - create a new pCode from a char string           */
2794 /*-----------------------------------------------------------------*/
2795
2796
2797 pCode *pic16_newpCodeInlineP(char *cP)
2798 {
2799
2800   pCodeComment *pcc ;
2801     
2802   pcc = Safe_calloc(1,sizeof(pCodeComment));
2803
2804   pcc->pc.type = PC_INLINE;
2805   pcc->pc.prev = pcc->pc.next = NULL;
2806   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2807   pcc->pc.pb = NULL;
2808
2809   //  pcc->pc.analyze = genericAnalyze;
2810   pcc->pc.destruct = genericDestruct;
2811   pcc->pc.print = genericPrint;
2812
2813   if(cP)
2814     pcc->comment = Safe_strdup(cP);
2815   else
2816     pcc->comment = NULL;
2817
2818   return ( (pCode *)pcc);
2819
2820 }
2821
2822 /*-----------------------------------------------------------------*/
2823 /* newPcodeCharP - create a new pCode from a char string           */
2824 /*-----------------------------------------------------------------*/
2825
2826 pCode *pic16_newpCodeCharP(char *cP)
2827 {
2828
2829   pCodeComment *pcc ;
2830     
2831   pcc = Safe_calloc(1,sizeof(pCodeComment));
2832
2833   pcc->pc.type = PC_COMMENT;
2834   pcc->pc.prev = pcc->pc.next = NULL;
2835   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
2836   pcc->pc.pb = NULL;
2837
2838   //  pcc->pc.analyze = genericAnalyze;
2839   pcc->pc.destruct = genericDestruct;
2840   pcc->pc.print = genericPrint;
2841
2842   if(cP)
2843     pcc->comment = Safe_strdup(cP);
2844   else
2845     pcc->comment = NULL;
2846
2847   return ( (pCode *)pcc);
2848
2849 }
2850
2851 /*-----------------------------------------------------------------*/
2852 /* pic16_newpCodeFunction -                                              */
2853 /*-----------------------------------------------------------------*/
2854
2855
2856 pCode *pic16_newpCodeFunction(char *mod,char *f)
2857 {
2858   pCodeFunction *pcf;
2859
2860   pcf = Safe_calloc(1,sizeof(pCodeFunction));
2861   //_ALLOC(pcf,sizeof(pCodeFunction));
2862
2863   pcf->pc.type = PC_FUNCTION;
2864   pcf->pc.prev = pcf->pc.next = NULL;
2865   //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
2866   pcf->pc.pb = NULL;
2867
2868   //  pcf->pc.analyze = genericAnalyze;
2869   pcf->pc.destruct = genericDestruct;
2870   pcf->pc.print = pCodePrintFunction;
2871
2872   pcf->ncalled = 0;
2873
2874   if(mod) {
2875     //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
2876     pcf->modname = Safe_calloc(1,strlen(mod)+1);
2877     strcpy(pcf->modname,mod);
2878   } else
2879     pcf->modname = NULL;
2880
2881   if(f) {
2882     //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
2883     pcf->fname = Safe_calloc(1,strlen(f)+1);
2884     strcpy(pcf->fname,f);
2885   } else
2886     pcf->fname = NULL;
2887
2888   return ( (pCode *)pcf);
2889
2890 }
2891
2892 /*-----------------------------------------------------------------*/
2893 /* pic16_newpCodeFlow                                                    */
2894 /*-----------------------------------------------------------------*/
2895 static void destructpCodeFlow(pCode *pc)
2896 {
2897   if(!pc || !isPCFL(pc))
2898     return;
2899
2900 /*
2901   if(PCFL(pc)->from)
2902   if(PCFL(pc)->to)
2903 */
2904   pic16_unlinkpCode(pc);
2905
2906   deleteSet(&PCFL(pc)->registers);
2907   deleteSet(&PCFL(pc)->from);
2908   deleteSet(&PCFL(pc)->to);
2909   free(pc);
2910
2911 }
2912
2913 pCode *pic16_newpCodeFlow(void )
2914 {
2915   pCodeFlow *pcflow;
2916
2917   //_ALLOC(pcflow,sizeof(pCodeFlow));
2918   pcflow = Safe_calloc(1,sizeof(pCodeFlow));
2919
2920   pcflow->pc.type = PC_FLOW;
2921   pcflow->pc.prev = pcflow->pc.next = NULL;
2922   pcflow->pc.pb = NULL;
2923
2924   //  pcflow->pc.analyze = genericAnalyze;
2925   pcflow->pc.destruct = destructpCodeFlow;
2926   pcflow->pc.print = genericPrint;
2927
2928   pcflow->pc.seq = GpcFlowSeq++;
2929
2930   pcflow->from = pcflow->to = NULL;
2931
2932   pcflow->inCond = PCC_NONE;
2933   pcflow->outCond = PCC_NONE;
2934
2935   pcflow->firstBank = -1;
2936   pcflow->lastBank = -1;
2937
2938   pcflow->FromConflicts = 0;
2939   pcflow->ToConflicts = 0;
2940
2941   pcflow->end = NULL;
2942
2943   pcflow->registers = newSet();
2944
2945   return ( (pCode *)pcflow);
2946
2947 }
2948
2949 /*-----------------------------------------------------------------*/
2950 /*-----------------------------------------------------------------*/
2951 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
2952 {
2953   pCodeFlowLink *pcflowLink;
2954
2955   pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2956
2957   pcflowLink->pcflow = pcflow;
2958   pcflowLink->bank_conflict = 0;
2959
2960   return pcflowLink;
2961 }
2962
2963 /*-----------------------------------------------------------------*/
2964 /* pic16_newpCodeCSource - create a new pCode Source Symbol              */
2965 /*-----------------------------------------------------------------*/
2966
2967 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
2968 {
2969
2970   pCodeCSource *pccs;
2971     
2972   pccs = Safe_calloc(1,sizeof(pCodeCSource));
2973
2974   pccs->pc.type = PC_CSOURCE;
2975   pccs->pc.prev = pccs->pc.next = NULL;
2976   pccs->pc.pb = NULL;
2977
2978   pccs->pc.destruct = genericDestruct;
2979   pccs->pc.print = genericPrint;
2980
2981   pccs->line_number = ln;
2982   if(l)
2983     pccs->line = Safe_strdup(l);
2984   else
2985     pccs->line = NULL;
2986
2987   if(f)
2988     pccs->file_name = Safe_strdup(f);
2989   else
2990     pccs->file_name = NULL;
2991
2992   return ( (pCode *)pccs);
2993
2994 }
2995 /*-----------------------------------------------------------------*/
2996 /* pCodeLabelDestruct - free memory used by a label.               */
2997 /*-----------------------------------------------------------------*/
2998 static void pCodeLabelDestruct(pCode *pc)
2999 {
3000
3001   if(!pc)
3002     return;
3003
3004   if((pc->type == PC_LABEL) && PCL(pc)->label)
3005     free(PCL(pc)->label);
3006
3007   free(pc);
3008
3009 }
3010
3011 pCode *pic16_newpCodeLabel(char *name, int key)
3012 {
3013
3014   char *s = buffer;
3015   pCodeLabel *pcl;
3016     
3017   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3018
3019   pcl->pc.type = PC_LABEL;
3020   pcl->pc.prev = pcl->pc.next = NULL;
3021   //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3022   pcl->pc.pb = NULL;
3023
3024   //  pcl->pc.analyze = genericAnalyze;
3025   pcl->pc.destruct = pCodeLabelDestruct;
3026   pcl->pc.print = pCodePrintLabel;
3027
3028   pcl->key = key;
3029
3030   pcl->label = NULL;
3031   if(key>0) {
3032     sprintf(s,"_%05d_DS_",key);
3033   } else
3034     s = name;
3035
3036   if(s)
3037     pcl->label = Safe_strdup(s);
3038
3039   //fprintf(stderr,"pic16_newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
3040   return ( (pCode *)pcl);
3041
3042 }
3043
3044
3045 /*-----------------------------------------------------------------*/
3046 /* newpBlock - create and return a pointer to a new pBlock         */
3047 /*-----------------------------------------------------------------*/
3048 static pBlock *newpBlock(void)
3049 {
3050
3051   pBlock *PpB;
3052
3053   PpB = Safe_calloc(1,sizeof(pBlock) );
3054   PpB->next = PpB->prev = NULL;
3055
3056   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3057   PpB->tregisters = NULL;
3058   PpB->visited = 0;
3059   PpB->FlowTree = NULL;
3060
3061   return PpB;
3062
3063 }
3064
3065 /*-----------------------------------------------------------------*/
3066 /* pic16_newpCodeChain - create a new chain of pCodes                    */
3067 /*-----------------------------------------------------------------*
3068  *
3069  *  This function will create a new pBlock and the pointer to the
3070  *  pCode that is passed in will be the first pCode in the block.
3071  *-----------------------------------------------------------------*/
3072
3073
3074 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3075 {
3076
3077   pBlock *pB  = newpBlock();
3078
3079   pB->pcHead  = pB->pcTail = pc;
3080   pB->cmemmap = cm;
3081   pB->dbName  = c;
3082
3083   return pB;
3084 }
3085
3086 /*-----------------------------------------------------------------*/
3087 /* pic16_newpCodeOpLabel - Create a new label given the key              */
3088 /*  Note, a negative key means that the label is part of wild card */
3089 /*  (and hence a wild card label) used in the pCodePeep            */
3090 /*   optimizations).                                               */
3091 /*-----------------------------------------------------------------*/
3092
3093 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
3094 {
3095   char *s=NULL;
3096   static int label_key=-1;
3097
3098   pCodeOp *pcop;
3099
3100   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
3101   pcop->type = PO_LABEL;
3102
3103   pcop->name = NULL;
3104
3105   if(key>0)
3106     sprintf(s=buffer,"_%05d_DS_",key);
3107   else 
3108     s = name, key = label_key--;
3109
3110   if(s)
3111     pcop->name = Safe_strdup(s);
3112
3113   ((pCodeOpLabel *)pcop)->key = key;
3114
3115   //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
3116   return pcop;
3117 }
3118
3119 /*-----------------------------------------------------------------*/
3120 /*-----------------------------------------------------------------*/
3121 pCodeOp *pic16_newpCodeOpLit(int lit)
3122 {
3123   char *s = buffer;
3124   pCodeOp *pcop;
3125
3126
3127   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
3128   pcop->type = PO_LITERAL;
3129
3130   pcop->name = NULL;
3131   if(lit>=0) {
3132     sprintf(s,"0x%02x",lit);
3133     if(s)
3134       pcop->name = Safe_strdup(s);
3135   }
3136
3137   ((pCodeOpLit *)pcop)->lit = lit;
3138
3139   return pcop;
3140 }
3141
3142 /*-----------------------------------------------------------------*/
3143 /*-----------------------------------------------------------------*/
3144 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
3145 {
3146   pCodeOp *pcop;
3147
3148   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
3149   pcop->type = PO_IMMEDIATE;
3150   if(name) {
3151     regs *r = pic16_dirregWithName(name);
3152     pcop->name = Safe_strdup(name);
3153     PCOI(pcop)->r = r;
3154     if(r) {
3155       //fprintf(stderr, " pic16_newpCodeOpImmd reg %s exists\n",name);
3156       PCOI(pcop)->rIdx = r->rIdx;
3157     } else {
3158       //fprintf(stderr, " pic16_newpCodeOpImmd reg %s doesn't exist\n",name);
3159       PCOI(pcop)->rIdx = -1;
3160     }
3161     //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
3162   } else {
3163     pcop->name = NULL;
3164   }
3165
3166   PCOI(pcop)->index = index;
3167   PCOI(pcop)->offset = offset;
3168   PCOI(pcop)->_const = code_space;
3169
3170   return pcop;
3171 }
3172
3173 /*-----------------------------------------------------------------*/
3174 /*-----------------------------------------------------------------*/
3175 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
3176 {
3177   char *s = buffer;
3178   pCodeOp *pcop;
3179
3180
3181   if(!pcwb || !subtype) {
3182     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
3183     exit(1);
3184   }
3185
3186   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
3187   pcop->type = PO_WILD;
3188   sprintf(s,"%%%d",id);
3189   pcop->name = Safe_strdup(s);
3190
3191   PCOW(pcop)->id = id;
3192   PCOW(pcop)->pcwb = pcwb;
3193   PCOW(pcop)->subtype = subtype;
3194   PCOW(pcop)->matched = NULL;
3195
3196   return pcop;
3197 }
3198
3199 /*-----------------------------------------------------------------*/
3200 /*-----------------------------------------------------------------*/
3201 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace)
3202 {
3203   pCodeOp *pcop;
3204
3205   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
3206   pcop->type = PO_GPR_BIT;
3207   if(s)
3208     pcop->name = Safe_strdup(s);   
3209   else
3210     pcop->name = NULL;
3211
3212   PCORB(pcop)->bit = bit;
3213   PCORB(pcop)->inBitSpace = inBitSpace;
3214
3215   /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
3216   PCOR(pcop)->r = NULL;
3217   PCOR(pcop)->rIdx = 0;
3218   return pcop;
3219 }
3220
3221 /*-----------------------------------------------------------------*
3222  * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
3223  *
3224  * If rIdx >=0 then a specific register from the set of registers
3225  * will be selected. If rIdx <0, then a new register will be searched
3226  * for.
3227  *-----------------------------------------------------------------*/
3228
3229 pCodeOp *pic16_newpCodeOpReg(int rIdx)
3230 {
3231   pCodeOp *pcop;
3232
3233   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3234
3235   pcop->name = NULL;
3236
3237   if(rIdx >= 0) {
3238     PCOR(pcop)->rIdx = rIdx;
3239     PCOR(pcop)->r = pic16_regWithIdx(rIdx);
3240   } else {
3241     PCOR(pcop)->r = pic16_findFreeReg(REG_GPR);
3242
3243     if(PCOR(pcop)->r)
3244       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3245   }
3246
3247   pcop->type = PCOR(pcop)->r->pc_type;
3248
3249   return pcop;
3250 }
3251
3252 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
3253 {
3254   pCodeOp *pcop;
3255
3256   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
3257   PCOR(pcop)->r = pic16_allocRegByName(name, 1);
3258   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
3259   pcop->type = PCOR(pcop)->r->pc_type;
3260   pcop->name = PCOR(pcop)->r->name;
3261
3262   return pcop;
3263 }
3264
3265 /*-----------------------------------------------------------------*/
3266 /*-----------------------------------------------------------------*/
3267
3268 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3269 {
3270   pCodeOp *pcop;
3271
3272   switch(type) {
3273   case PO_BIT:
3274   case PO_GPR_BIT:
3275     pcop = pic16_newpCodeOpBit(name, -1,0);
3276     break;
3277
3278   case PO_LITERAL:
3279     pcop = pic16_newpCodeOpLit(-1);
3280     break;
3281
3282   case PO_LABEL:
3283     pcop = pic16_newpCodeOpLabel(NULL,-1);
3284     break;
3285   case PO_GPR_TEMP:
3286     pcop = pic16_newpCodeOpReg(-1);
3287     break;
3288
3289   case PO_GPR_REGISTER:
3290     if(name)
3291       pcop = pic16_newpCodeOpRegFromStr(name);
3292     else
3293       pcop = pic16_newpCodeOpReg(-1);
3294     break;
3295
3296   default:
3297     pcop = Safe_calloc(1,sizeof(pCodeOp) );
3298     pcop->type = type;
3299     if(name)
3300       pcop->name = Safe_strdup(name);   
3301     else
3302       pcop->name = NULL;
3303   }
3304
3305   return pcop;
3306 }
3307
3308 /*-----------------------------------------------------------------*/
3309 /*-----------------------------------------------------------------*/
3310 void pic16_pCodeConstString(char *name, char *value)
3311 {
3312   pBlock *pb;
3313
3314   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
3315
3316   if(!name || !value)
3317     return;
3318
3319   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3320
3321   pic16_addpBlock(pb);
3322
3323   sprintf(buffer,"; %s = %s",name,value);
3324   
3325   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3326   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3327
3328   do {
3329     pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3330   }while (*value++);
3331
3332
3333 }
3334
3335 /*-----------------------------------------------------------------*/
3336 /*-----------------------------------------------------------------*/
3337 static void pCodeReadCodeTable(void)
3338 {
3339   pBlock *pb;
3340
3341   fprintf(stderr, " %s\n",__FUNCTION__);
3342
3343   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3344
3345   pic16_addpBlock(pb);
3346
3347   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3348   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3349   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3350   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3351
3352   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3353   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3354   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3355   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3356
3357
3358 }
3359
3360 /*-----------------------------------------------------------------*/
3361 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list   */
3362 /*-----------------------------------------------------------------*/
3363 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3364 {
3365
3366   if(!pc)
3367     return;
3368
3369   if(!pb->pcHead) {
3370     /* If this is the first pcode to be added to a block that
3371      * was initialized with a NULL pcode, then go ahead and
3372      * make this pcode the head and tail */
3373     pb->pcHead  = pb->pcTail = pc;
3374   } else {
3375     //    if(pb->pcTail)
3376     pb->pcTail->next = pc;
3377
3378     pc->prev = pb->pcTail;
3379     pc->pb = pb;
3380
3381     pb->pcTail = pc;
3382   }
3383 }
3384
3385 /*-----------------------------------------------------------------*/
3386 /* pic16_addpBlock - place a pBlock into the pFile                 */
3387 /*-----------------------------------------------------------------*/
3388 void pic16_addpBlock(pBlock *pb)
3389 {
3390   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3391
3392   if(!the_pFile) {
3393     /* First time called, we'll pass through here. */
3394     //_ALLOC(the_pFile,sizeof(pFile));
3395     the_pFile = Safe_calloc(1,sizeof(pFile));
3396     the_pFile->pbHead = the_pFile->pbTail = pb;
3397     the_pFile->functions = NULL;
3398     return;
3399   }
3400
3401   the_pFile->pbTail->next = pb;
3402   pb->prev = the_pFile->pbTail;
3403   pb->next = NULL;
3404   the_pFile->pbTail = pb;
3405 }
3406
3407 /*-----------------------------------------------------------------*/
3408 /* removepBlock - remove a pBlock from the pFile                   */
3409 /*-----------------------------------------------------------------*/
3410 static void removepBlock(pBlock *pb)
3411 {
3412   pBlock *pbs;
3413
3414   if(!the_pFile)
3415     return;
3416
3417
3418   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3419
3420   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3421     if(pbs == pb) {
3422
3423       if(pbs == the_pFile->pbHead)
3424         the_pFile->pbHead = pbs->next;
3425
3426       if (pbs == the_pFile->pbTail) 
3427         the_pFile->pbTail = pbs->prev;
3428
3429       if(pbs->next)
3430         pbs->next->prev = pbs->prev;
3431
3432       if(pbs->prev)
3433         pbs->prev->next = pbs->next;
3434
3435       return;
3436
3437     }
3438   }
3439
3440   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3441
3442 }
3443
3444 /*-----------------------------------------------------------------*/
3445 /* printpCode - write the contents of a pCode to a file            */
3446 /*-----------------------------------------------------------------*/
3447 static void printpCode(FILE *of, pCode *pc)
3448 {
3449
3450   if(!pc || !of)
3451     return;
3452
3453   if(pc->print) {
3454     pc->print(of,pc);
3455     return;
3456   }
3457
3458   fprintf(of,"warning - unable to print pCode\n");
3459 }
3460
3461 /*-----------------------------------------------------------------*/
3462 /* pic16_printpBlock - write the contents of a pBlock to a file    */
3463 /*-----------------------------------------------------------------*/
3464 void pic16_printpBlock(FILE *of, pBlock *pb)
3465 {
3466   pCode *pc;
3467
3468   if(!pb)
3469     return;
3470
3471   if(!of)
3472     of = stderr;
3473
3474   for(pc = pb->pcHead; pc; pc = pc->next)
3475     printpCode(of,pc);
3476
3477 }
3478
3479 /*-----------------------------------------------------------------*/
3480 /*                                                                 */
3481 /*       pCode processing                                          */
3482 /*                                                                 */
3483 /*                                                                 */
3484 /*                                                                 */
3485 /*-----------------------------------------------------------------*/
3486
3487 void pic16_unlinkpCode(pCode *pc)
3488 {
3489
3490
3491   if(pc) {
3492 #ifdef PCODE_DEBUG
3493     fprintf(stderr,"Unlinking: ");
3494     printpCode(stderr, pc);
3495 #endif
3496     if(pc->prev) 
3497       pc->prev->next = pc->next;
3498     if(pc->next)
3499       pc->next->prev = pc->prev;
3500
3501     pc->prev = pc->next = NULL;
3502   }
3503 }
3504
3505 /*-----------------------------------------------------------------*/
3506 /*-----------------------------------------------------------------*/
3507
3508 static void genericDestruct(pCode *pc)
3509 {
3510
3511   pic16_unlinkpCode(pc);
3512
3513   if(isPCI(pc)) {
3514     /* For instructions, tell the register (if there's one used)
3515      * that it's no longer needed */
3516     regs *reg = pic16_getRegFromInstruction(pc);
3517     if(reg)
3518       deleteSetItem (&(reg->reglives.usedpCodes),pc);
3519   }
3520
3521   /* Instead of deleting the memory used by this pCode, mark
3522    * the object as bad so that if there's a pointer to this pCode
3523    * dangling around somewhere then (hopefully) when the type is
3524    * checked we'll catch it.
3525    */
3526
3527   pc->type = PC_BAD;
3528
3529   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3530
3531   //free(pc);
3532
3533 }
3534
3535
3536 /*-----------------------------------------------------------------*/
3537 /*-----------------------------------------------------------------*/
3538 static void pBlockRegs(FILE *of, pBlock *pb)
3539 {
3540
3541   regs  *r;
3542
3543   r = setFirstItem(pb->tregisters);
3544   while (r) {
3545     r = setNextItem(pb->tregisters);
3546   }
3547 }
3548
3549
3550 /*-----------------------------------------------------------------*/
3551 /*-----------------------------------------------------------------*/
3552 char *pic16_get_op(pCodeOp *pcop,char *buffer, int size)
3553 {
3554   regs *r;
3555   static char b[50];
3556   char *s;
3557   int use_buffer = 1;    // copy the string to the passed buffer pointer
3558
3559   if(!buffer) {
3560     buffer = b;
3561     size = sizeof(b);
3562     use_buffer = 0;     // Don't bother copying the string to the buffer.
3563   } 
3564
3565   if(pcop) {
3566     switch(pcop->type) {
3567     case PO_INDF0:
3568     case PO_FSR0:
3569       if(use_buffer) {
3570         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3571         return buffer;
3572       }
3573       return PCOR(pcop)->r->name;
3574       break;
3575     case PO_GPR_TEMP:
3576       r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3577
3578       if(use_buffer) {
3579         SAFE_snprintf(&buffer,&size,"%s",r->name);
3580         return buffer;
3581       }
3582
3583       return r->name;
3584
3585
3586     case PO_IMMEDIATE:
3587       s = buffer;
3588
3589       if(PCOI(pcop)->_const) {
3590
3591         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3592           SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3593                         pcop->name,
3594                         PCOI(pcop)->index,
3595                         8 * PCOI(pcop)->offset );
3596         } else
3597           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
3598       } else {
3599       
3600         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
3601           SAFE_snprintf(&s,&size,"(%s + %d)",
3602                         pcop->name,
3603                         PCOI(pcop)->index );
3604         } else {
3605           if(PCOI(pcop)->offset)
3606             SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
3607           else
3608             SAFE_snprintf(&s,&size,"%s",pcop->name);
3609         }
3610       }
3611
3612       return buffer;
3613
3614     case PO_DIR:
3615       s = buffer;
3616       //size = sizeof(buffer);
3617       if( PCOR(pcop)->instance) {
3618         SAFE_snprintf(&s,&size,"(%s + %d)",
3619                       pcop->name,
3620                       PCOR(pcop)->instance );
3621         //fprintf(stderr,"PO_DIR %s\n",buffer);
3622       } else
3623         SAFE_snprintf(&s,&size,"%s",pcop->name);
3624       return buffer;
3625
3626     default:
3627       if  (pcop->name) {
3628         if(use_buffer) {
3629           SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3630           return buffer;
3631         }
3632         return pcop->name;
3633       }
3634
3635     }
3636   }
3637
3638   return "NO operand";
3639
3640 }
3641
3642 /*-----------------------------------------------------------------*/
3643 /*-----------------------------------------------------------------*/
3644 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
3645 {
3646
3647   if(pcc )
3648     return pic16_get_op(pcc->pcop,NULL,0);
3649   
3650   return ("ERROR Null: "__FUNCTION__);
3651
3652 }
3653
3654 /*-----------------------------------------------------------------*/
3655 /*-----------------------------------------------------------------*/
3656 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3657 {
3658
3659   fprintf(of,"pcodeopprint- not implemented\n");
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /*-----------------------------------------------------------------*/
3664 static char *pCode2str(char *str, int size, pCode *pc)
3665 {
3666   char *s = str;
3667
3668   switch(pc->type) {
3669
3670   case PC_OPCODE:
3671
3672     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3673
3674     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3675
3676       if(PCI(pc)->isBitInst) {
3677         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3678           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3679             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
3680                           PCI(pc)->pcop->name ,
3681                           PCI(pc)->pcop->name );
3682           else
3683             SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)), 
3684                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
3685         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3686           SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3687         }else
3688           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
3689         //PCI(pc)->pcop->t.bit );
3690       } else {
3691
3692         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3693           if( PCI(pc)->num_ops == 3)
3694             SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3695           else
3696             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
3697
3698         }else {
3699           SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
3700
3701           if( PCI(pc)->num_ops == 3)
3702             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3703         }
3704       }
3705
3706     }
3707     break;
3708
3709   case PC_COMMENT:
3710     /* assuming that comment ends with a \n */
3711     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3712     break;
3713
3714   case PC_INLINE:
3715     /* assuming that inline code ends with a \n */
3716     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3717     break;
3718
3719   case PC_LABEL:
3720     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3721     break;
3722   case PC_FUNCTION:
3723     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3724     break;
3725   case PC_WILD:
3726     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3727     break;
3728   case PC_FLOW:
3729     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3730     break;
3731   case PC_CSOURCE:
3732     SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3733     break;
3734
3735   case PC_BAD:
3736     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3737   }
3738
3739   return str;
3740
3741 }
3742
3743 /*-----------------------------------------------------------------*/
3744 /* genericPrint - the contents of a pCode to a file                */
3745 /*-----------------------------------------------------------------*/
3746 static void genericPrint(FILE *of, pCode *pc)
3747 {
3748
3749   if(!pc || !of)
3750     return;
3751
3752   switch(pc->type) {
3753   case PC_COMMENT:
3754     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3755     break;
3756
3757   case PC_INLINE:
3758     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3759      break;
3760
3761   case PC_OPCODE:
3762     // If the opcode has a label, print that first
3763     {
3764       pBranch *pbl = PCI(pc)->label;
3765       while(pbl && pbl->pc) {
3766         if(pbl->pc->type == PC_LABEL)
3767           pCodePrintLabel(of, pbl->pc);
3768         pbl = pbl->next;
3769       }
3770     }
3771
3772     if(PCI(pc)->cline) 
3773       genericPrint(of,PCODE(PCI(pc)->cline));
3774
3775     {
3776       char str[256];
3777       
3778       pCode2str(str, 256, pc);
3779
3780       fprintf(of,"%s",str);
3781
3782       /* Debug */
3783       if(pic16_debug_verbose) {
3784         fprintf(of, "\t;key=%03x",pc->seq);
3785         if(PCI(pc)->pcflow)
3786           fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3787       }
3788     }
3789 #if 0
3790     {
3791       pBranch *dpb = pc->to;   // debug
3792       while(dpb) {
3793         switch ( dpb->pc->type) {
3794         case PC_OPCODE:
3795           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3796           break;
3797         case PC_LABEL:
3798           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3799           break;
3800         case PC_FUNCTION:
3801           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3802           break;
3803         case PC_FLOW:
3804           fprintf(of, "\t;flow");
3805           break;
3806         case PC_COMMENT:
3807         case PC_WILD:
3808           break;
3809         }
3810         dpb = dpb->next;
3811       }
3812     }
3813 #endif
3814     fprintf(of,"\n");
3815     break;
3816
3817   case PC_WILD:
3818     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3819     if(PCW(pc)->pci.label)
3820       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3821
3822     if(PCW(pc)->operand) {
3823       fprintf(of,";\toperand  ");
3824       pCodeOpPrint(of,PCW(pc)->operand );
3825     }
3826     break;
3827
3828   case PC_FLOW:
3829     if(pic16_debug_verbose) {
3830       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3831       if(PCFL(pc)->ancestor)
3832         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3833       fprintf(of,"\n");
3834
3835     }
3836     break;
3837
3838   case PC_CSOURCE:
3839     fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3840     break;
3841   case PC_LABEL:
3842   default:
3843     fprintf(of,"unknown pCode type %d\n",pc->type);
3844   }
3845
3846 }
3847
3848 /*-----------------------------------------------------------------*/
3849 /* pCodePrintFunction - prints function begin/end                  */
3850 /*-----------------------------------------------------------------*/
3851
3852 static void pCodePrintFunction(FILE *of, pCode *pc)
3853 {
3854
3855   if(!pc || !of)
3856     return;
3857
3858   if( ((pCodeFunction *)pc)->modname) 
3859     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3860
3861   if(PCF(pc)->fname) {
3862     pBranch *exits = PCF(pc)->to;
3863     int i=0;
3864     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3865     while(exits) {
3866       i++;
3867       exits = exits->next;
3868     }
3869     //if(i) i--;
3870     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3871     
3872   }else {
3873     if((PCF(pc)->from && 
3874         PCF(pc)->from->pc->type == PC_FUNCTION &&
3875         PCF(PCF(pc)->from->pc)->fname) )
3876       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3877     else
3878       fprintf(of,"; exit point [can't find entry point]\n");
3879   }
3880 }
3881 /*-----------------------------------------------------------------*/
3882 /* pCodePrintLabel - prints label                                  */
3883 /*-----------------------------------------------------------------*/
3884
3885 static void pCodePrintLabel(FILE *of, pCode *pc)
3886 {
3887
3888   if(!pc || !of)
3889     return;
3890
3891   if(PCL(pc)->label) 
3892     fprintf(of,"%s\n",PCL(pc)->label);
3893   else if (PCL(pc)->key >=0) 
3894     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3895   else
3896     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3897
3898 }
3899 /*-----------------------------------------------------------------*/
3900 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
3901 /*                         remove it if it is found.               */
3902 /*-----------------------------------------------------------------*/
3903 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3904 {
3905   pBranch *b, *bprev;
3906
3907
3908   bprev = NULL;
3909
3910   if(pcl->type == PC_OPCODE)
3911     b = PCI(pcl)->label;
3912   else {
3913     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3914     exit(1);
3915
3916   }
3917
3918   //fprintf (stderr, "%s \n",__FUNCTION__);
3919   //pcl->print(stderr,pcl);
3920   //pc->print(stderr,pc);
3921   while(b) {
3922     if(b->pc == pc) {
3923       //fprintf (stderr, "found label\n");
3924
3925       /* Found a label */
3926       if(bprev) {
3927         bprev->next = b->next;  /* Not first pCode in chain */
3928         free(b);
3929       } else {
3930         pc->destruct(pc);
3931         PCI(pcl)->label = b->next;   /* First pCode in chain */
3932         free(b);
3933       }
3934       return;  /* A label can't occur more than once */
3935     }
3936     bprev = b;
3937     b = b->next;
3938   }
3939
3940 }
3941
3942 /*-----------------------------------------------------------------*/
3943 /*-----------------------------------------------------------------*/
3944 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
3945 {
3946   pBranch *b;
3947
3948   if(!h)
3949     return n;
3950
3951   if(h == n)
3952     return n;
3953
3954   b = h;
3955   while(b->next)
3956     b = b->next;
3957
3958   b->next = n;
3959
3960   return h;
3961   
3962 }  
3963 /*-----------------------------------------------------------------*/
3964 /* pBranchLink - given two pcodes, this function will link them    */
3965 /*               together through their pBranches                  */
3966 /*-----------------------------------------------------------------*/
3967 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3968 {
3969   pBranch *b;
3970
3971   // Declare a new branch object for the 'from' pCode.
3972
3973   //_ALLOC(b,sizeof(pBranch));
3974   b = Safe_calloc(1,sizeof(pBranch));
3975   b->pc = PCODE(t);             // The link to the 'to' pCode.
3976   b->next = NULL;
3977
3978   f->to = pic16_pBranchAppend(f->to,b);
3979
3980   // Now do the same for the 'to' pCode.
3981
3982   //_ALLOC(b,sizeof(pBranch));
3983   b = Safe_calloc(1,sizeof(pBranch));
3984   b->pc = PCODE(f);
3985   b->next = NULL;
3986
3987   t->from = pic16_pBranchAppend(t->from,b);
3988   
3989 }
3990
3991 #if 0
3992 /*-----------------------------------------------------------------*/
3993 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3994 /*               a pCode                                           */
3995 /*-----------------------------------------------------------------*/
3996 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3997 {
3998   while(pb) {
3999
4000     if(pb->pc == pc)
4001       return pb;
4002
4003     pb = pb->next;
4004   }
4005
4006   return NULL;
4007 }
4008
4009 /*-----------------------------------------------------------------*/
4010 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
4011 /*-----------------------------------------------------------------*/
4012 static void pCodeUnlink(pCode *pc)
4013 {
4014   pBranch *pb1,*pb2;
4015   pCode *pc1;
4016
4017   if(!pc->prev || !pc->next) {
4018     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4019     exit(1);
4020   }
4021
4022   /* first remove the pCode from the chain */
4023   pc->prev->next = pc->next;
4024   pc->next->prev = pc->prev;
4025
4026   /* Now for the hard part... */
4027
4028   /* Remove the branches */
4029
4030   pb1 = pc->from;
4031   while(pb1) {
4032     pc1 = pb1->pc;    /* Get the pCode that branches to the
4033                        * one we're unlinking */
4034
4035     /* search for the link back to this pCode (the one we're
4036      * unlinking) */
4037     if(pb2 = pBranchFind(pc1->to,pc)) {
4038       pb2->pc = pc->to->pc;  // make the replacement
4039
4040       /* if the pCode we're unlinking contains multiple 'to'
4041        * branches (e.g. this a skip instruction) then we need
4042        * to copy these extra branches to the chain. */
4043       if(pc->to->next)
4044         pic16_pBranchAppend(pb2, pc->to->next);
4045     }
4046     
4047     pb1 = pb1->next;
4048   }
4049
4050
4051 }
4052 #endif
4053 /*-----------------------------------------------------------------*/
4054 /*-----------------------------------------------------------------*/
4055 #if 0
4056 static void genericAnalyze(pCode *pc)
4057 {
4058   switch(pc->type) {
4059   case PC_WILD:
4060   case PC_COMMENT:
4061     return;
4062   case PC_LABEL:
4063   case PC_FUNCTION:
4064   case PC_OPCODE:
4065     {
4066       // Go through the pCodes that are in pCode chain and link
4067       // them together through the pBranches. Note, the pCodes
4068       // are linked together as a contiguous stream like the 
4069       // assembly source code lines. The linking here mimics this
4070       // except that comments are not linked in.
4071       // 
4072       pCode *npc = pc->next;
4073       while(npc) {
4074         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4075           pBranchLink(pc,npc);
4076           return;
4077         } else
4078           npc = npc->next;
4079       }
4080       /* reached the end of the pcode chain without finding
4081        * an instruction we could link to. */
4082     }
4083     break;
4084   case PC_FLOW:
4085     fprintf(stderr,"analyze PC_FLOW\n");
4086
4087     return;
4088   case PC_BAD:
4089     fprintf(stderr,,";A bad pCode is being used\n");
4090
4091   }
4092 }
4093 #endif
4094
4095 /*-----------------------------------------------------------------*/
4096 /*-----------------------------------------------------------------*/
4097 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4098 {
4099   pBranch *pbr;
4100
4101   if(pc->type == PC_LABEL) {
4102     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
4103       return TRUE;
4104   }
4105   if(pc->type == PC_OPCODE) {
4106     pbr = PCI(pc)->label;
4107     while(pbr) {
4108       if(pbr->pc->type == PC_LABEL) {
4109         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
4110           return TRUE;
4111       }
4112       pbr = pbr->next;
4113     }
4114   }
4115
4116   return FALSE;
4117 }
4118
4119 /*-----------------------------------------------------------------*/
4120 /*-----------------------------------------------------------------*/
4121 static int checkLabel(pCode *pc)
4122 {
4123   pBranch *pbr;
4124
4125   if(pc && isPCI(pc)) {
4126     pbr = PCI(pc)->label;
4127     while(pbr) {
4128       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4129         return TRUE;
4130
4131       pbr = pbr->next;
4132     }
4133   }
4134
4135   return FALSE;
4136 }
4137
4138 /*-----------------------------------------------------------------*/
4139 /* findLabelinpBlock - Search the pCode for a particular label     */
4140 /*-----------------------------------------------------------------*/
4141 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4142 {
4143   pCode  *pc;
4144
4145   if(!pb)
4146     return NULL;
4147
4148   for(pc = pb->pcHead; pc; pc = pc->next) 
4149     if(compareLabel(pc,pcop_label))
4150       return pc;
4151     
4152   return NULL;
4153 }
4154
4155 /*-----------------------------------------------------------------*/
4156 /* findLabel - Search the pCode for a particular label             */
4157 /*-----------------------------------------------------------------*/
4158 static pCode * findLabel(pCodeOpLabel *pcop_label)
4159 {
4160   pBlock *pb;
4161   pCode  *pc;
4162
4163   if(!the_pFile)
4164     return NULL;
4165
4166   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4167     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4168       return pc;
4169   }
4170
4171   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4172   return NULL;
4173 }
4174
4175 /*-----------------------------------------------------------------*/
4176 /* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
4177 /*                 in the linked list                              */
4178 /*-----------------------------------------------------------------*/
4179 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4180 {
4181
4182   while(pc) {
4183     if(pc->type == pct)
4184       return pc;
4185
4186     pc = pc->next;
4187   }
4188
4189   return NULL;
4190 }
4191
4192 /*-----------------------------------------------------------------*/
4193 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
4194 /*                 in the linked list                              */
4195 /*-----------------------------------------------------------------*/
4196 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4197 {
4198
4199   while(pc) {
4200     if(pc->type == pct)
4201       return pc;
4202
4203     pc = pc->prev;
4204   }
4205
4206   return NULL;
4207 }
4208 /*-----------------------------------------------------------------*/
4209 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
4210 /*                       in the linked list                        */
4211 /*-----------------------------------------------------------------*/
4212 pCode * pic16_findNextInstruction(pCode *pci)
4213 {
4214   pCode *pc = pci;
4215
4216   while(pc) {
4217     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4218       return pc;
4219
4220 #ifdef PCODE_DEBUG
4221     fprintf(stderr,"pic16_findNextInstruction:  ");
4222     printpCode(stderr, pc);
4223 #endif
4224     pc = pc->next;
4225   }
4226
4227   //fprintf(stderr,"Couldn't find instruction\n");
4228   return NULL;
4229 }
4230
4231 /*-----------------------------------------------------------------*/
4232 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
4233 /*                       in the linked list                        */
4234 /*-----------------------------------------------------------------*/
4235 pCode * pic16_findPrevInstruction(pCode *pci)
4236 {
4237   return findPrevpCode(pci, PC_OPCODE);
4238 }
4239
4240 /*-----------------------------------------------------------------*/
4241 /* findFunctionEnd - given a pCode find the end of the function    */
4242 /*                   that contains it                              */
4243 /*-----------------------------------------------------------------*/
4244 static pCode * findFunctionEnd(pCode *pc)
4245 {
4246
4247   while(pc) {
4248     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
4249       return pc;
4250
4251     pc = pc->next;
4252   }
4253
4254   fprintf(stderr,"Couldn't find function end\n");
4255   return NULL;
4256 }
4257
4258 #if 0
4259 /*-----------------------------------------------------------------*/
4260 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
4261 /*                instruction with which it is associated.         */
4262 /*-----------------------------------------------------------------*/
4263 static void AnalyzeLabel(pCode *pc)
4264 {
4265
4266   pCodeUnlink(pc);
4267
4268 }
4269 #endif
4270
4271 #if 0
4272 static void AnalyzeGOTO(pCode *pc)
4273 {
4274
4275   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4276
4277 }
4278
4279 static void AnalyzeSKIP(pCode *pc)
4280 {
4281
4282   pBranchLink(pc,pic16_findNextInstruction(pc->next));
4283   pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4284
4285 }
4286
4287 static void AnalyzeRETURN(pCode *pc)
4288 {
4289
4290   //  branch_link(pc,findFunctionEnd(pc->next));
4291
4292 }
4293
4294 #endif
4295
4296 /*-----------------------------------------------------------------*/
4297 /*-----------------------------------------------------------------*/
4298 regs * pic16_getRegFromInstruction(pCode *pc)
4299 {
4300
4301   if(!pc                   || 
4302      !isPCI(pc)            ||
4303      !PCI(pc)->pcop        ||
4304      PCI(pc)->num_ops == 0 ||
4305      (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4306     return NULL;
4307
4308   switch(PCI(pc)->pcop->type) {
4309   case PO_INDF0:
4310   case PO_FSR0:
4311     return PCOR(PCI(pc)->pcop)->r;
4312
4313     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4314
4315   case PO_BIT:
4316   case PO_GPR_TEMP:
4317     //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4318     return PCOR(PCI(pc)->pcop)->r;
4319
4320   case PO_IMMEDIATE:
4321     if(PCOI(PCI(pc)->pcop)->r)
4322       return (PCOI(PCI(pc)->pcop)->r);
4323
4324     //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4325     return pic16_dirregWithName(PCI(pc)->pcop->name);
4326     //return NULL; // PCOR(PCI(pc)->pcop)->r;
4327
4328   case PO_GPR_BIT:
4329     return PCOR(PCI(pc)->pcop)->r;
4330
4331   case PO_DIR:
4332     //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4333     return PCOR(PCI(pc)->pcop)->r;
4334   case PO_LITERAL:
4335     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4336     break;
4337
4338   default:
4339     //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4340     //genericPrint(stderr, pc);
4341     break;
4342   }
4343
4344   return NULL;
4345
4346 }
4347
4348 /*-----------------------------------------------------------------*/
4349 /*-----------------------------------------------------------------*/
4350
4351 static void AnalyzepBlock(pBlock *pb)
4352 {
4353   pCode *pc;
4354
4355   if(!pb)
4356     return;
4357
4358   /* Find all of the registers used in this pBlock 
4359    * by looking at each instruction and examining it's
4360    * operands
4361    */
4362   for(pc = pb->pcHead; pc; pc = pc->next) {
4363
4364     /* Is this an instruction with operands? */
4365     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4366
4367       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4368
4369         /* Loop through all of the registers declared so far in
4370            this block and see if we find this one there */
4371
4372         regs *r = setFirstItem(pb->tregisters);
4373
4374         while(r) {
4375           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4376             PCOR(PCI(pc)->pcop)->r = r;
4377             break;
4378           }
4379           r = setNextItem(pb->tregisters);
4380         }
4381
4382         if(!r) {
4383           /* register wasn't found */
4384           //r = Safe_calloc(1, sizeof(regs));
4385           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
4386           //addSet(&pb->tregisters, r);
4387           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
4388           //PCOR(PCI(pc)->pcop)->r = r;
4389           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
4390         }/* else 
4391           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
4392          */
4393       }
4394       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
4395         if(PCOR(PCI(pc)->pcop)->r) {
4396           pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
4397           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
4398         } else {
4399           if(PCI(pc)->pcop->name)
4400             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
4401           else
4402             fprintf(stderr,"ERROR: NULL register\n");
4403         }
4404       }
4405     }
4406
4407
4408   }
4409 }
4410
4411 /*-----------------------------------------------------------------*/
4412 /* */
4413 /*-----------------------------------------------------------------*/
4414 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
4415
4416 static void InsertpFlow(pCode *pc, pCode **pflow)
4417 {
4418   if(*pflow)
4419     PCFL(*pflow)->end = pc;
4420
4421   if(!pc || !pc->next)
4422     return;
4423
4424   *pflow = pic16_newpCodeFlow();
4425   pic16_pCodeInsertAfter(pc, *pflow);
4426 }
4427
4428 /*-----------------------------------------------------------------*/
4429 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
4430 /*                         the flow blocks.                        */
4431 /*
4432  * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
4433  * point the instruction flow changes. 
4434  */
4435 /*-----------------------------------------------------------------*/
4436 void pic16_BuildFlow(pBlock *pb)
4437 {
4438   pCode *pc;
4439   pCode *last_pci=NULL;
4440   pCode *pflow=NULL;
4441   int seq = 0;
4442
4443   if(!pb)
4444     return;
4445
4446   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
4447   /* Insert a pCodeFlow object at the beginning of a pBlock */
4448
4449   InsertpFlow(pb->pcHead, &pflow);
4450
4451   //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
4452   //pflow->next = pb->pcHead;  /* Make the current head the next object */
4453   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
4454   //pb->pcHead = pflow;        /* Make the Flow object the head */
4455   //pflow->pb = pb;
4456
4457   for( pc = pic16_findNextInstruction(pb->pcHead);
4458        pc != NULL;
4459        pc=pic16_findNextInstruction(pc)) { 
4460
4461     pc->seq = seq++;
4462     PCI(pc)->pcflow = PCFL(pflow);
4463
4464     //fprintf(stderr," build: ");
4465     //pflow->print(stderr,pflow);
4466
4467     if( PCI(pc)->isSkip) {
4468
4469       /* The two instructions immediately following this one 
4470        * mark the beginning of a new flow segment */
4471
4472       while(pc && PCI(pc)->isSkip) {
4473
4474         PCI(pc)->pcflow = PCFL(pflow);
4475         pc->seq = seq-1;
4476         seq = 1;
4477
4478         InsertpFlow(pc, &pflow);
4479         pc=pic16_findNextInstruction(pc->next);
4480       }
4481
4482       seq = 0;
4483
4484       if(!pc)
4485         break;
4486
4487       PCI(pc)->pcflow = PCFL(pflow);
4488       pc->seq = 0;
4489       InsertpFlow(pc, &pflow);
4490
4491     } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
4492
4493       InsertpFlow(pc, &pflow);
4494       seq = 0;
4495
4496     } else if (checkLabel(pc)) { 
4497
4498       /* This instruction marks the beginning of a
4499        * new flow segment */
4500
4501       pc->seq = 0;
4502       seq = 1;
4503
4504       /* If the previous pCode is not a flow object, then 
4505        * insert a new flow object. (This check prevents 
4506        * two consecutive flow objects from being insert in
4507        * the case where a skip instruction preceeds an
4508        * instruction containing a label.) */
4509
4510       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4511         InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
4512
4513       PCI(pc)->pcflow = PCFL(pflow);
4514       
4515     }
4516     last_pci = pc;
4517     pc = pc->next;
4518   }
4519
4520   //fprintf (stderr,",end seq %d",GpcFlowSeq);
4521   if(pflow)
4522     PCFL(pflow)->end = pb->pcTail;
4523 }
4524
4525 /*-------------------------------------------------------------------*/
4526 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
4527 /*                           the flow blocks.                        */
4528 /*
4529  * unBuildFlow removes pCodeFlow objects from a pCode chain
4530  */
4531 /*-----------------------------------------------------------------*/
4532 static void unBuildFlow(pBlock *pb)
4533 {
4534   pCode *pc,*pcnext;
4535
4536   if(!pb)
4537     return;
4538
4539   pc = pb->pcHead;
4540
4541   while(pc) {
4542     pcnext = pc->next;
4543
4544     if(isPCI(pc)) {
4545
4546       pc->seq = 0;
4547       if(PCI(pc)->pcflow) {
4548         //free(PCI(pc)->pcflow);
4549         PCI(pc)->pcflow = NULL;
4550       }
4551
4552     } else if(isPCFL(pc) )
4553       pc->destruct(pc);
4554
4555     pc = pcnext;
4556   }
4557
4558
4559 }
4560
4561 /*-----------------------------------------------------------------*/
4562 /*-----------------------------------------------------------------*/
4563 static void dumpCond(int cond)
4564 {
4565
4566   static char *pcc_str[] = {
4567     //"PCC_NONE",
4568     "PCC_REGISTER",
4569     "PCC_REGISTER2",
4570     "PCC_C",
4571     "PCC_Z",
4572     "PCC_DC",
4573     "PCC_OV",
4574     "PCC_N",
4575     "PCC_W",
4576     "PCC_EXAMINE_PCOP",
4577     "PCC_LITERAL",
4578     "PCC_REL_ADDR"
4579   };
4580
4581   int ncond = sizeof(pcc_str) / sizeof(char *);
4582   int i,j;
4583
4584   fprintf(stderr, "0x%04X\n",cond);
4585
4586   for(i=0,j=1; i<ncond; i++, j<<=1)
4587     if(cond & j)
4588       fprintf(stderr, "  %s\n",pcc_str[i]);
4589
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /*-----------------------------------------------------------------*/
4594 static void FlowStats(pCodeFlow *pcflow)
4595 {
4596
4597   pCode *pc;
4598
4599   if(!isPCFL(pcflow))
4600     return;
4601
4602   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4603
4604   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
4605
4606   if(!pc) {
4607     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4608     return;
4609   }
4610
4611
4612   fprintf(stderr, "  FlowStats inCond: ");
4613   dumpCond(pcflow->inCond);
4614   fprintf(stderr, "  FlowStats outCond: ");
4615   dumpCond(pcflow->outCond);
4616
4617 }
4618
4619 /*-----------------------------------------------------------------*
4620  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4621  *    if it affects the banking bits. 
4622  * 
4623  * return: -1 == Banking bits are unaffected by this pCode.
4624  *
4625  * return: > 0 == Banking bits are affected.
4626  *
4627  *  If the banking bits are affected, then the returned value describes
4628  * which bits are affected and how they're affected. The lower half
4629  * of the integer maps to the bits that are affected, the upper half
4630  * to whether they're set or cleared.
4631  *
4632  *-----------------------------------------------------------------*/
4633
4634 static int isBankInstruction(pCode *pc)
4635 {
4636   regs *reg;
4637   int bank = -1;
4638
4639   if(!isPCI(pc))
4640     return -1;
4641
4642   if( PCI(pc)->op == POC_MOVLB ||
4643       (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
4644     bank = PCOL(pc)->lit;
4645   }
4646
4647   return bank;
4648 }
4649
4650
4651 /*-----------------------------------------------------------------*/
4652 /*-----------------------------------------------------------------*/
4653 static void FillFlow(pCodeFlow *pcflow)
4654 {
4655
4656   pCode *pc;
4657   int cur_bank;
4658
4659   if(!isPCFL(pcflow))
4660     return;
4661
4662   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4663
4664   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
4665
4666   if(!pc) {
4667     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4668     return;
4669   }
4670
4671   cur_bank = -1;
4672
4673   do {
4674     isBankInstruction(pc);
4675     pc = pc->next;
4676   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4677
4678 /*
4679   if(!pc ) {
4680     fprintf(stderr, "  FillFlow - Bad end of flow\n");
4681   } else {
4682     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
4683     pc->print(stderr,pc);
4684   }
4685
4686   fprintf(stderr, "  FillFlow inCond: ");
4687   dumpCond(pcflow->inCond);
4688   fprintf(stderr, "  FillFlow outCond: ");
4689   dumpCond(pcflow->outCond);
4690 */
4691 }
4692
4693 /*-----------------------------------------------------------------*/
4694 /*-----------------------------------------------------------------*/
4695 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4696 {
4697   pCodeFlowLink *fromLink, *toLink;
4698
4699   if(!from || !to || !to->pcflow || !from->pcflow)
4700     return;
4701
4702   fromLink = pic16_newpCodeFlowLink(from->pcflow);
4703   toLink   = pic16_newpCodeFlowLink(to->pcflow);
4704
4705   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
4706   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4707
4708 }
4709
4710 /*-----------------------------------------------------------------*
4711  * void LinkFlow(pBlock *pb)
4712  *
4713  * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
4714  * non-branching segments. In LinkFlow, we determine the execution
4715  * order of these segments. For example, if one of the segments ends
4716  * with a skip, then we know that there are two possible flow segments
4717  * to which control may be passed.
4718  *-----------------------------------------------------------------*/
4719 static void LinkFlow(pBlock *pb)
4720 {
4721   pCode *pc=NULL;
4722   pCode *pcflow;
4723   pCode *pct;
4724
4725   //fprintf(stderr,"linkflow \n");
4726
4727   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
4728        pcflow != NULL;
4729        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4730
4731     if(!isPCFL(pcflow))
4732       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4733
4734     //fprintf(stderr," link: ");
4735     //pcflow->print(stderr,pcflow);
4736
4737     //FillFlow(PCFL(pcflow));
4738
4739     pc = PCFL(pcflow)->end;
4740
4741     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4742     if(isPCI_SKIP(pc)) {
4743       //fprintf(stderr, "ends with skip\n");
4744       //pc->print(stderr,pc);
4745       pct=pic16_findNextInstruction(pc->next);
4746       LinkFlow_pCode(PCI(pc),PCI(pct));
4747       pct=pic16_findNextInstruction(pct->next);
4748       LinkFlow_pCode(PCI(pc),PCI(pct));
4749       continue;
4750     }
4751
4752     if(isPCI_BRANCH(pc)) {
4753       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4754
4755       //fprintf(stderr, "ends with branch\n  ");
4756       //pc->print(stderr,pc);
4757
4758       if(!(pcol && isPCOLAB(pcol))) {
4759         if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4760           pc->print(stderr,pc);
4761           fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4762         }
4763         continue;
4764       }
4765
4766       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4767         LinkFlow_pCode(PCI(pc),PCI(pct));
4768       else
4769         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4770                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4771   //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4772
4773       continue;
4774     }
4775
4776     if(isPCI(pc)) {
4777       //fprintf(stderr, "ends with non-branching instruction:\n");
4778       //pc->print(stderr,pc);
4779
4780       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
4781
4782       continue;
4783     }
4784
4785     if(pc) {
4786       //fprintf(stderr, "ends with unknown\n");
4787       //pc->print(stderr,pc);
4788       continue;
4789     }
4790
4791     //fprintf(stderr, "ends with nothing: ERROR\n");
4792     
4793   }
4794 }
4795 /*-----------------------------------------------------------------*/
4796 /*-----------------------------------------------------------------*/
4797
4798 /*-----------------------------------------------------------------*/
4799 /*-----------------------------------------------------------------*/
4800 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
4801 {
4802
4803   if(!pc || !pcflow)
4804     return 0;
4805
4806   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4807     return 0;
4808
4809   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4810     return 1;
4811
4812   return 0;
4813 }
4814
4815 /*-----------------------------------------------------------------*/
4816 /* BanksUsedFlow - Identify which banks are used in flow 2.        */
4817 /*-----------------------------------------------------------------*/
4818 static void BanksUsedFlow2(pCode *pcflow)
4819 {
4820   pCode *pc=NULL;
4821
4822   int bank = -1;
4823   bool RegUsed = 0;
4824
4825   regs *reg;
4826
4827   if(!isPCFL(pcflow)) {
4828     fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4829     return;
4830   }
4831
4832   pc = pic16_findNextInstruction(pcflow->next);
4833
4834   PCFL(pcflow)->lastBank = -1;
4835
4836   while(pic16_isPCinFlow(pc,pcflow)) {
4837
4838     int bank_selected = isBankInstruction(pc);
4839
4840     //if(PCI(pc)->pcflow) 
4841     //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4842
4843     if(bank_selected >= 0) {
4844       //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4845
4846       /* This instruction is modifying banking bits before accessing registers */
4847       if(!RegUsed)
4848         PCFL(pcflow)->firstBank = -1;
4849
4850       if(PCFL(pcflow)->lastBank == -1)
4851         PCFL(pcflow)->lastBank = 0;
4852
4853       bank = 1 << bank_selected;
4854       PCFL(pcflow)->lastBank |= bank;
4855                                  
4856
4857     } else { 
4858       reg = pic16_getRegFromInstruction(pc);
4859
4860       if(reg && !pic16_isREGinBank(reg, bank)) {
4861         int allbanks = pic16_REGallBanks(reg);
4862         if(bank == -1)
4863           PCFL(pcflow)->firstBank = allbanks;
4864
4865         PCFL(pcflow)->lastBank = allbanks;
4866
4867         bank = allbanks;
4868       }
4869       RegUsed = 1;
4870     }
4871
4872     pc = pic16_findNextInstruction(pc->next);
4873   }
4874
4875 //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4876 //        pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4877
4878
4879
4880 }
4881 /*-----------------------------------------------------------------*/
4882 /*-----------------------------------------------------------------*/
4883 static void BanksUsedFlow(pBlock *pb)
4884 {
4885   pCode *pcflow;
4886
4887
4888   //pb->pcHead->print(stderr, pb->pcHead);
4889
4890   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
4891   //pcflow->print(stderr,pcflow);
4892
4893   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
4894        pcflow != NULL;
4895        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
4896
4897     BanksUsedFlow2(pcflow);
4898   }
4899
4900 }
4901
4902
4903 /*-----------------------------------------------------------------*/
4904 /*-----------------------------------------------------------------*/
4905 static void insertBankSwitch(int position, pCode *pc, int bsr)
4906 {
4907   pCode *new_pc;
4908
4909   if(!pc)
4910     return;
4911
4912   new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
4913
4914   if(position) {
4915     /* insert the bank switch after this pc instruction */
4916     pCode *pcnext = pic16_findNextInstruction(pc);
4917     pic16_pCodeInsertAfter(pc, new_pc);
4918     if(pcnext)
4919       pc = pcnext;
4920
4921   } else
4922     pic16_pCodeInsertAfter(pc->prev, new_pc);
4923
4924   /* Move the label, if there is one */
4925
4926   if(PCI(pc)->label) {
4927     PCI(new_pc)->label = PCI(pc)->label;
4928     PCI(pc)->label = NULL;
4929   }
4930
4931   /* The new instruction has the same pcflow block */
4932   PCI(new_pc)->pcflow = PCI(pc)->pcflow;
4933
4934 }
4935 /*-----------------------------------------------------------------*/
4936 /*-----------------------------------------------------------------*/
4937 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4938 {
4939   pCode *pc=NULL;
4940   pCode *pcprev=NULL;
4941   pCode *new_pc;
4942
4943   regs *reg;
4944
4945   if(!pcfl)
4946     return;
4947
4948   pc = pic16_findNextInstruction(pcfl->pc.next);
4949
4950   while(pic16_isPCinFlow(pc,PCODE(pcfl))) {
4951
4952     reg = pic16_getRegFromInstruction(pc);
4953 #if 0
4954     if(reg) {
4955       fprintf(stderr, "  %s  ",reg->name);
4956       fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4957
4958     }
4959 #endif
4960
4961     if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) || 
4962           ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
4963         (!isPCI_LIT(pc)) ){
4964
4965       /* Examine the instruction before this one to make sure it is
4966        * not a skip type instruction */
4967       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4968
4969       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4970         int reg_bank;
4971
4972         reg_bank =  (reg) ? REG_BANK(reg) : 0;
4973
4974         
4975         if (cur_bank != reg_bank) {
4976           //fprintf(stderr, "Cool! can switch banks\n");
4977           cur_bank = reg_bank;
4978           insertBankSwitch(0, pc, cur_bank);
4979         }
4980
4981       } else {
4982         //fprintf(stderr, "Bummer can't switch banks\n");
4983         ;
4984       }
4985     }
4986
4987     pcprev = pc;
4988     pc = pic16_findNextInstruction(pc->next);
4989
4990   }
4991
4992   if(pcprev && cur_bank) {
4993     /* Brute force - make sure that we point to bank 0 at the
4994      * end of each flow block */
4995     new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
4996     pic16_pCodeInsertAfter(pcprev, new_pc);
4997       cur_bank = 0;
4998     //fprintf(stderr, "Brute force switch\n");
4999   }
5000
5001 }
5002
5003 /*-----------------------------------------------------------------*/
5004 /*int compareBankFlow - compare the banking requirements between   */
5005 /*  flow objects. */
5006 /*-----------------------------------------------------------------*/
5007 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5008 {
5009
5010   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5011     return 0;
5012
5013   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5014     return 0;
5015
5016   if(pcflow->firstBank == -1)
5017     return 0;
5018
5019
5020   if(pcflowLink->pcflow->firstBank == -1) {
5021     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
5022                                         pcflowLink->pcflow->to : 
5023                                         pcflowLink->pcflow->from);
5024     return compareBankFlow(pcflow, pctl, toORfrom);
5025   }
5026
5027   if(toORfrom) {
5028     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5029       return 0;
5030
5031     pcflowLink->bank_conflict++;
5032     pcflowLink->pcflow->FromConflicts++;
5033     pcflow->ToConflicts++;
5034   } else {
5035     
5036     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5037       return 0;
5038
5039     pcflowLink->bank_conflict++;
5040     pcflowLink->pcflow->ToConflicts++;
5041     pcflow->FromConflicts++;
5042
5043   }
5044   /*
5045   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5046           pcflowLink->pcflow->pc.seq,
5047           pcflowLink->pcflow->FromConflicts,
5048           pcflowLink->pcflow->ToConflicts);
5049   */
5050   return 1;
5051
5052 }
5053 /*-----------------------------------------------------------------*/
5054 /*-----------------------------------------------------------------*/
5055 static void FixBankFlow(pBlock *pb)
5056 {
5057   pCode *pc=NULL;
5058   pCode *pcflow;
5059   pCodeFlowLink *pcfl;
5060
5061   pCode *pcflow_max_To=NULL;
5062   pCode *pcflow_max_From=NULL;
5063   int max_ToConflicts=0;
5064   int max_FromConflicts=0;
5065
5066   //fprintf(stderr,"Fix Bank flow \n");
5067   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5068
5069
5070   /*
5071     First loop through all of the flow objects in this pcode block
5072     and fix the ones that have banking conflicts between the 
5073     entry and exit.
5074   */
5075
5076   //fprintf(stderr, "FixBankFlow - Phase 1\n");
5077
5078   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5079        pcflow != NULL;
5080        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5081
5082     if(!isPCFL(pcflow)) {
5083       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5084       continue;
5085     }
5086
5087     if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
5088        PCFL(pcflow)->firstBank >= 0 &&
5089        PCFL(pcflow)->lastBank >= 0 ) {
5090
5091       int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
5092         PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
5093
5094       FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
5095       BanksUsedFlow2(pcflow);
5096
5097     }
5098   }
5099
5100   //fprintf(stderr, "FixBankFlow - Phase 2\n");
5101
5102   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5103        pcflow != NULL;
5104        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5105
5106     int nFlows;
5107     int nConflicts;
5108
5109     if(!isPCFL(pcflow)) {
5110       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
5111       continue;
5112     }
5113
5114     PCFL(pcflow)->FromConflicts = 0;
5115     PCFL(pcflow)->ToConflicts = 0;
5116
5117     nFlows = 0;
5118     nConflicts = 0;
5119
5120     //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
5121     pcfl = setFirstItem(PCFL(pcflow)->from);
5122     while (pcfl) {
5123
5124       pc = PCODE(pcfl->pcflow);
5125
5126       if(!isPCFL(pc)) {
5127         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5128         pc->print(stderr,pc);
5129       }
5130
5131       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
5132       nFlows++;
5133
5134       pcfl=setNextItem(PCFL(pcflow)->from);
5135     }
5136
5137     if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
5138       //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5139
5140       FixRegisterBankingInFlow(PCFL(pcflow),0);
5141       BanksUsedFlow2(pcflow);
5142
5143       continue;  /* Don't need to check the flow from here - it's already been fixed */
5144
5145     }
5146
5147     nFlows = 0;
5148     nConflicts = 0;
5149
5150     pcfl = setFirstItem(PCFL(pcflow)->to);
5151     while (pcfl) {
5152
5153       pc = PCODE(pcfl->pcflow);
5154       if(!isPCFL(pc)) {
5155         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5156         pc->print(stderr,pc);
5157       }
5158
5159       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
5160       nFlows++;
5161
5162       pcfl=setNextItem(PCFL(pcflow)->to);
5163     }
5164
5165     if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
5166       //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
5167
5168       FixRegisterBankingInFlow(PCFL(pcflow),0);
5169       BanksUsedFlow2(pcflow);
5170     }
5171   }
5172
5173   /*
5174     Loop through the flow objects again and find the ones with the 
5175     maximum conflicts
5176   */
5177
5178   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5179        pcflow != NULL;
5180        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5181
5182     if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
5183       pcflow_max_To = pcflow;
5184
5185     if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
5186       pcflow_max_From = pcflow;
5187   }
5188 /*
5189   if(pcflow_max_To)
5190     fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
5191             PCFL(pcflow_max_To)->pc.seq,
5192             PCFL(pcflow_max_To)->ToConflicts);
5193
5194   if(pcflow_max_From)
5195     fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
5196             PCFL(pcflow_max_From)->pc.seq,
5197             PCFL(pcflow_max_From)->FromConflicts);
5198 */
5199 }
5200
5201 /*-----------------------------------------------------------------*/
5202 /*-----------------------------------------------------------------*/
5203 static void DumpFlow(pBlock *pb)
5204 {
5205   pCode *pc=NULL;
5206   pCode *pcflow;
5207   pCodeFlowLink *pcfl;
5208
5209
5210   fprintf(stderr,"Dump flow \n");
5211   pb->pcHead->print(stderr, pb->pcHead);
5212
5213   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5214   pcflow->print(stderr,pcflow);
5215
5216   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5217        pcflow != NULL;
5218        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5219
5220     if(!isPCFL(pcflow)) {
5221       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5222       continue;
5223     }
5224     fprintf(stderr,"dumping: ");
5225     pcflow->print(stderr,pcflow);
5226     FlowStats(PCFL(pcflow));
5227
5228     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5229
5230       pc = PCODE(pcfl->pcflow);
5231
5232       fprintf(stderr, "    from seq %d:\n",pc->seq);
5233       if(!isPCFL(pc)) {
5234         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5235         pc->print(stderr,pc);
5236       }
5237
5238     }
5239
5240     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5241
5242       pc = PCODE(pcfl->pcflow);
5243
5244       fprintf(stderr, "    to seq %d:\n",pc->seq);
5245       if(!isPCFL(pc)) {
5246         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5247         pc->print(stderr,pc);
5248       }
5249
5250     }
5251
5252   }
5253
5254 }
5255
5256 /*-----------------------------------------------------------------*/
5257 /*-----------------------------------------------------------------*/
5258 static int OptimizepBlock(pBlock *pb)
5259 {
5260   pCode *pc, *pcprev;
5261   int matches =0;
5262
5263   if(!pb || !peepOptimizing)
5264     return 0;
5265
5266   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5267 /*
5268   for(pc = pb->pcHead; pc; pc = pc->next)
5269     matches += pic16_pCodePeepMatchRule(pc);
5270 */
5271
5272   pc = pic16_findNextInstruction(pb->pcHead);
5273   if(!pc)
5274     return 0;
5275
5276   pcprev = pc->prev;
5277   do {
5278
5279
5280     if(pic16_pCodePeepMatchRule(pc)) {
5281
5282       matches++;
5283
5284       if(pcprev)
5285         pc = pic16_findNextInstruction(pcprev->next);
5286       else 
5287         pc = pic16_findNextInstruction(pb->pcHead);
5288     } else
5289       pc = pic16_findNextInstruction(pc->next);
5290   } while(pc);
5291
5292   if(matches)
5293     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5294   return matches;
5295
5296 }
5297
5298 /*-----------------------------------------------------------------*/
5299 /*-----------------------------------------------------------------*/
5300 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5301 {
5302   pCode *pc;
5303
5304   for(pc = pcs; pc; pc = pc->next) {
5305
5306     if((pc->type == PC_OPCODE) && 
5307        (PCI(pc)->pcop) && 
5308        (PCI(pc)->pcop->type == PO_LABEL) &&
5309        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5310       return pc;
5311   }
5312  
5313
5314   return NULL;
5315 }
5316
5317 /*-----------------------------------------------------------------*/
5318 /*-----------------------------------------------------------------*/
5319 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5320 {
5321
5322   char *s=NULL;
5323
5324   if(isPCI(pc) && 
5325      (PCI(pc)->pcop) && 
5326      (PCI(pc)->pcop->type == PO_LABEL)) {
5327
5328     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5329
5330     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5331     if(pcol->pcop.name)
5332       free(pcol->pcop.name);
5333
5334     /* If the key is negative, then we (probably) have a label to
5335      * a function and the name is already defined */
5336        
5337     if(pcl->key>0)
5338       sprintf(s=buffer,"_%05d_DS_",pcl->key);
5339     else 
5340       s = pcl->label;
5341
5342     //sprintf(buffer,"_%05d_DS_",pcl->key);
5343     if(!s) {
5344       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5345     }
5346     pcol->pcop.name = Safe_strdup(s);
5347     pcol->key = pcl->key;
5348     //pc->print(stderr,pc);
5349
5350   }
5351
5352
5353 }
5354
5355 /*-----------------------------------------------------------------*/
5356 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
5357 /*                            pCode chain if they're not used.     */
5358 /*-----------------------------------------------------------------*/
5359 static void pBlockRemoveUnusedLabels(pBlock *pb)
5360 {
5361   pCode *pc; pCodeLabel *pcl;
5362
5363   if(!pb)
5364     return;
5365
5366   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5367
5368     pBranch *pbr = PCI(pc)->label;
5369     if(pbr && pbr->next) {
5370       pCode *pcd = pb->pcHead;
5371
5372       //fprintf(stderr, "multiple labels\n");
5373       //pc->print(stderr,pc);
5374
5375       pbr = pbr->next;
5376       while(pbr) {
5377
5378         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5379           //fprintf(stderr,"Used by:\n");
5380           //pcd->print(stderr,pcd);
5381
5382           exchangeLabels(PCL(pbr->pc),pcd);
5383
5384           pcd = pcd->next;
5385         }
5386         pbr = pbr->next;
5387       }
5388     }
5389   }
5390
5391   for(pc = pb->pcHead; pc; pc = pc->next) {
5392
5393     if(isPCL(pc)) // pc->type == PC_LABEL)
5394       pcl = PCL(pc);
5395     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5396       pcl = PCL(PCI(pc)->label->pc);
5397     else continue;
5398
5399     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5400
5401     /* This pCode is a label, so search the pBlock to see if anyone
5402      * refers to it */
5403
5404     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5405     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5406       /* Couldn't find an instruction that refers to this label
5407        * So, unlink the pCode label from it's pCode chain
5408        * and destroy the label */
5409       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5410
5411       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5412       if(pc->type == PC_LABEL) {
5413         pic16_unlinkpCode(pc);
5414         pCodeLabelDestruct(pc);
5415       } else {
5416         unlinkpCodeFromBranch(pc, PCODE(pcl));
5417         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5418           free(pc->label);
5419         }*/
5420       }
5421
5422     }
5423   }
5424
5425 }
5426
5427
5428 /*-----------------------------------------------------------------*/
5429 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
5430 /*                     chain and put them into pBranches that are  */
5431 /*                     associated with the appropriate pCode       */
5432 /*                     instructions.                               */
5433 /*-----------------------------------------------------------------*/
5434 void pic16_pBlockMergeLabels(pBlock *pb)
5435 {
5436   pBranch *pbr;
5437   pCode *pc, *pcnext=NULL;
5438
5439   if(!pb)
5440     return;
5441
5442   /* First, Try to remove any unused labels */
5443   //pBlockRemoveUnusedLabels(pb);
5444
5445   /* Now loop through the pBlock and merge the labels with the opcodes */
5446
5447   pc = pb->pcHead;
5448   //  for(pc = pb->pcHead; pc; pc = pc->next) {
5449
5450   while(pc) {
5451     pCode *pcn = pc->next;
5452
5453     if(pc->type == PC_LABEL) {
5454
5455       //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5456       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5457       if((pcnext = pic16_findNextInstruction(pc) )) {
5458
5459         // Unlink the pCode label from it's pCode chain
5460         pic16_unlinkpCode(pc);
5461         
5462         //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5463         // And link it into the instruction's pBranch labels. (Note, since
5464         // it's possible to have multiple labels associated with one instruction
5465         // we must provide a means to accomodate the additional labels. Thus
5466         // the labels are placed into the singly-linked list "label" as 
5467         // opposed to being a single member of the pCodeInstruction.)
5468
5469         //_ALLOC(pbr,sizeof(pBranch));
5470         pbr = Safe_calloc(1,sizeof(pBranch));
5471         pbr->pc = pc;
5472         pbr->next = NULL;
5473
5474         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5475
5476       } else {
5477         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5478       }
5479     } else if(pc->type == PC_CSOURCE) {
5480
5481       /* merge the source line symbolic info into the next instruction */
5482       if((pcnext = pic16_findNextInstruction(pc) )) {
5483
5484         // Unlink the pCode label from it's pCode chain
5485         pic16_unlinkpCode(pc);
5486         PCI(pcnext)->cline = PCCS(pc);
5487         //fprintf(stderr, "merging CSRC\n");
5488         //genericPrint(stderr,pcnext);
5489       }
5490
5491     }
5492     pc = pcn;
5493   }
5494   pBlockRemoveUnusedLabels(pb);
5495
5496 }
5497
5498 /*-----------------------------------------------------------------*/
5499 /*-----------------------------------------------------------------*/
5500 static int OptimizepCode(char dbName)
5501 {
5502 #define MAX_PASSES 4
5503
5504   int matches = 0;
5505   int passes = 0;
5506   pBlock *pb;
5507
5508   if(!the_pFile)
5509     return 0;
5510
5511   DFPRINTF((stderr," Optimizing pCode\n"));
5512
5513   do {
5514     matches = 0;
5515     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5516       if('*' == dbName || getpBlock_dbName(pb) == dbName)
5517         matches += OptimizepBlock(pb);
5518     }
5519   }
5520   while(matches && ++passes < MAX_PASSES);
5521
5522   return matches;
5523 }
5524
5525 /*-----------------------------------------------------------------*/
5526 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
5527 /*-----------------------------------------------------------------*/
5528
5529 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5530 {
5531   pCodeOp *pcop;
5532
5533   pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5534
5535   if( !( (pcop->type == PO_LABEL) ||
5536          (pcop->type == PO_LITERAL) ||
5537          (pcop->type == PO_STR) ))
5538     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
5539
5540   return pcop;
5541 }
5542
5543
5544
5545 #if 0
5546 /*-----------------------------------------------------------------*/
5547 /*-----------------------------------------------------------------*/
5548 int InstructionRegBank(pCode *pc)
5549 {
5550   regs *reg;
5551
5552   if( (reg = pic16_getRegFromInstruction(pc)) == NULL)
5553     return -1;
5554
5555   return REG_BANK(reg);
5556
5557 }
5558 #endif
5559
5560 /*-----------------------------------------------------------------*/
5561 /*-----------------------------------------------------------------*/
5562 static void FixRegisterBanking(pBlock *pb)
5563 {
5564   pCode *pc=NULL;
5565   pCode *pcprev=NULL;
5566
5567   int cur_bank;
5568   regs *reg;
5569
5570   if(!pb)
5571     return;
5572
5573   //pc = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5574   pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5575   if(!pc)
5576     return;
5577   /* loop through all of the flow blocks with in one pblock */
5578
5579   //fprintf(stderr,"Register banking\n");
5580   cur_bank = 0;
5581   do {
5582     /* at this point, pc should point to a PC_FLOW object */
5583
5584
5585     /* for each flow block, determine the register banking 
5586        requirements */
5587
5588     //    do {
5589       if(isPCI(pc)) {
5590         //genericPrint(stderr, pc);
5591
5592         reg = pic16_getRegFromInstruction(pc);
5593 #if 0
5594         if(reg) {
5595           fprintf(stderr, "  %s  ",reg->name);
5596           fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\n",
5597                   reg->address,REG_BANK(reg),reg->isBitField);
5598
5599         }
5600 #endif
5601
5602         if( ( (reg && !isACCESS_BANK(reg) && REG_BANK(reg)!=cur_bank) || 
5603               ((PCI(pc)->op == POC_CALL) && (cur_bank != 0) ) ) &&
5604             (!isPCI_LIT(pc)) ){
5605
5606
5607           /* Examine the instruction before this one to make sure it is
5608            * not a skip type instruction */
5609           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5610
5611           if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5612             int reg_bank;
5613
5614             reg_bank =  (reg) ? REG_BANK(reg) : 0;
5615           
5616             if (cur_bank != reg_bank) {
5617               cur_bank = reg_bank;
5618               insertBankSwitch(0, pc, cur_bank);
5619             }
5620
5621           }else {
5622             //fprintf(stderr, "Bummer can't switch banks\n");
5623             ;
5624           }
5625         }
5626
5627         pcprev = pc;
5628
5629       }
5630
5631       pc = pc->next;
5632       // } while(pc && !(isPCFL(pc))); 
5633
5634
5635   }while (pc);
5636
5637   if(pcprev && cur_bank) {
5638
5639     int pos = 1;  /* Assume that the bank switch instruction(s)
5640                    * are inserted after this instruction */
5641
5642     if((PCI(pcprev)->op == POC_RETLW) || 
5643        (PCI(pcprev)->op == POC_RETURN) || 
5644        (PCI(pcprev)->op == POC_RETFIE)) {
5645
5646       /* oops, a RETURN - we need to switch banks *before* the RETURN */
5647
5648       pos = 0;
5649
5650     } 
5651             
5652     /* Brute force - make sure that we point to bank 0 at the
5653      * end of each flow block */
5654
5655     insertBankSwitch(pos, pcprev, 0);
5656 /*
5657     new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
5658     pic16_pCodeInsertAfter(pcprev, new_pc);
5659 */
5660     cur_bank = 0;
5661     //fprintf(stderr, "Brute force switch\n");
5662   }
5663
5664 }
5665
5666
5667
5668
5669 #if 0
5670         if(reg && REG_BANK(reg)!=cur_bank) {
5671           //fprintf(stderr,"need to switch banks\n");
5672           /* Examine the instruction before this one to make sure it is
5673            * not a skip type instruction */
5674           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5675           if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5676             int b = cur_bank ^ REG_BANK(reg);
5677
5678             cur_bank = REG_BANK(reg);
5679
5680             switch(b & 3) {
5681             case 0:
5682               break;
5683             case 1:
5684               insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5685               break;
5686             case 2:
5687               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5688               insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5689               break;
5690             case 3:
5691               if(cur_bank & 3) {
5692                 insertBankSwitch(0, pc, cur_bank&1, PIC_RP0_BIT);
5693                 insertBankSwitch(0, pc, cur_bank&2, PIC_RP1_BIT);
5694               } else
5695                 insertBankSwitch(0, pc, -1, -1);
5696               break;
5697
5698             }
5699 #endif
5700
5701
5702
5703
5704 static void pBlockDestruct(pBlock *pb)
5705 {
5706
5707   if(!pb)
5708     return;
5709
5710
5711   free(pb);
5712
5713 }
5714
5715 /*-----------------------------------------------------------------*/
5716 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5717 /*                                  name dbName and combine them   */
5718 /*                                  into one block                 */
5719 /*-----------------------------------------------------------------*/
5720 static void mergepBlocks(char dbName)
5721 {
5722
5723   pBlock *pb, *pbmerged = NULL,*pbn;
5724
5725   pb = the_pFile->pbHead;
5726
5727   //fprintf(stderr," merging blocks named %c\n",dbName);
5728   while(pb) {
5729
5730     pbn = pb->next;
5731     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5732     if( getpBlock_dbName(pb) == dbName) {
5733
5734       //fprintf(stderr," merged block %c\n",dbName);
5735
5736       if(!pbmerged) {
5737         pbmerged = pb;
5738       } else {
5739         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
5740         /* pic16_addpCode2pBlock doesn't handle the tail: */
5741         pbmerged->pcTail = pb->pcTail;
5742
5743         pb->prev->next = pbn;
5744         if(pbn) 
5745           pbn->prev = pb->prev;
5746
5747
5748         pBlockDestruct(pb);
5749       }
5750       //pic16_printpBlock(stderr, pbmerged);
5751     } 
5752     pb = pbn;
5753   }
5754
5755 }
5756
5757 /*-----------------------------------------------------------------*/
5758 /* AnalyzeFlow - Examine the flow of the code and optimize         */
5759 /*                                                                 */
5760 /* level 0 == minimal optimization                                 */
5761 /*   optimize registers that are used only by two instructions     */
5762 /* level 1 == maximal optimization                                 */
5763 /*   optimize by looking at pairs of instructions that use the     */
5764 /*   register.                                                     */
5765 /*-----------------------------------------------------------------*/
5766
5767 static void AnalyzeFlow(int level)
5768 {
5769   static int times_called=0;
5770
5771   pBlock *pb;
5772
5773   if(!the_pFile)
5774     return;
5775
5776
5777   /* if this is not the first time this function has been called,
5778      then clean up old flow information */
5779   if(times_called++) {
5780     for(pb = the_pFile->pbHead; pb; pb = pb->next)
5781       unBuildFlow(pb);
5782
5783     pic16_RegsUnMapLiveRanges();
5784
5785   }
5786
5787   GpcFlowSeq = 1;
5788
5789   /* Phase 2 - Flow Analysis - Register Banking
5790    *
5791    * In this phase, the individual flow blocks are examined
5792    * and register banking is fixed.
5793    */
5794
5795   //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5796   //FixRegisterBanking(pb);
5797
5798   /* Phase 2 - Flow Analysis
5799    *
5800    * In this phase, the pCode is partition into pCodeFlow 
5801    * blocks. The flow blocks mark the points where a continuous
5802    * stream of instructions changes flow (e.g. because of
5803    * a call or goto or whatever).
5804    */
5805
5806   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5807     pic16_BuildFlow(pb);
5808
5809
5810   /* Phase 2 - Flow Analysis - linking flow blocks
5811    *
5812    * In this phase, the individual flow blocks are examined
5813    * to determine their order of excution.
5814    */
5815
5816   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5817     LinkFlow(pb);
5818
5819   /* Phase 3 - Flow Analysis - Flow Tree
5820    *
5821    * In this phase, the individual flow blocks are examined
5822    * to determine their order of excution.
5823    */
5824
5825   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5826     pic16_BuildFlowTree(pb);
5827
5828
5829   /* Phase x - Flow Analysis - Used Banks
5830    *
5831    * In this phase, the individual flow blocks are examined
5832    * to determine the Register Banks they use
5833    */
5834
5835   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5836     FixBankFlow(pb);
5837
5838
5839   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5840     pic16_pCodeRegMapLiveRanges(pb);
5841
5842   pic16_RemoveUnusedRegisters();
5843
5844   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5845   pic16_pCodeRegOptimizeRegUsage(level);
5846
5847   OptimizepCode('*');
5848
5849
5850 /*
5851   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5852     DumpFlow(pb);
5853 */
5854   /* debug stuff */ 
5855   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5856     pCode *pcflow;
5857     for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5858          (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5859          pcflow = pcflow->next) {
5860
5861       FillFlow(PCFL(pcflow));
5862     }
5863   }
5864
5865 /*
5866   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5867     pCode *pcflow;
5868     for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5869          (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
5870          pcflow = pcflow->next) {
5871
5872       FlowStats(PCFL(pcflow));
5873     }
5874   }
5875 */
5876 }
5877
5878 /*-----------------------------------------------------------------*/
5879 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
5880 /*                  assigned to the registers.                     */
5881 /*                                                                 */
5882 /*-----------------------------------------------------------------*/
5883
5884 void pic16_AnalyzeBanking(void)
5885 {
5886   pBlock  *pb;
5887
5888   if(!pic16_picIsInitialized()) {
5889     fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5890     fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5891     fprintf(stderr,"support/scripts/inc2h.pl\n");
5892     fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5893
5894     exit(1);
5895   }
5896
5897   /* Phase x - Flow Analysis - Used Banks
5898    *
5899    * In this phase, the individual flow blocks are examined
5900    * to determine the Register Banks they use
5901    */
5902
5903   AnalyzeFlow(0);
5904   AnalyzeFlow(1);
5905
5906   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5907     BanksUsedFlow(pb);
5908   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5909     FixRegisterBanking(pb);
5910
5911 }
5912
5913 /*-----------------------------------------------------------------*/
5914 /* buildCallTree - Look at the flow and extract all of the calls.  */
5915 /*-----------------------------------------------------------------*/
5916 static set *register_usage(pBlock *pb);
5917
5918 static void buildCallTree(void    )
5919 {
5920   pBranch *pbr;
5921   pBlock  *pb;
5922   pCode   *pc;
5923
5924   if(!the_pFile)
5925     return;
5926
5927
5928
5929   /* Now build the call tree.
5930      First we examine all of the pCodes for functions.
5931      Keep in mind that the function boundaries coincide
5932      with pBlock boundaries. 
5933
5934      The algorithm goes something like this:
5935      We have two nested loops. The outer loop iterates
5936      through all of the pBlocks/functions. The inner
5937      loop iterates through all of the pCodes for
5938      a given pBlock. When we begin iterating through
5939      a pBlock, the variable pc_fstart, pCode of the start
5940      of a function, is cleared. We then search for pCodes
5941      of type PC_FUNCTION. When one is encountered, we
5942      initialize pc_fstart to this and at the same time
5943      associate a new pBranch object that signifies a 
5944      branch entry. If a return is found, then this signifies
5945      a function exit point. We'll link the pCodes of these
5946      returns to the matching pc_fstart.
5947
5948      When we're done, a doubly linked list of pBranches
5949      will exist. The head of this list is stored in
5950      `the_pFile', which is the meta structure for all
5951      of the pCode. Look at the pic16_printCallTree function
5952      on how the pBranches are linked together.
5953
5954    */
5955   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5956     pCode *pc_fstart=NULL;
5957     for(pc = pb->pcHead; pc; pc = pc->next) {
5958       if(isPCF(pc)) {
5959         if (PCF(pc)->fname) {
5960
5961           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
5962             //fprintf(stderr," found main \n");
5963             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
5964             pb->dbName = 'M';
5965           }
5966
5967           pbr = Safe_calloc(1,sizeof(pBranch));
5968           pbr->pc = pc_fstart = pc;
5969           pbr->next = NULL;
5970
5971           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
5972
5973           // Here's a better way of doing the same:
5974           addSet(&pb->function_entries, pc);
5975
5976         } else {
5977           // Found an exit point in a function, e.g. return
5978           // (Note, there may be more than one return per function)
5979           if(pc_fstart)
5980             pBranchLink(PCF(pc_fstart), PCF(pc));
5981
5982           addSet(&pb->function_exits, pc);
5983         }
5984       } else if(isCALL(pc)) {
5985         addSet(&pb->function_calls,pc);
5986       }
5987     }
5988   }
5989
5990   /* Re-allocate the registers so that there are no collisions
5991    * between local variables when one function call another */
5992
5993   // this is weird...
5994   //  pic16_deallocateAllRegs();
5995
5996   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5997     if(!pb->visited)
5998       register_usage(pb);
5999   }
6000
6001 }
6002
6003 /*-----------------------------------------------------------------*/
6004 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6005 /*                all of the logical connections.                  */
6006 /*                                                                 */
6007 /* Essentially what's done here is that the pCode flow is          */
6008 /* determined.                                                     */
6009 /*-----------------------------------------------------------------*/
6010
6011 void pic16_AnalyzepCode(char dbName)
6012 {
6013   pBlock *pb;
6014   int i,changes;
6015
6016   if(!the_pFile)
6017     return;
6018
6019   mergepBlocks('D');
6020
6021
6022   /* Phase 1 - Register allocation and peep hole optimization
6023    *
6024    * The first part of the analysis is to determine the registers
6025    * that are used in the pCode. Once that is done, the peep rules
6026    * are applied to the code. We continue to loop until no more
6027    * peep rule optimizations are found (or until we exceed the
6028    * MAX_PASSES threshold). 
6029    *
6030    * When done, the required registers will be determined.
6031    *
6032    */
6033   i = 0;
6034   do {
6035
6036     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6037     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6038
6039     /* First, merge the labels with the instructions */
6040     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6041       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6042
6043         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6044         //fprintf(stderr," analyze and merging block %c\n",dbName);
6045         pic16_pBlockMergeLabels(pb);
6046         AnalyzepBlock(pb);
6047       } else {
6048         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6049       }
6050     }
6051
6052     changes = OptimizepCode(dbName);
6053
6054   } while(changes && (i++ < MAX_PASSES));
6055
6056   buildCallTree();
6057 }
6058
6059 /*-----------------------------------------------------------------*/
6060 /* ispCodeFunction - returns true if *pc is the pCode of a         */
6061 /*                   function                                      */
6062 /*-----------------------------------------------------------------*/
6063 static bool ispCodeFunction(pCode *pc)
6064 {
6065
6066   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6067     return 1;
6068
6069   return 0;
6070 }
6071
6072 /*-----------------------------------------------------------------*/
6073 /* findFunction - Search for a function by name (given the name)   */
6074 /*                in the set of all functions that are in a pBlock */
6075 /* (note - I expect this to change because I'm planning to limit   */
6076 /*  pBlock's to just one function declaration                      */
6077 /*-----------------------------------------------------------------*/
6078 static pCode *findFunction(char *fname)
6079 {
6080   pBlock *pb;
6081   pCode *pc;
6082   if(!fname)
6083     return NULL;
6084
6085   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6086
6087     pc = setFirstItem(pb->function_entries);
6088     while(pc) {
6089     
6090       if((pc->type == PC_FUNCTION) &&
6091          (PCF(pc)->fname) && 
6092          (strcmp(fname, PCF(pc)->fname)==0))
6093         return pc;
6094
6095       pc = setNextItem(pb->function_entries);
6096
6097     }
6098
6099   }
6100   return NULL;
6101 }
6102
6103 static void MarkUsedRegisters(set *regset)
6104 {
6105
6106   regs *r1,*r2;
6107
6108   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6109     r2 = pic16_regWithIdx(r1->rIdx);
6110     r2->isFree = 0;
6111     r2->wasUsed = 1;
6112   }
6113 }
6114
6115 static void pBlockStats(FILE *of, pBlock *pb)
6116 {
6117
6118   pCode *pc;
6119   regs  *r;
6120
6121   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6122
6123   // for now just print the first element of each set
6124   pc = setFirstItem(pb->function_entries);
6125   if(pc) {
6126     fprintf(of,";entry:  ");
6127     pc->print(of,pc);
6128   }
6129   pc = setFirstItem(pb->function_exits);
6130   if(pc) {
6131     fprintf(of,";has an exit\n");
6132     //pc->print(of,pc);
6133   }
6134
6135   pc = setFirstItem(pb->function_calls);
6136   if(pc) {
6137     fprintf(of,";functions called:\n");
6138
6139     while(pc) {
6140       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6141         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
6142       }
6143       pc = setNextItem(pb->function_calls);
6144     }
6145   }
6146
6147   r = setFirstItem(pb->tregisters);
6148   if(r) {
6149     int n = elementsInSet(pb->tregisters);
6150
6151     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6152
6153     while (r) {
6154       fprintf(of,";   %s\n",r->name);
6155       r = setNextItem(pb->tregisters);
6156     }
6157   }
6158 }
6159
6160 /*-----------------------------------------------------------------*/
6161 /*-----------------------------------------------------------------*/
6162 #if 0
6163 static void sequencepCode(void)
6164 {
6165   pBlock *pb;
6166   pCode *pc;
6167
6168
6169   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6170
6171     pb->seq = GpCodeSequenceNumber+1;
6172
6173     for( pc = pb->pcHead; pc; pc = pc->next)
6174       pc->seq = ++GpCodeSequenceNumber;
6175   }
6176
6177 }
6178 #endif
6179
6180 /*-----------------------------------------------------------------*/
6181 /*-----------------------------------------------------------------*/
6182 static set *register_usage(pBlock *pb)
6183 {
6184   pCode *pc,*pcn;
6185   set *registers=NULL;
6186   set *registersInCallPath = NULL;
6187
6188   /* check recursion */
6189
6190   pc = setFirstItem(pb->function_entries);
6191
6192   if(!pc)
6193     return registers;
6194
6195   pb->visited = 1;
6196
6197   if(pc->type != PC_FUNCTION)
6198     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6199
6200   pc = setFirstItem(pb->function_calls);
6201   for( ; pc; pc = setNextItem(pb->function_calls)) {
6202
6203     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6204       char *dest = pic16_get_op_from_instruction(PCI(pc));
6205
6206       pcn = findFunction(dest);
6207       if(pcn) 
6208         registersInCallPath = register_usage(pcn->pb);
6209     } else
6210       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6211
6212   }
6213
6214 #ifdef PCODE_DEBUG
6215   pBlockStats(stderr,pb);  // debug
6216 #endif
6217
6218   // Mark the registers in this block as used.
6219
6220   MarkUsedRegisters(pb->tregisters);
6221   if(registersInCallPath) {
6222     /* registers were used in the functions this pBlock has called */
6223     /* so now, we need to see if these collide with the ones we are */
6224     /* using here */
6225
6226     regs *r1,*r2, *newreg;
6227
6228     DFPRINTF((stderr,"comparing registers\n"));
6229
6230     r1 = setFirstItem(registersInCallPath);
6231     while(r1) {
6232
6233       r2 = setFirstItem(pb->tregisters);
6234
6235       while(r2 && (r1->type != REG_STK)) {
6236
6237         if(r2->rIdx == r1->rIdx) {
6238           newreg = pic16_findFreeReg(REG_GPR);
6239
6240
6241           if(!newreg) {
6242             DFPRINTF((stderr,"Bummer, no more registers.\n"));
6243             exit(1);
6244           }
6245
6246           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6247                   r1->rIdx, newreg->rIdx));
6248           r2->rIdx = newreg->rIdx;
6249           //if(r2->name) free(r2->name);
6250           if(newreg->name)
6251             r2->name = Safe_strdup(newreg->name);
6252           else
6253             r2->name = NULL;
6254           newreg->isFree = 0;
6255           newreg->wasUsed = 1;
6256         }
6257         r2 = setNextItem(pb->tregisters);
6258       }
6259
6260       r1 = setNextItem(registersInCallPath);
6261     }
6262
6263     /* Collisions have been resolved. Now free the registers in the call path */
6264     r1 = setFirstItem(registersInCallPath);
6265     while(r1) {
6266       if(r1->type != REG_STK) {
6267         newreg = pic16_regWithIdx(r1->rIdx);
6268         newreg->isFree = 1;
6269       }
6270       r1 = setNextItem(registersInCallPath);
6271     }
6272
6273   }// else
6274   //    MarkUsedRegisters(pb->registers);
6275
6276   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6277 #ifdef PCODE_DEBUG
6278   if(registers) 
6279     DFPRINTF((stderr,"returning regs\n"));
6280   else
6281     DFPRINTF((stderr,"not returning regs\n"));
6282
6283   DFPRINTF((stderr,"pBlock after register optim.\n"));
6284   pBlockStats(stderr,pb);  // debug
6285 #endif
6286
6287   return registers;
6288 }
6289
6290 /*-----------------------------------------------------------------*/
6291 /* pct2 - writes the call tree to a file                           */
6292 /*                                                                 */
6293 /*-----------------------------------------------------------------*/
6294 static void pct2(FILE *of,pBlock *pb,int indent)
6295 {
6296   pCode *pc,*pcn;
6297   int i;
6298   //  set *registersInCallPath = NULL;
6299
6300   if(!of)
6301     return;
6302
6303   if(indent > 10)
6304     return; //recursion ?
6305
6306   pc = setFirstItem(pb->function_entries);
6307
6308   if(!pc)
6309     return;
6310
6311   pb->visited = 0;
6312
6313   for(i=0;i<indent;i++)   // Indentation
6314     fputc(' ',of);
6315
6316   if(pc->type == PC_FUNCTION)
6317     fprintf(of,"%s\n",PCF(pc)->fname);
6318   else
6319     return;  // ???
6320
6321
6322   pc = setFirstItem(pb->function_calls);
6323   for( ; pc; pc = setNextItem(pb->function_calls)) {
6324
6325     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6326       char *dest = pic16_get_op_from_instruction(PCI(pc));
6327
6328       pcn = findFunction(dest);
6329       if(pcn) 
6330         pct2(of,pcn->pb,indent+1);
6331     } else
6332       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6333
6334   }
6335
6336
6337 }
6338
6339
6340 /*-----------------------------------------------------------------*/
6341 /* pic16_printCallTree - writes the call tree to a file                  */
6342 /*                                                                 */
6343 /*-----------------------------------------------------------------*/
6344
6345 void pic16_printCallTree(FILE *of)
6346 {
6347   pBranch *pbr;
6348   pBlock  *pb;
6349   pCode   *pc;
6350
6351   if(!the_pFile)
6352     return;
6353
6354   if(!of)
6355     of = stderr;
6356
6357   fprintf(of, "\npBlock statistics\n");
6358   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
6359     pBlockStats(of,pb);
6360
6361
6362
6363   fprintf(of,"Call Tree\n");
6364   pbr = the_pFile->functions;
6365   while(pbr) {
6366     if(pbr->pc) {
6367       pc = pbr->pc;
6368       if(!ispCodeFunction(pc))
6369         fprintf(of,"bug in call tree");
6370
6371
6372       fprintf(of,"Function: %s\n", PCF(pc)->fname);
6373
6374       while(pc->next && !ispCodeFunction(pc->next)) {
6375         pc = pc->next;
6376         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6377           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6378       }
6379     }
6380
6381     pbr = pbr->next;
6382   }
6383
6384
6385   fprintf(of,"\n**************\n\na better call tree\n");
6386   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6387     if(pb->visited)
6388       pct2(of,pb,0);
6389   }
6390
6391   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6392     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6393   }
6394 }
6395
6396
6397
6398 /*-----------------------------------------------------------------*/
6399 /*                                                                 */
6400 /*-----------------------------------------------------------------*/
6401
6402 static void InlineFunction(pBlock *pb)
6403 {
6404   pCode *pc;
6405   pCode *pc_call;
6406
6407   if(!pb)
6408     return;
6409
6410   pc = setFirstItem(pb->function_calls);
6411
6412   for( ; pc; pc = setNextItem(pb->function_calls)) {
6413
6414     if(isCALL(pc)) {
6415       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6416       pCode *pct;
6417       pCode *pce;
6418
6419       pBranch *pbr;
6420
6421       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
6422         
6423         //fprintf(stderr,"Cool can inline:\n");
6424         //pcn->print(stderr,pcn);
6425
6426         //fprintf(stderr,"recursive call Inline\n");
6427         InlineFunction(pcn->pb);
6428         //fprintf(stderr,"return from recursive call Inline\n");
6429
6430         /*
6431           At this point, *pc points to a CALL mnemonic, and
6432           *pcn points to the function that is being called.
6433
6434           To in-line this call, we need to remove the CALL
6435           and RETURN(s), and link the function pCode in with
6436           the CALLee pCode.
6437
6438         */
6439
6440
6441         /* Remove the CALL */
6442         pc_call = pc;
6443         pc = pc->prev;
6444
6445         /* remove callee pBlock from the pBlock linked list */
6446         removepBlock(pcn->pb);
6447
6448         pce = pcn;
6449         while(pce) {
6450           pce->pb = pb;
6451           pce = pce->next;
6452         }
6453
6454         /* Remove the Function pCode */
6455         pct = pic16_findNextInstruction(pcn->next);
6456
6457         /* Link the function with the callee */
6458         pc->next = pcn->next;
6459         pcn->next->prev = pc;
6460         
6461         /* Convert the function name into a label */
6462
6463         pbr = Safe_calloc(1,sizeof(pBranch));
6464         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6465         pbr->next = NULL;
6466         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6467         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6468
6469         /* turn all of the return's except the last into goto's */
6470         /* check case for 2 instruction pBlocks */
6471         pce = pic16_findNextInstruction(pcn->next);
6472         while(pce) {
6473           pCode *pce_next = pic16_findNextInstruction(pce->next);
6474
6475           if(pce_next == NULL) {
6476             /* found the last return */
6477             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
6478
6479             //fprintf(stderr,"found last return\n");
6480             //pce->print(stderr,pce);
6481             pce->prev->next = pc_call->next;
6482             pc_call->next->prev = pce->prev;
6483             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6484                                                       PCI(pce)->label);
6485           }
6486
6487           pce = pce_next;
6488         }
6489
6490
6491       }
6492     } else
6493       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6494
6495   }
6496
6497 }
6498
6499 /*-----------------------------------------------------------------*/
6500 /*                                                                 */
6501 /*-----------------------------------------------------------------*/
6502
6503 void pic16_InlinepCode(void)
6504 {
6505
6506   pBlock  *pb;
6507   pCode   *pc;
6508
6509   if(!the_pFile)
6510     return;
6511
6512   if(!functionInlining)
6513     return;
6514
6515   /* Loop through all of the function definitions and count the
6516    * number of times each one is called */
6517   //fprintf(stderr,"inlining %d\n",__LINE__);
6518
6519   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6520
6521     pc = setFirstItem(pb->function_calls);
6522
6523     for( ; pc; pc = setNextItem(pb->function_calls)) {
6524
6525       if(isCALL(pc)) {
6526         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6527         if(pcn && isPCF(pcn)) {
6528           PCF(pcn)->ncalled++;
6529         }
6530       } else
6531         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6532
6533     }
6534   }
6535
6536   //fprintf(stderr,"inlining %d\n",__LINE__);
6537
6538   /* Now, Loop through the function definitions again, but this
6539    * time inline those functions that have only been called once. */
6540   
6541   InlineFunction(the_pFile->pbHead);
6542   //fprintf(stderr,"inlining %d\n",__LINE__);
6543
6544   for(pb = the_pFile->pbHead; pb; pb = pb->next)
6545     unBuildFlow(pb);
6546
6547 }