📄 dsp16xx.c
字号:
/* Subroutines for assembler code output on the DSP1610. Copyright (C) 1994, 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by Michael Collison (collison@world.std.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* Some output-actions in dsp1600.md need these. */#include "config.h"#include <stdio.h>#include "rtl.h"#include "regs.h"#include "hard-reg-set.h"#include "real.h"#include "insn-config.h"#include "conditions.h"#include "insn-flags.h"#include "output.h"#include "insn-attr.h"#include "tree.h"#include "expr.h"#include "flags.h"char *text_seg_name;char *rsect_text;char *data_seg_name;char *rsect_data;char *bss_seg_name;char *rsect_bss;char *const_seg_name;char *rsect_const;char *chip_name;char *save_chip_name;/* Save the operands of a compare. The 16xx has not lt or gt, so in these cases we swap the operands and reverse the condition */rtx dsp16xx_compare_op0;rtx dsp16xx_compare_op1;struct rtx_def *(*dsp16xx_compare_gen)();static char *fp;static char *sp;static char *rr;static char *a1h;struct dsp16xx_frame_info current_frame_info;struct dsp16xx_frame_info zero_frame_info;rtx dsp16xx_addhf3_libcall = (rtx) 0;rtx dsp16xx_subhf3_libcall = (rtx) 0;rtx dsp16xx_mulhf3_libcall = (rtx) 0;rtx dsp16xx_divhf3_libcall = (rtx) 0;rtx dsp16xx_cmphf3_libcall = (rtx) 0;rtx dsp16xx_fixhfhi2_libcall = (rtx) 0;rtx dsp16xx_floathihf2_libcall = (rtx) 0;rtx dsp16xx_neghf2_libcall = (rtx) 0;rtx dsp16xx_mulhi3_libcall = (rtx) 0;rtx dsp16xx_udivqi3_libcall = (rtx) 0;rtx dsp16xx_udivhi3_libcall = (rtx) 0;rtx dsp16xx_divqi3_libcall = (rtx) 0;rtx dsp16xx_divhi3_libcall = (rtx) 0;rtx dsp16xx_modqi3_libcall = (rtx) 0;rtx dsp16xx_modhi3_libcall = (rtx) 0;rtx dsp16xx_umodqi3_libcall = (rtx) 0;rtx dsp16xx_umodhi3_libcall = (rtx) 0;rtx dsp16xx_ashrhi3_libcall = (rtx) 0;rtx dsp16xx_ashlhi3_libcall = (rtx) 0;rtx dsp16xx_ucmphi2_libcall = (rtx) 0;rtx dsp16xx_lshrhi3_libcall = (rtx) 0;char *himode_reg_name[] = HIMODE_REGISTER_NAMES;#define SHIFT_INDEX_1 0#define SHIFT_INDEX_4 1#define SHIFT_INDEX_8 2#define SHIFT_INDEX_16 3static char *ashift_right_asm[] = { "%0=%0>>1", "%0=%0>>4", "%0=%0>>8", "%0=%0>>16"};static char *ashift_right_asm_first[] = { "%0=%1>>1", "%0=%1>>4", "%0=%1>>8", "%0=%1>>16"};static char *ashift_left_asm[] = { "%0=%0<<1", "%0=%0<<4", "%0=%0<<8", "%0=%0<<16"};static char *ashift_left_asm_first[] = { "%0=%1<<1", "%0=%1<<4", "%0=%1<<8", "%0=%1<<16"};static char *lshift_right_asm[] = { "%0=%0>>1\n\t%0=%b0&0x7fff", "%0=%0>>4\n\t%0=%b0&0x0fff", "%0=%0>>8\n\t%0=%b0&0x00ff", "%0=%0>>16\n\t%0=%b0&0x0000"};static char *lshift_right_asm_first[] = { "%0=%1>>1\n\t%0=%b0&0x7fff", "%0=%1>>4\n\t%0=%b0&0x0fff", "%0=%1>>8\n\t%0=%b0&0x00ff", "%0=%1>>16\n\t%0=%b0&0x0000"};int hard_regno_mode_ok (regno, mode)int regno;enum machine_mode mode;{ switch ((int) mode) { case VOIDmode: return 1; /* We can't use the c0-c2 for QImode, since they are only 8 bits in length */ case QImode: if (regno != REG_C0 && regno != REG_C1 && regno != REG_C2) return 1; else return 0; /* We only allow a0, a1, y, and p to be allocated for 32-bit modes. Additionally we allow the virtual ybase registers to be used for 32-bit modes. */ case HFmode: case SFmode: case DFmode: case XFmode: case HImode: case SImode: case DImode: if (regno == REG_A0 || regno == REG_A1 || regno == REG_Y || regno == REG_PROD || (IS_YBASE_REGISTER_WINDOW(regno) && ((regno & 1) == 0))) return 1; else return 0; default: return 0; }}enum reg_classdsp16xx_reg_class_from_letter (c)int c;{ switch (c) { case 'A': return ACCUM_REGS; case 'h': return ACCUM_HIGH_REGS; case 'j': return A0H_REG; case 'k': return A0L_REG; case 'q': return A1H_REG; case 'u': return A1L_REG; case 'x': return X_REG; case 'y': return YH_REG; case 'z': return YL_REG; case 't': return P_REG; case 'Z': return Y_OR_P_REGS; case 'd': return ACCUM_Y_OR_P_REGS; case 'C': return NO_FRAME_Y_ADDR_REGS; case 'a': return Y_ADDR_REGS; case 'B': return (TARGET_BMU ? BMU_REGS : NO_REGS); case 'Y': return YBASE_VIRT_REGS; case 'v': return PH_REG; case 'w': return PL_REG; case 'W': return J_REG; case 'e': return YBASE_ELIGIBLE_REGS; case 'b': return ACCUM_LOW_REGS; case 'c': return NON_YBASE_REGS; case 'f': return Y_REG; case 'D': return SLOW_MEM_LOAD_REGS; default: fatal ("Invalid register class letter %c", c); return NO_REGS; }}/* Return the class number of the smallest class containing reg number REGNO. */int regno_reg_class(regno)int regno;{ switch (regno) { case REG_A0L: return (int) A0L_REG; case REG_A1L: return (int) A1L_REG; case REG_A0: return (int) A0H_REG; case REG_A1: return (int) A1H_REG; case REG_X: return (int) X_REG; case REG_Y: return (int) YH_REG; case REG_YL: return (int) YL_REG; case REG_PROD: return (int) PH_REG; case REG_PRODL: return (int) PL_REG; case REG_R0: case REG_R1: case REG_R2: case REG_R3: return (int) Y_ADDR_REGS; case REG_J: return (int) J_REG; case REG_K: return (int) GENERAL_REGS; case REG_YBASE: return (int) GENERAL_REGS; case REG_PT: return (int) GENERAL_REGS; case REG_AR0: case REG_AR1: case REG_AR2: case REG_AR3: return (int) BMU_REGS; case REG_C0: case REG_C1: case REG_C2: return (int) GENERAL_REGS; case REG_PR: return (int) GENERAL_REGS; case REG_RB: return (int) GENERAL_REGS; case REG_YBASE0: case REG_YBASE1: case REG_YBASE2: case REG_YBASE3: case REG_YBASE4: case REG_YBASE5: case REG_YBASE6: case REG_YBASE7: case REG_YBASE8: case REG_YBASE9: case REG_YBASE10: case REG_YBASE11: case REG_YBASE12: case REG_YBASE13: case REG_YBASE14: case REG_YBASE15: case REG_YBASE16: case REG_YBASE17: case REG_YBASE18: case REG_YBASE19: case REG_YBASE20: case REG_YBASE21: case REG_YBASE22: case REG_YBASE23: case REG_YBASE24: case REG_YBASE25: case REG_YBASE26: case REG_YBASE27: case REG_YBASE28: case REG_YBASE29: case REG_YBASE30: case REG_YBASE31: return (int) YBASE_VIRT_REGS; default: return (int) NO_REGS; }}/* A C expression for the maximum number of consecutive registers of class CLASS needed to hold a value of mode MODE */intclass_max_nregs(class, mode)enum reg_class class;enum machine_mode mode;{ return (GET_MODE_SIZE(mode));}enum reg_classlimit_reload_class (mode, class)enum machine_mode mode;enum reg_class class;{ switch ((int) class) { case NO_REGS: case A0H_REG: case A0L_REG: case A0_REG: case A1H_REG: return class; case ACCUM_HIGH_REGS: fatal ("ACCUM_HIGH_REGS class in limit_reload_class"); case A1L_REG: case ACCUM_LOW_REGS: case A1_REG: return class; case ACCUM_REGS: if (GET_MODE_SIZE(mode) == 1) return ACCUM_LOW_REGS; else return class; case X_REG: case X_OR_ACCUM_LOW_REGS: return class; case X_OR_ACCUM_REGS: if (GET_MODE_SIZE(mode) == 1) return X_OR_ACCUM_LOW_REGS; else return class; case YH_REG: return class; case YH_OR_ACCUM_HIGH_REGS: fatal ("YH_OR_ACCUM_HIGH_REGS found in limit_reload_class"); case X_OR_YH_REGS: return class; case YL_REG: /* Register 'yl' is invalid for QImode, so we should never see it. */ fatal ("YL found in limit_reload_class"); case YL_OR_ACCUM_LOW_REGS: case X_OR_YL_REGS: return class; case Y_REG: if (GET_MODE_SIZE(mode) > 1) return class; else return YH_REG; case ACCUM_OR_Y_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return YL_OR_ACCUM_LOW_REGS; case PH_REG: case X_OR_PH_REGS: case PL_REG: case PL_OR_ACCUM_LOW_REGS: case X_OR_PL_REGS: return class; case P_REG: if (GET_MODE_SIZE(mode) > 1) return class; else return PL_REG; case ACCUM_OR_P_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return PL_OR_ACCUM_LOW_REGS; case YL_OR_P_REGS: case ACCUM_LOW_OR_YL_OR_P_REGS: return class; case Y_OR_P_REGS: return class; case ACCUM_Y_OR_P_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return ACCUM_LOW_OR_YL_OR_P_REGS; case NO_FRAME_Y_ADDR_REGS: case Y_ADDR_REGS: case ACCUM_LOW_OR_Y_ADDR_REGS: return class; case ACCUM_OR_Y_ADDR_REGS: if (GET_MODE_SIZE(mode) > 1) return ACCUM_REGS; else return ACCUM_LOW_OR_Y_ADDR_REGS; case X_OR_Y_ADDR_REGS: return class; case Y_OR_Y_ADDR_REGS: case P_OR_Y_ADDR_REGS: case NON_HIGH_YBASE_ELIGIBLE_REGS: case J_REG: return class; case YBASE_ELIGIBLE_REGS: if (GET_MODE_SIZE(mode) > 1) return ACCUM_Y_P_OR_YBASE_REGS; else return NON_HIGH_YBASE_ELIGIBLE_REGS; case J_OR_DAU_16_BIT_REGS: if (GET_MODE_SIZE(mode) == 1) return J_REG; else return class; case BMU_REGS: case NOHIGH_NON_ADDR_REGS: return class; case NON_ADDR_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return NOHIGH_NON_ADDR_REGS; case NOHIGH_NON_YBASE_REGS: return class; case NON_YBASE_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return NOHIGH_NON_YBASE_REGS; case YBASE_VIRT_REGS: case ACCUM_LOW_OR_YBASE_REGS: return class; case ACCUM_OR_YBASE_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return ACCUM_LOW_OR_YBASE_REGS; case X_OR_YBASE_REGS: return class; case Y_OR_YBASE_REGS: case ACCUM_LOW_YL_PL_OR_YBASE_REGS: case P_OR_YBASE_REGS: return class; case ACCUM_Y_P_OR_YBASE_REGS: return ACCUM_LOW_YL_PL_OR_YBASE_REGS; case Y_ADDR_OR_YBASE_REGS: case YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS: return class; case YBASE_OR_YBASE_ELIGIBLE_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return YBASE_OR_NOHIGH_YBASE_ELIGIBLE_REGS; case NO_HIGH_ALL_REGS: return class; case ALL_REGS: if (GET_MODE_SIZE(mode) > 1) return class; else return NO_HIGH_ALL_REGS; default: return class; }}intdsp16xx_register_move_cost (from, to)enum reg_class from, to;{#if 0 if (from == NO_REGS || to == NO_REGS || (from == to)) return 2;#endif if (from == A0H_REG || from == A0L_REG || from == A0_REG || from == A1H_REG || from == ACCUM_HIGH_REGS || from == A1L_REG || from == ACCUM_LOW_REGS || from == A1_REG || from == ACCUM_REGS) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -