📄 s390.c
字号:
value >>= 8; if ((value & 0xff) != (unsigned)(def & 0xff)) { if (part != -1) return -1; else part = i; } } return part == -1 ? 0 : (n_parts - 1 - part); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) { unsigned HOST_WIDE_INT value; int n_parts = GET_MODE_SIZE (mode); int i, part = -1; for (i = 0; i < n_parts; i++) { if (i == 0) value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op); else if (i == HOST_BITS_PER_WIDE_INT / 8) value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op); else value >>= 8; if ((value & 0xff) != (unsigned)(def & 0xff)) { if (part != -1) return -1; else part = i; } } return part == -1 ? 0 : (n_parts - 1 - part); } return -1; }/* Extract the QImode part number PART from integer constant OP of mode MODE. */ints390_extract_qi (op, mode, part) rtx op; enum machine_mode mode; int part;{ int n_parts = GET_MODE_SIZE (mode); if (part < 0 || part >= n_parts) abort(); else part = n_parts - 1 - part; if (GET_CODE (op) == CONST_INT) { unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op); return ((value >> (8 * part)) & 0xff); } else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode) { unsigned HOST_WIDE_INT value; if (part < HOST_BITS_PER_WIDE_INT / 8) value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op); else value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op), part -= HOST_BITS_PER_WIDE_INT / 8; return ((value >> (8 * part)) & 0xff); } abort ();}/* Change optimizations to be performed, depending on the optimization level. LEVEL is the optimization level specified; 2 if `-O2' is specified, 1 if `-O' is specified, and 0 if neither is specified. SIZE is non-zero if `-Os' is specified and zero otherwise. */voidoptimization_options (level, size) int level ATTRIBUTE_UNUSED; int size ATTRIBUTE_UNUSED;{#ifdef HAVE_decrement_and_branch_on_count /* When optimizing, enable use of BRCT instruction. */ if (level >= 1) flag_branch_on_count_reg = 1;#endif}voidoverride_options (){ /* Acquire a unique set number for our register saves and restores. */ s390_sr_alias_set = new_alias_set ();}/* Map for smallest class containing reg regno. */enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] ={ GENERAL_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, FP_REGS, ADDR_REGS, NO_REGS, ADDR_REGS };/* Return true if OP a (const_int 0) operand. OP is the current operation. MODE is the current operation mode. */ intconst0_operand (op, mode) register rtx op; enum machine_mode mode;{ return op == CONST0_RTX (mode);}/* Return true if OP is constant. OP is the current operation. MODE is the current operation mode. */intconsttable_operand (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ return CONSTANT_P (op);}/* Return true if the mode of operand OP matches MODE. If MODE is set to VOIDmode, set it to the mode of OP. */ static intcheck_mode (op, mode) register rtx op; enum machine_mode *mode;{ if (*mode == VOIDmode) *mode = GET_MODE (op); else { if (GET_MODE (op) != VOIDmode && GET_MODE (op) != *mode) return 0; } return 1;}/* Return true if OP a valid operand for the LARL instruction. OP is the current operation. MODE is the current operation mode. */intlarl_operand (op, mode) register rtx op; enum machine_mode mode;{ if (! check_mode (op, &mode)) return 0; /* Allow labels and local symbols. */ if (GET_CODE (op) == LABEL_REF) return 1; if (GET_CODE (op) == SYMBOL_REF && (!flag_pic || SYMBOL_REF_FLAG (op) || CONSTANT_POOL_ADDRESS_P (op))) return 1; /* Everything else must have a CONST, so strip it. */ if (GET_CODE (op) != CONST) return 0; op = XEXP (op, 0); /* Allow adding *even* constants. */ if (GET_CODE (op) == PLUS) { if (GET_CODE (XEXP (op, 1)) != CONST_INT || (INTVAL (XEXP (op, 1)) & 1) != 0) return 0; op = XEXP (op, 0); } /* Labels and local symbols allowed here as well. */ if (GET_CODE (op) == LABEL_REF) return 1; if (GET_CODE (op) == SYMBOL_REF && (!flag_pic || SYMBOL_REF_FLAG (op) || CONSTANT_POOL_ADDRESS_P (op))) return 1; /* Now we must have a @GOTENT offset or @PLT stub. */ if (GET_CODE (op) == UNSPEC && XINT (op, 1) == 111) return 1; if (GET_CODE (op) == UNSPEC && XINT (op, 1) == 113) return 1; return 0;}/* Return true if OP is a valid FP-Register. OP is the current operation. MODE is the current operation mode. */intfp_operand (op, mode) register rtx op; enum machine_mode mode;{ register enum rtx_code code = GET_CODE (op); if (! check_mode (op, &mode)) return 0; if (code == REG && REGNO_OK_FOR_FP_P (REGNO (op))) return 1; else return 0;}/* Helper routine to implement s_operand and s_imm_operand. OP is the current operation. MODE is the current operation mode. ALLOW_IMMEDIATE specifies whether immediate operands should be accepted or not. */static intgeneral_s_operand (op, mode, allow_immediate) register rtx op; enum machine_mode mode; int allow_immediate;{ struct s390_address addr; /* Call general_operand first, so that we don't have to check for many special cases. */ if (!general_operand (op, mode)) return 0; /* Just like memory_operand, allow (subreg (mem ...)) after reload. */ if (reload_completed && GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == MEM) op = SUBREG_REG (op); switch (GET_CODE (op)) { /* Constants that we are sure will be forced to the literal pool in reload are OK as s-operand. Note that we cannot call s390_preferred_reload_class here because it might not be known yet at this point whether the current function is a leaf or not. */ case CONST_INT: case CONST_DOUBLE: if (!allow_immediate || reload_completed) break; if (!legitimate_reload_constant_p (op)) return 1; if (!TARGET_64BIT) return 1; break; /* Memory operands are OK unless they already use an index register. */ case MEM: if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) return 1; if (s390_decompose_address (XEXP (op, 0), &addr, FALSE) && !addr.indx) return 1; break; default: break; } return 0;}/* Return true if OP is a valid S-type operand. OP is the current operation. MODE is the current operation mode. */ints_operand (op, mode) register rtx op; enum machine_mode mode;{ return general_s_operand (op, mode, 0);}/* Return true if OP is a valid S-type operand or an immediate operand that can be addressed as S-type operand by forcing it into the literal pool. OP is the current operation. MODE is the current operation mode. */ints_imm_operand (op, mode) register rtx op; enum machine_mode mode;{ return general_s_operand (op, mode, 1);}/* Return true if OP is a valid operand for the BRAS instruction. OP is the current operation. MODE is the current operation mode. */intbras_sym_operand (op, mode) register rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ register enum rtx_code code = GET_CODE (op); /* Allow SYMBOL_REFs. */ if (code == SYMBOL_REF) return 1; /* Allow @PLT stubs. */ if (code == CONST && GET_CODE (XEXP (op, 0)) == UNSPEC && XINT (XEXP (op, 0), 1) == 113) return 1; return 0;}/* Return true if OP is a load multiple operation. It is known to be a PARALLEL and the first section will be tested. OP is the current operation. MODE is the current operation mode. */intload_multiple_operation (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ int count = XVECLEN (op, 0); unsigned int dest_regno; rtx src_addr; int i, off; /* Perform a quick check so we don't blow up below. */ if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM) return 0; dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0))); src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0); /* Check, is base, or base + displacement. */ if (GET_CODE (src_addr) == REG) off = 0; else if (GET_CODE (src_addr) == PLUS && GET_CODE (XEXP (src_addr, 0)) == REG && GET_CODE (XEXP (src_addr, 1)) == CONST_INT) { off = INTVAL (XEXP (src_addr, 1)); src_addr = XEXP (src_addr, 0); } else return 0; if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx) return 0; for (i = 1; i < count; i++) { rtx elt = XVECEXP (op, 0, i); if (GET_CODE (elt) != SET || GET_CODE (SET_DEST (elt)) != REG || GET_MODE (SET_DEST (elt)) != Pmode || REGNO (SET_DEST (elt)) != dest_regno + i || GET_CODE (SET_SRC (elt)) != MEM || GET_MODE (SET_SRC (elt)) != Pmode || GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS || ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr) || GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != off + i * UNITS_PER_WORD) return 0; } return 1;}/* Return true if OP is a store multiple operation. It is known to be a PARALLEL and the first section will be tested. OP is the current operation. MODE is the current operation mode. */intstore_multiple_operation (op, mode) rtx op; enum machine_mode mode ATTRIBUTE_UNUSED;{ int count = XVECLEN (op, 0); unsigned int src_regno; rtx dest_addr; int i, off; /* Perform a quick check so we don't blow up below. */ if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG) return 0; src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0))); dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0); /* Check, is base, or base + displacement. */ if (GET_CODE (dest_addr) == REG) off = 0; else if (GET_CODE (dest_addr) == PLUS && GET_CODE (XEXP (dest_addr, 0)) == REG && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT) { off = INTVAL (XEXP (dest_addr, 1)); dest_addr = XEXP (dest_addr, 0); } else return 0; if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx) return 0; for (i = 1; i < count; i++) { rtx elt = XVECEXP (op, 0, i); if (GET_CODE (elt) != SET || GET_CODE (SET_SRC (elt)) != REG || GET_MODE (SET_SRC (elt)) != Pmode || REGNO (SET_SRC (elt)) != src_regno + i || GET_CODE (SET_DEST (elt)) != MEM || GET_MODE (SET_DEST (elt)) != Pmode || GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS || ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr) || GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != off + i * UNITS_PER_WORD) return 0; } return 1;}/* Return true if OP contains a symbol reference */intsymbolic_reference_mentioned_p (op) rtx op;{ register const char *fmt; register int i; if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF) return 1; fmt = GET_RTX_FORMAT (GET_CODE (op)); for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--) { if (fmt[i] == 'E') { register int j;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -