📄 gen386.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 INTEL_386/****************************************************************************** * * This module contains all the code generation routines for * evaluating expressions and conditions for the INTEL 80386 * processor. * *****************************************************************************/#define GEN_MODULE#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen386.h"#include "outproto.h"/********************************************************* Macro Definitions */#define AL_DEFAULT (g_alignments[bt_ellipsis])/********************************************************** Static Variables *//* * Command line options */static unsigned peep_option = PEEP_ALL; /* peephole optimisations */static int stackopt_option = OPT_MINIMUM; /* Use lazy stack optimisation */static int regs_used = 0; /* number of register variable allocated */static REGMASK restore_mask; /* register restore mask */static SIZE max_stack_adjust = 0L; /* largest amount stack is altered */static REG regframe = FRAMEPTR;#ifdef FLOAT_IEEEstatic ADDRESS ax_reg = { am_dreg, AX, (REG) 0, (DEEP) 0, {NIL_EXPR}};#endif /* FLOAT_IEEE */static ADDRESS ecx_reg = { am_dreg, ECX, (REG) 0, (DEEP) 0, {NIL_EXPR}};static ADDRESS edi_reg = { am_dreg, EDI, (REG) 0, (DEEP) 0, {NIL_EXPR}};static ADDRESS esi_reg = { am_dreg, ESI, (REG) 0, (DEEP) 0, {NIL_EXPR}};static ADDRESS esp_reg = { am_dreg, ESP, (REG) 0, (DEEP) 0, {NIL_EXPR}};static ADDRESS eax_reg = { am_dreg, EAX, (REG) 0, (DEEP) 0, {NIL_EXPR}};static ADDRESS edx_reg = { am_dreg, EDX, (REG) 0, (DEEP) 0, {NIL_EXPR}};static REGTYPE reg_type[] = { (REGTYPE) (D_REG | A_REG | X_REG | T_REG), /* EAX */ (REGTYPE) (D_REG | A_REG | X_REG | T_REG), /* EDX */ (REGTYPE) (D_REG | A_REG | Y_REG | T_REG | C_REG), /* ECX */ (REGTYPE) 0, /* EBX */ (REGTYPE) 0, /* ESI */ (REGTYPE) 0, /* EDI */ (REGTYPE) 0, /* ESP */ (REGTYPE) 0, /* EBP */ (REGTYPE) 0, /* AX */ (REGTYPE) 0, /* DX */ (REGTYPE) 0, /* CX */ (REGTYPE) 0, /* BX */ (REGTYPE) 0, /* SI */ (REGTYPE) 0, /* DI */ (REGTYPE) 0, /* SP */ (REGTYPE) 0, /* BP */ (REGTYPE) 0, /* AL */ (REGTYPE) 0, /* DL */ (REGTYPE) 0, /* CL */ (REGTYPE) 0, /* BL */ (REGTYPE) (F_REG | T_REG), /* ST0 */ (REGTYPE) (F_REG | T_REG), /* ST1 */ (REGTYPE) (F_REG | T_REG), /* ST2 */ (REGTYPE) (F_REG | T_REG), /* ST3 */ (REGTYPE) (F_REG | T_REG), /* ST4 */ (REGTYPE) (F_REG | T_REG), /* ST5 */ (REGTYPE) (F_REG | T_REG), /* ST6 */ (REGTYPE) (F_REG | T_REG) /* ST7 */};/* * The following tables specify the alignment requirements of the * basic types depending on the processor type. */static SIZE alignments_386[] = { 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_floatimaginary */ 4L, /* bt_doubleimaginary */ 4L, /* bt_longdoubleimaginary */ 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_386[0];#endif /* MULTIPLE_PROCESSORS *//*********************************************** Static Function Definitions */static ADDRESS *func_result P_ ((FLAGS, SIZE, TYP *));static ADDRESS *g_aincdec P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_asbin 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_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_bin P_ ((const EXPR *, FLAGS, OPCODE));static ADDRESS *g_cast P_ ((ADDRESS *, TYP *, TYP *, FLAGS));static ADDRESS *g_deref P_ ((const EXPR *, TYP *));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_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_amode P_ ((AMODE));static ADDRESS *mk_expr P_ ((AMODE, EXPR *));static ADDRESS *mk_legal P_ ((ADDRESS *, FLAGS, TYP *));static ADDRESS *mk_direct P_ ((EXPR *));static ADDRESS *mk_indirect P_ ((REG, EXPR *));static ADDRESS *mk_strlab P_ ((const CHAR *));static OPCODE g_compare P_ ((const EXPR *, OPCODE, OPCODE));static OPCODE g_test P_ ((const EXPR *, OPCODE));static SIZE g_parms P_ ((const EXPR *));static SIZE push_param P_ ((const EXPR *));static void g_falsejp P_ ((const EXPR *, LABEL));static void g_rotate P_ ((ADDRESS *, ILEN, int, TYP *, int));static void g_truejp P_ ((const EXPR *, LABEL));static void structassign P_ ((ADDRESS *, ADDRESS *, SIZE));#ifdef FLOAT_IEEEstatic void call_library P_ ((const CHAR *));#endif /* FLOAT_IEEE *//*********************************************** Global Function Definitions */#ifdef MULTIPLE_PROCESSORSPRIVATE BOOL g_is_bigendian P_ ((void));PRIVATE BOOL g_is_ascending_stack P_ ((void));PRIVATE void g_auto_align P_ ((void));PRIVATE void g_flush P_ ((SYM *));PRIVATE void g_allocate P_ ((CSE *));PRIVATE void g_entry P_ ((SIZE));PRIVATE void g_epilogue P_ ((void));PRIVATE 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_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));PRIVATE void g_initialize P_ ((void));#endif /* MULTIPLE_PROCESSORS *//*****************************************************************************/#ifdef FLOAT_IEEE/* * 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, NIL_TYP); g_code (op_call, IL0, mk_strlab (nameof (sp)), NIL_ADDRESS);}#endif /* FLOAT_IEEE */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; assert (ap != NIL_ADDRESS); newap = (ADDRESS *) xalloc (sizeof (ADDRESS)); *newap = *ap; newap->mode = mode; return newap;}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 an immediate value i. */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));}/* * 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);}/* * 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;}/* * 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);}/* * make an address reference to a register. */ADDRESS *mk_reg P1 (REG, reg){ ADDRESS *ap; switch (reg) { case EAX: case EBX: case ECX: case EDX: case ESI: case EDI: case ESP: case EBP: ap = mk_amode (am_dreg); ap->preg = reg; break;#ifdef FLOAT_IEEE case ST0: case ST1: case ST2: case ST3: case ST4: case ST5: case ST6: case ST7: ap = mk_amode (am_freg); ap->preg = reg; break;#endif /* FLOAT_IEEE */ default: CANNOT_REACH_HERE (); ap = NIL_ADDRESS; } return ap;}ADDRESS *mk_mreg P2 (REG, r1, REG, r2){ ADDRESS *ap; ap = mk_amode (am_mreg); ap->preg = r1; ap->sreg = r2; return ap;}static ADDRESS *mk_offset P2 (ADDRESS *, ap, SIZE, off){ switch (ap->mode) { case am_ind: ap = copy_addr (ap, am_indx); ap->u.offset = mk_const (off); return ap; case am_indx: case am_indx2: ap = copy_addr (ap, am_indx); ap->u.offset = mk_const (ap->u.offset->v.i + off); return ap; case am_direct: ap = copy_addr (ap, ap->mode); ap->u.offset = mk_add (ap->u.offset, mk_const (off)); return ap; default: return NIL_ADDRESS; }}static ADDRESS *mk_low P1 (ADDRESS *, ap){ switch (ap->mode) { case am_dreg: case am_areg: case am_freg: case am_immed: return ap; case am_mreg: return mk_reg (ap->preg); case am_ind: case am_indx: case am_indx2: case am_direct: return mk_offset (ap, 0L); default: CANNOT_REACH_HERE (); break; } return NIL_ADDRESS;}static ADDRESS *mk_high P1 (ADDRESS *, ap){ switch (ap->mode) { case am_mreg: return mk_reg (ap->sreg); case am_ind: case am_indx: case am_indx2: case am_direct: return mk_offset (ap, 4L); default: CANNOT_REACH_HERE (); break; } return NIL_ADDRESS;}/* * returns addressing mode of form offset(regframe) * size is rounded up to AL_DEFAULT */static ADDRESS *mk_scratch P1 (SIZE, size){ ADDRESS *ap; /* round up the request */ if (size % AL_DEFAULT) { size += AL_DEFAULT - (size % AL_DEFAULT); } /* 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 (-(lc_auto_max + act_scratch))); return ap;}/* * add a compiler generated label to the peep list. */PRIVATE void g_label P1 (LABEL, labno){ sync_stack (); g_code (op_label, IL0, mk_label (labno), NIL_ADDRESS);}#ifdef DEBUGOPT/* * add a source line number to the peep list. */PRIVATE void g_line P2 (LINE, line, const CHAR *, linetxt){ g_code (op_line, IL0, mk_line (line), mk_linetxt (linetxt));}#endif /*DEBUGOPT *//* * add a conditional branch instruction to the peep list. */static void g_cbranch P2 (OPCODE, op, LABEL, labno){ sync_stack (); g_code (op, IL0, mk_label (labno), NIL_ADDRESS);}/* * add a branch instruction to the peep list. */PRIVATE void g_branch P1 (LABEL, labno){ g_cbranch (op_bra, labno);}/* * adjust the stack by "bytes" bytes. */PRIVATE void g_stack P1 (SIZE, bytes){ if (bytes != 0L) { /* adjust stack pointer */ if (bytes == 4L && !is_register_used (ECX)) { g_code (op_pop, IL4, &ecx_reg, NIL_ADDRESS); } else { g_code (op_add, IL4, mk_immed (bytes), &esp_reg); } stack_offset -= bytes; if (max_stack_adjust < bytes) { max_stack_adjust = bytes; } }}/* * mk_legal will coerce the addressing mode in ap1 into a mode that is * satisfactory for the flag word. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -