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