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