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

📄 gen386.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_386/****************************************************************************** * *  This module contains all the code generation routines for *  evaluating expressions and conditions for the INTEL 80386 *  processor. * *****************************************************************************/#define GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen386.h"#include "outproto.h"/********************************************************* Macro Definitions */#define	AL_DEFAULT	(g_alignments[bt_ellipsis])/********************************************************** Static Variables *//* *   Command line options */static unsigned peep_option = PEEP_ALL;	/* peephole optimisations */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;#ifdef FLOAT_IEEEstatic ADDRESS ax_reg = {    am_dreg, AX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};#endif /* FLOAT_IEEE */static ADDRESS ecx_reg = {    am_dreg, ECX, (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 ADDRESS esp_reg = {    am_dreg, ESP, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS eax_reg = {    am_dreg, EAX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static ADDRESS edx_reg = {    am_dreg, EDX, (REG) 0, (DEEP) 0,    {NIL_EXPR}};static REGTYPE reg_type[] = {    (REGTYPE) (D_REG | A_REG | X_REG | T_REG),	/* EAX */    (REGTYPE) (D_REG | A_REG | X_REG | T_REG),	/* EDX */    (REGTYPE) (D_REG | A_REG | Y_REG | T_REG | C_REG),	/* ECX */    (REGTYPE) 0,		/* EBX */    (REGTYPE) 0,		/* ESI */    (REGTYPE) 0,		/* EDI */    (REGTYPE) 0,		/* ESP */    (REGTYPE) 0,		/* EBP */    (REGTYPE) 0,		/* AX */    (REGTYPE) 0,		/* DX */    (REGTYPE) 0,		/* CX */    (REGTYPE) 0,		/* BX */    (REGTYPE) 0,		/* SI */    (REGTYPE) 0,		/* DI */    (REGTYPE) 0,		/* SP */    (REGTYPE) 0,		/* BP */    (REGTYPE) 0,		/* AL */    (REGTYPE) 0,		/* DL */    (REGTYPE) 0,		/* CL */    (REGTYPE) 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_386[] = {    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    */    4L,				/* bt_int32     */    4L,				/* bt_uint32    */    4L,				/* bt_long      */    4L,				/* bt_ulong     */    4L,				/* bt_longlong  */    4L,				/* bt_ulonglong */    4L,				/* bt_float     */    4L,				/* bt_double    */    4L,				/* bt_longdouble */    4L,				/* bt_floatcomplex */    4L,				/* bt_doublecomplex */    4L,				/* bt_longdoublecomplex */    4L,				/* bt_floatimaginary */    4L,				/* bt_doubleimaginary */    4L,				/* bt_longdoubleimaginary */    4L,				/* bt_pointer16 */    4L,				/* bt_pointer32 */    4L,				/* bt_struct    */    4L,				/* bt_union     */    4L,				/* bt_func      */    4L,				/* bt_bitfield  */    4L,				/* bt_ubitfield */    1L,				/* bt_bbitfield */    4L				/* bt_ellipsis - used for alignment suitable for all types */};#ifndef MULTIPLE_PROCESSORSPRIVATE SIZE *g_alignments = &alignments_386[0];#endif /* MULTIPLE_PROCESSORS *//*********************************************** Static Function Definitions */static ADDRESS *func_result P_ ((FLAGS, SIZE, TYP *));static ADDRESS *g_aincdec P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_asbin P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_asbitfield P_ ((const EXPR *, FLAGS, OPCODE, BOOL));static ADDRESS *g_asdiv P_ ((const EXPR *, FLAGS, BOOL));static ADDRESS *g_asmul P_ ((const EXPR *, FLAGS));static ADDRESS *g_asshift P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_assign P_ ((const EXPR *, FLAGS));static ADDRESS *g_bin P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_cast P_ ((ADDRESS *, TYP *, TYP *, FLAGS));static ADDRESS *g_deref P_ ((const EXPR *, TYP *));static ADDRESS *g_div P_ ((const EXPR *, FLAGS, BOOL));static ADDRESS *g_expr P_ ((const EXPR *, FLAGS));static ADDRESS *g_fcall P_ ((const EXPR *, FLAGS));static ADDRESS *g_fderef P_ ((const EXPR *, FLAGS));static ADDRESS *g_hook P_ ((const EXPR *, FLAGS));static ADDRESS *g_mul P_ ((const EXPR *, FLAGS));static ADDRESS *g_shift P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_unary P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *mk_amode P_ ((AMODE));static ADDRESS *mk_expr P_ ((AMODE, EXPR *));static ADDRESS *mk_legal P_ ((ADDRESS *, FLAGS, TYP *));static ADDRESS *mk_direct P_ ((EXPR *));static ADDRESS *mk_indirect P_ ((REG, EXPR *));static ADDRESS *mk_strlab P_ ((const CHAR *));static OPCODE g_compare P_ ((const EXPR *, OPCODE, OPCODE));static OPCODE g_test P_ ((const EXPR *, OPCODE));static SIZE g_parms P_ ((const EXPR *));static SIZE push_param P_ ((const EXPR *));static void g_falsejp P_ ((const EXPR *, LABEL));static void g_rotate P_ ((ADDRESS *, ILEN, int, TYP *, int));static void g_truejp P_ ((const EXPR *, LABEL));static void structassign P_ ((ADDRESS *, ADDRESS *, SIZE));#ifdef FLOAT_IEEEstatic void call_library P_ ((const CHAR *));#endif /* FLOAT_IEEE *//*********************************************** 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_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_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 *//*****************************************************************************/#ifdef FLOAT_IEEE/* * generate a call to a library routine. * it is assumed that lib_name won''t be clobbered */static void call_library P1 (const CHAR *, lib_name){    SYM    *sp;    sp = internal_symbol (lib_name, NIL_TYP);    g_code (op_call, IL0, mk_strlab (nameof (sp)), NIL_ADDRESS);}#endif /* FLOAT_IEEE */static ADDRESS *mk_amode P1 (AMODE, mode){    ADDRESS *ap;    ap = (ADDRESS *) xalloc (sizeof (ADDRESS));    ap->mode = mode;    return ap;}/* * copy an address mode structure. */static ADDRESS *copy_addr P2 (ADDRESS *, ap, AMODE, mode){    ADDRESS *newap;    assert (ap != NIL_ADDRESS);    newap = (ADDRESS *) xalloc (sizeof (ADDRESS));    *newap = *ap;    newap->mode = mode;    return newap;}static ADDRESS *mk_expr P2 (AMODE, mode, EXPR *, ep){    ADDRESS *ap;    ap = mk_amode (mode);    ap->u.offset = ep;    return ap;}/* * 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));}/* * make a node to reference a line number. */static ADDRESS *mk_line P1 (LINE, i){    return mk_expr (am_line, mk_const ((IVAL) i));}/* * 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);}/* * 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;}/* * 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);}/* * 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);	ap->preg = reg;	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);	ap->preg = reg;	break;#endif /* FLOAT_IEEE */    default:	CANNOT_REACH_HERE ();	ap = NIL_ADDRESS;    }    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;}static ADDRESS *mk_offset P2 (ADDRESS *, ap, SIZE, off){    switch (ap->mode) {    case am_ind:	ap = copy_addr (ap, am_indx);	ap->u.offset = mk_const (off);	return ap;    case am_indx:    case am_indx2:	ap = copy_addr (ap, am_indx);	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:	return NIL_ADDRESS;    }}static ADDRESS *mk_low P1 (ADDRESS *, ap){    switch (ap->mode) {    case am_dreg:    case am_areg:    case am_freg:    case am_immed:	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);    default:	CANNOT_REACH_HERE ();	break;    }    return NIL_ADDRESS;}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, 4L);    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 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 */	if (bytes == 4L && !is_register_used (ECX)) {	    g_code (op_pop, IL4, &ecx_reg, NIL_ADDRESS);	} else {	    g_code (op_add, IL4, 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. */

⌨️ 快捷键说明

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