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