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

📄 gen86.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989   starting an 68000 C compiler, starting with material *        originally by M. Brandt * 1990   68000 C compiler further bug fixes *        started i386 port (December) * 1991   i386 port finished (January) *        further corrections in the front end and in the 68000 *        code generator. *        The next port will be a SPARC port */#include "config.h"#ifdef INTEL_86/****************************************************************************** * * this module contains all of the code generation routines for evaluating * expressions and conditions for the INTEL 8086 processor. * *****************************************************************************/#define GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen86.h"#include "outproto.h"/********************************************************* Macro Definitions */#define	AL_DEFAULT	(g_alignments[bt_ellipsis])/********************************************************** Static Variables */static unsigned peep_option = PEEP_ALL;	/* peephole optimisation */static int target_option = target_8086;	/* code generator target */static int stackopt_option = OPT_MINIMUM;	/* Use lazy stack optimisation */static int regs_used = 0;	/* number of register variable allocated */static REGMASK restore_mask;	/* register restore mask */static SIZE max_stack_adjust = 0L;	/* largest amount stack is altered */static REG regframe = FRAMEPTR;static SETVAL regsave_option = EMPTY_SET;	/* registers to save on call */static ADDRESS eax_reg = {    am_dreg, EAX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS ecx_reg = {    am_dreg, ECX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS edx_reg = {    am_dreg, EDX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS esp_reg = {    am_dreg, ESP, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS edi_reg = {    am_dreg, EDI, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS esi_reg = {    am_dreg, ESI, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static REGTYPE reg_type[] = {    (REGTYPE) (D_REG | T_REG | X_REG),	/* EAX */    (REGTYPE) (D_REG | T_REG | X_REG),	/* EDX */    (REGTYPE) (D_REG | T_REG | Y_REG | C_REG),	/* ECX */    (REGTYPE) (D_REG | T_REG),	/* EBX */    (REGTYPE) (A_REG | T_REG),	/* ESI */    (REGTYPE) (A_REG | T_REG),	/* EDI */    0,				/* ESP */    0,				/* EBP */    0,				/* AX */    0,				/* DX */    0,				/* CX */    0,				/* BX */    0,				/* SI */    0,				/* DI */    0,				/* SP */    0,				/* BP */    0,				/* AL */    0,				/* DL */    0,				/* CL */    0,				/* BL */    (REGTYPE) (F_REG | T_REG),	/* ST0 */    (REGTYPE) (F_REG | T_REG),	/* ST1 */    (REGTYPE) (F_REG | T_REG),	/* ST2 */    (REGTYPE) (F_REG | T_REG),	/* ST3 */    (REGTYPE) (F_REG | T_REG),	/* ST4 */    (REGTYPE) (F_REG | T_REG),	/* ST5 */    (REGTYPE) (F_REG | T_REG),	/* ST6 */    (REGTYPE) (F_REG | T_REG)	/* ST7 */};/* *  The following tables specify the alignment requirements of the *  basic types depending on the processor type. */static SIZE alignments_8086[] = {    1L,				/* bt_void      */    1L,				/* bt_bool      */    1L,				/* bt_char      */    1L,				/* bt_charu     */    1L,				/* bt_uchar     */    1L,				/* bt_schar     */    2L,				/* bt_short     */    2L,				/* bt_ushort    */    2L,				/* bt_int16     */    2L,				/* bt_uint16    */    2L,				/* bt_int32     */    2L,				/* bt_uint32    */    2L,				/* bt_long      */    2L,				/* bt_ulong     */    2L,				/* bt_longlong  */    2L,				/* bt_ulonglong */    2L,				/* bt_float     */    2L,				/* bt_double    */    2L,				/* bt_longdouble */    2L,				/* bt_floatcomplex */    2L,				/* bt_doublecomplex */    2L,				/* bt_longdoublecomplex */    2L,				/* bt_floatimaginary */    2L,				/* bt_doubleimaginary */    2L,				/* bt_longdoubleimaginary */    2L,				/* bt_pointer16 */    2L,				/* bt_pointer32 */    2L,				/* bt_struct    */    2L,				/* bt_union     */    2L,				/* bt_func      */    2L,				/* bt_bitfield  */    2L,				/* bt_ubitfield */    1L,				/* bt_bbitfield */    2L				/* bt_ellipsis - used for alignment suitable for all types */};#ifndef MULTIPLE_PROCESSORSPRIVATE SIZE *g_alignments = &alignments_8086[0];#endif /* MULTIPLE_PROCESSORS *//*********************************************** Static Function Definitions */static ADDRESS *func_result P_ ((FLAGS, SIZE, TYP *));static ADDRESS *g_asbin P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_asbitfield P_ ((const EXPR *, FLAGS, OPCODE, BOOL));static ADDRESS *g_expr P_ ((const EXPR *, FLAGS));static ADDRESS *g_extend P_ ((ADDRESS *, TYP *, TYP *));static ADDRESS *mk_amode P_ ((AMODE));static ADDRESS *mk_expr P_ ((AMODE, EXPR *));static ADDRESS *mk_indirect P_ ((REG, EXPR *));static ADDRESS *mk_low P_ ((ADDRESS *));static ADDRESS *mk_high P_ ((ADDRESS *));static void g_compare P_ ((const EXPR *, OPCODE, OPCODE, LABEL));static void g_falsejp P_ ((const EXPR *, LABEL));static void g_test P_ ((const EXPR *));static void g_truejp P_ ((const EXPR *, LABEL));#ifdef STACK_CHECKstatic ADDRESS *mk_strlab P_ ((const CHAR *));#endif /* STACK_CHECK *//*********************************************** Global Function Definitions */#ifdef MULTIPLE_PROCESSORSPRIVATE BOOL g_is_bigendian P_ ((void));PRIVATE BOOL g_is_ascending_stack P_ ((void));PRIVATE void g_auto_align P_ ((void));PRIVATE void g_flush P_ ((SYM *));PRIVATE void g_allocate P_ ((CSE *));PRIVATE void g_branch P_ ((LABEL));PRIVATE void g_entry P_ ((SIZE));PRIVATE void g_epilogue P_ ((void));PRIVATE void g_expression P_ ((const EXPR *));PRIVATE void g_jfalse P_ ((const EXPR *, LABEL));PRIVATE void g_jtrue P_ ((const EXPR *, LABEL));PRIVATE void g_label P_ ((LABEL));PRIVATE void g_return P_ ((const EXPR *, TYP *));PRIVATE void g_stack P_ ((SIZE));PRIVATE void g_switch_compare P_ ((const EXPR *, STMT *));PRIVATE void g_switch_table P_ ((const EXPR *, const SWITCH *, UVAL, UVAL));PRIVATE void g_initialize P_ ((void));#endif /* MULTIPLE_PROCESSORS *//*****************************************************************************//* * copy an address mode structure. */static ADDRESS *copy_addr P2 (ADDRESS *, ap, AMODE, mode){    ADDRESS *newap;    if (ap == NIL_ADDRESS) {	FATAL ((__FILE__, "copy_addr", "ap == 0"));    }    newap = (ADDRESS *) xalloc (sizeof (ADDRESS));    *newap = *ap;    newap->mode = mode;    return newap;}static ADDRESS *mk_amode P1 (AMODE, mode){    ADDRESS *ap;    ap = (ADDRESS *) xalloc (sizeof (ADDRESS));    ap->mode = mode;    return ap;}static ADDRESS *mk_expr P2 (AMODE, mode, EXPR *, ep){    ADDRESS *ap;    ap = mk_amode (mode);    ap->u.offset = ep;    return ap;}#ifndef INTEL_386/* * make a node to reference an immediate value i. */ADDRESS *mk_immed P1 (IVAL, i){    return mk_expr (am_immed, mk_const (i));}/* * construct a reference node for an internal label number. */ADDRESS *mk_label P1 (LABEL, lab){    return mk_expr (am_direct, mk_lcon (lab));}#endif /* INTEL_386 */#ifdef DEBUGOPT/* * make a node to reference a line number. */static ADDRESS *mk_line P1 (LINE, i){    return mk_expr (am_line, mk_const ((IVAL) i));}#endif /* DEBUGOPT */#ifdef DEBUGOPT/* * make a node to reference a source line. */static ADDRESS *mk_linetxt P1 (const CHAR *, s){    EXPR   *ep;    ep = mk_node (en_str, NIL_EXPR, NIL_EXPR, tp_void);    ep->v.str = s;    return mk_expr (am_str, ep);}#endif /* DEBUGOPT *//* * make a direct reference to a node. */static ADDRESS *mk_direct P1 (EXPR *, ep){    return mk_expr (am_direct, ep);}/*   * make an indirect reference to a node. */static ADDRESS *mk_indirect P2 (REG, reg, EXPR *, ep){    ADDRESS *ap;    ap = mk_expr (am_indx, ep);    ap->preg = reg;    return ap;}#ifdef STACK_CHECK/* * generate a direct reference to a string label. */static ADDRESS *mk_strlab P1 (const CHAR *, s){    EXPR   *ep;    ep = mk_node (en_nacon, NIL_EXPR, NIL_EXPR, tp_void);    ep->v.str = s;    return mk_expr (am_direct, ep);}#endif /* STACK_CHECK */#ifndef INTEL_386/* * make an address reference to a register. */ADDRESS *mk_reg P1 (REG, reg){    ADDRESS *ap;    switch (reg) {    case EAX:    case EBX:    case ECX:    case EDX:    case ESI:    case EDI:    case ESP:    case EBP:	ap = mk_amode (am_dreg);	break;#ifdef FLOAT_IEEE    case ST0:    case ST1:    case ST2:    case ST3:    case ST4:    case ST5:    case ST6:    case ST7:	ap = mk_amode (am_freg);	break;#endif /* FLOAT_IEEE */    default:	CANNOT_REACH_HERE ();    }    ap->preg = reg;    return ap;}ADDRESS *mk_mreg P2 (REG, r1, REG, r2){    ADDRESS *ap;    ap = mk_amode (am_mreg);    ap->preg = r1;    ap->sreg = r2;    return ap;}#endif /* INTEL_386 */static ADDRESS *mk_offset P2 (ADDRESS *, ap, SIZE, off){    switch (ap->mode) {    case am_ind:	ap = mk_indirect (ap->preg, mk_const (off));	return ap;    case am_indx:    case am_indx2:	ap = copy_addr (ap, ap->mode);	ap->u.offset = mk_const (ap->u.offset->v.i + off);	return ap;    case am_direct:	ap = copy_addr (ap, ap->mode);	ap->u.offset = mk_add (ap->u.offset, mk_const (off));	return ap;    default:	/* address must be done "by hand" */	return NIL_ADDRESS;    }}/* *   Get the low address/reference for a 4 byte item */static ADDRESS *mk_low P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_dreg:    case am_areg:	return ap;    case am_mreg:	return mk_reg (ap->preg);    case am_ind:    case am_indx:    case am_indx2:    case am_direct:	return mk_offset (ap, 0L);    case am_immed:	return mk_immed ((IVAL) (ap->u.offset->v.u & 0x0000ffffL));    default:	CANNOT_REACH_HERE ();	break;    }    return NIL_ADDRESS;}/* *   Get the high address/reference for a 4 byte item */static ADDRESS *mk_high P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_mreg:	return mk_reg (ap->sreg);    case am_ind:    case am_indx:    case am_indx2:    case am_direct:	return mk_offset (ap, 2L);    case am_immed:	return mk_immed ((IVAL) ((ap->u.offset->v.u >> 16) & 0x0000ffffL));    default:	CANNOT_REACH_HERE ();	break;    }    return NIL_ADDRESS;}/* * returns addressing mode of form offset(regframe) * size is rounded up to AL_DEFAULT */static ADDRESS *mk_scratch P1 (SIZE, size){    ADDRESS *ap;    /* round up the request */    if (size % AL_DEFAULT) {	size += AL_DEFAULT - (size % AL_DEFAULT);    }    /* allocate the storage */    act_scratch += size;    /*     * The next statement could be deferred and put into the     * routine checkstack(), but this is just safer.     */    if (act_scratch > max_scratch) {	max_scratch = act_scratch;    }    ap = mk_indirect (regframe, mk_const (-(lc_auto_max + act_scratch)));    return ap;}/* * add a label node 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){    switch (bytes) {    case 0l:	return;    default:	g_code (op_add, IL2, mk_immed (bytes), &esp_reg);    }    stack_offset -= bytes;    if (max_stack_adjust < bytes) {	max_stack_adjust = bytes;    }}/* * mk_legal will coerce the addressing mode in ap1 into a mode that is * satisfactory for the flag word. */static ADDRESS *mk_legal P3 (ADDRESS *, ap, FLAGS, flags, TYP *, tp){    ADDRESS *ap1, *ap2;    SIZE    size = tp->size;    if (flags & F_NOVALUE) {	if (ap) {#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) {

⌨️ 快捷键说明

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