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