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