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

📄 gen68k.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	    }	    g_move ((ILEN) tp->size, ap1, ap2);	    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, FALSE);	}	flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES);#ifdef COLDFIRE	flagx2 = F_DREG;	if (!is_coldfire ()) {	    flagx2 |= F_IMMED;	}#else	flagx2 = F_DREG | F_IMMED;#endif /* COLDFIRE */	ap1 = g_expr (ep->v.p[0], flagx);	ap2 = g_expr (ep->v.p[1], flagx2);	ap2 = mk_quick2 (ap2, tp);	validate (ap1);	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:	flagx =	    (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_DREG | F_MEM | F_USES);#ifdef COLDFIRE	flagx2 = F_DREG;	if (!is_coldfire ()) {	    flagx2 |= F_IMMED;	}#else	flagx2 = F_DREG | F_IMMED;#endif /* COLDFIRE */	ap1 = g_expr (ep->v.p[0], flagx);	ap2 = g_expr (ep->v.p[1], flagx2);	validate (ap1);	switch (ap1->mode) {	    ADDRESS *ap3;	case am_ind:	case am_indx:	case am_indx2:	case am_indx3:	case am_indx4:	case am_direct:	    switch (ap2->mode) {		ADDRESS *ap4;	    case am_mreg:		ap4 = data_register ();		g_code (op_move, IL4, mk_low (ap1), ap4);		g_code (op, IL4, mk_high (ap2), mk_high (ap1));		switch (op) {		case op_add:		    g_code (op_addx, IL4, mk_low (ap2), ap4);		    break;		default:		    g_code (op_subx, IL4, mk_low (ap2), ap4);		    break;		}		g_code (op_move, IL4, ap4, mk_low (ap1));		freeop (ap4);		break;	    default:		ap3 = data_register ();		validate (ap2);		g_code (op_move, IL4, mk_low (ap2), ap3);		validate (ap1);		ap4 = data_register ();		g_code (op_move, IL4, mk_low (ap1), ap4);		switch (op) {		case op_add:		    g_code (op_add, IL4, mk_high (ap2), mk_high (ap1));		    g_code (op_addx, IL4, ap3, ap4);		    break;		default:		    g_code (op_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);		break;	    }	    break;	case am_mreg:	    ap3 = data_register ();	    g_code (op_move, IL4, mk_low (ap2), ap3);	    validate (ap1);	    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);	    break;	default:	    CANNOT_REACH_HERE ();	}	freeop (ap2);	validate (ap1);	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;	flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES);	ap1 = g_expr (ep->v.p[0], flagx);	ap2 = g_expr (ep->v.p[1], F_FREG);	validate (ap1);	g_fcode (op, (ILEN) tp->size, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, tp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "asadd", "illegal type %d", tp->type));    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/*============================================================================*//* * generate code to evaluate a restricted binary node and return the * addressing mode of the result. */static ADDRESS *g_logic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2, *ap3;    ILEN    ilen = (ILEN) ep->etp->size;    FLAGS   flagx;#ifdef COLDFIRE    if (is_coldfire ()) {	ilen = IL4;    }#endif /* COLDFIRE */    switch (ep->etp->size) {    case IL8:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | D_REG | F_COLD));	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_MEM | F_IMMED | F_COLD));	ap3 = data_register ();	validate (ap1);		/* in case push occurred */	g_code (op_move, IL4, mk_high (ap2), ap3);	g_code (op, IL4, ap3, mk_high (ap1));	g_code (op_move, IL4, mk_low (ap2), ap3);	g_code (op, IL4, ap3, mk_low (ap1));	freeop (ap3);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);    default:	ap1 = g_expr (ep->v.p[0], (FLAGS) (F_VOL | F_DREG | F_COLD));	if (op == op_eor) {	    flagx = (FLAGS) (F_DREG | F_IMMED | F_COLD);	} else {	    flagx = (FLAGS) ((F_ALL | F_COLD) & ~F_AREG);	}	if (ap1->mode == am_mreg)	    flagx = (FLAGS) (F_MEM | F_IMMED | F_COLD);	ap2 = g_expr (ep->v.p[1], flagx);	ap2 = mk_quick (ap2, ep->etp);	validate (ap1);		/* in case push occurred */	g_code (op, ilen, ap2, ap1);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);    }}/* * generate a &= or a |= ep. */static ADDRESS *g_aslogic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    FLAGS   flagx;    ADDRESS *ap1, *ap2;    TYP    *tp = ep->etp;    EXPR   *ep0 = ep->v.p[0];    if (ep0->nodetype == en_fieldref) {	UVAL    mask = (UVAL) bitmask (ep0->v.bit.width);	EXPR   *ep2;	ap1 = g_expr (ep->v.p[1], (FLAGS) (F_IMMED | F_DREG | F_VOL));	if (ap1->mode == am_immed) {	    if (op == op_or)		ap1->u.offset->v.u &= mask;	    else		ap1->u.offset->v.u |= ~mask;	    ap1->u.offset->v.u <<= (int) ep0->v.bit.offset;	} else {	    if (op == op_or)		g_immed (op_and, tp, (IVAL) mask, ap1);	    else		g_immed (op_or, tp, (IVAL) ~mask, ap1);	    g_rotate (ap1, ep->etp, -(int) ep0->v.bit.offset, tp_void, 0);	}	ep2 = mk_ref (ep0->v.p[0], tp_pointer);	ap2 = g_expr (ep2, F_MEM);	validate (ap1);	g_code (op, (ILEN) tp->size, ap1, ap2);	freeop (ap2);	if (!(flags & F_NOVALUE)) {	    freeop (ap1);	    ap1 = data_register ();	    g_code (op_move, (ILEN) tp->size, ap2, ap1);	    g_rotate (ap1, tp, (int) ep0->v.bit.offset, tp,		      (int) ep0->v.bit.width);	}	return mk_legal (ap1, flags, tp);    }    flagx = (flags & F_NOVALUE) ? F_ALL : (FLAGS) (F_ALL | F_USES);    ap1 = g_expr (ep0, flagx);    ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_COLD));    ap2 = mk_quick (ap2, ep->etp);    validate (ap1);    switch (tp->size) {    case IL8:	g_code (op, IL4, mk_high (ap2), mk_high (ap1));	g_code (op, IL4, mk_low (ap2), mk_low (ap1));	freeop (ap2);	return mk_legal (ap1, flags, tp);    default:	if (ap1->mode == am_areg || is_coldfire ()) {	    ADDRESS *ap3 = data_register ();	    g_move ((ILEN) tp->size, ap1, ap3);	    ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_COLD), tp);	    g_code (op, (ILEN) tp->size, ap2, ap3);	    g_move ((ILEN) tp->size, ap3, ap1);	    freeop (ap3);	} else {	    g_code (op, (ILEN) tp->size, ap2, ap1);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);    }}/*============================================================================*/static ADDRESS *g_shft P4 (OPCODE, op, ILEN, ilen, ADDRESS *, ap1, ADDRESS *,			   ap2){    LABEL   label;    switch (ilen) {    case IL1:    case IL2:    case IL4:	/* quick constant only legal if 1<=const<=8 */	if (ap1->mode == am_immed && is_icon (ap1->u.offset)) {	    IVAL    i = ap1->u.offset->v.i;	    if (i == 16L && ilen == IL4) {		switch (op) {		case op_asl:		    g_code (op_swap, IL0, ap2, NIL_ADDRESS);		    g_code (op_clr, IL2, ap2, NIL_ADDRESS);		    break;		case op_asr:		    g_code (op_swap, IL0, ap2, NIL_ADDRESS);		    g_code (op_ext, IL4, ap2, NIL_ADDRESS);		    break;		case op_lsr:		    g_code (op_clr, IL2, ap2, NIL_ADDRESS);		    g_code (op_swap, IL0, ap2, NIL_ADDRESS);		    break;		default:		    CANNOT_REACH_HERE ();		}		return ap1;	    }	    if ((i > 8L) || (i < 1L)) {		ap1 = mk_legal (ap1, F_DREG, tp_char);	    }	}	validate (ap2);	g_code (op, ilen, ap1, ap2);	break;    case IL8:	if (ap1->mode == am_immed && is_icon (ap1->u.offset)) {	    IVAL    i = ap1->u.offset->v.i;	    if (i == 32L) {		switch (op) {		case op_asl:		    g_code (op_move, IL4, mk_high (ap2), mk_low (ap2));		    g_code (op_clr, IL4, mk_high (ap2), NIL_ADDRESS);		    break;		case op_asr:		    g_code (op_move, IL4, mk_low (ap2), mk_high (ap2));		    g_code (op_slt, IL0, mk_low (ap2), NIL_ADDRESS);		    break;		case op_lsr:		    g_code (op_move, IL4, mk_low (ap2), mk_high (ap2));		    g_code (op_clr, IL4, mk_low (ap2), NIL_ADDRESS);		    break;		default:		    CANNOT_REACH_HERE ();		}		return ap1;	    }	}	label = nextlabel++;	ap1 = mk_legal (ap1, F_DREG, tp_ulong);	g_label (label);	switch (op) {	case op_asl:	    g_code (op, IL4, mk_high (ap2), NIL_ADDRESS);	    g_code (op_roxl, IL4, mk_low (ap2), NIL_ADDRESS);	    break;	case op_asr:	    g_code (op, IL4, mk_low (ap2), NIL_ADDRESS);	    g_code (op_roxr, IL4, mk_high (ap2), NIL_ADDRESS);	    break;	case op_lsr:	    g_code (op, IL4, mk_low (ap2), NIL_ADDRESS);	    g_code (op_roxr, IL4, mk_high (ap2), NIL_ADDRESS);	    break;	default:	    CANNOT_REACH_HERE ();	}	g_code (op_dbra, IL0, ap1, mk_label (label));	break;    default:	CANNOT_REACH_HERE ();    }    return ap1;}/* * generate code to evaluate a shift node and return the address mode of the * result. */static ADDRESS *g_shift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    TYP    *tp = ep->etp;    ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_VOL | F_COLD));    ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_COLD));    validate (ap1);    ap2 = g_shft (op, (ILEN) tp->size, ap2, ap1);    freeop (ap2);    return mk_legal (ap1, flags, tp);}/* * generate shift equals operators. */static ADDRESS *g_asshift P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    FLAGS   flagx;    ADDRESS *ap1, *ap2, *ap3;    TYP    *tp = ep->etp;    switch (tp->type) {    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:    case bt_ushort:    case bt_short:    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, FALSE);	    }	    flagx = (FLAGS) (F_ALL | F_USES);	    ap1 = g_expr (ep->v.p[0], flagx);	    ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED));	    /* quick constant if 1<=const<=8 */	    if (ap2->mode == am_immed && is_icon (ap2->u.offset)		&& (ap2->u.offset->v.i > 8L || ap2->u.offset->v.i < 1L)) {		ap2 = mk_legal (ap2, F_DREG, tp_char);	    }	    validate (ap1);	    ap3 = data_register ();	    g_move ((ILEN) tp->size, ap1, ap3);	    ap3 = mk_legal (ap3, (FLAGS) (F_DREG | F_COLD), tp);	    g_code (op, IL4, ap2, ap3);	    g_move ((ILEN) tp->size, ap3, ap1);	    freeop (ap3);	    freeop (ap2);	    return mk_legal (ap1, flags, tp);	}	/*lint -fallthrough */#endif /* COLDFIRE */    case bt_int32:    case bt_uint32:    case bt_ulong:    case bt_long:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, FALSE);	}	flagx = (FLAGS) (F_ALL | F_USES);	ap1 = g_expr (ep->v.p[0], flagx);	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED));	/* quick constant if 1<=const<=8 */	if (ap2->mode == am_immed && is_icon (ap2->u.offset)	    && (ap2->u.offset->v.i > 8L || ap2->u.offset->v.i < 1L)) {	    ap2 = mk_legal (ap2, F_DREG, tp_char);	}	validate (ap1);	if (ap1->mode == am_dreg) {	    g_code (op, (ILEN) tp->size, ap2, ap1);	} else {#if 0	    /*	     * assemblers cannot agree on the operands for this special	     * version of the shift operator	     */	    if (tp->size == 2L && is_icon (ep->v.p[1])		&& ep->v.p[1]->v.i == 1) {		g_code (op, 2, ap1, NIL_ADDRESS);		return mk_legal (ap1, flags, tp);	    }#endif	    ap3 = data_register ();	    g_move ((ILEN) tp->size, ap1, ap3);	    g_code (op, (ILEN) tp->size, ap2, ap3);	    g_move ((ILEN) tp->size, ap3, ap1);	    freeop (ap3);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);    default:	FATAL ((__FILE__, "g_asshift", "illegal type %d", tp->type));    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/*============================================================================*//* * generate code to evaluate a divide operator */static ADDRESS *g_div P3 (const EXPR *, ep, FLAGS, flags, BOOL, mod){    ADDRESS *ap1, *ap2;    OPCODE  op = op_divu;    TYP    *tp = ep->etp;    TYP    *tp2 = tp_ushort;    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    switch (tp->type) {    case bt_char:    case bt_schar:	tp = tp_short;	op = op_divs;	/*lint -fallthrough */    case bt_uchar:    case bt_charu:	ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL));	ap1 = g_extend (ap1, tp, tp2);	ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG));	ap2 = g_extend (ap2, tp, tp2);	validate (ap1);	ap1 = g_extend (ap1, tp, tp_long);	g_code (op, IL0, ap2, ap1);	if (mod) {	    g_code (op_swap, IL0, ap1, NIL_ADDRESS);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);    case bt_short:    case bt_int16:	op = op_divs;	/*lint -fallthrough */    case bt_ushort:    case bt_uint16:	ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL));	ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG));	validate (ap1);	ap1 = g_extend (ap1, ep0->etp, tp_long);	g_code (op, IL0, ap2, ap1);	if (mod) {	    g_code (op_swap, IL0, ap1, NIL_ADDRESS);	}	freeop (ap2);	return mk_legal (ap1, flags, tp);    case bt_int32:    case bt_long:	op = op_divs;	/*lint -fallthrough */    case bt_uint32:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep0, (FLAGS) (F_DREG | F_VOL));	ap2 = g_expr (ep1, (FLAGS) (F_ALL & ~F_AREG));	validate (ap1);	g_code (op, IL4, ap2, ap1);	freeop (ap

⌨️ 快捷键说明

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