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

📄 gen386.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
static ADDRESS *mk_legal P3 (ADDRESS *, ap, FLAGS, flags, TYP *, tp){    ADDRESS *ap2;    ILEN    ilen = (ILEN) tp->size;    if (flags & F_NOVALUE) {	if (ap != NIL_ADDRESS) {#ifdef FLOAT_IEEE	    if (ap->mode == am_freg) {		g_fcode (op_fstp, IL10, mk_reg (ST0), NIL_ADDRESS);	    }#endif /* FLOAT_IEEE */	    freeop (ap);	}	return NIL_ADDRESS;    }    if (ap == NIL_ADDRESS) {	FATAL ((__FILE__, "mk_legal", "ap == 0"));    }    switch (ap->mode) {    case am_immed:	if (flags & F_IMMED) {	    return ap;		/* mode ok */	}	break;    case am_dreg:	if (flags & F_DREG) {	    if ((flags & F_VOL) && !is_temporary_register (ap->preg)) {		break;	    }	    if ((flags & F_NOEDI) && (ap->preg == EDI || ap->preg == ESI)) {		break;	    }	    if ((flags & F_NOECX) && (ap->preg == ECX)) {		break;	    }	    if (flags & F_EAXEDX) {		break;	    }	    return ap;	}#ifdef FLOAT_IEEE	if (flags & F_FREG) {	    ADDRESS *ap1;	    ap1 = mk_indirect (ESP, mk_const (-4L));	    g_code (op_mov, IL4, ap, ap1);	    g_code (op_fild, IL4, ap1, NIL_ADDRESS);	    freeop (ap);	    ap = float_register ();	    return ap;	}	break;    case am_freg:	if (flags & F_FREG) {	    return ap;	}#endif /* FLOAT_IEEE */	break;    case am_mreg:	if (flags & F_DREG) {	    if ((flags & F_NOEDI) && ((ap->preg == EDI || ap->preg == ESI) ||				      (ap->sreg == EDI || ap->sreg == EDI)))		break;	    if ((flags & F_VOL) && !is_temporary_register (ap->preg) &&		!is_temporary_register (ap->sreg))		break;	    if ((flags & F_EAXEDX)		&& ((ap->preg != EAX) || (ap->sreg != EDX))) {		break;	    }	    return ap;	}	break;    case am_ind:    case am_indx:    case am_indx2:    case am_direct:	if (flags & F_MEM) {	    return ap;	}	break;    default:	FATAL (	       (__FILE__, "mk_legal", "mode == %d, flags = 0x%x", ap->mode,		flags));    }    if (flags & F_DREG) {	freeop (ap);		/* maybe we can use it */	if (flags & F_ECX) {	    ap2 = cx_register ();	    g_code (op_mov, IL2, ap, ap2);	    return ap2;	}	if (flags & F_EAXEDX) {	    ap2 = axdx_register ();	    g_code (op_mov, IL4, ap, mk_low (ap2));	} else {	    ap2 = data_register ();	    /*	     * byte transfers from %edi/%esi to a scratch register come up here	     */	    if (ap->mode == am_dreg && (ap->preg == ESI || ap->preg == EDI)		&& ilen == IL1) {		ilen = IL2;	    }	    g_code (op_mov, ilen, ap, ap2);	}	return ap2;    }#ifdef FLOAT_IEEE    if (flags & F_FREG) {	freeop (ap);	switch (tp->type) {	case bt_float:	case bt_double:	case bt_longdouble:	    ap2 = float_register ();	    g_fcode (op_fld, ilen, ap, NIL_ADDRESS);	    return ap2;	case bt_char:	case bt_schar:/*KDW */	case bt_short:	case bt_int16:	case bt_long:	case bt_int32:	    ap2 = float_register ();	    g_code (op_fild, ilen, ap, NIL_ADDRESS);	    return ap2;	default:	    break;	}    }#endif /* FLOAT_IEEE */    if (flags & F_MEM) {	freeop (ap);	ap2 = mk_scratch (tp->size);	switch (tp->size) {	case 1L:	case 2L:	case 4L:	    switch (ap->mode) {#ifdef FLOAT_IEEE	    case am_freg:		g_fcode (op_fstp, ilen, ap2, NIL_ADDRESS);		break;#endif /* FLOAT_IEEE */	    default:		g_code (op_mov, ilen, ap, ap2);		break;	    }	    break;	case 8L:	    switch (ap->mode) {#ifdef FLOAT_IEEE	    case am_freg:		g_fcode (op_fstp, ilen, ap2, NIL_ADDRESS);		break;#endif /* FLOAT_IEEE */	    case am_mreg:		g_code (op_mov, IL4, mk_high (ap), mk_high (ap2));		g_code (op_mov, IL4, mk_low (ap), mk_low (ap2));		break;	    default:		g_code (op_mov, ilen, ap, ap2);		break;	    }	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	return ap2;    }    FATAL (	   (__FILE__, "mk_legal", "mode = %d, flags = 0x%x", ap->mode,	    flags));    return NIL_ADDRESS;}/* * 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;    ap1 = g_expr (ep->v.p[0], (FLAGS) (F_DREG | F_IMMED | F_VOL));    switch (ap1->mode) {    case am_dreg:	ap2 = g_expr (ep->v.p[1], F_ALL);	validate (ap1);	break;    case am_immed:	ap2 = ap1;	ap1 = g_expr (ep->v.p[1], (FLAGS) (F_DREG | F_IMMED | F_VOL));	break;    default:	CANNOT_REACH_HERE ();    }    switch (ap1->mode) {    case am_dreg:	if (!is_temporary_register (ap1->preg)) {	    ap1 = copy_addr (ap1, ap1->mode);	    switch (ap2->mode) {	    case am_dreg:		/* 0(Rn,Rm) */		ap1->mode = am_indx2;		ap1->sreg = ap2->preg;		ap1->deep = ap2->deep;		ap1->u.offset = mk_const (0L);		return ap1;	    default:		break;	    }	}	break;    case am_immed:	switch (ap2->mode) {	case am_immed:	    ap1 = copy_addr (ap1, am_direct);	    ap1->u.offset = mk_add (ap1->u.offset, ap2->u.offset);	    return ap1;	case am_dreg:	    g_code (op_add, IL4, ap1, ap2);	    ap2 = copy_addr (ap2, am_ind);	    return ap2;	default:	    CANNOT_REACH_HERE ();	}	break;    default:	CANNOT_REACH_HERE ();    }    freeop (ap2);    if (!is_temporary_register (ap1->preg)) {	ap1 = mk_legal (ap1, (FLAGS) (F_DREG | F_VOL), tp_pointer);    }    g_code (op_add, IL4, ap2, ap1);    ap1 = copy_addr (ap1, am_ind);    return ap1;}/* * rotate a bitfield into the required position (assumes ap is a register) */static void g_rotate P5 (ADDRESS *, ap, ILEN, ilen, int, offset, TYP *, tp,			 int, width){    OPCODE  op;    switch (tp->type) {    case bt_int16:    case bt_int32:	/* sign bitfield */	g_code (op_asl, ilen, mk_immed (32L - (IVAL) offset - (IVAL) width),		ap);	g_code (op_asr, ilen, mk_immed (32L - (IVAL) width), ap);	break;    default:	/* offset is in range -31 .. 31 */	if (offset < 0) {	    offset += ilen * 8;	}	/* offset in range 0..31 */	if (offset != 0) {	    if (offset > 15) {		op = op_rol;		offset = 32 - offset;	    } else {		op = op_ror;	    }	    g_code (op, ilen, mk_immed ((IVAL) offset), ap);	}	if (!is_void (tp)) {	    g_code (op_and, ilen, mk_immed ((IVAL) bitmask ((BITSIZE) width)),		    ap);	}    }}static ADDRESS *g_extend P3 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2){    OPCODE  op;    ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), tp1);    switch (tp2->type) {    case bt_int16:    case bt_uint16:    case bt_short:    case bt_ushort:	switch (tp1->type) {	case bt_char:	case bt_schar:	    op = op_movsbw;	    g_code (op, IL0, ap, ap);	    break;	case bt_uchar:	case bt_charu:	    op = op_movzbw;	    g_code (op, IL0, ap, ap);	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	break;    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	switch (tp1->type) {	case bt_char:	case bt_schar:	    op = op_movsbl;	    g_code (op, IL0, ap, ap);	    break;	case bt_int16:	case bt_short:	    op = op_movswl;	    g_code (op, IL0, ap, ap);	    break;	case bt_uchar:	case bt_charu:	    op = op_movzbl;	    g_code (op, IL0, ap, ap);	    break;	case bt_uint16:	case bt_ushort:	    op = op_movzwl;	    g_code (op, IL0, ap, ap);	    break;	case bt_int32:	case bt_uint32:	case bt_long:	case bt_ulong:	case bt_pointer32:	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}    default:	break;    }    return ap;}/* * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P2 (const EXPR *, ep, TYP *, tp){    ADDRESS *ap1;    if (is_structure_type (tp) || is_array_assignment (tp)) {	return g_expr (ep, F_ALL);    }    switch (ep->nodetype) {    case en_add:	return g_index (ep);    case en_autocon:	ap1 = mk_indirect (regframe, mk_const (ep->v.i));	return ap1;    default:	ap1 = g_expr (ep, (FLAGS) (F_DREG | F_IMMED));	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;    ap = g_deref (ep->v.p[0], ep->etp);    ap = mk_legal (ap, (FLAGS) (F_DREG | F_VOL), ep->etp);    g_rotate (ap, (ILEN) ep->etp->size, (int) ep->v.bit.offset, ep->etp,	      (int) ep->v.bit.width);    return mk_legal (ap, flags, ep->etp);}/*============================================================================*/#ifdef FLOAT_IEEEstatic void push_rtl_params P2 (const EXPR *, ep1, const EXPR *, ep2){    ADDRESS *ap, *ap2;    is_parameter++;    temp_inv ();    ap = g_expr (ep1, F_MEM);    ap2 = data_register ();    g_code (op_lea, IL4, ap, ap2);    g_code (op_push, IL4, ap2, NIL_ADDRESS);    freeop (ap2);    freeop (ap);    if (ep2) {	ap = g_expr (ep2, F_MEM);	ap2 = data_register ();	g_code (op_lea, IL0, ap, ap2);	g_code (op_push, IL4, ap2, NIL_ADDRESS);	freeop (ap2);	freeop (ap);    }}#endif /* FLOAT_IEEE *//*============================================================================*//* * generate code to evaluate a unary minus or complement. */static ADDRESS *g_unary P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap;    switch (ep->etp->type) {    case bt_char:    case bt_charu:    case bt_uchar:    case bt_schar:    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) ep->etp->size, ap, NIL_ADDRESS);	return mk_legal (ap, flags, ep->etp);#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	ap = g_expr (ep->v.p[0], F_FREG);	g_code (op_fchs, IL0, NIL_ADDRESS, NIL_ADDRESS);	return mk_legal (ap, flags, ep->etp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_unary", "illegal type or operation"));	break;    }    return NIL_ADDRESS;}/* * generate code to evaluate a autoincrement/autodecrement node */static ADDRESS *g_aincdec P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;#ifdef FLOAT_IEEE    ILEN    ilen;#endif /* FLOAT_IEEE */    switch (ep->etp->type) {    case bt_char:    case bt_charu:    case bt_uchar:    case bt_schar:    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:	if (ep->v.p[0]->nodetype == en_fieldref) {	    return g_asbitfield (ep, flags, op, FALSE);	}	if (flags & F_NOVALUE) {	    ap1 = NIL_ADDRESS;	    ap2 = g_expr (ep->v.p[0], F_ALL);	} else {	    ap1 = data_register ();	    ap2 = g_expr (ep->v.p[0], (FLAGS) (F_MEM | F_DREG));	    validate (ap1);	    g_code (op_mov, (ILEN) ep->etp->size, ap2, ap1);	}	g_code (op, (ILEN) ep->etp->size, mk_immed (ep->v.p[1]->v.i), ap2);	freeop (ap2);	return mk_legal (ap1, flags, ep->etp);#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	if (flags & F_NOVALUE) {	    return g_asbin (ep, flags, op);	}	ilen = (ILEN) ep->etp->size;	ap1 = g_expr (ep->v.p[0], F_MEM);	g_fcode (op_fld, ilen, ap1, NIL_ADDRESS);	/* save result */	ap2 = g_expr (ep->v.p[1], F_FREG);	validate (ap1);	switch (op) {	case op_add:	    g_fcode (op_fadd, ilen, ap1, NIL_ADDRESS);	    break;	case op_sub:	    g_fcode (op_fsubr, ilen, ap1, NIL_ADDRESS);	    break;	default:	    FATAL ((__FILE__, "g_aincdec", "illegal op %d", op));	}	freeop (ap2);	freeop (ap1);	g_fcode (op_fstp, ilen, ap1, NIL_ADDRESS);	ap1 = float_register ();	return mk_legal (ap1, flags, ep->etp);#endif /* FLOAT_IEEE */    default:	FATAL ((__FILE__, "g_aincdec", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/*============================================================================*//* * generate code to evaluate a binary node and return the addressing mode of * the result. */static ADDRESS *g_bin P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    TYP    *tp = ep->etp;    FLAGS   f = F_ALL;    switch (tp->type) {    case bt_char:    case bt_charu:    case bt_uchar:    case bt_schar:

⌨️ 快捷键说明

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