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