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

📄 genarm.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static void g_test P1 (const EXPR *, ep){    ADDRESS *ap;    switch (ep->etp->type) {    case bt_char:    case bt_schar:    case bt_short:    case bt_int16:    case bt_int32:    case bt_long:    case bt_uchar:    case bt_charu:    case bt_ushort:    case bt_uint16:    case bt_uint32:    case bt_ulong:    case bt_pointer32:	ap = g_expr (ep, F_REG);	g_code (op_movs, cc_al, ap, ap, NIL_ADDRESS);	freeop (ap);	return;    default:	FATAL ((__FILE__, "g_test", "typ = %d\n", ep->etp->type));	break;    }}/* * generate a jump to label if the node passed evaluates to a true condition. */static void g_truejp P2 (const EXPR *, ep, LABEL, label){    CONDITION cc;    LABEL   lab0;    if (is_icon (ep)) {	if (ep->v.i) {	    g_branch (label);	}	return;    }    switch (ep->nodetype) {    case en_eq:	VOIDCAST g_compare (ep);	cc = cc_eq;	goto cont1;    case en_ne:	VOIDCAST g_compare (ep);	cc = cc_ne;	goto cont1;    case en_lt:	cc = g_compare (ep) ? cc_cc : cc_lt;	goto cont1;    case en_le:	cc = g_compare (ep) ? cc_ls : cc_le;	goto cont1;    case en_gt:	cc = g_compare (ep) ? cc_hi : cc_gt;	goto cont1;    case en_ge:	cc = g_compare (ep) ? cc_cs : cc_ge;      cont1:	g_cbranch (cc, label);	return;    case en_land:	lab0 = nextlabel++;	g_falsejp (ep->v.p[0], lab0);	g_truejp (ep->v.p[1], label);	g_label (lab0);	return;    case en_lor:	g_truejp (ep->v.p[0], label);	g_truejp (ep->v.p[1], label);	return;    case en_not:	g_falsejp (ep->v.p[0], label);	return;    default:	g_test (ep);	g_cbranch (cc_ne, label);	return;    }}/* * generate code to execute a jump to label if the expression passed is * false. */static void g_falsejp P2 (const EXPR *, ep, LABEL, label){    CONDITION cc;    LABEL   lab0;    if (is_icon (ep)) {	if (ep->v.i) {	    g_branch (label);	}	return;    }    switch (ep->nodetype) {    case en_eq:	VOIDCAST g_compare (ep);	cc = cc_ne;	goto cont1;    case en_ne:	VOIDCAST g_compare (ep);	cc = cc_eq;	goto cont1;    case en_lt:	cc = g_compare (ep) ? cc_cs : cc_ge;	goto cont1;    case en_le:	cc = g_compare (ep) ? cc_hi : cc_gt;	goto cont1;    case en_gt:	cc = g_compare (ep) ? cc_ls : cc_le;	goto cont1;    case en_ge:	cc = g_compare (ep) ? cc_cc : cc_lt;      cont1:	g_cbranch (cc, label);	return;    case en_land:	g_falsejp (ep->v.p[0], label);	g_falsejp (ep->v.p[1], label);	return;    case en_lor:	lab0 = nextlabel++;	g_truejp (ep->v.p[0], lab0);	g_falsejp (ep->v.p[1], label);	g_label (lab0);	return;    case en_not:	g_truejp (ep->v.p[0], label);	return;    default:	g_test (ep);	g_cbranch (cc_eq, label);	return;    }}PRIVATE void g_jtrue P2 (const EXPR *, ep, LABEL, label){    initstack ();    g_truejp (ep, label);    checkstack ();}PRIVATE void g_jfalse P2 (const EXPR *, ep, LABEL, label){    initstack ();    g_falsejp (ep, label);    checkstack ();}PRIVATE void g_switch_table P4 (const EXPR *, ep, const SWITCH *, sw, UVAL,				min_caselabel, UVAL, max_caselabel){    (void) ep;    (void) sw;    (void) min_caselabel;    (void) max_caselabel;    initstack ();    checkstack ();}/* * Generate the body of a switch statement by comparing each case value * in turn.   The comparison is in fact done by using subtraction as this * actually generates more efficient code (and would work best if the * labels were sorted!) */PRIVATE void g_switch_compare P2 (const EXPR *, ep, STMT *, stmt){    (void) ep;    (void) stmt;    initstack ();    checkstack ();}PRIVATE void g_entry P1 (SIZE, frame_size){    (void) frame_size;#if 0    SYM    *sp;    if (framesize > 0L) {	sp = runtime_symbol (SYM_STACK);	g_code (op_bl, cc_al, mk_strlab (nameof (sp)), NIL_ADDRESS,		NIL_ADDRESS);    }#endif}PRIVATE void g_return P2 (const EXPR *, stmtexp, TYP *, tp){    ADDRESS *ap;    (void) tp;    initstack ();    ap = g_expr (stmtexp, F_ALL);    g_code (op_mov, cc_al, mk_reg (reg_usage->result->reg[0]), ap,	    NIL_ADDRESS);    freeop (ap);    checkstack ();}PRIVATE void g_epilogue P0 (void){    if (restore_mask) {	g_code (op_ldmea, cc_al, mk_reg (FRAMEPTR), mk_mask (restore_mask),		NIL_ADDRESS);    }    g_code (op_mov, cc_al, mk_reg (R14), mk_reg (R15), NIL_ADDRESS);}/* * allocate will allocate registers for the expressions that have a high * enough desirability. */PRIVATE void g_allocate P1 (CSE *, olist){    CSE    *csp;    REG     reg = (REG) ((int) max_reg + 1);    REGMASK mask = (REGMASK) 0;    TYP    *tp;    regs_used = 0;    for (csp = olist; csp != NIL_CSE; csp = csp->next) {	tp = csp->exp->etp;	if (!reg_option && desire (csp) < (USES) 5000) {	    csp->reg = NO_REG;	} else if (reg < frameptr		   && csp->exp->nodetype != en_icon		   && csp->exp->nodetype != en_nacon		   && (tp->type == bt_pointer32 ||		       tp->type == bt_long ||		       tp->type == bt_ulong ||		       tp->type == bt_int16 ||		       tp->type == bt_uint16 ||		       tp->type == bt_int32 ||		       tp->type == bt_uint32 ||		       tp->type == bt_short ||		       tp->type == bt_ushort ||		       tp->type == bt_char ||		       tp->type == bt_schar ||		       tp->type == bt_uchar || tp->type == bt_charu)) {	    csp->reg = reg++;	    mask |= REGBIT (csp->reg);	    regs_used++;	} else {	    csp->reg = NO_REG;	}    }    if (mask != (REGMASK) 0) {	g_code (op_stmfd, cc_al, mk_reg (STACKPTR), mk_mask (mask),		NIL_ADDRESS);    }    restore_mask = mask;}/* *	 Go through the common sub-expression tree and check to see if *	 any registers must be loaded with a value. */PRIVATE void g_preload P1 (CSE *, olist){    CSE    *csp;    EXPR   *ep;    ADDRESS *ap, *ap2;    for (csp = olist; csp != NIL_CSE; csp = csp->next) {	if (csp->reg != NO_REG) {	    ep = csp->exp;	    if ((!is_lvalue (ep)) || ep->v.p[0]->v.i > 0L) {		initstack ();		ap = g_expr (ep, F_ALL);		ap2 = mk_reg (csp->reg);		g_code (op_mov, cc_al, ap, ap2, NIL_ADDRESS);		freeop (ap);	    }	}    }}PRIVATE void g_flush P1 (SYM *, sp){    put_literals ();    if (sp) {	put_cseg (alignment_of_type (typeof (sp)));	put_name (sp);    }    flush_peep (peep_option);    put_epilogue (sp, nextlabel++);
}PRIVATE void g_auto_align P0 (void){    if (lc_auto_max % AL_DEFAULT != 0L) {	lc_auto_max += AL_DEFAULT - (lc_auto_max % AL_DEFAULT);    }}PRIVATE BOOL g_is_bigendian P0 (void){    return TRUE;}PRIVATE BOOL g_is_ascending_stack P0 (void){    return FALSE;}/* *	 This routine does any code generator specific transformations *	 on the expression tree. * *	 For example it can replace operator nodes with calls to runtime *	 routines.	 This allows the global optimiser to perform optimisations *	 on such calls which wouldn't be possible if the calls were *	 generated in the code generator routines themselves. */PRIVATE EXPR *g_transform P1 (EXPR *, ep){    if (ep == NIL_EXPR) {	return ep;    }    switch (ep->nodetype) {    case en_icon:    case en_nacon:    case en_labcon:    case en_autocon:    case en_sym:    case en_ref:    case en_fieldref:    case en_register:    case en_uminus:    case en_test:    case en_not:    case en_compl:    case en_ainc:    case en_adec:    case en_cast:    case en_deref:    case en_add:    case en_sub:    case en_div:    case en_mod:    case en_lsh:    case en_rsh:    case en_and:    case en_or:    case en_xor:    case en_land:    case en_lor:    case en_eq:    case en_ne:    case en_lt:    case en_le:    case en_gt:    case en_ge:    case en_cond:    case en_comma:    case en_list:    case en_asadd:    case en_assub:    case en_asmul:    case en_asdiv:    case en_asor:    case en_asxor:    case en_asand:    case en_asmod:    case en_aslsh:    case en_asrsh:    case en_fcall:    case en_call:
    case en_usercall:    case en_assign:    case en_mul:	break;    default:	CANNOT_REACH_HERE ();	break;    }    return ep;}/* *	 This routine is called after the global optimizer has done it's *	 work re-organizing the expression tree.  This allows a code *	 generator to make code generator specific changes to the expression *	 tree which will result in better code generation. */PRIVATE EXPR *g_order P1 (EXPR *, ep){    return ep;}/* *	 This routine is called when the compiler is initialising, i.e. *	 before it even starts scanning tokens. */PRIVATE void g_initialize P0 (void){    if (!optimize_option) {	stackopt_option = 0;    }    if (stackopt_option) {	is_parameter = FALSE;    }}/* *	 This routine is called when the compiler is closing down. */PRIVATE void g_terminate P0 (void){}/* *	 Returns the current register usage. */PRIVATE REGUSAGE *g_regusage P1 (TYP *, tp){    (void) tp;    return reg_usage;}#ifdef MULTIPLE_PROCESSORS#define MCARM_FUNCS (void *)&mcarm_funcs#else#define MCARM_FUNCS (void *)NULL#endif /* MULTIPLE_PROCESSORS */static OPTSET peepset[] = {    {(const CHAR *) "none", PEEP_NONE},    {(const CHAR *) "flow", PEEP_FLOW},    {(const CHAR *) "all", PEEP_ALL},    {(const CHAR *) NULL, 0}};static OPTENUM yesnoopts[] = {    {(const CHAR *) "yes", 1},    {(const CHAR *) "no", 0},    {(const CHAR *) NULL, 0}};static OPTION opts[] = {    {     (const CHAR *) "peep=", set_option,     {&peep_option},     {&peepset[0]}     },    {     (const CHAR *) "prefix=", string_option,     {(void *) &external_prefix},     {NULL}     },    {     (const CHAR *) "reg=", enumeration_option,     {&reg_option},     {&yesnoopts[0]}     },#ifdef TRANSLATE    {     (const CHAR *) "trans=", enumeration_option,     {&trans_option},     {&yesnoopts[0]}     },#endif /* TRANSLATE */#ifdef MULTIPLE_ASSEMBLERS#ifdef TARGET_ARM    {     (const CHAR *) "armarm", chip_option,     {&armarm_funcs},     {MCARM_FUNCS}     },#endif /* TARGET_OBJ */#ifdef TARGET_OBJ    {     (const CHAR *) "objarm", chip_option,     {&armobj_funcs},     {MCARM_FUNCS}     },#endif /* TARGET_OBJ */#else#ifdef TARGET_ARM    {     (const CHAR *) "armarm", chip_option,     {NULL},     {MCARM_FUNCS}     },#endif /* TARGET_OBJ */#ifdef TARGET_OBJ    {     (const CHAR *) "objarm", chip_option,     {NULL},     {MCARM_FUNCS}     },#endif /* TARGET_OBJ */#endif /* MULTIPLE_ASSEMBLERS */    {     (const CHAR *) NULL, NULL,     {NULL},     {NULL}     }};OPTIONS optsarm = {    (const CHAR *) "ARM ",    opts};#ifdef MULTIPLE_PROCESSORSstruct genfuncs mcarm_funcs = {    g_expression,    g_jtrue,    g_jfalse,    g_stack,    g_switch_table,    g_switch_compare,    g_entry,    g_return,    g_epilogue,    g_label,    g_branch,#ifdef DEBUGOPT    g_line,#endif				/*DEBUGOPT */    g_allocate,    g_preload,    g_flush,    g_auto_align,    g_is_bigendian,    g_is_ascending_stack,    g_order,    g_transform,    g_initialize,    g_terminate,    g_regusage,    &alignments_arm[0]};#endif /* MULTIPLE_PROCESSORS */#endif /* ARM */

⌨️ 快捷键说明

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