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 + -
显示快捷键?