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