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