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

📄 genc30.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 * * * 1995   Ivo Oesch, Started in to write a codegenerator for the *        signalprocessor TMS320C30 (December) *//****************************************************************************** * * this module contains all of the code generation routines for evaluating * expressions and conditions. * *****************************************************************************/#include "config.h"#ifdef TMS320C30#define	GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genc30.h"#include "outproto.h"/********************************************************* Macro Definitions */#define NEW_BITFIELDSTUFF#define best_flags(requested, possible) ((FLAGS)((requested&possible)!=0 ? requested&possible : possible))#define isanyreg(AP) ((AP->mode==am_areg)||(AP->mode==am_dreg)||(AP->mode==am_ireg)||(AP->mode==am_sreg))#define AL_DEFAULT      (g_alignments[bt_ellipsis])#define is_op3_violated(ap) (  ((ap)->mode == am_ainc)  || ((ap)->mode == am_adec)   \		             ||((ap)->mode == am_preinc)|| ((ap)->mode == am_predec) \		             ||((ap)->mode == am_direct)|| ((ap)->mode == am_immed)  \		             ||((ap)->mode == am_const_direct))/********************************************************** Type Definitions */typedef struct _itree{    LABEL   label;    EXPR   *value;    struct _itree *less;    struct _itree *more;}ITREE;/********************************************************** Static Variables */static unsigned peep_option = PEEP_STANDARD;	/* peehole optimisations */static int regs_used = 0;	/* number of register variable allocated */static int address_reg_used = 0;	/* number of register variable allocated to addressregisters */static REGMASK restore_mask;	/* register restore mask */static REGMASK floatrestore_mask;	/* register restore mask */static REGMASK interrupt_restore_mask = 0;	/* register restore mask */static REGMASK interrupt_floatrestore_mask = 0;	/* register restore mask */static REGMASK return_register_mask = 0;	/* used returnregister */static SIZE max_stack_adjust = 0L;	/* largest amount stack is altered */static REGMASK forced_save_mask = 0;#if 0static REGMASK forced_floatsave_mask = 0;#else#define forced_floatsave_mask (forced_save_mask & MASK_REG_DATA)#endif/* *  The following tables specify the alignment requirements of the *  basic types depending on the processor type. */static SIZE alignments_c30[] = {    1L,				/* bt_void      */    1L,				/* bt_bool      */    1L,				/* bt_char      */    1L,				/* bt_charu     */    1L,				/* bt_uchar     */    1L,				/* bt_schar     */    1L,				/* bt_short     */    1L,				/* bt_ushort    */    1L,				/* bt_int16     */    1L,				/* bt_uint16    */    1L,				/* bt_int32     */    1L,				/* bt_uint32    */    1L,				/* bt_long      */    1L,				/* bt_ulong     */    1L,				/* bt_longlong  */    1L,				/* bt_ulonglong */    1L,				/* bt_float     */    1L,				/* bt_double    */    1L,				/* bt_longdouble */    1L,				/* bt_floatcomplex */    1L,				/* bt_doublecomplex */    1L,				/* bt_longdoublecomplex */    1L,				/* bt_floatimaginary */    1L,				/* bt_doubleimaginary */    1L,				/* bt_longdoubleimaginary */    1L,				/* bt_pointer16 */    1L,				/* bt_pointer32 */    1L,				/* bt_struct    */    1L,				/* bt_union     */    1L,				/* bt_func      */    1L,				/* bt_bitfield  */    1L,				/* bt_ubitfield */    1L,				/* bt_bbitfield */    1L				/* bt_ellipsis - used for alignment suitable for all types */};/* * support routines, define as pointers to be sure to have only * one copy in memory of them, else symsearch does not work * properly sinc it compares pointers and not contents of strings */static const CHAR *psup_fpdiv = SUP_FPDIV;static const CHAR *psup_fprem = SUP_FPREM;static const CHAR *psup_ldiv = SUP_LDIV;static const CHAR *psup_lrem = SUP_LREM;static const CHAR *psup_uldiv = SUP_ULDIV;static const CHAR *psup_ulrem = SUP_ULREM;static int opt_const_in_ram = OPT_NO;static int opt_true_long = OPT_NO;static int stackopt_option = OPT_SAFE;static int opt_shortfloat = 1;static int interrupt_option = OPT_NO;static int opt_traps = OPT_NO;int     opt_branches = OPT_LEVEL1;int     opt_delayed_branches = 2;const CHAR *opt_peep_sequence = (const CHAR *) "";int     opt_peep_test = 0;REG     frameptr = FRAMEPTR;#ifndef MULTIPLE_PROCESSORSPRIVATE SIZE *g_alignments = &alignments_c30[0];#endif /* MULTIPLE_PROCESSORS *//*********************************************** Static Function Definitions */static ADDRESS *as_fcall P_ ((const EXPR *, FLAGS, const CHAR *, ITYPE));static ADDRESS *func_result P_ ((FLAGS, SIZE, TYP *));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 *, TYP *, TYP *, FLAGS));static ADDRESS *g_conditionalloadP_ ((const EXPR *, ADDRESS *, ADDRESS *, ITYPE, FLAGS));static ADDRESS *g_deref P_ ((const EXPR *, TYP *, FLAGS));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_index P_ ((const EXPR *));static ADDRESS *g_logic P_ ((const EXPR *, FLAGS, OPCODE));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_legal P_ ((ADDRESS *, FLAGS, ITYPE));static ADDRESS *mk_ilabel P_ ((const EXPR *));static ADDRESS *check_trap P_ ((const EXPR *));static ADDRESS *mk_indirect P_ ((REG, EXPR *));static BOOL g_compare P_ ((const EXPR *));static BOOL tst_iconst P_ ((const EXPR *));static EXPR *copy_iexpr P_ ((const EXPR *));static SIZE g_parms P_ ((const EXPR *));static SIZE push_param P_ ((const EXPR *));static void call_library_r0_r1 P_ ((const CHAR *));static void g_immed P_ ((OPCODE, IVAL, ADDRESS *));static void g_rotate P_ ((ADDRESS *, int, TYP *, int));static void g_test P_ ((const EXPR *));static void structassign P_ ((ADDRESS *, ADDRESS *, SIZE));static void g_truejp P_ ((const EXPR *, LABEL));static void g_falsejp P_ ((const EXPR *, LABEL));static void allocate_blockrepeat_registers P_ ((void));/*********************************************** 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 *//*****************************************************************************//*****************************************************************************/static ADDRESS *mk_amode P1 (AMODE, mode){    ADDRESS *ap;    ap = (ADDRESS *) xalloc ((size_t) 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 (ADDRESS *, ap, AMODE, mode){    ADDRESS *newap;    assert (ap);    newap = (ADDRESS *) xalloc ((size_t) sizeof (ADDRESS));    *newap = *ap;    newap->mode = mode;    return newap;}/* * make a node to reference an signed immediate value i. */static ADDRESS *mk_immed P1 (IVAL, i){    if ((i <= 32767L) && (i >= -32768L))	return mk_expr (am_immed, mk_const (i));    else	return mk_ilabel (mk_const (i));}/* * make a node to reference an unsigned immediate value i. */static ADDRESS *mk_uimmed P1 (IVAL, i){    if (i < 0)	FATAL ((__FILE__, "mk_uimmed", "value is negative %ld", i));    if (i <= 0xFFFFL)	return mk_expr (am_immed, mk_const (i));    else	return mk_ilabel (mk_const (i));}/* * construct a reference node for an internal label number. */ADDRESS *mk_label P1 (LABEL, lab){    return mk_expr (am_const_direct, mk_lcon (lab));}static ADDRESS *mk_Jumplabel P1 (LABEL, lab){    return mk_expr (am_immed, 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_immed, ep);}/* * generate a call to a library routine. * it is assumed that lib_name won''t be clobbered */static void call_library_r0_r1 P1 (const CHAR *, lib_name){    SYM    *sp;    sp = internal_symbol (lib_name, tp_void);    /* routines are using all temporary-registers, so      * intrruptroutines must save them     */    interrupt_restore_mask |=	MEMBER (REG_R0) | MEMBER (REG_R1) | MEMBER (REG_R2) | MEMBER (REG_AR0)	| MEMBER (REG_AR1);    interrupt_floatrestore_mask |=	MEMBER (REG_R0) | MEMBER (REG_R1) | MEMBER (REG_R2);    /*     *  op_xcall is a marker for the peephole-optimizer,     *  it assumes, that only xcall uses R0 and R1 registers     *  for parameterpassing.     *  all other calls are assumed to use stack for     *  parameterpassing, so values of r0 and r1 (and     *  all other tempregs) may be invalidated/overwritten     *  before functionscall.     */    g_code (op_xcall, OP_INT, mk_strlab (nameof (sp)), NIL_ADDRESS);}/* *  make an address reference to a register. */ADDRESS *mk_reg P1 (REG, r){    ADDRESS *ap;    switch (r) {    case REG_R0:    case REG_R1:    case REG_R2:    case REG_R3:    case REG_R4:    case REG_R5:    case REG_R6:    case REG_R7:	ap = mk_amode (am_dreg);	ap->preg = r;	break;    case REG_AR0:    case REG_AR1:    case REG_AR2:    case REG_AR3:    case REG_AR4:    case REG_AR5:    case REG_AR6:    case REG_AR7:	ap = mk_amode (am_areg);	ap->preg = r;	break;    case REG_IR0:    case REG_IR1:	ap = mk_amode (am_ireg);	ap->preg = r;	break;    case REG_DP:    case REG_BK:    case REG_SP:    case REG_ST:    case REG_IE:    case REG_IF:    case REG_IOF:    case REG_RS:    case REG_RE:    case REG_RC:	ap = mk_amode (am_sreg);	ap->preg = r;	break;    default:	CANNOT_REACH_HERE ();	ap = NIL_ADDRESS;    }    interrupt_restore_mask |= MEMBER (r);    return ap;}/* * make an address reference to a floatregister. */ADDRESS *mk_freg P1 (REG, r){    ADDRESS *ap;    assert (r <= REG_R7);    ap = mk_amode (am_freg);    ap->preg = r;    interrupt_restore_mask |= MEMBER (r);    interrupt_floatrestore_mask |= MEMBER (r);    return ap;}/* * returns addressing mode of form offset(frameptr) * 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;    }    /* do not add act_scratch, because pointer must point to start of     * scratch area     */    ap = mk_indirect (frameptr, mk_const ((lc_auto_max + 1)));    return ap;}/* * push all register in the masks onto stack. */static void push_registers P2 (REGMASK, mask, REGMASK, floatmask){    REG     reg;    for (reg = MAX_REG; reg >= REG_R0; reg--) {	/* Check which registers are set in mask */	if ((mask & MEMBER (reg)) != 0) {	    g_code (op_pushnopeep, OP_INT, mk_reg (reg), NIL_ADDRESS);

⌨️ 快捷键说明

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