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

📄 gen68k.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	    ap1->u.offset = mk_const ((IVAL) 0L);	    return ap1;	}    }    if (ap2->mode == am_immed) {	if (ap1->mode == am_immed) {	    ap1 = copy_addr (ap1, am_direct);	    ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset);	    return ap1;	}	if (is_short (ap2->u.offset)) {	    ap1 = mk_legal (ap1, F_AREG, tp_pointer);	    ap1 = copy_addr (ap1, am_indx);	    ap1->u.offset = ap2->u.offset;	    return ap1;	}    }    freeop (ap2);		/* release any temps in ap2 */    if (!is_temporary_register (ap1->preg)) {	/* ap1 is not volatile ... */	ap1 = mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), tp_pointer);    }    g_add (IL4, ap2, ap1);	/* add left to address reg */    ap1 = copy_addr (ap1, am_ind);    return ap1;			/* return indirect */}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P3 (const EXPR *, ep, const TYP *, tp, FLAGS, flags){    ADDRESS *ap1;    SIZE    size = tp->size;    EXPR   *ep2;    /*     * If a reference to a struct/union is required, return a     * pointer to the struct instead     */    if (is_structure_type (tp)#ifdef FLOAT_SUPPORT	|| is_complex_type (tp)#endif /* FLOAT_SUPPORT */	|| is_array_assignment (tp)) {	return g_expr (ep, F_ALL);    }    switch (ep->nodetype) {    case en_add:	return g_index (ep);    case en_global:	ep2 = mk_global (SUP_DATA, ep);	switch (datamodel_option) {	case model_small:	    ap1 = mk_indirect (regdata, ep2);	    break;	case model_large:	    ap1 = address_register ();	    g_move (IL4, mk_expr (am_immed, ep2), ap1);	    ap1 = copy_addr (ap1, am_indx3);	    ap1->sreg = regdata;	    ap1->u.offset = mk_const ((IVAL) 0L);	    break;	default:	    CANNOT_REACH_HERE ();	}	return ap1;    case en_autocon:	if (ep->v.i >= -32768L && ep->v.i <= 32767L) {	    ap1 = mk_indirect (regframe, mk_const (ep->v.i));	} else {	    ap1 = address_register ();	    g_move (IL4, mk_immed (ep->v.i), ap1);	    g_add (IL4, mk_reg (regframe), ap1);	    ap1 = copy_addr (ap1, am_ind);	}	return ap1;    case en_ainc:	/* special 68000 instructions */	if ((size == 1L || size == 2L || size == 4L)	    && ep->v.p[1]->v.i == (IVAL) size	    && ep->v.p[0]->nodetype == en_register	    && is_address_register (ep->v.p[0]->v.r)	    && !(flags & F_USES)) {	    /* (An)+ */	    ap1 = mk_amode (am_ainc);	    ap1->preg = ep->v.p[0]->v.r;	    return ap1;	}	/*lint -fallthrough */    default:	ap1 = g_expr (ep, (FLAGS) (F_AREG | F_IMMED));	/* generate address */	if (ap1->mode == am_immed) {	    return copy_addr (ap1, am_direct);	} else {	    return copy_addr (ap1, am_ind);	}    }}/* * get a bitfield value */static ADDRESS *g_fderef P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap;    TYP    *tp = ep->etp;    ap = g_deref (ep->v.p[0], tp, F_ALL);    ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), tp);    g_rotate (ap, tp, (int) ep->v.bit.offset, tp, (int) ep->v.bit.width);    return mk_legal (ap, flags, tp);}/*============================================================================*/#ifdef FLOAT_SUPPORTstatic void push_rtl_params P2 (const EXPR *, ep1, const EXPR *, ep2){#ifdef FLOAT_IEEE    ADDRESS *ap;    is_parameter++;    temp_inv (NIL_REGUSAGE);    ap = g_expr (ep1, F_MEM);    g_code (op_pea, IL0, ap, NIL_ADDRESS);    freeop (ap);    if (ep2) {	ap = g_expr (ep2, F_MEM);	g_code (op_pea, IL0, ap, NIL_ADDRESS);	freeop (ap);    }#endif /* FLOAT_IEEE */#ifdef FLOAT_MFFP    is_parameter++;    temp_inv (NIL_REGUSAGE);    VOIDCAST push_param (ep1);    if (ep2) {	VOIDCAST push_param (ep2);    }#endif /* FLOAT_MFFP */    is_parameter--;}#endif /* FLOAT_SUPPORT *//*============================================================================*//* * generate code to evaluate a unary minus or complement. float: unary minus * calls a library function */static ADDRESS *g_unary P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap;    TYP    *tp = ep->etp;    switch (tp->type) {    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL));	g_code (op, (ILEN) tp->size, ap, NIL_ADDRESS);	return mk_legal (ap, flags, tp);#ifdef LONGLONG_SUPPORT    case bt_ulonglong:    case bt_longlong:	ap = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL));	g_code (op, IL4, mk_high (ap), NIL_ADDRESS);	switch (op) {	case op_neg:	    g_code (op_negx, IL4, mk_low (ap), NIL_ADDRESS);	    break;	case op_not:	    g_code (op, IL4, mk_low (ap), NIL_ADDRESS);	    break;	default:	    CANNOT_REACH_HERE ();	}	return mk_legal (ap, flags, tp);#endif /* LONGLONG_SUPPORT */    default:	FATAL (	       (__FILE__, "g_unary", "illegal type %d or operation %d",		tp->type, op));    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/*============================================================================*//* * generate an auto increment or decrement node. op should be either op_add * (for increment) or op_sub (for decrement). */static ADDRESS *g_aincdec P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2, *ap3;    TYP    *tp = ep->etp;    FLAGS   flagx;    switch (tp->type) {    case bt_bool:	ap1 = g_expr (ep->v.p[0], F_ALL);	switch (op) {	case op_add:	    g_move ((ILEN) tp->size, mk_immed ((IVAL) 1L), ap1);	    break;	default:	    g_move ((ILEN) tp->size, mk_immed ((IVAL) 0L), ap1);	    break;	}	return mk_legal (ap1, flags, tp);    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:#ifdef COLDFIRE	if (is_coldfire ()) {	    if (ep->v.p[0]->nodetype == en_fieldref) {		return g_asbitfield (ep, flags, op, TRUE);	    }	    ap1 = temp_reg (flags);	    ap2 = g_expr (ep->v.p[0], F_ALL);	    validate (ap1);	    g_move ((ILEN) tp->size, ap2, ap1);	    ap1 =		g_extend (ap1, tp, is_signed_type (tp) ? tp_long : tp_ulong);	    ap3 = g_expr (ep->v.p[1], F_IMMED);	    validate (ap1);	    switch (op) {	    case op_add:		g_add (IL4, ap3, ap1);		break;	    default:		g_sub (IL4, ap3, ap1);		break;	    }	    g_move ((ILEN) tp->size, ap1, ap2);	    if (!(flags & F_NOVALUE)) {		switch (op) {		case op_add:		    g_sub (IL4, ap3, ap1);		    break;		default:		    g_add (IL4, ap3, ap1);		    break;		}	    }	    freeop (ap3);	    freeop (ap2);	    return mk_legal (ap1, flags, tp);	}	/*lint -fallthrough */#endif /* COLDFIRE */    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, TRUE);	}	flagx = is_coldfire ()? F_DREG : F_IMMED;	if (flags & F_NOVALUE) {	/* don''t need result */	    ap1 = g_expr (ep->v.p[0], F_ALL);	    ap2 = g_expr (ep->v.p[1], flagx);	    switch (op) {	    case op_add:		g_add ((ILEN) tp->size, ap2, ap1);		break;	    default:		g_sub ((ILEN) tp->size, ap2, ap1);		break;	    }	} else {	    ap1 = temp_reg (flags);	    ap2 = g_expr (ep->v.p[0], (FLAGS) (F_ALL | F_USES));	    validate (ap1);	    g_move ((ILEN) tp->size, ap2, ap1);	    ap3 = g_expr (ep->v.p[1], flagx);	    validate (ap2);	    switch (op) {	    case op_add:		g_add ((ILEN) tp->size, ap3, ap2);		break;	    default:		g_sub ((ILEN) tp->size, ap3, ap2);		break;	    }	    freeop (ap3);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);#ifdef LONGLONG_SUPPORT    case bt_longlong:    case bt_ulonglong:	flagx = F_DREG | F_IMMED;	if (flags & F_NOVALUE) {	/* don''t need result */	    ADDRESS *ap4;	    ap1 = g_expr (ep->v.p[0], F_ALL);	    ap2 = g_expr (ep->v.p[1], flagx);	    validate (ap1);	    ap3 = data_register ();	    g_code (op_move, IL4, mk_low (ap2), ap3);	    ap4 = data_register ();	    g_code (op_move, IL4, mk_low (ap1), ap4);	    switch (op) {	    case op_add:		g_add (IL4, mk_high (ap2), mk_high (ap1));		g_code (op_addx, IL4, ap3, ap4);		break;	    default:		g_sub (IL4, mk_high (ap2), mk_high (ap1));		g_code (op_subx, IL4, ap3, ap4);		break;	    }	    g_code (op_move, IL4, ap4, mk_low (ap1));	    freeop (ap4);	    freeop (ap3);	    freeop (ap2);	} else {	    ADDRESS *ap4;	    ap1 = g_expr (ep->v.p[0], F_ALL);	    g_move8 (ap1, &push);	    ap2 = g_expr (ep->v.p[1], flagx);	    validate (ap1);	    ap3 = data_register ();	    g_code (op_move, IL4, mk_low (ap2), ap3);	    ap4 = data_register ();	    g_code (op_move, IL4, mk_low (ap1), ap4);	    switch (op) {	    case op_add:		g_add (IL4, mk_high (ap2), mk_high (ap1));		g_code (op_addx, IL4, ap3, ap4);		break;	    default:		g_sub (IL4, mk_high (ap2), mk_high (ap1));		g_code (op_subx, IL4, ap3, ap4);		break;	    }	    g_code (op_move, IL4, ap4, mk_low (ap1));	    freeop (ap4);	    freeop (ap3);	    freeop (ap2);	    freeop (ap1);	    ap1 = mdata_register ();	    g_move8 (&pop, ap1);	}	validate (ap1);	return mk_legal (ap1, flags, tp);#endif /* LONGLONG_SUPPORT */    default:	FATAL ((__FILE__, "g_aincdec", "illegal type %d or float", tp->type));    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/*============================================================================*//* * generate code to evaluate a binary node and return the addressing mode of * the result. */static ADDRESS *g_addsub P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    TYP    *tp = ep->etp;    switch (tp->type) {    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:	ap1 =	    g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_COLD | (flags & F_DREG)));	ap2 = g_expr (ep->v.p[1], (FLAGS) ((F_ALL & ~F_AREG) | F_COLD));	validate (ap1);		/* in case push occurred */	switch (op) {	case op_add:	    g_add ((ILEN) tp->size, ap2, ap1);	    break;	default:	    g_sub ((ILEN) tp->size, ap2, ap1);	    break;	}	freeop (ap2);	return mk_legal (ap1, flags, tp);    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap1 =	    g_expr (ep->v.p[0],		    (FLAGS) (F_VOL | F_COLD | (flags & (F_DREG | F_AREG))));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_ALL | F_COLD));	validate (ap1);		/* in case push occurred */	switch (op) {	case op_add:	    g_add ((ILEN) tp->size, ap2, ap1);	    break;	default:	    g_sub ((ILEN) tp->size, ap2, ap1);	    break;	}	freeop (ap2);	return mk_legal (ap1, flags, tp);#ifdef LONGLONG_SUPPORT    case bt_longlong:    case bt_ulonglong:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_COLD | F_DREG));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_MEM | F_COLD));	validate (ap1);	{	    ADDRESS *ap3 = data_register ();	    g_code (op_move, IL4, mk_low (ap2), ap3);	    validate (ap1);	/* in case push occurred */	    switch (op) {	    case op_add:		g_code (op_add, IL4, mk_high (ap2), mk_high (ap1));		g_code (op_addx, IL4, ap3, mk_low (ap1));		break;	    default:		g_code (op_sub, IL4, mk_high (ap2), mk_high (ap1));		g_code (op_subx, IL4, ap3, mk_low (ap1));		break;	    }	    freeop (ap3);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);#endif /* LONGLONG_SUPPORT */#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	op = (op == op_add) ? op_fadd : op_fsub;	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_FREG));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_FREG | F_MEM));	validate (ap1);		/* in case push occurred */	g_fcode (op, (ILEN) tp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, tp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_addsub", "illegal type %d", tp->type));    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/* * generate a plus equal or a minus equal node. */static ADDRESS *g_asadd P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    FLAGS   flagx, flagx2;    ADDRESS *ap1, *ap2;    TYP    *tp = ep->etp;    switch (tp->type) {    case bt_bool:	ap1 = g_expr (ep->v.p[0], F_ALL);	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG));	validate (ap1);	switch (ap2->mode) {	case am_immed:	    switch (op) {	    case op_add:		ap2->u.offset->v.i = (IVAL) (ap2->u.offset->v.i != 0L);		break;	    default:		ap2->u.offset->v.i = (IVAL) (ap2->u.offset->v.i == 0L);		break;	    }	    break;	default:	    break;	}	g_code (op_or, (ILEN) tp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, tp);    case bt_char:    case bt_charu:    case bt_schar:    case bt_uchar:    case bt_short:    case bt_ushort:    case bt_int16:    case bt_uint16:#ifdef COLDFIRE	if (is_coldfire ()) {	    ADDRESS *ap3;	    if (ep->v.p[0]->nodetype == en_fieldref) {		return g_asbitfield (ep, flags, op, TRUE);	    }	    ap1 = temp_reg (flags);	    ap2 = g_expr (ep->v.p[0], F_ALL);	    validate (ap1);	    g_move ((ILEN) tp->size, ap2, ap1);	    ap1 =		g_extend (ap1, tp, is_signed_type (tp) ? tp_long : tp_ulong);	    ap3 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG));	    validate (ap1);	    switch (op) {	    case op_add:		g_add (IL4, ap3, ap1);		break;	    default:		g_sub (IL4, ap3, ap1);		break;

⌨️ 快捷键说明

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