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