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

📄 gen68k.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 MC680X0/*****************************************************************************/#define GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen68k.h"#include "outproto.h"/********************************************************* Macro Definitions */#define AL_DEFAULT	(g_alignments[bt_ellipsis])/********************************************************** Static Variables *//* *	 Command line options */static unsigned peep_option = (MEMBER (PEEP_INSTRUCTION) | MEMBER (PEEP_JUMPS));	/* peehole optimisations */static int stackopt_option = OPT_MINIMUM;	/* Use lazy stack optimisation */static int regframe_option = (int) A6;static int regdata_option = (int) A5;
static SETVAL regunused_option = Ox0UL;static SETVAL regtemp_option =    (MEMBER (D0) | MEMBER (D1) | MEMBER (D2) | MEMBER (A0) | MEMBER (A1) |     MEMBER (FP0) | MEMBER (FP1) | MEMBER (FP2));static int codemodel_option = (int) model_absolute;static int interrupt_option = 0;#ifdef COLDFIRE_DEFAULTint     target_option = (int) target_coldfire;#elseint     target_option = (int) target_68000;#endif /* COLDFIRE_DEFAULT */static int regs_used = 0;	/* number of register variable allocated */static int fregs_used = 0;	/* number of FP register variable allocated */static REGMASK restore_mask;	/* register restore mask */#ifdef FLOAT_IEEEstatic REGMASK restore_fmask;	/* floating point register restore mask */#endif /* FLOAT_IEEE */static SIZE max_stack_adjust = 0L;	/* largest amount stack is altered */static REG regframe = FRAMEPTR;static REG regdata = DATAPTR;static LISTVAL regreturn_list = { 0 };static ADDRESS push = {    am_adec, STACKPTR, (REG) 0, (DEEP) 0,    {NIL_EXPR}		/*lint !e708*/	/* union initialization */};static ADDRESS pop = {    am_ainc, STACKPTR, (REG) 0, (DEEP) 0,    {NIL_EXPR}		/*lint !e708*/	/* union initialization */};/* *	 The following tables specify the alignment requirements of the *	 basic types depending on the processor type. */static SIZE alignments_68000[] = {    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_68000[0];#endif /* MULTIPLE_PROCESSORS *//*********************************************** Static Function Definitions */static ADDRESS *g_addsub P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_aincdec P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_asadd 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_aslogic P_ ((const EXPR *, FLAGS, OPCODE));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_cast P_ ((ADDRESS *, const TYP *, const TYP *, FLAGS));static ADDRESS *g_deref P_ ((const EXPR *, const TYP *, FLAGS));static ADDRESS *g_div P_ ((const EXPR *, FLAGS, BOOL));static ADDRESS *g_expr P_ ((const EXPR *, FLAGS));static ADDRESS *g_extend P_ ((ADDRESS *, const TYP *, const TYP *));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_index P_ ((const EXPR *));static ADDRESS *g_logic P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_mul P_ ((const EXPR *, FLAGS));static ADDRESS *mk_offset P_ ((ADDRESS *, SIZE));static ADDRESS *g_shift P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_unary P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_xmul P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_shft P_ ((OPCODE, ILEN, ADDRESS *, ADDRESS *));static ADDRESS *mk_amode P_ ((AMODE));static ADDRESS *mk_expr P_ ((AMODE, EXPR *));static ADDRESS *mk_direct P_ ((EXPR *));static ADDRESS *mk_high P_ ((ADDRESS *));static ADDRESS *mk_top P_ ((ADDRESS *));static ADDRESS *mk_indirect P_ ((REG, EXPR *));static ADDRESS *mk_legal P_ ((ADDRESS *, FLAGS, const TYP *));static ADDRESS *mk_low P_ ((ADDRESS *));static ADDRESS *mk_rmask P_ ((REGMASK));static ADDRESS *mk_smask P_ ((REGMASK));static BOOL g_compare P_ ((const EXPR *));static BOOL is_byte P_ ((const EXPR *));static BOOL is_ushort P_ ((const EXPR *));static BOOL tst_short P_ ((const EXPR *));static BOOL tst_ushort P_ ((const EXPR *));static SIZE g_parms P_ ((const EXPR *));static SIZE push_param P_ ((const EXPR *));static void g_call P_ ((ADDRESS *));static void g_cbranch P_ ((OPCODE, LABEL));static void g_falsejp P_ ((const EXPR *, LABEL));static void g_immed P_ ((OPCODE, const TYP *, IVAL, ADDRESS *));static void g_rotate P_ ((ADDRESS *, const TYP *, int, const TYP *, int));static void g_test P_ ((const EXPR *));static void g_truejp P_ ((const EXPR *, LABEL));static void structassign P_ ((ADDRESS *, ADDRESS *, SIZE, const TYP *));static ADDRESS *func_result P_ ((FLAGS, SIZE, const TYP *));#ifdef FLOAT_SUPPORTstatic void push_rtl_params P_ ((const EXPR *, const EXPR *));#endif /* FLOAT_SUPPORT *//*********************************************** Global Function Definitions */#ifdef MULTIPLE_PROCESSORSPRIVATE BOOL g_is_ascending_stack P_ ((void));PRIVATE BOOL g_is_bigendian P_ ((void));PRIVATE EXPR *g_transform P_ ((EXPR *));PRIVATE void g_allocate P_ ((CSE *));PRIVATE void g_auto_align P_ ((void));PRIVATE void g_entry P_ ((SIZE));PRIVATE void g_epilogue P_ ((void));PRIVATE void g_expression P_ ((const EXPR *));PRIVATE void g_flush P_ ((SYM *));PRIVATE void g_initialize P_ ((void));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));#endif /* MULTIPLE_PROCESSORS *//*****************************************************************************//* * this module contains all of the code generation routines for evaluating * expressions and conditions. */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;}/* * 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);}/* * copy an address mode structure. */ADDRESS *copy_addr P2 (const ADDRESS *, ap, AMODE, mode){    ADDRESS *newap;    assert (ap);    newap = (ADDRESS *) xalloc (sizeof (ADDRESS));    *newap = *ap;    newap->mode = mode;    return newap;}/* * make a node to reference an immediate value i. */static 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));}/* * 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);}#if defined(FLOAT_IEEE) || defined(STACK_CHECK)/* * 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, tp_void);    g_call (mk_strlab (nameof (sp)));}#endif /* FLOAT_IEEE || STACK_CHECK *//* *	 make an address reference to a register. */ADDRESS *mk_reg P1 (REG, r){    ADDRESS *ap;    switch (r) {    case D0:    case D1:    case D2:    case D3:    case D4:    case D5:    case D6:    case D7:	ap = mk_amode (am_dreg);	ap->preg = r;	break;    case A0:    case A1:    case A2:    case A3:    case A4:    case A5:    case A6:    case A7:	ap = mk_amode (am_areg);	ap->preg = r;	break;    case FP0:    case FP1:    case FP2:    case FP3:    case FP4:    case FP5:    case FP6:    case FP7:	ap = mk_amode (am_freg);	ap->preg = r;	break;    default:	CANNOT_REACH_HERE ();    }    return ap;}/* *	 make an address reference to 3 registers. */ADDRESS *mk_xreg P3 (REG, r1, REG, r2, REG, r3){    ADDRESS *ap;    ap = mk_amode (am_xreg);    ap->preg = r1;    ap->sreg = r2;    ap->u.xreg = r3;    return ap;}/* *	 make an address reference to 2 registers. */ADDRESS *mk_mreg P2 (REG, r1, REG, r2){    ADDRESS *ap;    ap = mk_amode (am_mreg);    ap->preg = r1;    ap->sreg = r2;    return ap;}/* * returns addressing mode of form offset(regframe) * size is rounded up to AL_DEFAULT */static ADDRESS *mk_scratch P1 (SIZE, size){    ADDRESS *ap;    SIZE    default_alignment = AL_DEFAULT;    /* round up the request */    if (size % default_alignment) {	size += default_alignment - (size % default_alignment);    }    /* 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 ((IVAL) -(lc_auto_max + act_scratch)));    return ap;}/* * generate the mask address structure. */static ADDRESS *mk_rmask P1 (REGMASK, mask){    ADDRESS *ap;    ap = mk_amode (am_rmask);    ap->u.mask = mask;    return ap;}/* * generate the mask address structure. */static ADDRESS *mk_smask P1 (REGMASK, mask){    ADDRESS *ap;    ap = mk_amode (am_smask);    ap->u.mask = mask;    return ap;}/* * 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;}/* * return true if the node passed can be generated as a short offset. */BOOL is_short P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= -32768L && ep->v.i <= 32767L);}/* * return true if the node passed can be generated as a short offset. */static BOOL is_ushort P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= 0L && ep->v.i <= 65535L);}static BOOL is_byte P1 (const EXPR *, ep){    return is_icon (ep) && (ep->v.i >= -128L && ep->v.i <= 127L);}/* * tests if node is a integer constant falling in the range of uns. short or * if node is cast from uns. short, uns. char or char. */static BOOL tst_ushort P1 (const EXPR *, ep){    if (is_ushort (ep)) {	return TRUE;    }    switch (ep->etp->type) {    case bt_char:    case bt_charu:    case bt_uchar:    case bt_schar:    case bt_ushort:    case bt_uint16:	return TRUE;    default:	break;    }    if (ep->nodetype == en_cast) {	switch (ep->v.p[0]->etp->type) {	case bt_char:	case bt_charu:	case bt_uchar:	case bt_schar:	case bt_ushort:	case bt_uint16:	    return TRUE;	default:	    return FALSE;	}    }    return FALSE;}/* * tests if node is a integer constant falling in the range of short or if * node is cast from short. */static BOOL tst_short P1 (const EXPR *, ep){    if (is_short (ep)) {	return TRUE;    }    switch (ep->etp->type) {

⌨️ 快捷键说明

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