📄 gen68k.c
字号:
/* * 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 + -