⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 genc30.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	if ((floatmask & MEMBER (reg)) != 0) {	    g_code (op_pushfnopeep, OP_FLOAT, mk_reg (reg), NIL_ADDRESS);	}    }}/* * pop all registers in the masks from the stack. */static void pop_registers P2 (REGMASK, mask, REGMASK, floatmask){    REG     reg;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	/* Check which registers are set in mask */	if ((floatmask & MEMBER (reg)) != 0) {	    g_code (op_popf, OP_FLOAT, NIL_ADDRESS, mk_reg (reg));	}	if ((mask & MEMBER (reg)) != 0) {	    g_code (op_pop, OP_INT, NIL_ADDRESS, mk_reg (reg));	}    }}/* * reads all register in the mask from the stack * this version does not use pop, but indeed address based on framepointer * and offset of the pushed registers from framepointer * generates in some cases faster code than poped version * since sp must not be set correctly as in the pop-variant */static void pop_fast_registers P3 (REGMASK, mask, REGMASK, floatmask, IVAL,				   offset){    REG     reg;    ADDRESS *ap;    for (reg = REG_R0; reg <= MAX_REG; reg++) {	/* Check which registers are set in mask */	if ((floatmask & MEMBER (reg)) != 0) {	    ap = mk_amode (am_indx);	    ap->preg = frameptr;	/* frame pointer */	    ap->u.offset = mk_const (offset--);	    g_code (op_popldf, OP_FLOAT, ap, mk_reg (reg));	}	if ((mask & MEMBER (reg)) != 0) {	    ap = mk_amode (am_indx);	    ap->preg = frameptr;	/* frame pointer */	    ap->u.offset = mk_const (offset--);	    g_code (op_popldi, OP_INT, ap, mk_reg (reg));	}    }}/* * make a direct reference to a node. */static ADDRESS *mk_immediatelabel P1 (EXPR *, ep){    return mk_expr (am_immed, ep);}/* * make an indirect reference to a node */static ADDRESS *mk_indirect P2 (REG, reg, EXPR *, ep){    ADDRESS *ap;    ap = mk_expr (am_indx, ep);    ap->preg = reg;    return ap;}#ifdef FLOAT_SUPPORT/* * make a node to reference an immediate value f. */static ADDRESS *mk_immedfloat P1 (RVAL, f){    ADDRESS *ap;    ap = mk_amode (am_immed);    ap->u.offset = mk_fcon (&f, tp_double);    return ap;}#endif /* FLOAT_SUPPORT */static void allocate_blockrepeat_registers (void){    interrupt_restore_mask |=	MEMBER (REG_RC) | MEMBER (REG_RS) | MEMBER (REG_RE);}/* * Generate a label which points to an integer constant.  This routine * ensures that only one copy of the constant is generated. */static ADDRESS *mk_ilabel P1 (const EXPR *, ep){    ITREE  *p, *q;    int     local_global = global_flag;    LABEL   lab;    EXPRTYPE type;    static ITREE *iitree = NULL;	/* Tree for integer constants */    static ITREE *ilabtree = NULL;	/* Tree for label   constants */    static ITREE *inatree = NULL;	/* Tree for na      constants */    static ITREE *iexprtree = NULL;	/* Tree for expr    constants */    lab = nextlabel++;    type = ep->nodetype;    if (tst_iconst (ep)) {	type = en_icon;	/*	 *FATAL((__FILE__,"mk_ilabel", "icon not supportet now"));	 */    }    switch (type) {    case en_icon:	p = iitree;	break;    case en_nacon:	p = inatree;	break;    case en_labcon:	p = ilabtree;	break;    case en_add:    case en_sub:    case en_cast:    case en_uminus:	p = iexprtree;	break;    default:	FATAL ((__FILE__, "mk_ilabel", "illegal nodetype %d", type));    }    /* in the moment we do not try to build a tree */    for (q = p; p; p = p->more) {	if (is_equalnode (p->value, ep)) {	    return mk_label (p->label);	}	q = p;    }    global_flag = 1;    p = (ITREE *) xalloc ((int) sizeof (ITREE));    p->label = lab;    p->value = copy_iexpr (ep);    p->less = p->more = NULL;    global_flag = local_global;    if (q == NULL) {	switch (type) {	case en_icon:	    iitree = p;	    break;	case en_nacon:	    inatree = p;	    break;	case en_labcon:	    ilabtree = p;	    break;	case en_add:	case en_sub:	case en_cast:	case en_uminus:	    iexprtree = p;	    break;	default:	    break;	}    }    /*else if (q->value < val) */    /*  q->less = p;          */    else	q->more = p;    put_kseg (alignment_of_type (tp_double));    put_label (lab);    put_pointer (ep);    return mk_label (lab);}/*****************************************************************************/static EXPR *copy_iexpr P1 (const EXPR *, ep){    EXPR   *newep;    if (ep == NIL_EXPR)	return NIL_EXPR;    newep = copynode (ep);    switch (ep->nodetype) {    case en_icon:    case en_autocon:    case en_labcon:    case en_nacon:	return newep;    case en_add:    case en_sub:	newep->v.p[0] = copy_iexpr (ep->v.p[0]);	newep->v.p[1] = copy_iexpr (ep->v.p[1]);	return newep;    case en_cast:    case en_uminus:	newep->v.p[0] = copy_iexpr (ep->v.p[0]);	return newep;    default:	FATAL ((__FILE__, "copy_iexpr", "illegal nodetype %d", ep->nodetype));	return NIL_EXPR;    }}/**************************************************************************************//* * return true if the node passed can be used as offset in addressgeneration. */static BOOL is_offset P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= -255L && ep->v.i <= 255L);}/* * return true if the node passed can be generated as a short offset. */static BOOL is_short P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= -32768L && ep->v.i <= 32767L);}/* * return true if the node passed can be generated as a unsigned short * offset. */static BOOL is_ushort P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= 0L && ep->v.i <= 0xFFFFL);}/* * delivers true, if node can ba evaluated to an addressingmode * suitable for an 3-operand instruction * (register, *an, *+an(1), *-an(1), *-an(irm), *+an(irm)) *                                   ^^^^^^^^^^^^^^^^^^^^-not included yet * * Autoincrements are currently not accepted for 3-op-instructions * ->could give troubles when both operands are the same address- *   registers (*arn++(1), *arm++(1), r) arn == arm *     * * Attention!! do not forget to change makro is_op3_violated() *             if you add the auto-/pre-incre-/decre-ments  */static BOOL is_op3_possible (EXPR *node){    /* Look for register */    if (node->nodetype == en_register) {	return TRUE;    }    /* look for autocons *ar7+(1) or *ar7-(1) */    if ((node->nodetype == en_autocon)	&& (node->v.i >= -1)	&& (node->v.i <= 1)) {	return TRUE;    }    if (node->nodetype == en_ref) {	switch (node->v.p[0]->nodetype) {	    /* Look for *arn */	case en_register:	    if (is_address_register (node->v.p[0]->v.r)) {		return TRUE;	    }	    break;	    /* look for indexnode *arn+(1) or *arn-(1) */	case en_add:	    if ((node->v.p[0]->v.p[0]->nodetype == en_register)		&& (is_address_register (node->v.p[0]->v.p[0]->v.r))		&& is_icon (node->v.p[0]->v.p[1])		&& (node->v.p[0]->v.p[1]->v.i >= -1)		&& (node->v.p[0]->v.p[1]->v.i <= 1)) {		return TRUE;	    }	    /* look for indexnode *arn+(1) or *arn-(1), nodes of add swapped */	    if ((node->v.p[0]->v.p[1]->nodetype == en_register)		&& (is_address_register (node->v.p[0]->v.p[1]->v.r))		&& is_icon (node->v.p[0]->v.p[0])		&& (node->v.p[0]->v.p[0]->v.i >= -1)		&& (node->v.p[0]->v.p[0]->v.i <= 1)) {		return TRUE;	    }	    break;#if 0				/* currently not supported */	case en_ainc:	case en_adec:	    /* look for autoincre/decrement *arn++(1) / *arn--(1) */	    if (ep->v.p[1]->v.i == 1		&& ep->v.p[0]->nodetype == en_register		&& is_address_register (ep->v.p[0]->v.r)) {		return TRUE;	    }	    break;	case en_asadd:	case en_assub:	    /* look for preincre/decrement *++arn(1) / *--arn(1) */	    if (is_icon (ep->v.p[1])		&& ep->v.p[1]->v.i == 1		&& ep->v.p[0]->nodetype == en_register		&& is_address_register (ep->v.p[0]->v.r)) {		/* *++An(1) */		return TRUE;	    }	    break;#endif	default:	    break;	}    }    return FALSE;}#ifdef FLOAT_SUPPORTBOOL    is_short_float (const RVAL f, BTYPE tp){    int     i;    RVAL    intpart;    if ((f > MAX_POS_SHORT_FLOAT) || (f < MIN_NEG_SHORT_FLOAT))	return (FALSE);    if (f == 0.0)	return (TRUE);    if ((f > MAX_NEG_SHORT_FLOAT) && (f < MIN_POS_SHORT_FLOAT))	return (FALSE);    /*     *  perhaps here should follow a check for the precision     *  sinc shortfloats only offers a precision of 11 Mantissabits     *  and sometimes we dont want to loose precision of constants     *  but in the moment I dont know how to do this check     *     */    /* We differ now in precission between float and (long-)double */    /* we have 3 options (opt_shortfloat):     * 0 we use shortfloats only if we are absolutely sure they     *   wont bring any loss in precision     *     * 1 floats are allways represented in shortform if they are in     *   range, double and longdouble only if there is no loss in     *   precision     *     * 3 floats, doubles ans longdoubles  are allways represented     *   in shortform if they are in range, there may be a loss in     *   precision     */    if ((tp == bt_float) && (opt_shortfloat > 0))	return (TRUE);    if (opt_shortfloat > 1)	return (TRUE);    /* cut away the fractional part */    i = (int) f;    intpart = (RVAL) i;    /* we use immediates for long and double only for     * floats with no fractional part, then we can     * be sure we dont loss any precission     * It's not the best solution, but for now it has to do     * it would be better to lock if the number has not more than     * 12 significant mantissabit and if the exponent is between     * +7 and -7 (base 2, of course), then the number can be represented     * in the short form without any losses     */    if (intpart == f)	return (TRUE);#if 0    /* New way to find out if a number can be represented with 11     * mantissabits, needs still to be tested     */    /* shift mantissa, until first mantissabit has reached position     * of bit 11 in an integer     */    if (f > 0.0) {	while (f < ((double) (1UL << 11))) {	    f = f + f;	}    } else {	while (f > ((double) (-(1UL << 11)))) {	    f = f + f;	}    }    /* cut away the fractional part */    i = (int) f;    intpart = i;    /* if there are no bits used in the fractionalpart we     * may use the short integerformat     */    if (intpart == f)	return (TRUE);#endif    return (FALSE);}#endif /* FLOAT_SUPPORT *//* * tests if it is a labelfree constant node, that means either en_icon, * or sums or differences of such nodes */static BOOL tst_iconst P1 (const EXPR *, ep){    switch (ep->nodetype) {    case en_icon:	return TRUE;    case en_add:    case en_sub:	return tst_iconst (ep->v.p[0]) && tst_iconst (ep->v.p[1]);#ifndef RELOC_BUG    case en_cast:#endif    case en_uminus:	return tst_iconst (ep->v.p[0]);    default:	break;    }    return FALSE;}/* * Checks, if the given nacon-name is a valid * trapname, eg is __trap_00 to __trap_31. * also valid names are __trap_nn_xxxx, where * xxx is any valid sequence of identifiercharacters. * if so, returns an address containing the immediatevalue * of the trapnumber, otherwise returns NIL_ADDRESS * is used to convert functionscalls named __trap_nn to * trapu-opcodes, simplifies interface to operating- * systems. */static ADDRESS *check_trap P1 (const EXPR *, ep){    static const CHAR *trapname = (const CHAR *) "__trap_nn";    const CHAR *p, *q;    IVAL    i;    /*     *  Check if trapp option was enabled     */    if (opt_traps == OPT_NO) {	return NIL_ADDRESS;    }    if (ep->nodetype == en_nacon) {	p = ep->v.str;	q = trapname;	while (*q != 'n') {	    if (*q++ != *p++) {		return NIL_ADDRESS;	    }	}	if ((*p > '3') || (*p < '0')) {	    return NIL_ADDRESS;	}	i = (IVAL) (10 * ((int) *p++ - '0'));	if ((*p > '9') || (*p < '0')) {	    return NIL_ADDRESS;	}	i += (IVAL) ((int) *p++ - '0');	/* Check if number is in range and for end of string */	if ((i > 31) || ((*p != 0) && (*p != '_'))) {	    return NIL_ADDRESS;	}	return (mk_immed (i));    }    return NIL_ADDRESS;}/* * mk_legal will coerce the addressing mode in ap1 into a mode that is * satisfactory for the flag word. */static ADDRESS *mk_legal P3 (ADDRESS *, ap, FLAGS, flags, ITYPE, size){    ADDRESS *ap2, *ap3;    OPCODE  OpSto, OpLd;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -