reg68k.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 787 行 · 第 1/2 页
C
787 行
/* * 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 *//****************************************************************************** * * Register allocation (for the expression evaluation) * This modules handles the management of scratch registers. * It keeps track of the allocated registers and of the stack * *****************************************************************************/#include "config.h"#ifdef MC680X0#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "gen68k.h"/*********************************************** Static Function Definitions */static void g_push P_ ((REG, DEEP));static void g_pop P_ ((REG, DEEP));static REG next_reg P_ ((REG, REGTYPE));/********************************************************** Static Variables *//* * This data structure is used to keep track of registers which * have been pushed onto the stack. */static struct{ REG reg; DEEP depth;} reg_stack[(int) MAX_REG_STACK + 1];static DEEP stack_depth;/* * This data structure is used to keep track of register which * have been allocated. */static struct{ REG reg; BOOL pushed;} reg_alloc[(int) MAX_REG_STACK + 1];static DEEP alloc_depth;/* * Define the registers which must be saved by a function if * they are used. * If the register is used to return a value then it needn't be * saved. * If the register is used to pass a parameter then it needn't be * saved. */static REG saved_registers[] = { D3, D4, D5, D6, D7, A2, A3, A4, A5, A6, A7#ifdef FLOAT_IEEE , FP2, FP3, FP4, FP5, FP6, FP7#endif /* FLOAT_IEEE */};static REGLIST saved_list = { (int) (sizeof (saved_registers) / sizeof (REG)), &saved_registers[0]};/* * Define the registers which are used to return the results * from a function call. */static REG result_registers[] = { D0, D1, D2};static REGLIST result_list = { (int) (sizeof (result_registers) / sizeof (REG)), &result_registers[0]};static REGUSAGE rusage = { &saved_list, &result_list};REGUSAGE *reg_usage = &rusage;REGTYPE regtype[NUM_REGS] = { D_REG, /* D0 */ D_REG, /* D1 */ D_REG, /* D2 */ D_REG, /* D3 */ D_REG, /* D4 */ D_REG, /* D5 */ D_REG, /* D6 */ D_REG, /* D7 */ A_REG, /* A0 */ A_REG, /* A1 */ A_REG, /* A2 */ A_REG, /* A3 */ A_REG, /* A4 */ A_REG, /* A5 */ A_REG, /* A6 */ A_REG, /* A7 */#ifdef FLOAT_IEEE F_REG, /* FP0 */ F_REG, /* FP1 */ F_REG, /* FP2 */ F_REG, /* FP3 */ F_REG, /* FP4 */ F_REG, /* FP5 */ F_REG, /* FP6 */ F_REG /* FP7 */ #else /* */ 0, 0, 0, 0, 0, 0, 0, 0#endif /* FLOAT_IEEE */};static DEEP reg_in_use[NUM_REGS];static REGMASK associated_regs[NUM_REGS];static ADDRESS apush = { am_adec, STACKPTR, (REG) 0, EMPTY, {NIL_EXPR} /*lint !e708*/ /* union initialization */};static ADDRESS apop = { am_ainc, STACKPTR, (REG) 0, EMPTY, {NIL_EXPR} /*lint !e708*/ /* union initialization */};static REG next_data; /* next temporary data register */static REG start_data; /* initial temporary data register */static REG next_addr; /* next temporary address register */static REG start_addr; /* initial temporary address register */#ifdef FLOAT_IEEEstatic REG next_float; /* next temporary floating point register */static REG start_float; /* initial temporary floating point register */#endif /* FLOAT_IEEE *//*****************************************************************************//* * This routine generates code to push a register onto the stack. */static void g_push P2 (REG, reg, DEEP, depth){ ADDRESS *ap; sync_stack (); ap = mk_reg (reg); switch (reg) { case D0: case D1: case D2: case D3: case D4: case D5: case D6: case D7: case A0: case A1: case A2: case A3: case A4: case A5: case A6: case A7: g_move (IL4, ap, &apush); break;#ifdef FLOAT_IEEE case FP0: case FP1: case FP2: case FP3: case FP4: case FP5: case FP6: case FP7: g_fcode (op_fmove, IL12, ap, &apush); break;#endif /* FLOAT_IEEE */ default: CANNOT_REACH_HERE (); } reg_stack[stack_depth].reg = reg; reg_stack[stack_depth].depth = depth; if (reg_alloc[depth].pushed) { FATAL ((__FILE__, "g_push", "reg %d already pushed", (int) reg)); } reg_alloc[depth].pushed = TRUE; /* check on stack overflow */ if (++stack_depth > MAX_REG_STACK) { FATAL ((__FILE__, "g_push", "register stack overflow")); }}/* * Generate code to pop a register from the stack. */static void g_pop P2 (REG, reg, DEEP, depth){ ADDRESS *ap; /* check on stack underflow */ if (stack_depth-- == EMPTY) { FATAL ((__FILE__, "g_pop", "register stack empty")); } /* check if the desired register really is on stack */ if (reg_stack[stack_depth].depth != depth) { FATAL ( (__FILE__, "g_pop", "register order (%d,%d)", (int) depth, (int) reg_stack[stack_depth].depth)); } /* check if the register which is restored is really void */ if (reg_in_use[reg] != UNUSED) { FATAL ((__FILE__, "g_pop", "register %d in use", (int) reg)); } reg_in_use[reg] = depth; sync_stack (); ap = mk_reg (reg); switch (reg) { case D0: case D1: case D2: case D3: case D4: case D5: case D6: case D7: case A0: case A1: case A2: case A3: case A4: case A5: case A6: case A7: g_move (IL4, &apop, ap); break;#ifdef FLOAT_IEEE case FP0: case FP1: case FP2: case FP3: case FP4: case FP5: case FP6: case FP7: g_fcode (op_fmove, IL12, &apop, ap); break;#endif /* FLOAT_IEEE */ default: CANNOT_REACH_HERE (); } /* clear the push_flag */ reg_alloc[depth].pushed = FALSE;}/* * This routine should be called before each expression is * evaluated to make sure the stack is balanced and all of * the registers are marked free. * * This is also a good place to free all 'pseudo' registers * in the stack frame by setting act_scratch to zero. */void initstack P0 (void){ REG reg; start_data = next_data = next_reg (D7, D_REG); start_addr = next_addr = next_reg (A7, A_REG);#ifdef FLOAT_IEEE start_float = next_float = next_reg (FP7, F_REG);#endif /* FLOAT_IEEE */ for (reg = D0; reg <= MAX_REG; reg++) { reg_in_use[reg] = UNUSED; associated_regs[reg] = (REGMASK) 0; } stack_depth = EMPTY; alloc_depth = EMPTY; act_scratch = 0L;}/* * This routines checks if all allocated registers were freed. */void checkstack P0 (void){ REG reg; if (next_data != start_data) { FATAL ( (__FILE__, "checkstack", "D%d not next temporary", (int) start_data - (int) D0)); } if (next_addr != start_addr) { FATAL ( (__FILE__, "checkstack", "A%d not next temporary", (int) start_addr - (int) A0)); }#ifdef FLOAT_IEEE if (next_float != start_float) { FATAL ( (__FILE__, "checkstack", "FP%d not next temporary", (int) start_float - (int) FP0)); }#endif for (reg = D0; reg <= MAX_REG; reg++) { if ((regtype[reg] & T_REG) && (reg_in_use[reg] != UNUSED)) { FATAL ( (__FILE__, "checkstack", "register %d still in use", (int) reg)); } } if (stack_depth != EMPTY) { FATAL ((__FILE__, "checkstack", "register stack not empty")); } if (alloc_depth != EMPTY) { FATAL ( (__FILE__, "checkstack", "allocated register stack not empty")); }}/* * Validate will make sure that if a register within an address * mode has been pushed onto the stack that it is popped back * at this time. */void validate P1 (const ADDRESS *, ap){ REG reg;
assert (ap != NULL);
switch (ap->mode) { case am_xreg: reg = ap->u.xreg; if (is_temporary_data_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, (DEEP) ((int) ap->deep + 2)); } /*lint -fallthrough */ case am_mreg: reg = ap->sreg; if (is_temporary_data_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, (DEEP) ((int) ap->deep + 1)); } /*lint -fallthrough */ case am_dreg: reg = ap->preg; if (is_temporary_data_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, ap->deep); } break; case am_indx2: case am_indx4: reg = ap->sreg; if (is_temporary_data_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, ap->deep); } goto common; /*lint !e801*/ /* use of goto deprecated */ case am_indx3:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?