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