📄 flowc30.c
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989 starting an 68000 C compiler, starting with material * originally by M. Brandt * 1990 68000 C compiler further bug fixes * started i386 port (December) * 1991 i386 port finished (January) * further corrections in the front end and in the 68000 * code generator. * The next port will be a SPARC port * * 1995 Ivo Oesch, Started to build a codegenerator for the * signalprocessor TMS320C30 (December) * * Examines dataflow and checks if data is already in a register * when read-accesses to external ram occurs * needs multiple-passes to work *//*****************************************************************************/#include "config.h"#ifdef PEEPFLOW#ifdef TMS320C30#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genc30.h"#include "outproto.h"/********************************************************* Macro Definitions */#define ENHANCED_FLOW/*****************************************************************************/#ifdef DEBUG/* * To print out the Regusage into assembler-output * Just to check if everything works as I thought */static void print_flowlist P1 (FLOWLISTENTRY *, list){ FLOWLISTENTRY *p; for (p = list; p != NULL; p = p->next) { putamode_tst (p->ap);#ifdef NO_MIX_WITH_FLOAT if (p->type == OP_FLOAT) { dprintf (DEBUG_FLOW, " [F]; "); } else { dprintf (DEBUG_FLOW, " [I]; "); }#else dprintf (DEBUG_FLOW, "; ");#endif }}/* * To to print out the Regusage into assembler-output * Just to check if everything works as I thought */static void print_regusage P1 (FLOWLISTENTRY **, RegUsage){ REG reg; for (reg = REG_R0; reg <= MAX_REG; reg++) { if (RegUsage[reg] != NULL) { putreg_tst (reg); dprintf (DEBUG_FLOW, ": "); print_flowlist (RegUsage[reg]); dprintf (DEBUG_FLOW, "\n"); } }}#endif /* DEBUG *//* * Searchs the address 'ap' in the flowlist 'head' and and * returns a pointer to it (or NULL if not found) */static FLOWLISTENTRY *search_flowlist_entry P3 (FLOWLISTENTRY *, head, ADDRESS *, ap, ITYPE, type){ FLOWLISTENTRY *p;#ifdef NO_MIX_WITH_FLOAT ITYPE TypeOfThisList; if (head != NULL) { TypeOfThisList = head->type; }#endif for (p = head; p != NULL; p = p->next) {#ifdef NO_MIX_WITH_FLOAT if (TypeOfThisList != p->type) { FATAL ( (__FILE__, "search_flowlist_entry", "mixed int and float in list")); }#endif if (is_equal_address (p->ap, ap)) {#ifdef NO_MIX_WITH_FLOAT if (p->type == type) { return p; }#else return p;#endif } } return NULL;}/* * Adds the address 'ap' to the flowlist of register 'reg' in regusage * unsuitable 'ap's and double-entries are supressed */static void add_flow_list P4 (FLOWLISTENTRY **, RegUsage, REG, reg, ADDRESS *, ap, ITYPE, type){ FLOWLISTENTRY *Entry; ADDRESS *ap1; IVAL offset; if ((ap->mode == am_ainc) || (ap->mode == am_adec)) { /* ainc could be treated as am_indx with offset = -increment * in list, sinc addressregister points increment farther than * value was written * except it was stored with itself (arn, *arn++) */ if ((ap->preg == reg) || (ap->u.offset->nodetype != en_icon)) { return; } ap1 = copy_addr (ap, am_indx); offset = (ap->mode == am_ainc) ? -ap->u.offset->v.i : ap->u.offset->v.i; ap1->u.offset = mk_const ((long) offset); ap = ap1; } if ((ap->mode == am_preinc) || (ap->mode == am_predec)) { /* preinc could be treated as am_ind in list, sinc * addressregister points still to the same location * except it was stored with itself (arn, *++arn) */ if (ap->preg == reg) { return; } ap = copy_addr (ap, am_ind); } /* * check if equivalent entry is already in list */ if (search_flowlist_entry (*RegUsage, ap, type) == NULL) { Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY)); Entry->ap = ap;#ifdef NO_MIX_WITH_FLOAT Entry->type = type;#endif Entry->next = *RegUsage; *RegUsage = Entry; }}/* * adds the flowlist 'dest' to the flowlist '*regusage', double- * entries are supressed */static void add_list_to_flow_list P2 (FLOWLISTENTRY **, RegUsage, FLOWLISTENTRY *, src){ FLOWLISTENTRY *Entry; FLOWLISTENTRY *p; for (p = src; p != NULL; p = p->next) { /* * check if equivalent entry is already in list */ if (search_flowlist_entry (*RegUsage, p->ap, p->type) == NULL) { Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY)); Entry->ap = p->ap;#ifdef NO_MIX_WITH_FLOAT Entry->type = p->type;#endif Entry->next = *RegUsage; *RegUsage = Entry; } }}/* * clears the ap-list of the register reg and adds the entry ap * if it is suitable (not if it refers to our own register) * (ldi *ar2, ar2, ar2 is changed during the operation) * autoincrements are also not suitable, they never point * to the same value the next time */static void new_flow_list P4 (FLOWLISTENTRY **, RegUsage, REG, reg, ADDRESS *, ap, ITYPE, type){ FLOWLISTENTRY *Entry; ADDRESS *ap1; IVAL offset; switch (ap->mode) { case am_indx2: case am_indxs: if (ap->sreg == reg) { *RegUsage = NULL; return; } /*FALLTHRU */ case am_ind: case am_const_ind: case am_indx: if (ap->preg == reg) { *RegUsage = NULL; return; } break; case am_preinc: case am_predec: /* * preinc could be treated as am_ind in list, sinc * addressregister points still to the same location * except it was loaded with itself (*++arn, arn) */ if (ap->preg == reg) { *RegUsage = NULL; return; } ap = copy_addr (ap, am_ind); break; case am_ainc: case am_adec: /* * ainc could be treated as am_indx with offset = -increment * in list, sinc addressregister points increment farther than * value was written * except it was loaded with itself (*arn++, arn) */ if ((ap->preg == reg) || (ap->u.offset->nodetype != en_icon)) { *RegUsage = NULL; return; } ap1 = copy_addr (ap, am_indx); offset = (ap->mode == am_ainc) ? -ap->u.offset->v.i : ap->u.offset->v.i; ap1->u.offset = mk_const (offset); ap = ap1; break; default: break; } Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY)); Entry->ap = ap;#ifdef NO_MIX_WITH_FLOAT Entry->type = type;#endif Entry->next = NULL; *RegUsage = Entry;}/* * Generates a duplicate of the delivered flowlist * and returns a pointer to it */static FLOWLISTENTRY *copy_flow_list P1 (FLOWLISTENTRY *, List){ FLOWLISTENTRY *NewList = NULL; FLOWLISTENTRY *Entry = NULL; FLOWLISTENTRY *p; for (p = List; p != NULL; p = p->next) { Entry = (FLOWLISTENTRY *) xalloc ((size_t) sizeof (FLOWLISTENTRY)); Entry->ap = p->ap;#ifdef NO_MIX_WITH_FLOAT Entry->type = p->type;#endif Entry->next = NewList; NewList = Entry; } return NewList;}/* * Only entries contained in both lists are delivered back in dest * (the biggest common set is returned in dest) * * Returns the amount of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int merge_flow_list P2 (FLOWLISTENTRY **, dest, FLOWLISTENTRY *, src){ FLOWLISTENTRY *Last = NULL; FLOWLISTENTRY *p; int changes = 0; for (p = *dest; p != NULL; p = p->next) { if (search_flowlist_entry (src, p->ap, p->type) == NULL) { changes++; if (Last == NULL) { *dest = p->next; } else { Last->next = p->next; } } Last = p; } return changes;}/* * removes all entries from dest-flowlist which references * register reg in any way * REG_MEMORY is a pseudo-reg and means any memory-access */static void remove_from_flowlist P2 (FLOWLISTENTRY **, dest, REG, reg){ FLOWLISTENTRY *Last = NULL; FLOWLISTENTRY *p; if (reg == REG_MEMORY) { for (p = *dest; p != NULL; p = p->next) { if ((p->ap->mode == am_indx) || (p->ap->mode == am_ind) /* || (p->ap->mode == am_const_ind) */ || (p->ap->mode == am_direct) /* || (p->ap->mode == am_const_direct) */ || (p->ap->mode == am_ainc) || (p->ap->mode == am_adec) || (p->ap->mode == am_preinc) || (p->ap->mode == am_predec) || (p->ap->mode == am_indx2) || (p->ap->mode == am_indxs)) { if (Last == NULL) { *dest = p->next; } else { Last->next = p->next; } } Last = p; } } else { for (p = *dest; p != NULL; p = p->next) { if (is_register_used (reg, p->ap)) { if (Last == NULL) { *dest = p->next; } else { Last->next = p->next; } } Last = p; } }}/* * clears the whole regusage-list */static void clear_regusage P1 (FLOWLISTENTRY **, RegUsage){ REG reg; for (reg = REG_R0; reg <= MAX_REG; reg++) { RegUsage[reg] = NULL; }}/* * Searchs if any register already contains the value corresponding * to ap. if a register is found, its number is returned, otherewise * -1 is returnned */static REG search_in_regusage P3 (FLOWLISTENTRY **, RegUsage, ADDRESS *, ap, ITYPE, type){ REG reg; for (reg = REG_R0; reg <= MAX_REG; reg++) { if (search_flowlist_entry (RegUsage[reg], ap, type) != NULL) { return reg; } } return NO_REG;}/* * Produces a copy of an registerusage-list and returns a pointer to it */static FLOWLISTENTRY **copy_regusage P1 (FLOWLISTENTRY **, RegUsage){ FLOWLISTENTRY **NewRegUsage; FLOWLISTENTRY **p; REG reg; NewRegUsage = (FLOWLISTENTRY **) xalloc ((size_t) sizeof (FLOWLISTENTRY * [MAX_REG + 1])); for (reg = REG_R0, p = NewRegUsage; reg <= MAX_REG; reg++, p++) { *p = copy_flow_list (RegUsage[reg]); } return NewRegUsage;}/* * Merges the biggest common registerusage-set from dst and src * into src * * Returns the amount of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */static int merge_regusage P2 (FLOWLISTENTRY **, dest, FLOWLISTENTRY **, src){ REG reg; int changes = 0; for (reg = REG_R0; reg <= MAX_REG; reg++) { changes += merge_flow_list (&(dest[reg]), src[reg]); } return changes;}/* * Removes all references to and from register reg */static void remove_from_regusage P2 (FLOWLISTENTRY **, RegUsage, REG, reg){ REG r; if (reg != REG_MEMORY) { RegUsage[reg] = NULL; } for (r = REG_R0; r <= MAX_REG; r++) { remove_from_flowlist (&(RegUsage[r]), reg); }}/* * Removes all references to and from all temporary registers */static void clear_tempreg_usage P1 (FLOWLISTENTRY **, RegUsage){ REG reg; for (reg = REG_R0; reg <= MAX_DATA; reg++) { RegUsage[reg] = NULL; remove_from_regusage (RegUsage, reg); } for (reg = REG_AR0; reg <= MAX_ADDR; reg++) { RegUsage[reg] = NULL; remove_from_regusage (RegUsage, reg); }}/* * Attachs the Regusagelist to the Label which is destination of * ip (ip must be jump or branch) * The usagelist of the label is corrected to the biggest common set * of regusage and the old List of the label. * * Returns the amount of changes which have been done. * Is needed for the multipass, we are looping through the code * until no more changes are done */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -