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