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

📄 genc30.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (flags & F_NOVALUE) {	freeop (ap);	return NIL_ADDRESS;    }    if (ap == NIL_ADDRESS) {	FATAL ((__FILE__, "mk_legal", "ap = 0"));	return NIL_ADDRESS;    }    switch (size) {    case OP_INT:	OpSto = op_sti;	OpLd = op_ldi;	if (flags & F_FREG) {	    FATAL ((__FILE__, "mk_legal", "op_int float mixed with integer"));	}	break;    case OP_FLOAT:	OpSto = op_stf;	OpLd = op_ldf;	if (flags & F_XREG) {	    FATAL (		   (__FILE__, "mk_legal",		    "op_float float mixed with integer"));	}	break;    default:	FATAL ((__FILE__, "mk_legal", "illegal size0"));	break;    }    switch (ap->mode) {    case am_immed:	if (flags & F_IMMED) {	    return ap;		/* mode ok */	}	break;    case am_areg:	if (flags & F_AREG	    && (!(flags & F_VOL) || is_temporary_register (ap->preg))) {	    return ap;	}	if (flags & F_FREG) {	    FATAL (		   (__FILE__, "mk_legal",		    "am_areg float mixed with integer"));	}	break;    case am_ireg:	if (flags & F_IREG	    && (!(flags & F_VOL) || is_temporary_register (ap->preg))) {	    return ap;	}	if (flags & F_FREG) {	    FATAL (		   (__FILE__, "mk_legal",		    "am_ireg float mixed with integer"));	}	break;    case am_dreg:	if (flags & F_DREG	    && (!(flags & F_VOL) || is_temporary_register (ap->preg))) {	    return ap;	}	if (flags & F_FREG) {	    FATAL (		   (__FILE__, "mk_legal",		    "am_dreg float mixed with integer"));	}	break;    case am_freg:	if (flags & F_FREG	    && (!(flags & F_VOL) || is_temporary_register (ap->preg))) {	    return ap;	}	if (flags & F_XREG) {	    FATAL (		   (__FILE__, "mk_legal",		    "am_freg float mixed with integer"));	}	break;    case am_ind:    case am_const_ind:    case am_indx:    case am_indx2:    case am_indxs:    case am_direct:    case am_const_direct:    case am_adec:    case am_ainc:    case am_preinc:    case am_predec:	if (flags & F_MEM)	    return ap;	break;    default:	break;    }    if ((flags & F_XREG) != 0) {	/* decide, which mode is better */	if (is_free_data () && (flags & F_DREG)) {	    freeop (ap);	/* maybe we can use it... */	    ap2 = data_register (F_DREG);	/* allocate to dreg */	    g_code (op_ldi, OP_INT, ap, ap2);	    return ap2;	}	if (is_free_addr () && (flags & F_AREG)) {	    freeop (ap);	/* maybe we can use it... */	    ap2 = address_register ();	/* allocate to dreg */	    g_code (op_ldi, OP_INT, ap, ap2);	    return ap2;	}	if (is_free_ireg () && (flags & F_IREG)) {	    freeop (ap);	    ap2 = index_register ();	    g_code (op_ldi, OP_INT, ap, ap2);	    return ap2;	}    }    if (flags & F_DREG) {	freeop (ap);		/* maybe we can use it... */	ap2 = data_register (F_DREG);	/* allocate to dreg */	g_code (op_ldi, OP_INT, ap, ap2);	return ap2;    }    if (flags & F_FREG) {	freeop (ap);		/* maybe we can use it... */	ap2 = data_register (F_FREG);	/* allocate to dreg */	g_code (op_ldf, OP_FLOAT, ap, ap2);	return ap2;    }    if (flags & F_AREG) {	freeop (ap);	ap2 = address_register ();	g_code (op_ldi, OP_INT, ap, ap2);	return ap2;    }    if (flags & F_IREG) {	freeop (ap);	ap2 = index_register ();	g_code (op_ldi, OP_INT, ap, ap2);	return ap2;    }    if (flags & F_MEM) {	if (ap->mode == am_immed) {	    /* we can not store immediates directly in memory */	    freeop (ap);	    ap3 = data_register ((size == OP_INT) ? F_DREG : F_FREG);	    g_code (OpLd, size, ap, ap3);	    ap = ap3;	}	freeop (ap);	ap2 = mk_scratch (1L);	/* copy value into memory */	g_code (OpSto, size, ap, ap2);	return ap2;    }    FATAL ((__FILE__, "mk_legal", ""));    return NIL_ADDRESS;}/*****************************************************************************//* * add a compiler generated label to the peep list. */PRIVATE void g_label P1 (LABEL, labno){    sync_stack ();    g_code (op_label, OP_INT, mk_label (labno), NIL_ADDRESS);}#ifdef DEBUGOPT/* * add a source line number to the peep list. */PRIVATE void g_line P2 (LINE, line, const CHAR *, linetxt){    g_code3 (op_line, OP_INT, mk_line (line), mk_linetxt (linetxt),	     NIL_ADDRESS);}#endif /*DEBUGOPT *//* * add a conditional branch instruction to the peep list. */static void g_cbranch P2 (OPCODE, op, LABEL, labno){    sync_stack ();    g_code (op, OP_INT, mk_Jumplabel (labno), NIL_ADDRESS);}/* * add a branch instruction to the peep list. */PRIVATE void g_branch P1 (LABEL, labno){    g_cbranch (op_br, labno);}/* * adjust the stack by "bytes" bytes. */PRIVATE void g_stack P1 (SIZE, bytes){    if (bytes != 0L) {	/* adjust stack pointer */	g_immed (op_subi, bytes, mk_reg (STACKPTR));	stack_offset -= bytes;	if (max_stack_adjust < bytes)	    max_stack_adjust = bytes;    }}/* * Generate an instruction which takes an immediate option with optimal * (for space) instruction(s). */static void g_immed P3 (OPCODE, op, IVAL, i, ADDRESS *, ap){    if (ap != NIL_ADDRESS) {	if (!isanyreg (ap))	    FATAL ((__FILE__, "g_immed", "immed-to-memory"));    }    if ((i >= -32768L && i <= 32767L) || (opt_const_in_ram != OPT_NO)) {	g_code (op, OP_INT, mk_immed (i), ap);    } else {	/* bigger constants we must build by hand */	/* in future it could be solved through storing constants */	/* in datasegment and fetching them from there */	ADDRESS *ap1;	IVAL    low = (IVAL) ((UVAL) i & 0xFFFFL);	IVAL    high = (IVAL) ((UVAL) i >> 16);	if (op == op_ldi) {	    ap1 = ap;	} else {	    ap1 = temporary_register (F_XREG);	}	g_code (op_ldi, OP_INT, mk_immed (high), ap1);	if (high != 0) {	    g_code (op_lsh, OP_INT, mk_immed (16), ap1);	}	if (low != 0) {	    g_code (op_or, OP_INT, mk_uimmed (low), ap1);	}	if (op != op_ldi) {	    g_code (op, OP_INT, ap1, ap);	    freeop (ap1);	}    }}/* * Generate an instruction which takes an unsigned immediate option with * optimal (for space) instruction(s). */static void g_uimmed P3 (OPCODE, op, IVAL, i, ADDRESS *, ap){    if (ap != NIL_ADDRESS) {	if (!isanyreg (ap))	    FATAL ((__FILE__, "g_uimmed", "immed-to-memory"));    }    if ((i >= 0 && i <= 0xFFFFL) || (opt_const_in_ram != OPT_NO)) {	g_code (op, OP_INT, mk_uimmed (i), ap);    } else {	/* bigger constants we must build by hand */	/* in future it could be solved through storing constants */	/* in datasegment and fetching them from there */	ADDRESS *ap1 = temporary_register (F_XREG);	IVAL    low = (IVAL) ((UVAL) i & 0xFFFFL);	IVAL    high = (IVAL) ((UVAL) i >> 16);	g_code (op_ldi, OP_INT, mk_immed (high), ap1);	if (high != 0) {	    g_code (op_lsh, OP_INT, mk_immed (16), ap1);	}	if (low != 0) {	    g_code (op_or, OP_INT, mk_uimmed (low), ap1);	}	g_code (op, OP_INT, ap1, ap);	freeop (ap1);    }}/*----------------------------------------------------------------------------*//* * generate code to evaluate an index node and return the addressing * mode of the result. */static ADDRESS *g_index P1 (const EXPR *, ep){    ADDRESS *ap1, *ap2;    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    AMODE   mode;    /*     *  Try and ensure that we evaluate address registers first ....     *  this leads to better code.     */    switch (ep->nodetype) {    case en_add:	if (ep1->nodetype == en_register && is_address_register (ep1->v.r)) {	    ep0 = ep->v.p[1];	    ep1 = ep->v.p[0];	}	mode = am_indx2;	break;    case en_sub:	mode = am_indxs;	break;    default:	FATAL ((__FILE__, "g_index", "illegal nodetype %d ", ep->nodetype));    }    if (ep1->nodetype == en_register && ep0->nodetype == en_register) {	if (is_address_register (ep0->v.r) || (ep->nodetype == en_sub)) {	    /* first node is address register */	    ap1 = g_expr (ep0, F_AREG);	    ap1 = copy_addr (ap1, mode);	    ap2 = g_expr (ep1, F_IREG);	    ap1->sreg = ap2->preg;	    ap1->deep = ap2->deep;	    ap1->u.offset = mk_const (0L);	    return ap1;	} else if (is_address_register (ep1->v.r) && (ep->nodetype == en_add)) {	    /* second node is address register */	    ap1 = g_expr (ep1, F_AREG);	    ap1 = copy_addr (ap1, am_indx2);	/* (ARx,IRx) */	    ap2 = g_expr (ep0, F_IREG);	    ap1->sreg = ap2->preg;	    ap1->deep = ap2->deep;	    ap1->u.offset = mk_const (0L);	    return ap1;	}    }    /*     *   The general case (no register)     */    ap1 =	g_expr (ep0,		(ep->nodetype ==		 en_add) ? (FLAGS) (F_AREG | F_IMMED) : F_AREG);    switch (ap1->mode) {    case am_areg:	ap2 = g_expr (ep1, (FLAGS) (F_IREG | F_IMMED));	validate (ap1);	break;    case am_immed:	if (ep->nodetype == en_sub) {	    FATAL ((__FILE__, "g_index", "illegal adressmodee"));	}	ap2 = ap1;	ap1 = g_expr (ep1, (FLAGS) (F_AREG | F_IMMED));	validate (ap2);	break;    default:	CANNOT_REACH_HERE ();    }    /*     *  possible combinations:     *     *          F_IMMED +/- F_IMMED     *          F_AREG  +/- F_IMMED     *          F_AREG  +/- F_IREG     */    if (ap1->mode == am_areg) {	/* 	 *  watch out for:	 *          register(addr) + index_register	 *          register(addr) + data_register	 */	if (!is_temporary_register (ap1->preg)) {	    /* ap1 = tempref address register */	    ap1 = copy_addr (ap1, ap1->mode);	    switch (ap2->mode) {	    case am_ireg:		/* 0(ARx,IRy) */		ap1->mode = mode;		ap1->sreg = ap2->preg;		ap1->deep = ap2->deep;		ap1->u.offset = mk_const (0L);		return ap1;	    case am_immed:		if (!is_offset (ap2->u.offset))		    /* we want to add to ap1 later... */		    /* so copy it in scratchregister */		    ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), OP_INT);		break;	    default:		break;	    }/* needs some changes in the registermanagement before this can be done *//* we cannot correctly restore second temp if it has been pushed        *//* (we have only one depth-information per ap and so can only keep      *//* of one tempregister                                                  */#if 0	error, not suported now} else {	    /* ap1 is temporaryregister */	    switch (ap2->mode) {	    case am_ireg:		/* 0(ARx,IRy) */		ap1 = copy_addr (ap1, ap1->mode);		ap1->mode = am_indx2;		ap1->sreg = ap2->preg;		ap1->u.offset = mk_const (0L);		return ap1;	    default:		break;	    }#endif	}    }    if (ap2->mode == am_immed) {	if (ap1->mode == am_immed) {	    ap1 = copy_addr (ap1, am_direct);	    if (ep->nodetype == en_add) {		ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset);	    } else {		ap1->u.offset =		    mk_node (en_sub, ap1->u.offset, ap2->u.offset, tp_void);	    }	    return ap1;	}	if (is_offset (ap2->u.offset)) {	    ap1 = mk_legal (ap1, F_AREG, OP_INT);	    ap1 = copy_addr (ap1, am_indx);	    if (ep->nodetype == en_add) {		ap1->u.offset = ap2->u.offset;	    } else {		ap1->u.offset = mk_const (-ap2->u.offset->v.i);	    }	    return ap1;	}    }    /* just to be sure, ap1 should allready be volatile here... */    if (!is_temporary_register (ap1->preg)) {	/* ap1 is not volatile ... */	ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), OP_INT);    }    if (ep->nodetype == en_add) {	g_code (op_addi, OP_INT, ap2, ap1);	/* add left to address reg */    } else {	g_code (op_subi, OP_INT, ap2, ap1);	/* sub left to address reg */    }    ap1 = copy_addr (ap1, am_ind);    freeop (ap2);		/* release any temps in ap2 */    return ap1;			/* return indirect */}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P3 (const EXPR *, ep, TYP *, tp, FLAGS, flags){    ADDRESS *ap1;    /*     * If a reference to a struct/union is required, return a pointer to the     * struct instead     */    if (is_structure_type (tp) || is_array_assignment (tp)) {	return g_expr (ep, F_IALL);    }    switch (ep->nodetype) {#ifdef DEBUG    case en_sub:#endif    case en_add:	return g_index (ep);    case en_autocon:	if (ep->v.i >= -255L && ep->v.i < 255L) {	    ap1 = mk_indirect (frameptr, mk_const (ep->v.i));	} else {	    ap1 = address_register ();	    g_immed (op_ldi, ep->v.i, ap1);	    g_code (op_addi, OP_INT, mk_reg (frameptr), ap1);	    ap1 = copy_addr (ap1, am_ind);	}	return ap1;    case en_ainc:	/* special TMS320C30 instructions */	if (ep->v.p[1]->v.i <= 255L	/* if size less than max autoincrement */	    && ep->v.p[1]->v.i >= 0L	/* and if size positive */

⌨️ 快捷键说明

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