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

📄 gen86.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    case am_immed:	if (flags & F_IMMED) {	    return ap;		/* mode ok */	}	break;    case am_areg:	if (flags & F_AREG) {	    if ((flags & F_VOL) && !is_temporary_register (ap->preg)) {		break;	    }	    if ((flags & F_NOEDI) && (ap->preg == EDI || ap->preg == ESI)) {		break;	    }	    return ap;	}	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;	    }	    if ((flags & F_ECX) && (ap->preg != ECX)) {		break;	    }	    return ap;	}#ifdef FLOAT_IEEE	if (flags & F_FREG) {	    ap1 = mk_indirect (ESP, mk_const (-2l));	    g_code (op_mov, IL2, ap, ap1);	    g_fcode (op_fild, IL2, 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 == ESI))		break;	    if ((flags & F_VOL) && !is_temporary_register (ap->preg) &&		!is_temporary_register (ap->sreg))		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 reuse 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, IL2, ap, mk_low (ap2));	    return ap2;	}	switch (size) {	case 1L:	    /*	     *       byte transfers from %edi/%esi to a scratch register come	     *        up here	     */	    if (ap->mode == am_dreg && (ap->preg == ESI || ap->preg == EDI)) {		size = 2L;	    }	    /*FALLTHRU */	case 2L:	    ap2 = data_register ();	    g_code (op_mov, (ILEN) size, ap, ap2);	    return ap2;	case 4L:	    ap2 = mdata_register ();	    g_code (op_mov, IL2, mk_low (ap), mk_low (ap2));	    g_code (op_mov, IL2, mk_high (ap), mk_high (ap2));	    return ap2;	default:	    break;	}    }    if (flags & F_AREG) {	freeop (ap);		/* maybe we can reuse it */	switch (size) {	case 1L:	    ap2 = address_register ();	    ap1 = data_register ();	    g_code (op_mov, (ILEN) size, ap, ap1);	    ap1 = g_extend (ap1, tp, tp_short);	    g_code (op_mov, 2L, ap1, ap2);	    freeop (ap1);	    return ap2;	case 2L:	    ap2 = address_register ();	    g_code (op_mov, (ILEN) size, ap, ap2);	    return ap2;	default:	    break;	}    }#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) size, 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_fcode (op_fild, (ILEN) size, 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:	    switch (ap->mode) {#ifdef FLOAT_IEEE	    case am_freg:		g_fcode (op_fstp, (ILEN) size, ap2, NIL_ADDRESS);		break;#endif /* FLOAT_IEEE */	    default:		g_code (op_mov, (ILEN) size, ap, ap2);		break;	    }	    break;	case 4L:	    switch (ap->mode) {#ifdef FLOAT_IEEE	    case am_freg:		g_fcode (op_fstp, (ILEN) size, ap2, NIL_ADDRESS);		break;#endif /* FLOAT_IEEE */	    case am_mreg:		g_code (op_mov, IL2, mk_high (ap), mk_high (ap2));		g_code (op_mov, IL2, mk_low (ap), mk_low (ap2));		break;	    default:		g_code (op_mov, (ILEN) size, ap, ap2);	    }	    break;	case 8L:	case 10L:	    switch (ap->mode) {#ifdef FLOAT_IEEE	    case am_freg:		g_fcode (op_fstp, (ILEN) size, ap2, NIL_ADDRESS);		break;#endif /* FLOAT_IEEE */	    default:		break;	    }	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	return ap2;    }    FATAL (	   (__FILE__, "mk_legal", "mode = %d, flags = 0x%x", ap->mode,	    flags));    return NIL_ADDRESS;}static ADDRESS *g_index P1 (const EXPR *, ep){    ADDRESS *ap1, *ap2;    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    ap1 = g_expr (ep0, (FLAGS) (F_AREG | F_IMMED | F_VOL));    switch (ap1->mode) {    case am_areg:	ap2 = g_expr (ep1, F_ALL);	validate (ap1);	break;    case am_immed:	ap2 = ap1;	ap1 = g_expr (ep1, (FLAGS) (F_AREG | F_IMMED));	validate (ap2);	break;    default:	CANNOT_REACH_HERE ();    }    switch (ap1->mode) {    case am_areg:	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_areg:	    g_code (op_add, IL2, 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_AREG | F_VOL), tp_pointer);    }    g_code (op_add, IL2, 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 (tp->type != bt_void) {	    g_code (op_and, ilen, mk_immed ((IVAL) bitmask ((BITSIZE) width)),		    ap);	}    }}/* *   'ap' which has the size of type 'tp1' is to be extended to *   be the size of 'tp2'. */static ADDRESS *g_extend P3 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2){    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:	    if (ap->preg == EAX) {		g_code (op_cbw, IL0, NIL_ADDRESS, NIL_ADDRESS);	    } else {		if (target_option >= target_80186) {		    /* 80186 code */		    g_code (op_asl, IL2, mk_immed (8L), mk_low (ap));		    g_code (op_asr, IL2, mk_immed (8L), mk_low (ap));		} else {		    g_code (op_xchg, IL2, mk_low (ap), mk_reg (EAX));		    g_code (op_cbw, IL0, NIL_ADDRESS, NIL_ADDRESS);		    g_code (op_xchg, IL2, mk_reg (EAX), mk_low (ap));		}	    }	    break;	case bt_uchar:	case bt_charu:	    g_code (op_and, IL2, mk_immed (255L), ap);	    break;	case bt_int16:	case bt_uint16:	case bt_short:	case bt_ushort:	    break;	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	break;    case bt_int32:    case bt_long:    case bt_uint32:    case bt_ulong:    case bt_pointer32:	freeop (ap);	ap = mdata_register ();	switch (tp1->type) {	case bt_char:	case bt_schar:	    if (ap->preg == EAX) {		g_code (op_cbw, IL0, NIL_ADDRESS, NIL_ADDRESS);	    } else {		if (target_option >= target_80186) {		    /* 80186 code */		    g_code (op_asl, IL2, mk_immed (8L), mk_low (ap));		    g_code (op_asr, IL2, mk_immed (8L), mk_low (ap));		} else {		    g_code (op_xchg, IL2, mk_low (ap), mk_reg (EAX));		    g_code (op_cbw, IL0, NIL_ADDRESS, NIL_ADDRESS);		    g_code (op_xchg, IL2, mk_reg (EAX), mk_low (ap));		}	    }	    /*FALLTHRU */	case bt_int16:	case bt_short:	    if (ap->preg == EAX) {		g_code (op_cwd, IL0, NIL_ADDRESS, NIL_ADDRESS);	    } else {		g_code (op_mov, IL2, mk_immed (0L), mk_high (ap));		g_code (op_or, IL2, mk_low (ap), mk_low (ap));		g_code (op_bra, IL0, mk_label (nextlabel), NIL_ADDRESS);		g_code (op_not, IL2, mk_high (ap), NIL_ADDRESS);		g_label (nextlabel++);	    }	    break;	case bt_charu:	case bt_uchar:	    if (target_option >= target_80186) {		/* 80186 code */		g_code (op_shl, IL2, mk_immed (8L), mk_low (ap));		g_code (op_shr, IL2, mk_immed (8L), mk_low (ap));	    } else {		g_code (op_and, IL2, mk_immed (0xFF00L), mk_low (ap));	    }	    /*FALLTHRU */	case bt_uint16:	case bt_ushort:	case bt_pointer16:	    g_code (op_mov, IL2, mk_immed (0L), mk_high (ap));	    break;	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	break;    default:	FATAL (	       (__FILE__, "g_extend", "type1=%d, type2=%d", tp1->type,		tp2->type));	break;    }    return ap;}/*   * return the addressing mode of a dereferenced node. */static ADDRESS *g_deref P2 (const EXPR *, ep, TYP *, tp){    ADDRESS *ap1;    /*     *       If a reference to a structure/union is required, return a     *       pointer to the struct instead.     */    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:	return mk_indirect (regframe, mk_const (ep->v.i));    default:	ap1 = g_expr (ep, (FLAGS) (F_AREG | 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);}/* * 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:	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);    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));	switch (op) {	case op_neg:	    g_code (op, IL2, mk_low (ap), NIL_ADDRESS);	    g_code (op_adc, IL2, mk_immed (0L), mk_high (ap));	    g_code (op, IL2, mk_high (ap), NIL_ADDRESS);	    break;	case op_not:	    g_code (op, IL2, mk_low (ap), NIL_ADDRESS);	    g_code (op, IL2, mk_high (ap), NIL_ADDRESS);	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	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_fcode (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;

⌨️ 快捷键说明

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