reg68k.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 787 行 · 第 1/2 页
C
787 行
reg = ap->sreg; if (is_temporary_address_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, ap->deep); } goto common; /*lint !e801*/ /* use of goto deprecated */ case am_areg: case am_ind: case am_indx: case am_ainc: case am_adec: common: reg = ap->preg; if (is_temporary_address_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, ap->deep); } break;#ifdef FLOAT_IEEE case am_freg: reg = ap->preg; if (is_temporary_float_register (reg) && reg_alloc[ap->deep].pushed) { g_pop (reg, ap->deep); } break;#endif /* FLOAT_IEEE */ default: break; }}/* * Return the next register of type 'kind' */static REG next_reg P2 (REG, reg, REGTYPE, kind){ int count; for (count = 64; count; count--) { reg = (reg == FP7) ? D0 : (REG) ((int) reg + 1); if (((regtype[reg] & T_REG)) && (regtype[reg] & kind)) { return reg; } } return NO_REG;}/* * Return the previous register of type 'kind' */static REG prev_reg P2 (REG, reg, REGTYPE, kind){ int count; for (count = 64; count; count--) { reg = (reg == D0) ? FP7 : (REG) ((int) reg - 1); if (((regtype[reg] & T_REG)) && (regtype[reg] & kind)) { return reg; } } return NO_REG;}/* * Allocate a temporary register. Returns the next register * that will be allocated. */static REG allocate_register P2 (REG, reg, REGTYPE, kind){ if (reg_in_use[reg] != UNUSED) { /* * The next available register is already in use. * It (and any associated registers) must be pushed. */ REG r; REGMASK rmask = associated_regs[reg]; for (r = 0; r < NUM_REGS; r++) { if (rmask & REGBIT (r)) { g_push (r, reg_in_use[r]); reg_in_use[r] = UNUSED; } } } reg_in_use[reg] = alloc_depth; associated_regs[reg] = REGBIT (reg); reg_alloc[alloc_depth].reg = reg; reg_alloc[alloc_depth].pushed = FALSE; if (alloc_depth++ == MAX_REG_STACK) { FATAL ((__FILE__, "allocate_register", "register stack overflow")); } return next_reg (reg, kind);}/* * Allocate a temporary data register and return * it's addressing mode. */ADDRESS *data_register P0 (void){ ADDRESS *ap = mk_reg (next_data); next_data = allocate_register (next_data, D_REG); ap->deep = reg_in_use[ap->preg]; return ap;}/* * Allocate 2 temporary data registers and return * it's addressing mode. */ADDRESS *mdata_register P0 (void){ REG reg1; REG reg2; ADDRESS *ap; reg1 = next_data; next_data = allocate_register (next_data, D_REG); reg2 = next_data; next_data = allocate_register (next_data, D_REG); ap = mk_mreg (reg1, reg2); ap->deep = reg_in_use[reg1]; associated_regs[reg1] |= REGBIT (reg2); associated_regs[reg2] |= REGBIT (reg1); return ap;}/* * Allocate 3 temporary data registers and return * it's addressing mode. */ADDRESS *xdata_register P0 (void){ REG reg1; REG reg2; REG reg3; ADDRESS *ap; reg1 = next_data; next_data = allocate_register (next_data, D_REG); reg2 = next_data; next_data = allocate_register (next_data, D_REG); reg3 = next_data; next_data = allocate_register (next_data, D_REG); ap = mk_xreg (reg1, reg2, reg3); ap->deep = reg_in_use[reg1]; associated_regs[reg1] |= (REGBIT (reg2) | REGBIT (reg3)); associated_regs[reg2] |= (REGBIT (reg1) | REGBIT (reg3)); associated_regs[reg3] |= (REGBIT (reg1) | REGBIT (reg2)); return ap;}/* * Allocate a temporary addr register and return it's addressing mode. */ADDRESS *address_register P0 (void){ ADDRESS *ap = mk_reg (next_addr); next_addr = allocate_register (next_addr, A_REG); ap->deep = reg_in_use[ap->preg]; return ap;}#ifdef FLOAT_IEEE/* * Allocate a temporary floating point register and return it's * addressing mode. */ADDRESS *float_register P0 (void){ ADDRESS *ap = mk_reg (next_float); next_float = allocate_register (next_float, F_REG); ap->deep = reg_in_use[ap->preg]; return ap;}#endif /* FLOAT_IEEE *//* * Returns TRUE if a data register is available at ,,no cost'' (no push). * Used to determine e.g. whether cmp.w #0,An or move.l An,Dm is better */BOOL is_free_data P0 (void){ return (reg_in_use[next_data] == UNUSED);}/* * returns TRUE if an address register is available at * ,,no cost'' (no push). */BOOL is_free_addr P0 (void){ return (reg_in_use[next_addr] == UNUSED);}/* * Allocates a data or addressing register (whichever is free). * Otherwise allocates the first register which matches flags. */ADDRESS *temp_reg P1 (FLAGS, flags){ if (is_free_data () && (flags & F_DREG)) { return data_register (); } if (is_free_addr () && (flags & F_AREG)) { return address_register (); } if (flags & F_DREG) { return data_register (); } if (flags & F_AREG) { return address_register (); }#ifdef FLOAT_IEEE if (flags & F_FREG) { return float_register (); }#endif /* FLOAT_IEEE */ return NIL_ADDRESS;}/* * Deallocate the specified register. */static void deallocate_register P1 (REG, reg){ DEEP depth; if (!is_temporary_register (reg)) { return; } if (is_data_register (reg)) { next_data = prev_reg (next_data, D_REG); } else if (is_address_register (reg)) { next_addr = prev_reg (next_addr, A_REG);#ifdef FLOAT_IEEE } else if (is_float_register (reg)) { next_float = prev_reg (next_float, F_REG);#endif /* FLOAT_IEEE */ } depth = reg_in_use[reg]; reg_in_use[reg] = UNUSED; /* we should only free the most recently allocated register */ if (alloc_depth-- == EMPTY) { FATAL ((__FILE__, "deallocate_register", "register stack empty")); } if (alloc_depth != depth) { FATAL ((__FILE__, "deallocate_register", "register stack order")); } /* the just freed register should not be on stack */ if (reg_alloc[depth].pushed) { FATAL ((__FILE__, "deallocate_register", "register pushed")); }}/* * Release any temporary registers used in an addressing mode. */void freeop P1 (const ADDRESS *, ap){ DEEP depth; REG reg; if (ap == NIL_ADDRESS) { /* This can happen freeing a NOVALUE result */ return; } switch (ap->mode) { case am_xreg: deallocate_register (ap->u.xreg); /*lint -fallthrough */ case am_mreg: case am_indx2: case am_indx3: case am_indx4: deallocate_register (ap->sreg); /*lint -fallthrough */ case am_dreg: case am_areg: case am_ainc: case am_adec: case am_ind: case am_indx:#ifdef FLOAT_IEEE case am_freg:#endif /* FLOAT_IEEE */ reg = ap->preg; break; default: return; } if (!is_temporary_register (reg)) { return; } depth = reg_in_use[reg]; deallocate_register (reg); /* some consistency checks */ if (depth != ap->deep) { FATAL ((__FILE__, "freeop", "1")); }}/* * Push any used temporary registers. * * This is necessary across function calls * The reason for this hacking is actually that temp_inv() * should dump the registers in the correct order, * * The least recently allocate register first. * The most recently allocated register last. */void temp_inv P1 (REGUSAGE *, regusage){ DEEP deep; UNUSEDARG (regusage); for (deep = EMPTY; deep < alloc_depth; deep++) if (!reg_alloc[deep].pushed) { g_push (reg_alloc[deep].reg, deep); /* mark the register void */ reg_in_use[reg_alloc[deep].reg] = UNUSED; }}/* * Converts a list of registers into a register mask */REGMASK reglist_to_mask P1 (const REGLIST *, rp){ REGMASK mask = (REGMASK) 0; int num; for (num = 0; num < rp->number; num++) { mask |= REGBIT (rp->reg[num]); } return mask;}/* * Find a register of type 'kind' for a register variable. * The 'mask' parameter specifies those registers which are not to be * allocated. If there are no register suitable then * NO_REG is returned. */REG find_register P2 (REGTYPE, kind, REGMASK, mask){ REG reg; for (reg = D0; reg <= MAX_REG; reg++) { if (mask & REGBIT (reg)) { continue; } if (regtype[reg] & kind) { return reg; } } return NO_REG;}/* * Count the number of registers that have been specified in the * register mask. */int count_registers P1 (REGMASK, mask){ int count; REG reg; for (count = 0, reg = D0; reg <= MAX_REG; reg++) { if (mask & REGBIT (reg)) { count++; } } return count;}#endif /* MC680X0 */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?