📄 iq2000.c
字号:
} } else if (p_info->reverse_regs) { rtx temp = cmp0; cmp0 = cmp1; cmp1 = temp; } if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0) reg = cmp0; else { reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result; convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0); } if (test == ITEST_NE) { convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0); if (p_invert != NULL) *p_invert = 0; invert = 0; } else if (test == ITEST_EQ) { reg2 = invert ? gen_reg_rtx (mode) : result; convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0); reg = reg2; } if (invert) { rtx one; one = const1_rtx; convert_move (result, gen_rtx_XOR (mode, reg, one), 0); } return result;}/* Emit the common code for doing conditional branches. operand[0] is the label to jump to. The comparison operands are saved away by cmp{si,di,sf,df}. */voidgen_conditional_branch (rtx operands[], enum rtx_code test_code){ enum cmp_type type = branch_type; rtx cmp0 = branch_cmp[0]; rtx cmp1 = branch_cmp[1]; enum machine_mode mode; rtx reg; int invert; rtx label1, label2; switch (type) { case CMP_SI: case CMP_DI: mode = type == CMP_SI ? SImode : DImode; invert = 0; reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert); if (reg) { cmp0 = reg; cmp1 = const0_rtx; test_code = NE; } else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0) /* We don't want to build a comparison against a nonzero constant. */ cmp1 = force_reg (mode, cmp1); break; case CMP_SF: case CMP_DF: reg = gen_reg_rtx (CCmode); /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */ emit_insn (gen_rtx_SET (VOIDmode, reg, gen_rtx_fmt_ee (test_code == NE ? EQ : test_code, CCmode, cmp0, cmp1))); test_code = test_code == NE ? EQ : NE; mode = CCmode; cmp0 = reg; cmp1 = const0_rtx; invert = 0; break; default: abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1), "bad test"); } /* Generate the branch. */ label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); label2 = pc_rtx; if (invert) { label2 = label1; label1 = pc_rtx; } emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, gen_rtx_IF_THEN_ELSE (VOIDmode, gen_rtx_fmt_ee (test_code, mode, cmp0, cmp1), label1, label2)));}/* Initialize CUM for a function FNTYPE. */voidinit_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname ATTRIBUTE_UNUSED){ static CUMULATIVE_ARGS zero_cum; tree param; tree next_param; if (TARGET_DEBUG_D_MODE) { fprintf (stderr, "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype); if (!fntype) fputc ('\n', stderr); else { tree ret_type = TREE_TYPE (fntype); fprintf (stderr, ", fntype code = %s, ret code = %s\n", tree_code_name[(int)TREE_CODE (fntype)], tree_code_name[(int)TREE_CODE (ret_type)]); } } *cum = zero_cum; /* Determine if this function has variable arguments. This is indicated by the last argument being 'void_type_mode' if there are no variable arguments. The standard IQ2000 calling sequence passes all arguments in the general purpose registers in this case. */ for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0; param != 0; param = next_param) { next_param = TREE_CHAIN (param); if (next_param == 0 && TREE_VALUE (param) != void_type_node) cum->gp_reg_found = 1; }}/* Advance the argument of type TYPE and mode MODE to the next argument position in CUM. */voidfunction_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named){ if (TARGET_DEBUG_D_MODE) { fprintf (stderr, "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode)); fprintf (stderr, "%p", (void *) type); fprintf (stderr, ", %d )\n\n", named); } cum->arg_number++; switch (mode) { case VOIDmode: break; default: gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); cum->gp_reg_found = 1; cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); break; case BLKmode: cum->gp_reg_found = 1; cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); break; case SFmode: cum->arg_words ++; if (! cum->gp_reg_found && cum->arg_number <= 2) cum->fp_code += 1 << ((cum->arg_number - 1) * 2); break; case DFmode: cum->arg_words += 2; if (! cum->gp_reg_found && cum->arg_number <= 2) cum->fp_code += 2 << ((cum->arg_number - 1) * 2); break; case DImode: cum->gp_reg_found = 1; cum->arg_words += 2; break; case QImode: case HImode: case SImode: cum->gp_reg_found = 1; cum->arg_words ++; break; }}/* Return an RTL expression containing the register for the given mode MODE and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */struct rtx_def *function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named){ rtx ret; int regbase = -1; int bias = 0; unsigned int *arg_words = &cum->arg_words; int struct_p = (type != 0 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE)); if (TARGET_DEBUG_D_MODE) { fprintf (stderr, "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", cum->gp_reg_found, cum->arg_number, cum->arg_words, GET_MODE_NAME (mode)); fprintf (stderr, "%p", (void *) type); fprintf (stderr, ", %d ) = ", named); } cum->last_arg_fp = 0; switch (mode) { case SFmode: regbase = GP_ARG_FIRST; break; case DFmode: cum->arg_words += cum->arg_words & 1; regbase = GP_ARG_FIRST; break; default: gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); /* Drops through. */ case BLKmode: if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) cum->arg_words += (cum->arg_words & 1); regbase = GP_ARG_FIRST; break; case VOIDmode: case QImode: case HImode: case SImode: regbase = GP_ARG_FIRST; break; case DImode: cum->arg_words += (cum->arg_words & 1); regbase = GP_ARG_FIRST; } if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS) { if (TARGET_DEBUG_D_MODE) fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : ""); ret = 0; } else { gcc_assert (regbase != -1); if (! type || TREE_CODE (type) != RECORD_TYPE || ! named || ! TYPE_SIZE_UNIT (type) || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) ret = gen_rtx_REG (mode, regbase + *arg_words + bias); else { tree field; for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD && host_integerp (bit_position (field), 0) && int_bit_position (field) % BITS_PER_WORD == 0) break; /* If the whole struct fits a DFmode register, we don't need the PARALLEL. */ if (! field || mode == DFmode) ret = gen_rtx_REG (mode, regbase + *arg_words + bias); else { unsigned int chunks; HOST_WIDE_INT bitpos; unsigned int regno; unsigned int i; /* ??? If this is a packed structure, then the last hunk won't be 64 bits. */ chunks = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD; if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS) chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias; /* Assign_parms checks the mode of ENTRY_PARM, so we must use the actual mode here. */ ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks)); bitpos = 0; regno = regbase + *arg_words + bias; field = TYPE_FIELDS (type); for (i = 0; i < chunks; i++) { rtx reg; for (; field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && int_bit_position (field) >= bitpos) break; if (field && int_bit_position (field) == bitpos && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD) reg = gen_rtx_REG (DFmode, regno++); else reg = gen_rtx_REG (word_mode, regno); XVECEXP (ret, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (bitpos / BITS_PER_UNIT)); bitpos += 64; regno++; } } } if (TARGET_DEBUG_D_MODE) fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias], struct_p ? ", [struct]" : ""); } /* We will be called with a mode of VOIDmode after the last argument has been seen. Whatever we return will be passed to the call insn. If we need any shifts for small structures, return them in a PARALLEL. */ if (mode == VOIDmode) { if (cum->num_adjusts > 0) ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code, gen_rtvec_v (cum->num_adjusts, cum->adjust)); } return ret;}static intiq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED){ if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1) { if (TARGET_DEBUG_D_MODE) fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD); return UNITS_PER_WORD; } return 0;}/* Implement va_start. */voidiq2000_va_start (tree valist, rtx nextarg){ int int_arg_words; /* Find out how many non-float named formals. */ int gpr_save_area_size; /* Note UNITS_PER_WORD is 4 bytes. */ int_arg_words = current_function_args_info.arg_words; if (int_arg_words < 8 ) /* Adjust for the prologue's economy measure. */ gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD; else gpr_save_area_size = 0; /* Everything is in the GPR save area, or in the overflow area which is contiguous with it. */ nextarg = plus_constant (nextarg, - gpr_save_area_size); std_expand_builtin_va_start (valist, nextarg);}/* Allocate a chunk of memory for per-function machine-dependent data. */static struct machine_function *iq2000_init_machine_status (void){ struct machine_function *f; f = ggc_alloc_cleared (sizeof (struct machine_function)); return f;}/* Implement TARGET_HANDLE_OPTION. */static booliq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED){ switch (code) { case OPT_mcpu_: if (strcmp (arg, "iq10") == 0) iq2000_tune = PROCESSOR_IQ10; else if (strcmp (arg, "iq2000") == 0) iq2000_tune = PROCESSOR_IQ2000; else return false; return true; case OPT_march_: /* This option has no effect at the moment. */ return (strcmp (arg, "default") == 0 || strcmp (arg, "DEFAULT") == 0 || strcmp (arg, "iq2000") == 0); default: return true; }}/* Detect any conflicts in the switches. */voidoverride_options (void){ target_flags &= ~MASK_GPOPT; iq2000_isa = IQ2000_ISA_DEFAULT; /* Identify the processor type. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -