X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fpcode.c;h=1ffd594317409e08e54bf5311e032fa30e82b8f5;hb=bf67f8d705935961d3758f9735e5f528141a47be;hp=9b1da5cdbcff4a87ad1ed273a8527e8ab9fade69;hpb=e1a36b606f3b7c5fd7ef85cd16a8bba1db9fb984;p=fw%2Fsdcc diff --git a/src/pic16/pcode.c b/src/pic16/pcode.c index 9b1da5cd..1ffd5943 100644 --- a/src/pic16/pcode.c +++ b/src/pic16/pcode.c @@ -32,6 +32,8 @@ #include "ralloc.h" #include "device.h" +extern char *pic16_aopGet (struct asmop *aop, int offset, bool bit16, bool dname); + #if defined(__BORLANDC__) || defined(_MSC_VER) #define STRCASECMP stricmp #define inline @@ -4224,6 +4226,12 @@ pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt) return pcop; } +pCodeOp *pic16_newpCodeOpBit_simple (struct asmop *op, int offs, int bit) +{ + return pic16_newpCodeOpBit (pic16_aopGet(op,offs,FALSE,FALSE), + bit, 0, PO_GPR_REGISTER); +} + /*-----------------------------------------------------------------* * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register @@ -5029,7 +5037,14 @@ char *pic16_pCode2str(char *str, size_t size, pCode *pc) // fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n", // __FUNCTION__, __LINE__, r, (r)?r->name:"", (r)?r->accessBank:-1); - if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED")); + if(PCI(pc)->isAccess) { + static char *bank_spec[2][2] = { + { "", ", ACCESS" }, /* gpasm uses access bank by default */ + { ", B", ", BANKED" }/* MPASM (should) use BANKED by default */ + }; + + SAFE_snprintf(&s,&size,"%s", bank_spec[(r && !r->accessBank) ? 1 : 0][pic16_mplab_comp ? 1 : 0]); + } } // @@ -9689,6 +9704,18 @@ static defmap_t *copyDefmap (defmap_t *map) { return res; } +/* Insert a defmap item after the specified one. */ +static int defmapInsertAfter (defmap_t *ref, defmap_t *newItem) { + if (!ref || !newItem) return 1; + + newItem->next = ref->next; + newItem->prev = ref; + ref->next = newItem; + if (newItem->next) newItem->next->prev = newItem; + + return 0; +} + /* Check whether item (or an identical one) is already in the chain and add it if neccessary. * item is copied before insertion into chain and therefore left untouched. * Returns 1 iff the item has been inserted into the list, 0 otherwise. */ @@ -9899,18 +9926,18 @@ typedef struct stack_s { struct stack_s *next; } stackitem_t; -typedef stackitem_t *stack_t; +typedef stackitem_t *dynstack_t; static stackitem_t *free_stackitems = NULL; /* Create a stack with one item. */ -static stack_t *newStack () { - stack_t *s = (stack_t *) Safe_malloc (sizeof (stack_t)); +static dynstack_t *newStack () { + dynstack_t *s = (dynstack_t *) Safe_malloc (sizeof (dynstack_t)); *s = NULL; return s; } /* Remove a stack -- its items are only marked free. */ -static void deleteStack (stack_t *s) { +static void deleteStack (dynstack_t *s) { stackitem_t *i; while (*s) { @@ -9933,7 +9960,7 @@ static void releaseStack () { } // while } -static void stackPush (stack_t *stack, void *data) { +static void stackPush (dynstack_t *stack, void *data) { stackitem_t *i; if (free_stackitems) { @@ -9947,7 +9974,7 @@ static void stackPush (stack_t *stack, void *data) { *stack = i; } -static void *stackPop (stack_t *stack) { +static void *stackPop (dynstack_t *stack) { void *data; stackitem_t *i; @@ -9964,7 +9991,7 @@ static void *stackPop (stack_t *stack) { } #if 0 -static int stackContains (stack_t *s, void *data) { +static int stackContains (dynstack_t *s, void *data) { stackitem_t *i; if (!s) return 0; i = *s; @@ -9978,7 +10005,7 @@ static int stackContains (stack_t *s, void *data) { } #endif -static int stackIsEmpty (stack_t *s) { +static int stackIsEmpty (dynstack_t *s) { return (*s == NULL); } @@ -9999,7 +10026,7 @@ static void deleteState (state_t *s) { Safe_free (s); } -static int stateIsNew (state_t *state, stack_t *todo, stack_t *done) { +static int stateIsNew (state_t *state, dynstack_t *todo, dynstack_t *done) { stackitem_t *i; /* scan working list for state */ @@ -10086,8 +10113,8 @@ static int defmapFindAll (symbol_t sym, pCode *pc, defmap_t **chain) { pCodeFlow *curr; pCodeFlowLink *succ; state_t *state; - stack_t *todo; /** stack of state_t */ - stack_t *done; /** stack of state_t */ + dynstack_t *todo; /** stack of state_t */ + dynstack_t *done; /** stack of state_t */ int firstState, n_defs; @@ -10441,7 +10468,7 @@ int pic16_isAliveInFlow (symbol_t sym, int mask, pCodeFlow *pcfl, pCode *pc) { static int pic16_isAlive (symbol_t sym, pCode *pc) { int mask, visit; defmap_t *map; - stack_t *todo, *done; + dynstack_t *todo, *done; state_t *state; pCodeFlow *pcfl; pCodeFlowLink *succ; @@ -10796,7 +10823,40 @@ static symbol_t pic16_fsrsym_idx[][2] = { {SPO_FSR1L, SPO_FSR1H}, {SPO_FSR2L, SPO_FSR2H} }; - + +/* Merge multiple defmap entries for the same symbol for list's pCode. */ +static void mergeDefmapSymbols (defmap_t *list) { + defmap_t *ref, *curr, *temp; + + /* now make sure that each symbol occurs at most once per pc */ + ref = list; + while (ref && (ref->pc == list->pc)) { + curr = ref->next; + while (curr && (curr->pc == list->pc)) { + if (curr->sym == ref->sym) { + //fprintf (stderr, "Merging defmap entries for symbol %s\n", strFromSym (ref->sym)); + /* found a symbol occuring twice... merge the two */ + if (curr->acc.access.isRead) { + //if (ref->acc.access.isRead) fprintf (stderr, "symbol %s was marked twice as read at pc %p\n", strFromSym (ref->sym), ref->pc); + ref->acc.access.isRead = 1; + ref->acc.access.in_mask |= curr->acc.access.in_mask; + } + if (curr->acc.access.isWrite) { + //if (ref->acc.access.isWrite) fprintf (stderr, "symbol %s was marked twice as written at pc %p\n", strFromSym (ref->sym), ref->pc); + ref->acc.access.isWrite = 1; + ref->acc.access.mask |= curr->acc.access.mask; + } + temp = curr; + curr = curr->next; + deleteDefmap (temp); + continue; // do not skip curr! + } // if + curr = curr->next; + } // while + ref = ref->next; + } // while +} + /** Prepend list with the reads and definitions performed by pc. */ static defmap_t *createDefmap (pCode *pc, defmap_t *list) { pCodeInstruction *pci; @@ -10949,7 +11009,7 @@ static defmap_t *createDefmap (pCode *pc, defmap_t *list) { list = newDefmap (symFromStr ("WREG"), mask, mask, inCond & PCC_W, outCond & PCC_W, pc, newValnum (), list); } // if - /* keep STATUS read BEFORE STATUS write in the list */ + /* keep STATUS read BEFORE STATUS write in the list (still neccessary?) */ if (inCond & PCC_STATUS) { smask = 0; if (inCond & PCC_C) smask |= 1U << PIC_C_BIT; @@ -10993,6 +11053,8 @@ static defmap_t *createDefmap (pCode *pc, defmap_t *list) { /* make sure there is at least one entry for each pc (needed by list traversal routines) */ list = newDefmap (0, 0x00, 0x00, 0, 0, pc, 0, list); + + mergeDefmapSymbols (list); return list; } @@ -11331,17 +11393,44 @@ void pic16_fixDefmap (pCode *pc, pCode *newpc) { } // while } -void defmapReplaceSymRef (pCode *pc, symbol_t sym, symbol_t newsym) { - defmap_t *map; +/* Replace a defmap entry for sym with newsym for read accesses (isRead == 1) or + * write accesses (isRead == 0). */ +void defmapReplaceSymRef (pCode *pc, symbol_t sym, symbol_t newsym, int isRead) { + defmap_t *map, *map_start; + defmap_t *copy; if (!isPCI(pc)) return; + if (sym == newsym) return; map = PCI(pc)->pcflow->defmap; while (map && map->pc != pc) map = map->next; + map_start = map; while (map && map->pc == pc) { - if (map->sym == sym) map->sym = newsym; + if (map->sym == sym) { + assert ((isRead && map->acc.access.isRead) || ((!isRead) && (map->acc.access.isWrite))); + if (!(map->acc.access.isRead && map->acc.access.isWrite)) { + /* only one kind of access handled... this is easy */ + map->sym = newsym; + } else { + /* must copy defmap entry before replacing symbol... */ + copy = copyDefmap (map); + if (isRead) { + map->acc.access.isRead = 0; + copy->acc.access.isWrite = 0; + } else { + map->acc.access.isWrite = 0; + copy->acc.access.isRead = 0; + } + copy->sym = newsym; + /* insert copy into defmap chain */ + defmapInsertAfter (map, copy); + } + } map = map->next; } // while + + /* as this might introduce multiple defmap entries for newsym... */ + mergeDefmapSymbols (map_start); } /* Assign "better" valnums to results. */ @@ -11533,14 +11622,18 @@ static void assignValnums (pCode *pc) { } if (pic16_debug_verbose || pic16_pcode_verbose) pic16_InsertCommentAfter (pc->prev, "=DF= MOVWF: replaced by CLRF/SETF"); pic16_pCodeReplace (pc, newpc); - defmapReplaceSymRef (pc, SPO_WREG, 0); + defmapReplaceSymRef (pc, SPO_WREG, 0, 1); pic16_fixDefmap (pc, newpc); pc = newpc; /* This breaks the defmap chain's references to pCodes... fix it! */ if (!val->prev) PCI(pc)->pcflow->defmap = val->next; - deleteDefmap (val); // delete reference to WREG as in value - val = NULL; + if (!val->acc.access.isWrite) { + deleteDefmap (val); // delete reference to WREG as in value + val = NULL; + } else { + val->acc.access.isRead = 0; // delete reference to WREG as in value + } oldval = PCI(pc)->pcflow->defmap; while (oldval) { if (oldval->pc == pc) oldval->pc = newpc; @@ -11586,7 +11679,7 @@ static void assignValnums (pCode *pc) { pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: replaced by CRLF/SETF"); pic16_df_saved_bytes += PCI(pc)->isize - PCI(newpc)->isize; pic16_pCodeReplace (pc, newpc); - defmapReplaceSymRef (pc, sym1, 0); + defmapReplaceSymRef (pc, sym1, 0, 1); pic16_fixDefmap (pc, newpc); pc = newpc; break; // do not process instruction as MOVFF... @@ -11627,7 +11720,7 @@ static void assignValnums (pCode *pc) { pic16_df_saved_bytes += PCI(pc)->isize - PCI(newpc)->isize; pic16_pCodeReplace (pc, newpc); assert (val->sym == sym1 && val->acc.access.isRead && !val->acc.access.isWrite); - defmapReplaceSymRef (pc, sym1, copy->sym); + defmapReplaceSymRef (pc, sym1, copy->sym, 1); pic16_fixDefmap (pc, newpc); pc = newpc; }