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

📄 gen86.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    }    return size;}/* * push a list of parameters onto the stack and return the number of * bytes that the parameters occupy. */static SIZE g_parms P1 (const EXPR *, ep){    SIZE    size;    is_parameter++;    for (size = 0L; ep != NIL_EXPR; ep = ep->v.p[1]) {	size += push_param (ep->v.p[0]);    }    is_parameter--;    return size;}static ADDRESS *func_result P3 (FLAGS, flags, SIZE, bytes, TYP *, tp){    ADDRESS *ap;    stack_offset += bytes;    if (is_parameter) {	g_stack (bytes);    }    if (flags & F_NOVALUE) {	return NIL_ADDRESS;    }    switch (tp->type) {#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	ap = float_register ();	break;#endif /* FLOAT_IEEE */    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	if (!(flags & F_DREG)) {	    FATAL ((__FILE__, "func_result", "not F_DREG"));	}	ap = mdata_register ();	g_code (op_mov, IL2, mk_reg (reg_usage->result->reg[0]), mk_low (ap));	g_code (op_mov, IL2, mk_reg (reg_usage->result->reg[1]),		mk_high (ap));	break;    default:	if (flags & F_DREG) {	    ap = data_register ();	} else if (flags & F_AREG) {	    ap = address_register ();	} else {	    FATAL (		   (__FILE__, "func_result", "not F_DREG or F_AREG (%d)",		    flags));	}	if (ap->preg != reg_usage->result->reg[0]) {	    g_code (op_mov, IL2, &eax_reg, ap);	}	break;    }    return ap;}/* * generate a function call node and return the address mode of the result. */static ADDRESS *g_fcall P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap, *ap1;    SIZE    size;    EXPR   *ep0 = ep->v.p[0];    REG     reg;    if (!is_parameter && ep->nodetype != en_call) {	switch (stackopt_option) {	case OPT_SAFE:	    /*	     *       no stack optimisation	     */	    g_stack (stack_offset);	    break;	case OPT_MINIMUM:	    /*	     *       "Minimum" stack optimisation.  Perform a stack optimisation	     *       unless:	     *       1.  The alloca() routine is called	     *       2.  The function call is via a variable	     *       3.  The function starts with an underscore character	     */	    if ((ep0->nodetype != en_nacon) ||		(ep0->v.str[0] == (CHAR) '_') || (ep0->v.str == alloca_name)) {		g_stack (stack_offset);	    }	    break;	case OPT_AVERAGE:	    /*	     *       "Average" stack optimisation.   This will not suppress	     *       the optimisation on encountering calls to functions	     *       whose names begin with underscore.	     */	    if ((ep0->nodetype != en_nacon) || (ep0->v.str == alloca_name)) {		g_stack (stack_offset);	    }	    break;	case OPT_MAXIMUM:	    /*	     *       "Maximum" stack optimisation.   This will not suppress	     *       the optimisation on encountering calls to functions	     *       whose names begin with underscore or via a function	     *       variable.	     */	    if ((ep0->nodetype == en_nacon) && (ep0->v.str == alloca_name)) {		g_stack (stack_offset);	    }	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}    }    /* push any used registers */    temp_inv ();    for (reg = EAX; reg <= EBP; reg++) {	if (regsave_option & MEMBER (reg)) {	    g_code (op_push, IL2, mk_reg (reg), NIL_ADDRESS);	}    }    size = g_parms (ep->v.p[1]);	/* generate parameters */    /*     * for functions returning a structure or a union, push a pointer to the     * return value as additional argument The scratch space will be     * allocated in the stack frame of the calling function.     */    if (is_structure_type (ep->etp)) {	ap = mk_scratch (ep->etp->size);	ap1 = address_register ();	g_code (op_lea, IL2, ap, ap1);	g_code (op_push, IL2, ap1, NIL_ADDRESS);	freeop (ap1);	freeop (ap);	size += tp_pointer->size;    }    if (ep->nodetype == en_call) {	size = 0L;    }    /* call the function */    switch (ep0->nodetype) {    case en_nacon:    case en_labcon:	ap = mk_direct (ep0);	break;    default:	ap = g_expr (ep0, F_AREG);	ap = copy_addr (ap, am_ind);	ap->u.offset = NIL_EXPR;	freeop (ap);	break;    }    g_code (op_call, IL0, ap, NIL_ADDRESS);    for (reg = EBP + 1; reg > EAX; reg--) {	if (regsave_option & MEMBER ((int) reg - 1)) {	    g_stack (size);	    size = 0L;	    g_code (op_pop, IL2, mk_reg ((REG) ((int) reg - 1)), NIL_ADDRESS);	}    }    ap = func_result (flags, size, ep->etp);    return mk_legal (ap, flags, ep->etp);}/* * generates code for a en_cast node */static ADDRESS *g_cast P4 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2, FLAGS,			   flags){    ADDRESS *ap1;    if (flags & F_NOVALUE) {	freeop (ap);	return NIL_ADDRESS;    }    /*     *       Casts to a narrower integer type are no-ops since the 8086 is     *       low-endian to avoid code duplication, float/double is shared     */    switch (tp2->type) {	/* type to cast to */#ifdef FLOAT_IEEE    case bt_float:    case bt_double:    case bt_longdouble:	switch (tp1->type) {	case bt_float:	    if (tp2->type != bt_float && ap->mode == am_freg) {		/*		 *   A double or long double value which is in the FP		 *   registers must be stored and then reloaded in order		 *   to correctly round the bits of a float.  Although		 *   this looks like a NULL operation is isn't!		 */		ap1 = mk_scratch (tp_float->size);		g_fcode (op_fstp, IL4, ap1, NIL_ADDRESS);		g_fcode (op_fld, IL4, ap1, NIL_ADDRESS);		freeop (ap1);	    }	    /*FALLTHRU */	case bt_double:	    ap = mk_legal (ap, F_FREG, tp1);	    return mk_legal (ap, flags, tp2);	case bt_uchar:	case bt_schar:	case bt_char:	case bt_charu:	    ap = g_cast (ap, tp1, tp_short, F_ALL);	    /*FALLTHRU */	case bt_short:	case bt_int16:	    /*	     * For the conversion signed short --> float/double, there is	     * a 8087 instruction	     */	    switch (ap->mode) {	    default:		/*		 *   FPU-code for a signed short that is in a register:		 *   the value is written to the stack and loaded from		 *   there since there is no direct path between CPU		 *   and FPU registers.		 */		ap1 = mk_scratch (2L);		g_code (op_mov, IL2, ap, ap1);		g_fcode (op_fild, IL2, ap1, NIL_ADDRESS);		freeop (ap1);		break;	    case am_direct:	    case am_indx:	    case am_indx2:		g_fcode (op_fild, IL2, ap, NIL_ADDRESS);		break;	    }	    freeop (ap);	    ap = float_register ();	    return mk_legal (ap, flags, tp2);	case bt_pointer16:	case bt_ushort:	case bt_uint16:	    ap = g_cast (ap, tp1, tp_long, F_ALL);	    /*FALLTHRU */	case bt_int32:	case bt_long:	    /*	     *       For the conversion signed long --> float/double, there is	     *       a 8087 instruction	     */	    switch (ap->mode) {	    default:		/*		 *   FPU-code for a signed short that is in a register:		 *   the value is written to and stack and loaded from		 *   there since there is no direct path between CPU		 *   and FPU registers.		 */		ap1 = mk_scratch (4L);		g_code (op_mov, IL2, mk_low (ap), mk_low (ap1));		g_code (op_mov, IL2, mk_high (ap), mk_high (ap1));		g_fcode (op_fild, IL4, ap1, NIL_ADDRESS);		freeop (ap1);		break;	    case am_direct:	    case am_indx:	    case am_indx2:		g_fcode (op_fild, IL4, ap, NIL_ADDRESS);		break;	    }	    freeop (ap);	    ap = float_register ();	    return mk_legal (ap, flags, tp2);	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    ap = mk_legal (ap, F_DREG, tp1);	    ap1 = mk_scratch (8L);	    g_code (op_mov, IL2, mk_offset (ap1, 6L), mk_immed (0L));	    g_code (op_mov, IL2, mk_offset (ap1, 4L), mk_immed (0L));	    g_code (op_mov, IL2, mk_high (ap1), mk_high (ap));	    g_code (op_mov, IL2, mk_low (ap1), mk_low (ap));	    g_fcode (op_fild, IL4, ap1, NIL_ADDRESS);	    freeop (ap1);	    freeop (ap);	    ap = float_register ();	    return mk_legal (ap, flags, tp2);	default:	    break;	}	break;#endif /* FLOAT_IEEE */    case bt_uchar:    case bt_schar:    case bt_char:    case bt_charu:	flags = (FLAGS) (flags | F_NOEDI);	switch (tp1->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:	case bt_pointer16:	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    if (ap->mode == am_mreg) {		freeop (ap);		ap1 = data_register ();		g_code (op_mov, IL1, mk_low (ap), ap1);		ap = ap1;	    }	    return mk_legal (ap, flags, tp2);#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    freeop (ap);	    ap = data_register ();	    ap1 = mk_scratch (2L);	    g_fcode (op_fistp, IL2, ap1, NIL_ADDRESS);	    g_fcode (op_fwait, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_mov, IL2, ap1, ap);	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	default:	    break;	}	break;    case bt_short:    case bt_int16:	switch (tp1->type) {	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_short:	case bt_ushort:	case bt_int16:	case bt_uint16:	case bt_pointer16:	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    ap1 = mk_legal (ap, flags, tp2);	    freeop (ap1);	    ap = data_register ();	    g_code (op_mov, IL2, mk_low (ap1), ap);	    return mk_legal (ap, flags, tp2);#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    freeop (ap);	    ap = data_register ();	    ap1 = mk_scratch (2L);	    g_fcode (op_fistp, IL2, ap1, NIL_ADDRESS);	    g_fcode (op_fwait, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_mov, IL2, ap1, ap);	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	default:	    break;	}	break;    case bt_ushort:    case bt_uint16:    case bt_pointer16:	switch (tp1->type) {	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_short:	case bt_ushort:	case bt_int16:	case bt_uint16:	case bt_pointer16:	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    ap1 = mk_legal (ap, flags, tp2);	    freeop (ap1);	    ap = data_register ();	    g_code (op_mov, IL2, ap, mk_low (ap1));	    return mk_legal (ap, flags, tp2);#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    freeop (ap);	    ap = data_register ();	    ap1 = mk_scratch (2L);	    g_fcode (op_fistp, IL2, ap1, NIL_ADDRESS);	    g_fcode (op_fwait, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_mov, IL2, ap1, ap);	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	default:	    break;	}	break;    case bt_int32:    case bt_long:	switch (tp1->type) {	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	case bt_short:	case bt_ushort:	case bt_int16:	case bt_uint16:	case bt_pointer16:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    return mk_legal (ap, flags, tp2);#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    freeop (ap);	    ap = mdata_register ();	    ap1 = mk_scratch (4L);	    g_fcode (op_fistp, IL4, ap1, NIL_ADDRESS);	    g_fcode (op_fwait, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_mov, IL2, mk_low (ap1), mk_low (ap));	    g_code (op_mov, IL2, mk_high (ap1), mk_high (ap));	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	default:	    break;	}	break;    case bt_uint32:    case bt_ulong:    case bt_pointer32:	switch (tp1->type) {	case bt_charu:	case bt_uchar:	case bt_char:	case bt_schar:	case bt_short:	case bt_ushort:	case bt_int16:	case bt_uint16:	case bt_pointer16:	    ap = g_extend (ap, tp1, tp2);	    return mk_legal (ap, flags, tp2);	case bt_int32:	case bt_long:	case bt_uint32:	case bt_ulong:	case bt_pointer32:	    return mk_legal (ap, flags, tp2);#ifdef FLOAT_IEEE	case bt_float:	case bt_double:	case bt_longdouble:	    ap = mk_legal (ap, F_FREG, tp1);	    freeop (ap);	    ap = mdata_register ();	    ap1 = mk_scratch (8L);	    g_fcode (op_fistp, IL8, ap1, NIL_ADDRESS);	    g_fcode (op_fwait, IL0, NIL_ADDRESS, NIL_ADDRESS);	    g_code (op_mov, IL2, mk_low (ap1), mk_low (ap));	    g_code (op_mov, IL2, mk_high (ap1), mk_high (ap));	    freeop (ap1);	    return mk_legal (ap, flags, tp2);#endif /* FLOAT_IEEE */	default:	    break;	}    default:	break;    }    FATAL ((__FILE__, "g_cast", "type1=%d, type2=%d", tp1->type, tp2->type));    return NIL_ADDRESS;}/* * generate code to do a comparison of the two operands of node. */static void g_compare P4 (const EXPR *, ep, OPCODE, opu, OPCODE, ops, LABEL, label1){    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    ADDRESS *ap1, *ap2;    FLAGS   flagx;    LABEL   label2;    OPCODE  op1, op2, op3, op4;   

⌨️ 快捷键说明

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