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