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