- pCodeOp *pcop;
-
- pcop = newpCodeOpBit(pc->name, bitval, 0);
-
- if( !( (pcop->type == PO_LABEL) ||
- (pcop->type == PO_LITERAL) ||
- (pcop->type == PO_STR) ))
- PCOR(pcop)->r = PCOR(pc)->r; /* This is dangerous... */
-
- return pcop;
-}
-
-
-
-#if 0
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-int InstructionRegBank(pCode *pc)
-{
- regs *reg;
-
- if( (reg = getRegFromInstruction(pc)) == NULL)
- return -1;
-
- return REG_BANK(reg);
-
-}
-#endif
-
-/*-----------------------------------------------------------------*/
-/*-----------------------------------------------------------------*/
-void FixRegisterBanking(pBlock *pb)
-{
- pCode *pc=NULL;
- pCode *pcprev=NULL;
- pCode *new_pc;
-
- int cur_bank;
- regs *reg;
- // return;
- if(!pb)
- return;
-
- //pc = findNextpCode(pb->pcHead, PC_FLOW);
- pc = findNextpCode(pb->pcHead, PC_OPCODE);
- if(!pc)
- return;
- /* loop through all of the flow blocks with in one pblock */
-
- //fprintf(stderr,"Register banking\n");
- cur_bank = 0;
- do {
- /* at this point, pc should point to a PC_FLOW object */
-
-
- /* for each flow block, determine the register banking
- requirements */
-
- // do {
- if(isPCI(pc)) {
- //genericPrint(stderr, pc);
-
- reg = getRegFromInstruction(pc);
- #if 0
- if(reg) {
- fprintf(stderr, " %s ",reg->name);
- fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
-
- }
- #endif
- if(reg && REG_BANK(reg)!=cur_bank) {
- /* Examine the instruction before this one to make sure it is
- * not a skip type instruction */
- pcprev = findPrevpCode(pc->prev, PC_OPCODE);
- if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
- int b = cur_bank ^ REG_BANK(reg);
-
- //fprintf(stderr, "Cool! can switch banks\n");
- cur_bank = REG_BANK(reg);
- if(b & 1) {
- new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
- popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
- pCodeInsertAfter(pc->prev, new_pc);
- if(PCI(pc)->label) {
- PCI(new_pc)->label = PCI(pc)->label;
- PCI(pc)->label = NULL;
- }
- /*
- new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
- popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
- pCodeInsertAfter(pc, new_pc);
- */
-
- }
-
- } else {
- //fprintf(stderr, "Bummer can't switch banks\n");
- ;
- }
- }
- }
-
- pcprev = pc;
- pc = pc->next;
- // } while(pc && !(isPCFL(pc)));
-
-
- }while (pc);
-
- if(pcprev && cur_bank) {
- /* Brute force - make sure that we point to bank 0 at the
- * end of each flow block */
- new_pc = newpCode(POC_BCF,
- popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
- pCodeInsertAfter(pcprev, new_pc);
- cur_bank = 0;
- }
-
-}
-
-void pBlockDestruct(pBlock *pb)
-{
-
- if(!pb)
- return;
-
-
- free(pb);
-
-}
-
-/*-----------------------------------------------------------------*/
-/* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
-/* name dbName and combine them */
-/* into one block */
-/*-----------------------------------------------------------------*/
-void mergepBlocks(char dbName)
-{
-
- pBlock *pb, *pbmerged = NULL,*pbn;
-
- pb = the_pFile->pbHead;
-
- //fprintf(stderr," merging blocks named %c\n",dbName);
- while(pb) {
-
- pbn = pb->next;
- //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
- if( getpBlock_dbName(pb) == dbName) {
-
- //fprintf(stderr," merged block %c\n",dbName);
-
- if(!pbmerged) {
- pbmerged = pb;
- } else {
- addpCode2pBlock(pbmerged, pb->pcHead);
- /* addpCode2pBlock doesn't handle the tail: */
- pbmerged->pcTail = pb->pcTail;
-
- pb->prev->next = pbn;
- if(pbn)
- pbn->prev = pb->prev;
-
-
- pBlockDestruct(pb);
- }
- //printpBlock(stderr, pbmerged);
- }
- pb = pbn;
- }
-
-}
-
-/*-----------------------------------------------------------------*/
-/* AnalyzeBanking - Called after the memory addresses have been */
-/* assigned to the registers. */
-/* */
-/*-----------------------------------------------------------------*/
-void AnalyzeBanking(void)
-{
-
- pBlock *pb;
-
- if(!the_pFile)
- return;
-
-
- /* Phase 2 - Flow Analysis - Register Banking
- *
- * In this phase, the individual flow blocks are examined
- * and register banking is fixed.
- */
-
- //for(pb = the_pFile->pbHead; pb; pb = pb->next)
- //FixRegisterBanking(pb);
-
- /* Phase 2 - Flow Analysis
- *
- * In this phase, the pCode is partition into pCodeFlow
- * blocks. The flow blocks mark the points where a continuous
- * stream of instructions changes flow (e.g. because of
- * a call or goto or whatever).
- */
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next)
- BuildFlow(pb);
-
-
- /* Phase 2 - Flow Analysis - linking flow blocks
- *
- * In this phase, the individual flow blocks are examined
- * to determine their order of excution.
- */
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next)
- LinkFlow(pb);
-
-
- /* Phase x - Flow Analysis - Used Banks
- *
- * In this phase, the individual flow blocks are examined
- * to determine the Register Banks they use
- */
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next)
- BanksUsedFlow(pb);
-
- /* Phase x - Flow Analysis - Used Banks
- *
- * In this phase, the individual flow blocks are examined
- * to determine the Register Banks they use
- */
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next)
- FixBankFlow(pb);
-
-/*
- for(pb = the_pFile->pbHead; pb; pb = pb->next)
- DumpFlow(pb);
-*/
- /* debug stuff */
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- pCode *pcflow;
- for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
- (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
- pcflow = pcflow->next) {
-
- FillFlow(PCFL(pcflow));
- }
- }
-/*
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- pCode *pcflow;
- for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
- (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
- pcflow = pcflow->next) {
-
- FlowStats(PCFL(pcflow));
- }
- }
-*/
-}
-
-/*-----------------------------------------------------------------*/
-/* buildCallTree - look at the flow and extract all of the calls */
-/* */
-/*-----------------------------------------------------------------*/
-set *register_usage(pBlock *pb);
-
-void buildCallTree(void )
-{
- pBranch *pbr;
- pBlock *pb;
- pCode *pc;
-
- if(!the_pFile)
- return;
-
-
-
- /* Now build the call tree.
- First we examine all of the pCodes for functions.
- Keep in mind that the function boundaries coincide
- with pBlock boundaries.
-
- The algorithm goes something like this:
- We have two nested loops. The outer loop iterates
- through all of the pBlocks/functions. The inner
- loop iterates through all of the pCodes for
- a given pBlock. When we begin iterating through
- a pBlock, the variable pc_fstart, pCode of the start
- of a function, is cleared. We then search for pCodes
- of type PC_FUNCTION. When one is encountered, we
- initialize pc_fstart to this and at the same time
- associate a new pBranch object that signifies a
- branch entry. If a return is found, then this signifies
- a function exit point. We'll link the pCodes of these
- returns to the matching pc_fstart.
-
- When we're done, a doubly linked list of pBranches
- will exist. The head of this list is stored in
- `the_pFile', which is the meta structure for all
- of the pCode. Look at the printCallTree function
- on how the pBranches are linked together.
-
- */
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- pCode *pc_fstart=NULL;
- for(pc = pb->pcHead; pc; pc = pc->next) {
- if(isPCF(pc)) {
- if (PCF(pc)->fname) {
-
- if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
- //fprintf(stderr," found main \n");
- pb->cmemmap = NULL; /* FIXME do we need to free ? */
- pb->dbName = 'M';
- }
-
- pbr = Safe_calloc(1,sizeof(pBranch));
- pbr->pc = pc_fstart = pc;
- pbr->next = NULL;
-
- the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
-
- // Here's a better way of doing the same:
- addSet(&pb->function_entries, pc);
-
- } else {
- // Found an exit point in a function, e.g. return
- // (Note, there may be more than one return per function)
- if(pc_fstart)
- pBranchLink(PCF(pc_fstart), PCF(pc));
-
- addSet(&pb->function_exits, pc);
- }
- } else if(isCALL(pc)) {
- addSet(&pb->function_calls,pc);
- }
- }
- }
-
- /* Re-allocate the registers so that there are no collisions
- * between local variables when one function call another */
-
- pic14_deallocateAllRegs();
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- if(!pb->visited)
- register_usage(pb);
- }
-
-}
-
-/*-----------------------------------------------------------------*/
-/* AnalyzepCode - parse the pCode that has been generated and form */
-/* all of the logical connections. */
-/* */
-/* Essentially what's done here is that the pCode flow is */
-/* determined. */
-/*-----------------------------------------------------------------*/
-
-void AnalyzepCode(char dbName)
-{
- pBlock *pb;
- int i,changes;
-
- if(!the_pFile)
- return;
-
- mergepBlocks('D');
-
-
- /* Phase 1 - Register allocation and peep hole optimization
- *
- * The first part of the analysis is to determine the registers
- * that are used in the pCode. Once that is done, the peep rules
- * are applied to the code. We continue to loop until no more
- * peep rule optimizations are found (or until we exceed the
- * MAX_PASSES threshold).
- *
- * When done, the required registers will be determined.
- *
- */
- i = 0;
- do {
-
- DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
- //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
-
- /* First, merge the labels with the instructions */
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
- if('*' == dbName || getpBlock_dbName(pb) == dbName) {
-
- DFPRINTF((stderr," analyze and merging block %c\n",dbName));
- //fprintf(stderr," analyze and merging block %c\n",dbName);
- pBlockMergeLabels(pb);
- AnalyzepBlock(pb);
- } else {
- DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
- }
- }
-
- changes = OptimizepCode(dbName);
-
- } while(changes && (i++ < MAX_PASSES));
-
- buildCallTree();
-}
-
-/*-----------------------------------------------------------------*/
-/* ispCodeFunction - returns true if *pc is the pCode of a */
-/* function */
-/*-----------------------------------------------------------------*/
-bool ispCodeFunction(pCode *pc)
-{
-
- if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
- return 1;
-
- return 0;
-}
-
-/*-----------------------------------------------------------------*/
-/* findFunction - Search for a function by name (given the name) */
-/* in the set of all functions that are in a pBlock */
-/* (note - I expect this to change because I'm planning to limit */
-/* pBlock's to just one function declaration */
-/*-----------------------------------------------------------------*/
-pCode *findFunction(char *fname)
-{
- pBlock *pb;
- pCode *pc;
- if(!fname)
- return NULL;
-
- for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-
- pc = setFirstItem(pb->function_entries);
- while(pc) {
-
- if((pc->type == PC_FUNCTION) &&
- (PCF(pc)->fname) &&
- (strcmp(fname, PCF(pc)->fname)==0))
- return pc;
-
- pc = setNextItem(pb->function_entries);
-
- }
-
- }
- return NULL;
-}
-
-void MarkUsedRegisters(set *regset)
-{
-
- regs *r1,*r2;
-
- for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
- r2 = pic14_regWithIdx(r1->rIdx);
- r2->isFree = 0;
- r2->wasUsed = 1;
- }
-}
-
-void pBlockStats(FILE *of, pBlock *pb)
-{
-
- pCode *pc;
- regs *r;
-
- fprintf(of,";***\n; pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
-
- // for now just print the first element of each set
- pc = setFirstItem(pb->function_entries);
- if(pc) {
- fprintf(of,";entry: ");
- pc->print(of,pc);
- }
- pc = setFirstItem(pb->function_exits);
- if(pc) {
- fprintf(of,";has an exit\n");
- //pc->print(of,pc);
- }
-
- pc = setFirstItem(pb->function_calls);
- if(pc) {
- fprintf(of,";functions called:\n");
-
- while(pc) {
- if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
- fprintf(of,"; %s\n",get_op_from_instruction(PCI(pc)));
- }
- pc = setNextItem(pb->function_calls);
- }
- }
-
- r = setFirstItem(pb->tregisters);
- if(r) {
- int n = elementsInSet(pb->tregisters);
-
- fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
-
- while (r) {
- fprintf(of,"; %s\n",r->name);
- r = setNextItem(pb->tregisters);
- }
- }