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

📄 gen68k.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
	    break;	case 12L:	    g_move8 (ap, ap2);	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	return ap2;    }    FATAL ((__FILE__, "mk_legal", ""));
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/* * If ap is an immediate value between -128 and 127 and the size of the * operation is 4 bytes then load the value into a data register if * there is one free. */static ADDRESS *mk_quick P2 (ADDRESS *, ap, const TYP *, tp){    if (tp->size == 4L && is_free_data () &&	ap->mode == am_immed && is_byte (ap->u.offset)) {	ap = mk_legal (ap, F_DREG, tp);    }    return ap;}/* * If ap is an immediate value between -128 and 127, excluding the values * 1 to 8, and the size of the operation is 4 bytes then load the value into * a data register if there is one free. * This is used for "quick" operations to the "add" and "sub" commands * which aren't covered by the addq and subq instructions. * Don't "quick"en the value 0 as this is best left for the peephole * optimiser as it can then generally remove the instruction. */static ADDRESS *mk_quick2 P2 (ADDRESS *, ap, const TYP *, tp){    if (ap->mode == am_immed && is_icon (ap->u.offset) &&	(ap->u.offset->v.i < 0L || ap->u.offset->v.i > 8L)) {	ap = mk_quick (ap, tp);    }    return ap;}/* * add a compiler generated label to the peep list. */PRIVATE void g_label P1 (LABEL, labno){    sync_stack ();    g_code (op_label, IL0, mk_label (labno), NIL_ADDRESS);}#ifdef DEBUGOPT/* * add a source line number to the peep list. */PRIVATE void g_line P2 (LINE, line, const CHAR *, linetxt){    g_code (op_line, IL0, mk_line (line), mk_linetxt (linetxt));}#endif /*DEBUGOPT *//* * add a conditional branch instruction to the peep list. */static void g_cbranch P2 (OPCODE, op, LABEL, labno){    sync_stack ();    g_code (op, IL0, mk_label (labno), NIL_ADDRESS);}/* * add a branch instruction to the peep list. */PRIVATE void g_branch P1 (LABEL, labno){    g_cbranch (op_bra, labno);}/* * adjust the stack by "bytes" bytes. */PRIVATE void g_stack P1 (SIZE, bytes){    if (bytes != 0L) {	/* adjust stack pointer */	g_add (IL4, mk_immed ((IVAL) bytes), mk_reg (STACKPTR));	stack_offset -= bytes;	if (max_stack_adjust < bytes) {	    max_stack_adjust = bytes;	}    }}/* * Generate an instruction which takes an immediate option with optimal * (for space) instruction(s). */static void g_immed P4 (OPCODE, op, const TYP *, tp, IVAL, i, ADDRESS *, ap){    ADDRESS *ap1 = mk_immed (i);    ap1 = mk_quick (ap1, tp);    g_code (op, (ILEN) tp->size, ap1, ap);    freeop (ap1);}static void g_immed2 P4 (OPCODE, op, const TYP *, tp, IVAL, i, ADDRESS *, ap){    ADDRESS *ap1 = mk_immed (i);    ap1 = mk_quick2 (ap1, tp);    g_code (op, (ILEN) tp->size, ap1, ap);    freeop (ap1);}static ADDRESS *g_extend P3 (ADDRESS *, ap, const TYP *, tp1, const TYP *, tp2){    if (ap->mode == am_immed) {	return ap;    }    switch (tp2->type) {    case bt_int16:    case bt_uint16:    case bt_short:    case bt_ushort:	switch (tp1->type) {	case bt_char:	case bt_schar:	    ap = mk_legal (ap, F_DREG, tp1);	    g_code (op_ext, IL2, ap, NIL_ADDRESS);	    break;	case bt_bool:	case bt_uchar:	case bt_charu:	    g_code (op_and, IL2, mk_immed ((IVAL) 255L), ap);
	    break;	default:	    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:	    ap = mk_legal (ap, F_DREG, tp1);	    if (target_option >= target_coldfire) {		g_code (op_extb, IL4, ap, NIL_ADDRESS);	    } else {		g_code (op_ext, IL2, ap, NIL_ADDRESS);		g_code (op_ext, IL4, ap, NIL_ADDRESS);	    }	    break;	case bt_int16:	case bt_short:	    ap = mk_legal (ap, F_DREG, tp1);	    g_code (op_ext, IL4, ap, NIL_ADDRESS);	    break;	case bt_bool:	case bt_uchar:	case bt_charu:	    g_code (op_and, IL4, mk_immed ((IVAL) 255L), ap);	    break;	case bt_uint16:	case bt_ushort:	    g_code (op_and, IL4, mk_immed ((IVAL) 65535L), ap);	    break;	default:	    break;	}	break;#ifdef LONGLONG_SUPPORT    case bt_longlong:    case bt_ulonglong:	switch (tp1->type) {	    ADDRESS *ap1;	case bt_char:	case bt_schar:	    ap = mk_legal (ap, F_DREG | F_AREG | F_MEM, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL1, ap, mk_high (ap1));	    if (target_option >= target_coldfire) {		g_code (op_extb, IL4, mk_high (ap1), NIL_ADDRESS);	    } else {		g_code (op_ext, IL2, mk_high (ap1), NIL_ADDRESS);		g_code (op_ext, IL4, mk_high (ap1), NIL_ADDRESS);	    }	    g_code (op_slt, IL0, mk_low (ap1), NIL_ADDRESS);	    VOIDCAST g_extend (mk_low (ap1), tp_schar, tp_long);	    ap = ap1;	    break;	case bt_bool:	case bt_uchar:	case bt_charu:	    ap = mk_legal (ap, F_DREG | F_AREG | F_MEM, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL1, ap, mk_high (ap1));	    g_code (op_and, IL4, mk_immed ((IVAL) 255L), mk_high (ap1));	    g_code (op_clr, IL4, mk_low (ap1), NIL_ADDRESS);	    ap = ap1;	    break;	case bt_int16:	case bt_short:	    ap = mk_legal (ap, F_DREG | F_AREG | F_MEM, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL2, ap, mk_high (ap1));	    g_code (op_ext, IL4, mk_high (ap1), NIL_ADDRESS);	    g_code (op_slt, IL0, mk_low (ap1), NIL_ADDRESS);	    VOIDCAST g_extend (mk_low (ap1), tp_schar, tp_long);	    ap = ap1;	    break;	case bt_uint16:	case bt_ushort:	    ap = mk_legal (ap, F_DREG | F_AREG | F_MEM, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL2, ap, mk_high (ap1));	    g_code (op_and, IL4, mk_immed ((IVAL) 65535L), mk_high (ap));	    g_code (op_clr, IL4, mk_low (ap1), NIL_ADDRESS);	    ap = ap1;	    break;	case bt_int32:	case bt_long:	    ap = mk_legal (ap, F_DREG | F_AREG | F_MEM, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL4, ap, mk_high (ap1));	    g_code (op_slt, IL0, mk_low (ap1), NIL_ADDRESS);	    VOIDCAST g_extend (mk_low (ap1), tp_schar, tp_long);	    ap = ap1;	    break;	case bt_uint32:	case bt_ulong:	    ap = mk_legal (ap, F_DREG, tp1);	    freeop (ap);	    ap1 = mdata_register ();	    g_code (op_move, IL4, ap, mk_high (ap1));	    g_code (op_clr, IL4, mk_low (ap1), NIL_ADDRESS);	    ap = ap1;	    break;	default:	    break;	}	break;#endif /* LONGLONG_SUPPORT */    default:	CANNOT_REACH_HERE ();	break;    }    return ap;}static ADDRESS *mk_low P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_immed:	if (is_icon (ap->u.offset)) {	    EXPR   *ep = ap->u.offset;	    if (is_signed_type (ep->etp)) {		IVAL    i = ep->v.i;#ifdef LONGLONG		i >>= 32;#else		if (ep->v.i < 0) {		    i = (IVAL) -1;		} else {		    i = 0;		}#endif /* LONGLONG */		return mk_immed (i);	    } else {		UVAL    u = ep->v.u;#ifdef LONGLONG		u >>= 32;#else		u = 0;#endif /* LONGLONG */		return mk_immed ((IVAL) u);	    }	}	break;    case am_ainc:    case am_adec:    case am_freg:	return ap;    case am_mreg:    case am_xreg:	return mk_reg (ap->preg);    case am_ind:    case am_indx:    case am_indx2:    case am_indx3:    case am_indx4:    case am_direct:	return mk_offset (ap, 0L);    default:	FATAL ((__FILE__, "mk_low", "illegal mode %d", ap->mode));	break;    }    return NIL_ADDRESS;}static ADDRESS *mk_high P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_immed:	if (is_icon (ap->u.offset)) {#ifdef LONGLONG	    return mk_immed ((IVAL) (ap->u.offset->v.u & 0xFFFFFFFFUL));#else	    return mk_immed (ap->u.offset->v.i);#endif	}	break;    case am_dreg:    case am_areg:    case am_ainc:    case am_adec:	return ap;    case am_mreg:    case am_xreg:	return mk_reg (ap->sreg);    case am_ind:    case am_indx:    case am_indx2:    case am_indx3:    case am_indx4:    case am_direct:	return mk_offset (ap, 4L);    default:	FATAL ((__FILE__, "mk_high", "illegal mode %d", ap->mode));	break;    }    return NIL_ADDRESS;}static ADDRESS *mk_top P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_ainc:    case am_adec:	return ap;    case am_xreg:	return mk_reg (ap->u.xreg);    case am_ind:    case am_indx:    case am_indx2:    case am_indx3:    case am_indx4:    case am_direct:	return mk_offset (ap, 8L);    default:	FATAL ((__FILE__, "mk_top", "illegal mode %d", ap->mode));	break;    }
    return NIL_ADDRESS;	/*lint !e527*/	/* unreachable */}/* * return ap, if ap can be switched to address a location with a short * offset, otherwise return 0.	  Typical application: * cast long -> short: 8(a6) --> 10(a6) offset is a small number (1,2 or 3) */static ADDRESS *mk_offset P2 (ADDRESS *, ap, SIZE, off){    switch (ap->mode) {    case am_ind:	if (off) {	    ap = copy_addr (ap, am_indx);	    ap->u.offset = mk_const ((IVAL) off);	}	return ap;    case am_indx:	if (is_icon (ap->u.offset)	    && ((IVAL) off + ap->u.offset->v.i <= (IVAL) 32767L)) {	    ap = copy_addr (ap, ap->mode);	    ap->u.offset = mk_const (ap->u.offset->v.i + (IVAL) off);	    return ap;	}	break;    case am_indx2:    case am_indx3:    case am_indx4:	if (is_icon (ap->u.offset) &&	    ((IVAL) off + ap->u.offset->v.i <= (IVAL) 127L	     || target_option < target_68020)) {	    ap = copy_addr (ap, ap->mode);	    ap->u.offset = mk_const (ap->u.offset->v.i + (IVAL) off);	    return ap;	}	break;    case am_direct:	ap = copy_addr (ap, ap->mode);	ap->u.offset = mk_add (ap->u.offset, mk_const ((IVAL) off));	return ap;    default:	break;    }    /* special value indicating that it must be done by hand */    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;    EXPR   *ep0 = ep->v.p[0];    EXPR   *ep1 = ep->v.p[1];    /*     *      Try and ensure that we evaluate address registers first ...     *      this leads to better code     */    if (ep1->nodetype == en_register && is_address_register (ep1->v.r)) {	ep0 = ep->v.p[1];	ep1 = ep->v.p[0];    }    if (ep1->nodetype == en_register && ep0->nodetype == en_register) {	if (is_address_register (ep0->v.r)) {	    /* first node is address register */	    ap1 = g_expr (ep0, F_AREG);	    ap1 = copy_addr (ap1, am_none);	    ap2 = g_expr (ep1, (FLAGS) (F_AREG | F_DREG));	    if (ap2->mode == am_dreg) {		/* 0(Ax,Dx) */		ap1->mode = am_indx2;	    } else {		/* 0(Ax,Ay) */		ap1->mode = am_indx3;	    }	    ap1->sreg = ap2->preg;	    ap1->u.offset = mk_const ((IVAL) 0L);	    return ap1;	} else if (is_address_register (ep1->v.r)) {	    /* second node is address register */	    ap1 = g_expr (ep1, F_AREG);	    ap1 = copy_addr (ap1, am_indx2);	/* 0(Ax,Dx) */	    ap1->sreg = ep0->v.r;	    ap1->u.offset = mk_const ((IVAL) 0L);	    return ap1;	}    }    /*     *               The general case (no register)     */    ap1 = g_expr (ep0, (FLAGS) (F_AREG | F_IMMED));    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 ();    }    /*     *               possible combinations:     *     *                               F_AREG  + F_AREG     *                               F_AREG  + F_DREG     *                               F_AREG  + F_IMMED     *                               F_IMMED + F_IMMED     *                               F_IMMED + F_AREG     */    if (ap1->mode == am_areg) {	/*	 *       watch out for:	 *                       register(addr) + address_register	 *                       register(addr) + data_register	 */	if (!is_temporary_register (ap1->preg)) {	    /* ap1 = register variable address register */	    ap1 = copy_addr (ap1, ap1->mode);	    switch (ap2->mode) {	    case am_dreg:		/* 0(Ax,Dy) */		ap1->mode = am_indx2;		ap1->sreg = ap2->preg;		ap1->deep = ap2->deep;		ap1->u.offset = mk_const ((IVAL) 0L);		return ap1;	    case am_areg:		/* 0(Ax,Ay) */		ap1->mode = am_indx3;		ap1->sreg = ap2->preg;		ap1->deep = ap2->deep;		ap1->u.offset = mk_const ((IVAL) 0L);		return ap1;	    case am_immed:		if (!is_short (ap2->u.offset)) {		    /* we want to add to ap1 later... */		    ap1 =			mk_legal (ap1, (FLAGS) (F_AREG | F_VOL), tp_pointer);		}		break;	    default:		break;	    }	}	/*	 *       watch out for:	 *                       address_register + register(data)	 */	if (ap2->mode == am_dreg && !is_temporary_data_register (ap2->preg)) {	    ap1 = copy_addr (ap1, am_indx2);	    ap1->sreg = ap2->preg;

⌨️ 快捷键说明

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