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