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

📄 genarm.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 *//****************************************************************************** * * this module contains all of the code generation routines for evaluating * expressions and conditions. * *****************************************************************************/#include "config.h"#ifdef ARM#define GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "genarm.h"#include "outproto.h"/********************************************************* Macro Definitions */#define AL_DEFAULT	(g_alignments[bt_ellipsis])/*********************************************** Static Function Definitions */static ADDRESS *mk_legal P_ ((ADDRESS *, FLAGS));static BOOL g_compare P_ ((const EXPR *));static ADDRESS *g_cast P_ ((ADDRESS *, TYP *, TYP *, FLAGS));static ADDRESS *g_expr P_ ((const EXPR *, FLAGS));static void g_falsejp P_ ((const EXPR *, LABEL));static void g_truejp P_ ((const EXPR *, LABEL));#ifdef MULTIPLE_PROCESSORSPRIVATE 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_stack P_ ((SIZE));PRIVATE void g_switch_table P_ ((const EXPR *, const SWITCH *, UVAL, UVAL));PRIVATE void g_switch_compare P_ ((const EXPR *, STMT *));PRIVATE void g_entry P_ ((SIZE));PRIVATE void g_return P_ ((const EXPR *, TYP *));PRIVATE void g_epilogue P_ ((void));PRIVATE void g_allocate P_ ((CSE *));PRIVATE void g_flush P_ ((SYM *));PRIVATE void g_auto_align P_ ((void));PRIVATE BOOL g_is_bigendian P_ ((void));PRIVATE BOOL g_is_ascending_stack P_ ((void));PRIVATE void g_initialize P_ ((void));#endif /* MULTIPLE_PROCESSORS *//********************************************************** Static Variables */static unsigned peep_option = PEEP_ALL;	/* peephole optimisations */static int stackopt_option = 1L;	/* Use lazy stack optimisation */static BOOL regs_used = 0;	/* number of register variables allocated */static SIZE max_stack_adjust = 0L;	/* largest amount stack is altered */static REG frameptr = FRAMEPTR;static REGMASK restore_mask;	/* list of registers used by function *//* *	 The following tables specify the alignment requirements of the *	 basic types depending on the processor type. */static SIZE alignments_arm[] = {    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_float     */    4L,				/* bt_double    */    4L,				/* bt_longdouble */    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_arm[0];#endif /* MULTIPLE_PROCESSORS *//*****************************************************************************/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;    if (ap == NIL_ADDRESS) {	FATAL ((__FILE__, "copy_addr", "ap == 0"));    }    newap = (ADDRESS *) xalloc (sizeof (ADDRESS));    *newap = *ap;    newap->mode = mode;    return newap;}/* * make a ep to reference an immediate value i. */static ADDRESS *mk_immed P1 (IVAL, i){    ADDRESS *ap;    ap = mk_amode (am_immed);    ap->offset = mk_const (i);    return ap;}/* * construct a reference node for an internal label number. */static ADDRESS *mk_label P1 (LABEL, lab){    ADDRESS *ap;    ap = mk_amode (am_direct);    ap->offset = mk_lcon (lab);    return ap;}/* * make a node to reference a line number. */static ADDRESS *mk_line P1 (LINE, i){    ADDRESS *ap;    ap = mk_amode (am_line);    ap->offset = mk_const ((IVAL) i);    return ap;}#if 0/* * generate a direct reference to a string label. */ADDRESS *mk_strlab P1 (CHAR *, s){    ADDRESS *ap;    ap = mk_amode (am_direct);    ap->offset = mk_node (en_nacon, NIL_EXPR, NIL_EXPR, tp_void);    ap->offset->v.sp = s;    return ap;}#endif/* * make an address reference to a register. */ADDRESS *mk_reg P1 (REG, r){    ADDRESS *ap;    ap = mk_amode (am_reg);    ap->preg = r;    return ap;}/* * make an address reference to a register mask list. */static ADDRESS *mk_mask P1 (REGMASK, mask){    ADDRESS *ap;    ap = mk_amode (am_mask);    ap->offset = mk_const ((IVAL) mask);    return ap;}static ADDRESS *mk_direct P1 (EXPR *, ep){    ADDRESS *ap;    ap = mk_amode (am_direct);    ap->offset = ep;    return ap;}static ADDRESS *mk_address P3 (AMODE, mode, REG, reg, SIZE, off){    ADDRESS *ap;    ap = mk_amode (mode);    ap->preg = reg;    ap->offset = mk_const (off);    return ap;}static ADDRESS *mk_legal P2 (ADDRESS *, ap, FLAGS, flags){    ADDRESS *ap2;    if (flags & F_NOVALUE) {	freeop (ap);	return NIL_ADDRESS;    }    switch (ap->mode) {    case am_immed:	if (flags & F_IMMED) {	    return ap;	}	break;    case am_reg:	if (flags & F_REG) {	    return ap;	}	break;    default:	break;    }    if (flags & F_REG) {	freeop (ap);	ap2 = data_register ();	g_code (op_mov, cc_al, ap2, ap, NIL_ADDRESS);	return ap2;    }    FATAL ((__FILE__, "mk_legal", "mode = %d, flags = %d", ap->mode, flags));    return NIL_ADDRESS;}/* * add a compiler generated label to the peep list. */PRIVATE void g_label P1 (LABEL, labno){    sync_stack ();    g_code (op_label, cc_al, mk_label (labno), NIL_ADDRESS, NIL_ADDRESS);}#ifdef DEBUGOPT/* * add a source line number to the peep list. */PRIVATE void g_line P2 (LINE, line, const CHAR *, str){    (void) str;    g_code (op_line, cc_al, mk_line (line), NIL_ADDRESS, NIL_ADDRESS);}#endif /*DEBUGOPT *//* * add a conditional branch instruction to the peep list. */static void g_cbranch P2 (CONDITION, cc, LABEL, labno){    sync_stack ();    g_code (op_b, cc, mk_label (labno), NIL_ADDRESS, NIL_ADDRESS);}/* * add a branch instruction to the peep list. */PRIVATE void g_branch P1 (LABEL, labno){    g_code (op_b, cc_al, mk_label (labno), NIL_ADDRESS, NIL_ADDRESS);}/* * adjust the stack by "bytes" bytes. */PRIVATE void g_stack P1 (SIZE, bytes){    if (bytes != 0L) {	/* adjust stack pointer */	stack_offset -= bytes;	if (max_stack_adjust < bytes) {	    max_stack_adjust = bytes;	}    }}/* * generate the code to access an object. */static ADDRESS *g_deref P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1;    (void) flags;    switch (ep->nodetype) {    case en_autocon:	ap1 = mk_amode (am_pre);	ap1->preg = frameptr;	ap1->offset = mk_const (ep->v.i);	return ap1;    default:	ap1 = g_expr (ep, (FLAGS) (F_REG | F_IMMED));	if (ap1->mode == am_immed) {	    return copy_addr (ap1, am_pre);	}	return copy_addr (ap1, am_direct);    }}/* * generate the code for a unary minus */static ADDRESS *g_uminus P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_char:    case bt_schar:    case bt_uchar:    case bt_charu:    case bt_short:    case bt_int16:    case bt_ushort:    case bt_uint16:    case bt_long:    case bt_ulong:    case bt_int32:    case bt_uint32:    case bt_pointer32:	ap2 = g_expr (ep->v.p[0], F_REG);	freeop (ap2);	ap1 = data_register ();	g_code (op_rsb, cc_al, ap1, ap2, mk_immed (0L));	return mk_legal (ap1, flags);    default:	FATAL ((__FILE__, "g_uminus", "type = %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/* * generate the code for a negate */static ADDRESS *g_negate P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_char:    case bt_schar:    case bt_uchar:    case bt_charu:    case bt_short:    case bt_int16:    case bt_ushort:    case bt_uint16:    case bt_long:    case bt_ulong:    case bt_int32:    case bt_uint32:    case bt_pointer32:	ap2 = g_expr (ep->v.p[0], F_REG);	freeop (ap2);	ap1 = data_register ();	g_code (op_mvn, cc_al, ap1, ap2, NIL_ADDRESS);	return mk_legal (ap1, flags);    default:	FATAL ((__FILE__, "g_negate", "type = %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}/* * generate code to evaluate a and/or/xor node and return the addressing * node of the result */static ADDRESS *g_logic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep->v.p[0], F_REG);	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_REG | F_IMMED));	validate (ap1);	freeop (ap2);	g_code (op, cc_al, ap1, ap1, ap2);	return mk_legal (ap1, flags);    default:	FATAL ((__FILE__, "g_logic", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}static ADDRESS *g_aslogic P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    (void) flags;    (void) op;    FATAL ((__FILE__, "g_aslogic", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}/* * generate code to evaluate an add/subtract node and return the addressing * node of the result */static ADDRESS *g_add P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    ADDRESS *ap1, *ap2;    switch (ep->etp->type) {    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep->v.p[0], F_REG);	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_REG | F_IMMED));	validate (ap1);	freeop (ap2);	g_code (op, cc_al, ap1, ap1, ap2);	return mk_legal (ap1, flags);    default:	FATAL ((__FILE__, "g_add", "illegal type %d", ep->etp->type));	break;    }    return NIL_ADDRESS;}static ADDRESS *g_asadd P3 (const EXPR *, ep, FLAGS, flags, OPCODE, op){    (void) flags;    (void) op;    FATAL ((__FILE__, "g_asadd", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_mul P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    (void) ep;    FATAL ((__FILE__, "g_mul", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_asmul P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    FATAL ((__FILE__, "g_asmul", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_div P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    FATAL ((__FILE__, "g_div", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_asdiv P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    FATAL ((__FILE__, "g_asdiv", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_mod P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    FATAL ((__FILE__, "g_mod", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_asmod P2 (const EXPR *, ep, FLAGS, flags){    (void) flags;    FATAL ((__FILE__, "g_asmod", "typ = %d", ep->etp->type));    return NIL_ADDRESS;}static ADDRESS *g_lshift P2 (const EXPR *, ep, FLAGS, flags){    ADDRESS *ap1, *ap2, *ap3;    switch (ep->etp->type) {    case bt_int32:    case bt_uint32:    case bt_long:    case bt_ulong:    case bt_pointer32:	ap1 = g_expr (ep->v.p[0], F_REG);	ap2 = g_expr (ep->v.p[1], (FLAGS) (F_REG | F_IMMED));	validate (ap1);	freeop (ap2);

⌨️ 快捷键说明

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