📄 alpha.c
字号:
if (recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_ST && (set = single_set (dep_insn)) != 0 && GET_CODE (PATTERN (insn)) == SET && rtx_equal_p (SET_DEST (set), SET_SRC (PATTERN (insn)))) switch (get_attr_type (dep_insn)) { case TYPE_LD: /* No savings here. */ return cost; case TYPE_IMULL: case TYPE_IMULQ: /* In these cases, we save one cycle. */ return cost - 2; default: /* In all other cases, we save two cycles. */ return MAX (0, cost - 4); } /* Another case that needs adjustment is an arithmetic or logical operation. It's cost is usually one cycle, but we default it to two in the MD file. The only case that it is actually two is for the address in loads and stores. */ if (recog_memoized (dep_insn) >= 0 && get_attr_type (dep_insn) == TYPE_IADDLOG) switch (get_attr_type (insn)) { case TYPE_LD: case TYPE_ST: return cost; default: return 2; } /* The final case is when a compare feeds into an integer branch. The cost is only one cycle in that case. */ if (recog_memoized (dep_insn) >= 0 && get_attr_type (dep_insn) == TYPE_ICMP && recog_memoized (insn) >= 0 && get_attr_type (insn) == TYPE_IBR) return 2; /* Otherwise, return the default cost. */ return cost;}/* Print an operand. Recognize special options, documented below. */voidprint_operand (file, x, code) FILE *file; rtx x; char code;{ int i; switch (code) { case 'r': /* If this operand is the constant zero, write it as "$31". */ if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x)]); else if (x == CONST0_RTX (GET_MODE (x))) fprintf (file, "$31"); else output_operand_lossage ("invalid %%r value"); break; case 'R': /* Similar, but for floating-point. */ if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x)]); else if (x == CONST0_RTX (GET_MODE (x))) fprintf (file, "$f31"); else output_operand_lossage ("invalid %%R value"); break; case 'N': /* Write the 1's complement of a constant. */ if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%N value"); fprintf (file, "%ld", ~ INTVAL (x)); break; case 'P': /* Write 1 << C, for a constant C. */ if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%P value"); fprintf (file, "%ld", (HOST_WIDE_INT) 1 << INTVAL (x)); break; case 'h': /* Write the high-order 16 bits of a constant, sign-extended. */ if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%h value"); fprintf (file, "%ld", INTVAL (x) >> 16); break; case 'L': /* Write the low-order 16 bits of a constant, sign-extended. */ if (GET_CODE (x) != CONST_INT) output_operand_lossage ("invalid %%L value"); fprintf (file, "%ld", (INTVAL (x) & 0xffff) - 2 * (INTVAL (x) & 0x8000)); break; case 'm': /* Write mask for ZAP insn. */ if (GET_CODE (x) == CONST_DOUBLE) { HOST_WIDE_INT mask = 0; HOST_WIDE_INT value; value = CONST_DOUBLE_LOW (x); for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++, value >>= 8) if (value & 0xff) mask |= (1 << i); value = CONST_DOUBLE_HIGH (x); for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++, value >>= 8) if (value & 0xff) mask |= (1 << (i + sizeof (int))); fprintf (file, "%ld", mask & 0xff); } else if (GET_CODE (x) == CONST_INT) { HOST_WIDE_INT mask = 0, value = INTVAL (x); for (i = 0; i < 8; i++, value >>= 8) if (value & 0xff) mask |= (1 << i); fprintf (file, "%ld", mask); } else output_operand_lossage ("invalid %%m value"); break; case 'M': /* 'b', 'w', or 'l' as the value of the constant. */ if (GET_CODE (x) != CONST_INT || (INTVAL (x) != 8 && INTVAL (x) != 16 && INTVAL (x) != 32)) output_operand_lossage ("invalid %%M value"); fprintf (file, "%s", INTVAL (x) == 8 ? "b" : INTVAL (x) == 16 ? "w" : "l"); break; case 'U': /* Similar, except do it from the mask. */ if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xff) fprintf (file, "b"); else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffff) fprintf (file, "w");#if HOST_BITS_PER_WIDE_INT == 32 else if (GET_CODE (x) == CONST_DOUBLE && CONST_DOUBLE_HIGH (x) == 0 && CONST_DOUBLE_LOW (x) == -1) fprintf (file, "l");#else else if (GET_CODE (x) == CONST_INT && INTVAL (x) == 0xffffffff) fprintf (file, "l");#endif else output_operand_lossage ("invalid %%U value"); break; case 's': /* Write the constant value divided by 8. */ if (GET_CODE (x) != CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 && (INTVAL (x) & 7) != 8) output_operand_lossage ("invalid %%s value"); fprintf (file, "%ld", INTVAL (x) / 8); break; case 'S': /* Same, except compute (64 - c) / 8 */ if (GET_CODE (x) != CONST_INT && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64 && (INTVAL (x) & 7) != 8) output_operand_lossage ("invalid %%s value"); fprintf (file, "%ld", (64 - INTVAL (x)) / 8); break; case 'C': /* Write out comparison name. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%C value"); if (GET_CODE (x) == LEU) fprintf (file, "ule"); else if (GET_CODE (x) == LTU) fprintf (file, "ult"); else fprintf (file, "%s", GET_RTX_NAME (GET_CODE (x))); break; case 'D': /* Similar, but write reversed code. We can't get an unsigned code here. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%D value"); fprintf (file, "%s", GET_RTX_NAME (reverse_condition (GET_CODE (x)))); break; case 'c': /* Similar to `c', but swap. We can't get unsigned here either. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%D value"); fprintf (file, "%s", GET_RTX_NAME (swap_condition (GET_CODE (x)))); break; case 'd': /* Similar, but reverse and swap. We can't get unsigned here either. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%D value"); fprintf (file, "%s", GET_RTX_NAME (swap_condition (reverse_condition ((GET_CODE (x)))))); break; case 'E': /* Write the divide or modulus operator. */ switch (GET_CODE (x)) { case DIV: fprintf (file, "div%s", GET_MODE (x) == SImode ? "l" : "q"); break; case UDIV: fprintf (file, "div%su", GET_MODE (x) == SImode ? "l" : "q"); break; case MOD: fprintf (file, "rem%s", GET_MODE (x) == SImode ? "l" : "q"); break; case UMOD: fprintf (file, "rem%su", GET_MODE (x) == SImode ? "l" : "q"); break; default: output_operand_lossage ("invalid %%E value"); break; } break; case 'A': /* Write "_u" for unaligned access. */ if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == AND) fprintf (file, "_u"); break; case 0: if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x)]); else if (GET_CODE (x) == MEM) output_address (XEXP (x, 0)); else output_addr_const (file, x); break; default: output_operand_lossage ("invalid %%xn code"); }}/* Do what is necessary for `va_start'. The argument is ignored; We look at the current function to determine if stdarg or varargs is used and fill in an initial va_list. A pointer to this constructor is returned. */struct rtx_def *alpha_builtin_saveregs (arglist) tree arglist;{ rtx block, addr, argsize; tree fntype = TREE_TYPE (current_function_decl); int stdarg = (TYPE_ARG_TYPES (fntype) != 0 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) != void_type_node)); /* Compute the current position into the args, taking into account both registers and memory. Both of these are already included in current_function_args_info. */ argsize = GEN_INT (current_function_args_info * UNITS_PER_WORD); /* SETUP_INCOMING_VARARGS moves the starting address base up by 48, storing fp arg registers in the first 48 bytes, and the integer arg registers in the next 48 bytes. This is only done, however, if any integer registers need to be stored. If no integer registers need be stored, then we must subtract 48 in order to account for the integer arg registers which are counted in argsize above, but which are not actually stored on the stack. */ addr = (current_function_args_info <= 5 + stdarg ? plus_constant (virtual_incoming_args_rtx, 6 * UNITS_PER_WORD) : plus_constant (virtual_incoming_args_rtx, - (6 * UNITS_PER_WORD))); addr = force_operand (addr, NULL_RTX); /* Allocate the va_list constructor */ block = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD); RTX_UNCHANGING_P (block) = 1; RTX_UNCHANGING_P (XEXP (block, 0)) = 1; /* Store the address of the first integer register in the __base member. */#ifdef POINTERS_EXTEND_UNSIGNED addr = convert_memory_address (ptr_mode, addr);#endif emit_move_insn (change_address (block, ptr_mode, XEXP (block, 0)), addr); /* Store the argsize as the __va_offset member. */ emit_move_insn (change_address (block, TYPE_MODE (integer_type_node), plus_constant (XEXP (block, 0), POINTER_SIZE/BITS_PER_UNIT)), argsize); /* Return the address of the va_list constructor, but don't put it in a register. Doing so would fail when not optimizing and produce worse code when optimizing. */ return XEXP (block, 0);}/* This page contains routines that are used to determine what the function prologue and epilogue code will do and write them out. *//* Compute the size of the save area in the stack. */intalpha_sa_size (){ int size = 0; int i; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i]) size++; /* If some registers were saved but not reg 26, reg 26 must also be saved, so leave space for it. */ if (size != 0 && ! regs_ever_live[26]) size++; /* Our size must be even (multiple of 16 bytes). */ if (size & 1) size ++; return size * 8;}/* Return 1 if this function can directly return via $26. */intdirect_return (){ return (reload_completed && alpha_sa_size () == 0 && get_frame_size () == 0 && current_function_outgoing_args_size == 0 && current_function_pretend_args_size == 0);}/* Write a version stamp. Don't write anything if we are running as a cross-compiler. Otherwise, use the versions in /usr/include/stamp.h. */#if !defined(CROSS_COMPILE) && !defined(_WIN32)#include <stamp.h>#endifvoidalpha_write_verstamp (file) FILE *file;{#ifdef MS_STAMP char *p; fprintf (file, "\t.verstamp %d %d ", MS_STAMP, LS_STAMP); for (p = version_string; *p != ' ' && *p != 0; p++) fprintf (file, "%c", *p == '.' ? ' ' : *p); fprintf (file, "\n");#endif}/* Write code to add constant C to register number IN_REG (possibly 31) and put the result into OUT_REG. Use TEMP_REG as a scratch register; usually this will be OUT_REG, but should not be if OUT_REG is STACK_POINTER_REGNUM, since it must be updated in a single instruction. Write the code to FILE. */static voidadd_long_const (file, c, in_reg, out_reg, temp_reg) FILE *file; HOST_WIDE_INT c; int in_reg, out_reg, temp_reg;{ HOST_WIDE_INT low = (c & 0xffff) - 2 * (c & 0x8000); HOST_WIDE_INT tmp1 = c - low; HOST_WIDE_INT high = ((tmp1 >> 16) & 0xffff) - 2 * ((tmp1 >> 16) & 0x8000); HOST_WIDE_INT extra = 0; /* We don't have code to write out constants larger than 32 bits. */#if HOST_BITS_PER_LONG_INT == 64 if ((unsigned HOST_WIDE_INT) c >> 32 != 0) abort ();#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -