1 /*------------------------------------------------------------------------- 2 3 pcode.h - post code generation 4 Written By - Scott Dattalo scott@dattalo.com 5 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com 6 7 This program is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by the 9 Free Software Foundation; either version 2, or (at your option) any 10 later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 21 -------------------------------------------------------------------------*/ 22 23 //#include "ralloc.h" 24 struct reg_info; 25 26 /* 27 Post code generation 28 29 The post code generation is an assembler optimizer. The assembly code 30 produced by all of the previous steps is fully functional. This step 31 will attempt to analyze the flow of the assembly code and agressively 32 optimize it. The peep hole optimizer attempts to do the same thing. 33 As you may recall, the peep hole optimizer replaces blocks of assembly 34 with more optimal blocks (e.g. removing redundant register loads). 35 However, the peep hole optimizer has to be somewhat conservative since 36 an assembly program has implicit state information that's unavailable 37 when only a few instructions are examined. 38 Consider this example: 39 40 example1: 41 movwf t1 42 movf t1,w 43 44 The movf seems redundant since we know that the W register already 45 contains the same value of t1. So a peep hole optimizer is tempted to 46 remove the "movf". However, this is dangerous since the movf affects 47 the flags in the status register (specifically the Z flag) and subsequent 48 code may depend upon this. Look at these two examples: 49 50 example2: 51 movwf t1 52 movf t1,w ; Can't remove this movf 53 skpz 54 return 55 56 example3: 57 movwf t1 58 movf t1,w ; This movf can be removed 59 xorwf t2,w ; since xorwf will over write Z 60 skpz 61 return 62 63 */ 64 65 66 #ifndef __PCODE_H__ 67 #define __PCODE_H__ 68 69 /*********************************************************************** 70 * debug stuff 71 * 72 * The DFPRINTF macro will call fprintf if PCODE_DEBUG is defined. 73 * The macro is used like: 74 * 75 * DPRINTF(("%s #%d\n","test", 1)); 76 * 77 * The double parenthesis (()) are necessary 78 * 79 ***********************************************************************/ 80 //#define PCODE_DEBUG 81 82 #ifdef PCODE_DEBUG 83 #define DFPRINTF(args) (fprintf args) 84 #else 85 #define DFPRINTF(args) ; 86 #endif 87 88 89 #ifdef WORDS_BIGENDIAN 90 #define _ENDIAN(x) (3-x) 91 #else 92 #define _ENDIAN(x) (x) 93 #endif 94 95 96 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff) 97 98 99 /*********************************************************************** 100 * Extended Instruction Set/Indexed Literal Offset Mode * 101 * Set this macro to enable code generation with the extended * 102 * instruction set and the new Indexed Literal Offset Mode * 103 ***********************************************************************/ 104 #define XINST 1 105 106 /*********************************************************************** 107 * PIC status bits - this will move into device dependent headers 108 ***********************************************************************/ 109 #define PIC_C_BIT 0 110 #define PIC_DC_BIT 1 111 #define PIC_Z_BIT 2 112 #define PIC_OV_BIT 3 113 #define PIC_N_BIT 4 114 #define PIC_IRP_BIT 7 /* Indirect register page select */ 115 116 /*********************************************************************** 117 * PIC INTCON bits - this will move into device dependent headers 118 ***********************************************************************/ 119 #define PIC_RBIF_BIT 0 /* Port B level has changed flag */ 120 #define PIC_INTF_BIT 1 /* Port B bit 0 interrupt on edge flag */ 121 #define PIC_T0IF_BIT 2 /* TMR0 has overflowed flag */ 122 #define PIC_RBIE_BIT 3 /* Port B level has changed - Interrupt Enable */ 123 #define PIC_INTE_BIT 4 /* Port B bit 0 interrupt on edge - Int Enable */ 124 #define PIC_T0IE_BIT 5 /* TMR0 overflow Interrupt Enable */ 125 #define PIC_PIE_BIT 6 /* Peripheral Interrupt Enable */ 126 #define PIC_GIE_BIT 7 /* Global Interrupt Enable */ 127 128 /*********************************************************************** 129 * PIC bank definitions 130 ***********************************************************************/ 131 #define PIC_BANK_FIRST 0 132 #define PIC_BANK_LAST 0xf 133 134 135 /*********************************************************************** 136 * Operand types 137 ***********************************************************************/ 138 #define POT_RESULT 0 139 #define POT_LEFT 1 140 #define POT_RIGHT 2 141 142 143 /*********************************************************************** 144 * 145 * PIC_OPTYPE - Operand types that are specific to the PIC architecture 146 * 147 * If a PIC assembly instruction has an operand then here is where we 148 * associate a type to it. For example, 149 * 150 * movf reg,W 151 * 152 * The movf has two operands: 'reg' and the W register. 'reg' is some 153 * arbitrary general purpose register, hence it has the type PO_GPR_REGISTER. 154 * The W register, which is the PIC's accumulator, has the type PO_W. 155 * 156 ***********************************************************************/ 157 158 159 160 typedef enum 161 { 162 PO_NONE=0, // No operand e.g. NOP 163 PO_W, // The working register (as a destination) 164 PO_WREG, // The working register (as a file register) 165 PO_STATUS, // The 'STATUS' register 166 PO_BSR, // The 'BSR' register 167 PO_FSR0, // The "file select register" (in PIC18 family it's one 168 // of three) 169 PO_INDF0, // The Indirect register 170 PO_INTCON, // Interrupt Control register 171 PO_GPR_REGISTER, // A general purpose register 172 PO_GPR_BIT, // A bit of a general purpose register 173 PO_GPR_TEMP, // A general purpose temporary register 174 PO_SFR_REGISTER, // A special function register (e.g. PORTA) 175 PO_PCL, // Program counter Low register 176 PO_PCLATH, // Program counter Latch high register 177 PO_PCLATU, // Program counter Latch upper register 178 PO_PRODL, // Product Register Low 179 PO_PRODH, // Product Register High 180 PO_LITERAL, // A constant 181 PO_REL_ADDR, // A relative address 182 PO_IMMEDIATE, // (8051 legacy) 183 PO_DIR, // Direct memory (8051 legacy) 184 PO_CRY, // bit memory (8051 legacy) 185 PO_BIT, // bit operand. 186 PO_STR, // (8051 legacy) 187 PO_LABEL, 188 PO_WILD, // Wild card operand in peep optimizer 189 PO_TWO_OPS // combine two operands 190 } PIC_OPTYPE; 191 192 193 /*********************************************************************** 194 * 195 * PIC_OPCODE 196 * 197 * This is not a list of the PIC's opcodes per se, but instead 198 * an enumeration of all of the different types of pic opcodes. 199 * 200 ***********************************************************************/ 201 202 typedef enum 203 { 204 POC_WILD=-1, /* Wild card - used in the pCode peep hole optimizer 205 * to represent ANY pic opcode */ 206 POC_ADDLW=0, 207 POC_ADDWF, 208 POC_ADDFW, 209 POC_ADDFWC, 210 POC_ADDWFC, 211 POC_ANDLW, 212 POC_ANDWF, 213 POC_ANDFW, 214 POC_BC, 215 POC_BCF, 216 POC_BN, 217 POC_BNC, 218 POC_BNN, 219 POC_BNOV, 220 POC_BNZ, 221 POC_BOV, 222 POC_BRA, 223 POC_BSF, 224 POC_BTFSC, 225 POC_BTFSS, 226 POC_BTG, 227 POC_BZ, 228 POC_CALL, 229 POC_CLRF, 230 POC_CLRWDT, 231 POC_COMF, 232 POC_COMFW, 233 POC_CPFSEQ, 234 POC_CPFSGT, 235 POC_CPFSLT, 236 POC_DAW, 237 POC_DCFSNZ, 238 POC_DCFSNZW, 239 POC_DECF, 240 POC_DECFW, 241 POC_DECFSZ, 242 POC_DECFSZW, 243 POC_GOTO, 244 POC_INCF, 245 POC_INCFW, 246 POC_INCFSZ, 247 POC_INCFSZW, 248 POC_INFSNZ, 249 POC_INFSNZW, 250 POC_IORWF, 251 POC_IORFW, 252 POC_IORLW, 253 POC_LFSR, 254 POC_MOVF, 255 POC_MOVFW, 256 POC_MOVFF, 257 POC_MOVLB, 258 POC_MOVLW, 259 POC_MOVWF, 260 POC_MULLW, 261 POC_MULWF, 262 POC_NEGF, 263 POC_NOP, 264 POC_POP, 265 POC_PUSH, 266 POC_RCALL, 267 POC_RETFIE, 268 POC_RETLW, 269 POC_RETURN, 270 POC_RLCF, 271 POC_RLCFW, 272 POC_RLNCF, 273 POC_RLNCFW, 274 POC_RRCF, 275 POC_RRCFW, 276 POC_RRNCF, 277 POC_RRNCFW, 278 POC_SETF, 279 POC_SUBLW, 280 POC_SUBFWB, 281 POC_SUBWF, 282 POC_SUBFW, 283 POC_SUBWFB_D0, 284 POC_SUBWFB_D1, 285 POC_SUBFWB_D0, 286 POC_SUBFWB_D1, 287 POC_SWAPF, 288 POC_SWAPFW, 289 POC_TBLRD, 290 POC_TBLRD_POSTINC, 291 POC_TBLRD_POSTDEC, 292 POC_TBLRD_PREINC, 293 POC_TBLWT, 294 POC_TBLWT_POSTINC, 295 POC_TBLWT_POSTDEC, 296 POC_TBLWT_PREINC, 297 POC_TSTFSZ, 298 POC_XORLW, 299 POC_XORWF, 300 POC_XORFW, 301 302 POC_BANKSEL 303 304 /* pseudo-instructions */ 305 } PIC_OPCODE; 306 307 308 /*********************************************************************** 309 * PC_TYPE - pCode Types 310 ***********************************************************************/ 311 312 typedef enum 313 { 314 PC_COMMENT=0, /* pCode is a comment */ 315 PC_INLINE, /* user's inline code */ 316 PC_OPCODE, /* PORT dependent opcode */ 317 PC_LABEL, /* assembly label */ 318 PC_FLOW, /* flow analysis */ 319 PC_FUNCTION, /* Function start or end */ 320 PC_WILD, /* wildcard - an opcode place holder used 321 * in the pCode peep hole optimizer */ 322 PC_CSOURCE, /* C-Source Line */ 323 PC_ASMDIR, /* Assembler directive */ 324 PC_BAD, /* Mark the pCode object as being bad */ 325 PC_INFO /* pCode information node, used primarily in optimizing */ 326 } PC_TYPE; 327 328 329 /*********************************************************************** 330 * INFO_TYPE - information node types 331 ***********************************************************************/ 332 333 typedef enum 334 { 335 INF_OPTIMIZATION, /* structure contains optimization information */ 336 INF_LOCALREGS /* structure contains local register information */ 337 } INFO_TYPE; 338 339 340 341 /*********************************************************************** 342 * OPT_TYPE - optimization node types 343 ***********************************************************************/ 344 345 typedef enum 346 { 347 OPT_BEGIN, /* mark beginning of optimization block */ 348 OPT_END, /* mark ending of optimization block */ 349 OPT_JUMPTABLE_BEGIN, /* mark beginning of a jumptable */ 350 OPT_JUMPTABLE_END /* mark end of jumptable */ 351 } OPT_TYPE; 352 353 /*********************************************************************** 354 * LR_TYPE - optimization node types 355 ***********************************************************************/ 356 357 typedef enum 358 { 359 LR_ENTRY_BEGIN, /* mark beginning of optimization block */ 360 LR_ENTRY_END, /* mark ending of optimization block */ 361 LR_EXIT_BEGIN, 362 LR_EXIT_END 363 } LR_TYPE; 364 365 366 /************************************************/ 367 /*************** Structures ********************/ 368 /************************************************/ 369 /* These are here as forward references - the 370 * full definition of these are below */ 371 struct pCode; 372 struct pCodeWildBlock; 373 struct pCodeRegLives; 374 375 /************************************************* 376 pBranch 377 378 The first step in optimizing pCode is determining 379 the program flow. This information is stored in 380 single-linked lists in the for of 'from' and 'to' 381 objects with in a pcode. For example, most instructions 382 don't involve any branching. So their from branch 383 points to the pCode immediately preceding them and 384 their 'to' branch points to the pcode immediately 385 following them. A skip instruction is an example of 386 a pcode that has multiple (in this case two) elements 387 in the 'to' branch. A 'label' pcode is an where there 388 may be multiple 'from' branches. 389 *************************************************/ 390 391 typedef struct pBranch 392 { 393 struct pCode *pc; // Next pCode in a branch 394 struct pBranch *next; /* If more than one branch 395 * the next one is here */ 396 397 } pBranch; 398 399 /************************************************* 400 pCodeOp 401 402 pCode Operand structure. 403 For those assembly instructions that have arguments, 404 the pCode will have a pCodeOp in which the argument 405 can be stored. For example 406 407 movf some_register,w 408 409 'some_register' will be stored/referenced in a pCodeOp 410 411 *************************************************/ 412 413 typedef struct pCodeOp 414 { 415 PIC_OPTYPE type; 416 char *name; 417 418 } pCodeOp; 419 420 #if 0 421 typedef struct pCodeOpBit 422 { 423 pCodeOp pcop; 424 int bit; 425 unsigned int inBitSpace: 1; /* True if in bit space, else 426 just a bit of a register */ 427 } pCodeOpBit; 428 #endif 429 430 typedef struct pCodeOpLit 431 { 432 pCodeOp pcop; 433 int lit; 434 pCodeOp *arg2; /* needed as pCodeOpLit and pCodeOpLit2 are not separable via their type (PO_LITERAL) */ 435 } pCodeOpLit; 436 437 typedef struct pCodeOpLit2 438 { 439 pCodeOp pcop; 440 int lit; 441 pCodeOp *arg2; 442 } pCodeOpLit2; 443 444 445 typedef struct pCodeOpImmd 446 { 447 pCodeOp pcop; 448 int offset; /* low,high or upper byte of immediate value */ 449 int index; /* add this to the immediate value */ 450 unsigned _const:1; /* is in code space */ 451 452 int rIdx; /* If this immd points to a register */ 453 struct reg_info *r; /* then this is the reg. */ 454 455 } pCodeOpImmd; 456 457 typedef struct pCodeOpLabel 458 { 459 pCodeOp pcop; 460 int key; 461 } pCodeOpLabel; 462 463 typedef struct pCodeOpReg 464 { 465 pCodeOp pcop; // Can be either GPR or SFR 466 int rIdx; // Index into the register table 467 struct reg_info *r; 468 int instance; // byte # of Multi-byte registers 469 struct pBlock *pb; 470 } pCodeOpReg; 471 472 typedef struct pCodeOp2 473 { 474 pCodeOp pcop; // describes this pCodeOp 475 pCodeOp *pcopL; // reference to left pCodeOp (src) 476 pCodeOp *pcopR; // reference to right pCodeOp (dest) 477 } pCodeOp2; 478 479 typedef struct pCodeOpRegBit 480 { 481 pCodeOpReg pcor; // The Register containing this bit 482 int bit; // 0-7 bit number. 483 PIC_OPTYPE subtype; // The type of this register. 484 unsigned int inBitSpace: 1; /* True if in bit space, else 485 just a bit of a register */ 486 } pCodeOpRegBit; 487 488 489 typedef struct pCodeOpWild 490 { 491 pCodeOp pcop; 492 493 struct pCodeWildBlock *pcwb; 494 495 int id; /* index into an array of char *'s that will match 496 * the wild card. The array is in *pcp. */ 497 pCodeOp *subtype; /* Pointer to the Operand type into which this wild 498 * card will be expanded */ 499 pCodeOp *matched; /* When a wild matches, we'll store a pointer to the 500 * opcode we matched */ 501 502 pCodeOp *pcop2; /* second operand if exists */ 503 504 } pCodeOpWild; 505 506 507 typedef struct pCodeOpOpt 508 { 509 pCodeOp pcop; 510 511 OPT_TYPE type; /* optimization node type */ 512 513 char *key; /* key by which a block is identified */ 514 } pCodeOpOpt; 515 516 typedef struct pCodeOpLocalReg 517 { 518 pCodeOp pcop; 519 520 LR_TYPE type; 521 } pCodeOpLocalReg; 522 523 /************************************************* 524 pCode 525 526 Here is the basic build block of a PIC instruction. 527 Each pic instruction will get allocated a pCode. 528 A linked list of pCodes makes a program. 529 530 **************************************************/ 531 532 typedef struct pCode 533 { 534 PC_TYPE type; 535 536 struct pCode *prev; // The pCode objects are linked together 537 struct pCode *next; // in doubly linked lists. 538 539 int seq; // sequence number 540 541 struct pBlock *pb; // The pBlock that contains this pCode. 542 543 /* "virtual functions" 544 * The pCode structure is like a base class 545 * in C++. The subsequent structures that "inherit" 546 * the pCode structure will initialize these function 547 * pointers to something useful */ 548 // void (*analyze) (struct pCode *_this); 549 void (*destruct)(struct pCode *_this); 550 void (*print) (FILE *of,struct pCode *_this); 551 552 } pCode; 553 554 555 /************************************************* 556 pCodeComment 557 **************************************************/ 558 559 typedef struct pCodeComment 560 { 561 pCode pc; 562 563 char *comment; 564 565 } pCodeComment; 566 567 568 /************************************************* 569 pCodeCSource 570 **************************************************/ 571 572 typedef struct pCodeCSource 573 { 574 pCode pc; 575 576 int line_number; 577 char *line; 578 char *file_name; 579 580 } pCodeCSource; 581 582 583 /************************************************* 584 pCodeAsmDir 585 **************************************************/ 586 587 /************************************************* 588 pCodeFlow 589 590 The Flow object is used as marker to separate 591 the assembly code into contiguous chunks. In other 592 words, everytime an instruction cause or potentially 593 causes a branch, a Flow object will be inserted into 594 the pCode chain to mark the beginning of the next 595 contiguous chunk. 596 597 **************************************************/ 598 struct defmap_s; // defined in pcode.c 599 600 typedef struct pCodeFlow 601 { 602 pCode pc; 603 604 pCode *end; /* Last pCode in this flow. Note that 605 the first pCode is pc.next */ 606 607 /* set **uses; * map the pCode instruction inCond and outCond conditions 608 * in this array of set's. The reason we allocate an 609 * array of pointers instead of declaring each type of 610 * usage is because there are port dependent usage definitions */ 611 //int nuses; /* number of uses sets */ 612 613 set *from; /* flow blocks that can send control to this flow block */ 614 set *to; /* flow blocks to which this one can send control */ 615 struct pCodeFlow *ancestor; /* The most immediate "single" pCodeFlow object that 616 * executes prior to this one. In many cases, this 617 * will be just the previous */ 618 619 int inCond; /* Input conditions - stuff assumed defined at entry */ 620 int outCond; /* Output conditions - stuff modified by flow block */ 621 622 int firstBank; /* The first and last bank flags are the first and last */ 623 int lastBank; /* register banks used within one flow object */ 624 625 int FromConflicts; 626 int ToConflicts; 627 628 set *registers;/* Registers used in this flow */ 629 630 struct defmap_s *defmap; /* chronologically ordered list of definitions performed 631 in this flow (most recent at the front) */ 632 struct defmap_s *in_vals; /* definitions of all symbols reaching this flow 633 * symbols with multiple different definitions are stored 634 * with an assigned value of 0. */ 635 struct defmap_s *out_vals; /* definitions valid AFTER thie flow */ 636 637 } pCodeFlow; 638 639 /************************************************* 640 pCodeFlowLink 641 642 The Flow Link object is used to record information 643 about how consecutive excutive Flow objects are related. 644 The pCodeFlow objects demarcate the pCodeInstructions 645 into contiguous chunks. The FlowLink records conflicts 646 in the discontinuities. For example, if one Flow object 647 references a register in bank 0 and the next Flow object 648 references a register in bank 1, then there is a discontinuity 649 in the banking registers. 650 651 */ 652 typedef struct pCodeFlowLink 653 { 654 pCodeFlow *pcflow; /* pointer to linked pCodeFlow object */ 655 656 int bank_conflict; /* records bank conflicts */ 657 658 } pCodeFlowLink; 659 660 /************************************************* 661 pCodeInstruction 662 663 Here we describe all the facets of a PIC instruction 664 (expansion for the 18cxxx is also provided). 665 666 **************************************************/ 667 668 typedef struct pCodeInstruction 669 { 670 pCode pc; 671 672 PIC_OPCODE op; // The opcode of the instruction. 673 674 char const * const mnemonic; // Pointer to mnemonic string 675 676 char isize; // pCode instruction size 677 678 pBranch *from; // pCodes that execute before this one 679 pBranch *to; // pCodes that execute after 680 pBranch *label; // pCode instructions that have labels 681 682 pCodeOp *pcop; /* Operand, if this instruction has one */ 683 pCodeFlow *pcflow; /* flow block to which this instruction belongs */ 684 pCodeCSource *cline; /* C Source from which this instruction was derived */ 685 686 unsigned int num_ops; /* Number of operands (0,1,2 for mid range pics) */ 687 unsigned int isModReg: 1; /* If destination is W or F, then 1==F */ 688 unsigned int isBitInst: 1; /* e.g. BCF */ 689 unsigned int isBranch: 1; /* True if this is a branching instruction */ 690 unsigned int isSkip: 1; /* True if this is a skip instruction */ 691 unsigned int isLit: 1; /* True if this instruction has an literal operand */ 692 unsigned int isAccess: 1; /* True if this instruction has an access RAM operand */ 693 unsigned int isFastCall: 1; /* True if this instruction has a fast call/return mode select operand */ 694 unsigned int is2MemOp: 1; /* True is second operand is a memory operand VR - support for MOVFF */ 695 unsigned int is2LitOp: 1; /* True if instruction takes 2 literal operands VR - support for LFSR */ 696 697 PIC_OPCODE inverted_op; /* Opcode of instruction that's the opposite of this one */ 698 unsigned int inCond; // Input conditions for this instruction 699 unsigned int outCond; // Output conditions for this instruction 700 701 #define PCI_MAGIC 0x6e12 702 unsigned int pci_magic; // sanity check for pci initialization 703 } pCodeInstruction; 704 705 706 707 /************************************************* 708 pCodeAsmDir 709 **************************************************/ 710 711 typedef struct pCodeAsmDir 712 { 713 pCodeInstruction pci; 714 715 char *directive; 716 char *arg; 717 } pCodeAsmDir; 718 719 720 /************************************************* 721 pCodeLabel 722 **************************************************/ 723 724 typedef struct pCodeLabel 725 { 726 pCode pc; 727 728 char *label; 729 int key; 730 int force; /* label cannot be optimized out */ 731 732 } pCodeLabel; 733 734 /************************************************* 735 pCodeFunction 736 **************************************************/ 737 738 typedef struct pCodeFunction 739 { 740 pCode pc; 741 742 char *modname; 743 char *fname; /* If NULL, then this is the end of 744 a function. Otherwise, it's the 745 start and the name is contained 746 here */ 747 748 pBranch *from; // pCodes that execute before this one 749 pBranch *to; // pCodes that execute after 750 pBranch *label; // pCode instructions that have labels 751 752 int ncalled; /* Number of times function is called */ 753 754 int absblock; /* hack to emulate a block pCodes in absolute position 755 but not inside a function */ 756 int stackusage; /* stack positions used in function */ 757 758 } pCodeFunction; 759 760 761 /************************************************* 762 pCodeWild 763 **************************************************/ 764 765 typedef struct pCodeWild 766 { 767 pCodeInstruction pci; 768 769 int id; /* Index into the wild card array of a peepBlock 770 * - this wild card will get expanded into that pCode 771 * that is stored at this index */ 772 773 /* Conditions on wild pcode instruction */ 774 int mustBeBitSkipInst:1; 775 int mustNotBeBitSkipInst:1; 776 int invertBitSkipInst:1; 777 778 pCodeOp *operand; // Optional operand 779 pCodeOp *label; // Optional label 780 781 } pCodeWild; 782 783 784 /************************************************* 785 pInfo 786 787 Here are stored generic informaton 788 *************************************************/ 789 typedef struct pCodeInfo 790 { 791 pCodeInstruction pci; 792 793 INFO_TYPE type; /* info node type */ 794 795 pCodeOp *oper1; /* info node arguments */ 796 } pCodeInfo; 797 798 799 /************************************************* 800 pBlock 801 802 Here are PIC program snippets. There's a strong 803 correlation between the eBBlocks and pBlocks. 804 SDCC subdivides a C program into managable chunks. 805 Each chunk becomes a eBBlock and ultimately in the 806 PIC port a pBlock. 807 808 **************************************************/ 809 810 typedef struct pBlock 811 { 812 memmap *cmemmap; /* The snippet is from this memmap */ 813 char dbName; /* if cmemmap is NULL, then dbName will identify the block */ 814 pCode *pcHead; /* A pointer to the first pCode in a link list of pCodes */ 815 pCode *pcTail; /* A pointer to the last pCode in a link list of pCodes */ 816 817 struct pBlock *next; /* The pBlocks will form a doubly linked list */ 818 struct pBlock *prev; 819 820 set *function_entries; /* dll of functions in this pblock */ 821 set *function_exits; 822 set *function_calls; 823 set *tregisters; 824 825 set *FlowTree; 826 unsigned visited:1; /* set true if traversed in call tree */ 827 828 unsigned seq; /* sequence number of this pBlock */ 829 830 } pBlock; 831 832 /************************************************* 833 pFile 834 835 The collection of pBlock program snippets are 836 placed into a linked list that is implemented 837 in the pFile structure. 838 839 The pcode optimizer will parse the pFile. 840 841 **************************************************/ 842 843 typedef struct pFile 844 { 845 pBlock *pbHead; /* A pointer to the first pBlock */ 846 pBlock *pbTail; /* A pointer to the last pBlock */ 847 848 pBranch *functions; /* A SLL of functions in this pFile */ 849 850 } pFile; 851 852 853 854 /************************************************* 855 pCodeWildBlock 856 857 The pCodeWildBlock object keeps track of the wild 858 variables, operands, and opcodes that exist in 859 a pBlock. 860 **************************************************/ 861 typedef struct pCodeWildBlock { 862 pBlock *pb; 863 struct pCodePeep *pcp; // pointer back to ... I don't like this... 864 865 int nvars; // Number of wildcard registers in target. 866 char **vars; // array of pointers to them 867 868 int nops; // Number of wildcard operands in target. 869 pCodeOp **wildpCodeOps; // array of pointers to the pCodeOp's. 870 871 int nwildpCodes; // Number of wildcard pCodes in target/replace 872 pCode **wildpCodes; // array of pointers to the pCode's. 873 874 } pCodeWildBlock; 875 876 /************************************************* 877 pCodePeep 878 879 The pCodePeep object mimics the peep hole optimizer 880 in the main SDCC src (e.g. SDCCpeeph.c). Essentially 881 there is a target pCode chain and a replacement 882 pCode chain. The target chain is compared to the 883 pCode that is generated by gen.c. If a match is 884 found then the pCode is replaced by the replacement 885 pCode chain. 886 **************************************************/ 887 typedef struct pCodePeep { 888 pCodeWildBlock target; // code we'd like to optimize 889 pCodeWildBlock replace; // and this is what we'll optimize it with. 890 891 //pBlock *target; 892 //pBlock replace; // and this is what we'll optimize it with. 893 894 895 896 /* (Note: a wildcard register is a place holder. Any register 897 * can be replaced by the wildcard when the pcode is being 898 * compared to the target. */ 899 900 /* Post Conditions. A post condition is a condition that 901 * must be either true or false before the peep rule is 902 * accepted. For example, a certain rule may be accepted 903 * if and only if the Z-bit is not used as an input to 904 * the subsequent instructions in a pCode chain. 905 */ 906 unsigned int postFalseCond; 907 unsigned int postTrueCond; 908 909 } pCodePeep; 910 911 /************************************************* 912 913 pCode peep command definitions 914 915 Here are some special commands that control the 916 way the peep hole optimizer behaves 917 918 **************************************************/ 919 920 enum peepCommandTypes{ 921 NOTBITSKIP = 0, 922 BITSKIP, 923 INVERTBITSKIP, 924 _LAST_PEEP_COMMAND_ 925 }; 926 927 /************************************************* 928 peepCommand structure stores the peep commands. 929 930 **************************************************/ 931 932 typedef struct peepCommand { 933 int id; 934 char *cmd; 935 } peepCommand; 936 937 /************************************************* 938 pCode Macros 939 940 **************************************************/ 941 #define PCODE(x) ((pCode *)(x)) 942 #define PCI(x) ((pCodeInstruction *)(x)) 943 #define PCL(x) ((pCodeLabel *)(x)) 944 #define PCF(x) ((pCodeFunction *)(x)) 945 #define PCFL(x) ((pCodeFlow *)(x)) 946 #define PCFLINK(x)((pCodeFlowLink *)(x)) 947 #define PCW(x) ((pCodeWild *)(x)) 948 #define PCCS(x) ((pCodeCSource *)(x)) 949 #define PCAD(x) ((pCodeAsmDir *)(x)) 950 #define PCINF(x) ((pCodeInfo *)(x)) 951 952 #define PCOP(x) ((pCodeOp *)(x)) 953 #define PCOP2(x) ((pCodeOp2 *)(x)) 954 //#define PCOB(x) ((pCodeOpBit *)(x)) 955 #define PCOL(x) ((pCodeOpLit *)(x)) 956 #define PCOI(x) ((pCodeOpImmd *)(x)) 957 #define PCOLAB(x) ((pCodeOpLabel *)(x)) 958 #define PCOR(x) ((pCodeOpReg *)(x)) 959 //#define PCOR2(x) ((pCodeOpReg2 *)(x)) 960 #define PCORB(x) ((pCodeOpRegBit *)(x)) 961 #define PCOO(x) ((pCodeOpOpt *)(x)) 962 #define PCOLR(x) ((pCodeOpLocalReg *)(x)) 963 #define PCOW(x) ((pCodeOpWild *)(x)) 964 #define PCOW2(x) (PCOW(PCOW(x)->pcop2)) 965 #define PBR(x) ((pBranch *)(x)) 966 967 #define PCWB(x) ((pCodeWildBlock *)(x)) 968 969 970 /* 971 macros for checking pCode types 972 */ 973 #define isPCI(x) ((PCODE(x)->type == PC_OPCODE)) 974 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isBranch) 975 #define isPCI_SKIP(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip) 976 #define isPCI_LIT(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isLit) 977 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) && PCI(x)->isSkip && PCI(x)->isBitInst) 978 #define isPCFL(x) ((PCODE(x)->type == PC_FLOW)) 979 #define isPCF(x) ((PCODE(x)->type == PC_FUNCTION)) 980 #define isPCL(x) ((PCODE(x)->type == PC_LABEL)) 981 #define isPCW(x) ((PCODE(x)->type == PC_WILD)) 982 #define isPCCS(x) ((PCODE(x)->type == PC_CSOURCE)) 983 #define isPCAD(x) ((PCODE(x)->type == PC_ASMDIR)) 984 #define isPCINFO(x) ((PCODE(x)->type == PC_INFO)) 985 986 #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) 987 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) 988 #define isBSR_REG(r) ((r)->pc_type == PO_BSR) 989 #define isACCESS_BANK(r) (r->accessBank) 990 991 992 993 #define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) 994 995 /*-----------------------------------------------------------------* 996 * pCode functions. 997 *-----------------------------------------------------------------*/ 998 999 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand 1000 pCode *pic16_newpCodeCharP(const char *cP); // Create a new pCode given a char * 1001 pCode *pic16_newpCodeInlineP(const char *cP); // Create a new pCode given a char * 1002 pCode *pic16_newpCodeFunction(const char *g, const char *f); // Create a new function 1003 pCode *pic16_newpCodeLabel(const char *name,int key); // Create a new label given a key 1004 pCode *pic16_newpCodeLabelFORCE(const char *name, int key); // Same as newpCodeLabel but label cannot be optimized out 1005 pCode *pic16_newpCodeCSource(int ln, const char *f, const char *l); // Create a new symbol line 1006 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc); // Create a new pBlock 1007 void pic16_printpBlock(FILE *of, pBlock *pb); // Write a pBlock to a file 1008 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc); // Add a pCode to a pBlock 1009 void pic16_addpBlock(pBlock *pb); // Add a pBlock to a pFile 1010 void pic16_copypCode(FILE *of, char dbName); // Write all pBlocks with dbName to *of 1011 void pic16_movepBlock2Head(char dbName); // move pBlocks around 1012 void pic16_AnalyzepCode(char dbName); 1013 void pic16_OptimizeLocalRegs(void); 1014 void pic16_AssignRegBanks(void); 1015 void pic16_printCallTree(FILE *of); 1016 void pCodePeepInit(void); 1017 void pic16_pBlockConvert2ISR(pBlock *pb); 1018 void pic16_pBlockConvert2Absolute(pBlock *pb); 1019 void pic16_initDB(void); 1020 void pic16_emitDB(int c, char ptype, void *p); // Add DB directives to a pBlock 1021 void pic16_emitDS(const char *s, char ptype, void *p); 1022 void pic16_flushDB(char ptype, void *p); // Add pending DB data to a pBlock 1023 1024 pCode *pic16_newpCodeAsmDir(const char *asdir, const char *argfmt, ...); 1025 1026 pCodeOp *pic16_newpCodeOpLabel(const char *name, int key); 1027 pCodeOp *pic16_newpCodeOpImmd(const char *name, int offset, int index, int code_space); 1028 pCodeOp *pic16_newpCodeOpLit(int lit); 1029 pCodeOp *pic16_newpCodeOpLit12(int lit); 1030 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2); 1031 pCodeOp *pic16_newpCodeOpBit(const char *name, int bit,int inBitSpace, PIC_OPTYPE subt); 1032 pCodeOp *pic16_newpCodeOpBit_simple (struct asmop *op, int offs, int bit); 1033 pCodeOp *pic16_newpCodeOpRegFromStr(const char *name); 1034 pCodeOp *pic16_newpCodeOpReg(int rIdx); 1035 pCodeOp *pic16_newpCodeOp(const char *name, PIC_OPTYPE p); 1036 pCodeOp *pic16_newpCodeOp2(pCodeOp *src, pCodeOp *dst); 1037 pCodeOp *pic16_newpCodeOpRegNotVect(bitVect *bv); 1038 pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop); 1039 1040 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop); 1041 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, const char *key); 1042 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type); 1043 pCodeOp *pic16_newpCodeOpReg(int rIdx); 1044 1045 pCode * pic16_findNextInstruction(pCode *pci); 1046 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct); 1047 int pic16_isPCinFlow(const pCode *pc, const pCode *pcflow); 1048 struct reg_info * pic16_getRegFromInstruction(pCode *pc); 1049 struct reg_info * pic16_getRegFromInstruction2(pCode *pc); 1050 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size); 1051 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size); 1052 const char *dumpPicOptype(PIC_OPTYPE type); 1053 1054 extern void pic16_pcode_test(void); 1055 extern int pic16_debug_verbose; 1056 extern int pic16_pcode_verbose; 1057 1058 extern const char *LR_TYPE_STR[]; 1059 1060 1061 #ifndef debugf 1062 //#define debugf(frm, rest...) _debugf(__FILE__, __LINE__, frm, rest) 1063 #define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest) 1064 #define debugf2(frm, arg1, arg2) _debugf(__FILE__, __LINE__, frm, arg1, arg2) 1065 #define debugf3(frm, arg1, arg2, arg3) _debugf(__FILE__, __LINE__, frm, arg1, arg2, arg3) 1066 1067 #endif 1068 1069 extern void _debugf(char *f, int l, char *frm, ...); 1070 1071 1072 /*-----------------------------------------------------------------* 1073 * pCode objects. 1074 *-----------------------------------------------------------------*/ 1075 1076 extern pCodeOpReg pic16_pc_status; 1077 extern pCodeOpReg pic16_pc_intcon; 1078 extern pCodeOpReg pic16_pc_pcl; 1079 extern pCodeOpReg pic16_pc_pclath; 1080 extern pCodeOpReg pic16_pc_pclatu; 1081 extern pCodeOpReg pic16_pc_wreg; 1082 extern pCodeOpReg pic16_pc_tosl; 1083 extern pCodeOpReg pic16_pc_tosh; 1084 extern pCodeOpReg pic16_pc_tosu; 1085 extern pCodeOpReg pic16_pc_tblptrl; 1086 extern pCodeOpReg pic16_pc_tblptrh; 1087 extern pCodeOpReg pic16_pc_tblptru; 1088 extern pCodeOpReg pic16_pc_tablat; 1089 extern pCodeOpReg pic16_pc_bsr; 1090 extern pCodeOpReg pic16_pc_fsr0; 1091 extern pCodeOpReg pic16_pc_fsr0l; 1092 extern pCodeOpReg pic16_pc_fsr0h; 1093 extern pCodeOpReg pic16_pc_fsr1l; 1094 extern pCodeOpReg pic16_pc_fsr1h; 1095 extern pCodeOpReg pic16_pc_fsr2l; 1096 extern pCodeOpReg pic16_pc_fsr2h; 1097 extern pCodeOpReg pic16_pc_indf0; 1098 extern pCodeOpReg pic16_pc_postinc0; 1099 extern pCodeOpReg pic16_pc_postdec0; 1100 extern pCodeOpReg pic16_pc_preinc0; 1101 extern pCodeOpReg pic16_pc_plusw0; 1102 extern pCodeOpReg pic16_pc_indf1; 1103 extern pCodeOpReg pic16_pc_postinc1; 1104 extern pCodeOpReg pic16_pc_postdec1; 1105 extern pCodeOpReg pic16_pc_preinc1; 1106 extern pCodeOpReg pic16_pc_plusw1; 1107 extern pCodeOpReg pic16_pc_indf2; 1108 extern pCodeOpReg pic16_pc_postinc2; 1109 extern pCodeOpReg pic16_pc_postdec2; 1110 extern pCodeOpReg pic16_pc_preinc2; 1111 extern pCodeOpReg pic16_pc_plusw2; 1112 extern pCodeOpReg pic16_pc_prodl; 1113 extern pCodeOpReg pic16_pc_prodh; 1114 1115 extern pCodeOpReg pic16_pc_eecon1; 1116 extern pCodeOpReg pic16_pc_eecon2; 1117 extern pCodeOpReg pic16_pc_eedata; 1118 extern pCodeOpReg pic16_pc_eeadr; 1119 1120 extern pCodeOpReg pic16_pc_kzero; 1121 extern pCodeOpReg pic16_pc_wsave; /* wsave and ssave are used to save W and the Status */ 1122 extern pCodeOpReg pic16_pc_ssave; /* registers during an interrupt */ 1123 1124 extern pCodeOpReg *pic16_stackpnt_lo; 1125 extern pCodeOpReg *pic16_stackpnt_hi; 1126 extern pCodeOpReg *pic16_stack_postinc; 1127 extern pCodeOpReg *pic16_stack_postdec; 1128 extern pCodeOpReg *pic16_stack_preinc; 1129 extern pCodeOpReg *pic16_stack_plusw; 1130 1131 extern pCodeOpReg *pic16_framepnt_lo; 1132 extern pCodeOpReg *pic16_framepnt_hi; 1133 extern pCodeOpReg *pic16_frame_postinc; 1134 extern pCodeOpReg *pic16_frame_postdec; 1135 extern pCodeOpReg *pic16_frame_preinc; 1136 extern pCodeOpReg *pic16_frame_plusw; 1137 1138 extern pCodeOpReg pic16_pc_gpsimio; 1139 extern pCodeOpReg pic16_pc_gpsimio2; 1140 1141 #endif // __PCODE_H__ 1142