📄 rs6000.c
字号:
|| GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4) return 0; } return 1;}/* Similar, but tests for store multiple. Here, the second vector element is a CLOBBER. It will be tested later. */intstore_multiple_operation (op, mode) rtx op; enum machine_mode mode;{ int count = XVECLEN (op, 0) - 1; int src_regno; rtx dest_addr; int i; /* 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); for (i = 1; i < count; i++) { rtx elt = XVECEXP (op, 0, i + 1); if (GET_CODE (elt) != SET || GET_CODE (SET_SRC (elt)) != REG || GET_MODE (SET_SRC (elt)) != SImode || REGNO (SET_SRC (elt)) != src_regno + i || GET_CODE (SET_DEST (elt)) != MEM || GET_MODE (SET_DEST (elt)) != SImode || 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)) != i * 4) return 0; } return 1;}/* Return 1 if OP is a comparison operation that is valid for a branch insn. We only check the opcode against the mode of the CC value here. */intbranch_comparison_operator (op, mode) register rtx op; enum machine_mode mode;{ enum rtx_code code = GET_CODE (op); enum machine_mode cc_mode; if (GET_RTX_CLASS (code) != '<') return 0; cc_mode = GET_MODE (XEXP (op, 0)); if (GET_MODE_CLASS (cc_mode) != MODE_CC) return 0; if ((code == GT || code == LT || code == GE || code == LE) && cc_mode == CCUNSmode) return 0; if ((code == GTU || code == LTU || code == GEU || code == LEU) && (cc_mode != CCUNSmode)) return 0; return 1;}/* Return 1 if OP is a comparison operation that is valid for an scc insn. We check the opcode against the mode of the CC value and disallow EQ or NE comparisons for integers. */intscc_comparison_operator (op, mode) register rtx op; enum machine_mode mode;{ enum rtx_code code = GET_CODE (op); enum machine_mode cc_mode; if (GET_MODE (op) != mode && mode != VOIDmode) return 0; if (GET_RTX_CLASS (code) != '<') return 0; cc_mode = GET_MODE (XEXP (op, 0)); if (GET_MODE_CLASS (cc_mode) != MODE_CC) return 0; if (code == NE && cc_mode != CCFPmode) return 0; if ((code == GT || code == LT || code == GE || code == LE) && cc_mode == CCUNSmode) return 0; if ((code == GTU || code == LTU || code == GEU || code == LEU) && (cc_mode != CCUNSmode)) return 0; if (cc_mode == CCEQmode && code != EQ && code != NE) return 0; return 1;}/* Return 1 if ANDOP is a mask that has no bits on that are not in the mask required to convert the result of a rotate insn into a shift left insn of SHIFTOP bits. Both are known to be CONST_INT. */intincludes_lshift_p (shiftop, andop) register rtx shiftop; register rtx andop;{ int shift_mask = (~0 << INTVAL (shiftop)); return (INTVAL (andop) & ~shift_mask) == 0;}/* Similar, but for right shift. */intincludes_rshift_p (shiftop, andop) register rtx shiftop; register rtx andop;{ unsigned shift_mask = ~0; shift_mask >>= INTVAL (shiftop); return (INTVAL (andop) & ~ shift_mask) == 0;}/* Return the register class of a scratch register needed to copy IN into or out of a register in CLASS in MODE. If it can be done directly, NO_REGS is returned. */enum reg_classsecondary_reload_class (class, mode, in) enum reg_class class; enum machine_mode mode; rtx in;{ int regno = true_regnum (in); if (regno >= FIRST_PSEUDO_REGISTER) regno = -1; /* We can place anything into GENERAL_REGS and can put GENERAL_REGS into anything. */ if (class == GENERAL_REGS || class == BASE_REGS || (regno >= 0 && INT_REGNO_P (regno))) return NO_REGS; /* Constants, memory, and FP registers can go into FP registers. */ if ((regno == -1 || FP_REGNO_P (regno)) && (class == FLOAT_REGS || class == NON_SPECIAL_REGS)) return NO_REGS; /* We can copy among the CR registers. */ if ((class == CR_REGS || class == CR0_REGS) && regno >= 0 && CR_REGNO_P (regno)) return NO_REGS; /* Otherwise, we need GENERAL_REGS. */ return GENERAL_REGS;}/* Given a comparison operation, return the bit number in CCR to test. We know this is a valid comparison. SCC_P is 1 if this is for an scc. That means that %D will have been used instead of %C, so the bits will be in different places. Return -1 if OP isn't a valid comparison for some reason. */intccr_bit (op, scc_p) register rtx op; int scc_p;{ enum rtx_code code = GET_CODE (op); enum machine_mode cc_mode; int cc_regnum; int base_bit; if (GET_RTX_CLASS (code) != '<') return -1; cc_mode = GET_MODE (XEXP (op, 0)); cc_regnum = REGNO (XEXP (op, 0)); base_bit = 4 * (cc_regnum - 68); /* In CCEQmode cases we have made sure that the result is always in the third bit of the CR field. */ if (cc_mode == CCEQmode) return base_bit + 3; switch (code) { case NE: return scc_p ? base_bit + 3 : base_bit + 2; case EQ: return base_bit + 2; case GT: case GTU: return base_bit + 1; case LT: case LTU: return base_bit; case GE: case GEU: /* If floating-point, we will have done a cror to put the bit in the unordered position. So test that bit. For integer, this is ! LT unless this is an scc insn. */ return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit; case LE: case LEU: return cc_mode == CCFPmode || scc_p ? base_bit + 3 : base_bit + 1; default: abort (); }}/* Print an operand. Recognize special options, documented below. */voidprint_operand (file, x, code) FILE *file; rtx x; char code;{ int i; int val; /* These macros test for integers and extract the low-order bits. */#define INT_P(X) \((GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST_DOUBLE) \ && GET_MODE (X) == VOIDmode)#define INT_LOWPART(X) \ (GET_CODE (X) == CONST_INT ? INTVAL (X) : CONST_DOUBLE_LOW (X)) switch (code) { case 'h': /* If constant, output low-order five bits. Otherwise, write normally. */ if (INT_P (x)) fprintf (file, "%d", INT_LOWPART (x) & 31); else print_operand (file, x, 0); return; case 'H': /* X must be a constant. Output the low order 5 bits plus 24. */ if (! INT_P (x)) output_operand_lossage ("invalid %%H value"); fprintf (file, "%d", (INT_LOWPART (x) + 24) & 31); return; case 'b': /* Low-order 16 bits of constant, unsigned. */ if (! INT_P (x)) output_operand_lossage ("invalid %%b value"); fprintf (file, "%d", INT_LOWPART (x) & 0xffff); return; case 'w': /* If constant, low-order 16 bits of constant, signed. Otherwise, write normally. */ if (INT_P (x)) fprintf (file, "%d", (INT_LOWPART (x) & 0xffff) - 2 * (INT_LOWPART (x) & 0x8000)); else print_operand (file, x, 0); return; case 'W': /* If constant, low-order 16 bits of constant, unsigned. Otherwise, write normally. */ if (INT_P (x)) fprintf (file, "%d", INT_LOWPART (x) & 0xffff); else print_operand (file, x, 0); return; case 'u': /* High-order 16 bits of constant. */ if (! INT_P (x)) output_operand_lossage ("invalid %%u value"); fprintf (file, "%d", (INT_LOWPART (x) >> 16) & 0xffff); return; case 's': /* Low 5 bits of 32 - value */ if (! INT_P (x)) output_operand_lossage ("invalid %%s value"); fprintf (file, "%d", (32 - INT_LOWPART (x)) & 31); return; case 'S': /* Low 5 bits of 31 - value */ if (! INT_P (x)) output_operand_lossage ("invalid %%S value"); fprintf (file, "%d", (31 - INT_LOWPART (x)) & 31); return; case 'p': /* X is a CONST_INT that is a power of two. Output the logarithm. */ if (! INT_P (x) || (i = exact_log2 (INT_LOWPART (x))) < 0) output_operand_lossage ("invalid %%p value"); fprintf (file, "%d", i); return; case 'm': /* MB value for a mask operand. */ if (! mask_operand (x, VOIDmode)) output_operand_lossage ("invalid %%m value"); val = INT_LOWPART (x); /* If the high bit is set and the low bit is not, the value is zero. If the high bit is zero, the value is the first 1 bit we find from the left. */ if (val < 0 && (val & 1) == 0) { fprintf (file, "0"); return; } else if (val >= 0) { for (i = 1; i < 32; i++) if ((val <<= 1) < 0) break; fprintf (file, "%d", i); return; } /* Otherwise, look for the first 0 bit from the right. The result is its number plus 1. We know the low-order bit is one. */ for (i = 0; i < 32; i++) if (((val >>= 1) & 1) == 0) break; /* If we ended in ...01, I would be 0. The correct value is 31, so we want 31 - i. */ fprintf (file, "%d", 31 - i); return; case 'M': /* ME value for a mask operand. */ if (! mask_operand (x, VOIDmode)) output_operand_lossage ("invalid %%m value"); val = INT_LOWPART (x); /* If the low bit is set and the high bit is not, the value is 31. If the low bit is zero, the value is the first 1 bit we find from the right. */ if ((val & 1) && val >= 0) { fprintf (file, "31"); return; } else if ((val & 1) == 0) { for (i = 0; i < 32; i++) if ((val >>= 1) & 1) break; /* If we had ....10, I would be 0. The result should be 30, so we need 30 - i. */ fprintf (file, "%d", 30 - i); return; } /* Otherwise, look for the first 0 bit from the left. The result is its number minus 1. We know the high-order bit is one. */ for (i = 0; i < 32; i++) if ((val <<= 1) >= 0) break; fprintf (file, "%d", i); return; case 'f': /* X is a CR register. Print the shift count needed to move it to the high-order four bits. */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) output_operand_lossage ("invalid %%f value"); else fprintf (file, "%d", 4 * (REGNO (x) - 68)); return; case 'F': /* Similar, but print the count for the rotate in the opposite direction. */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) output_operand_lossage ("invalid %%F value"); else fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68)); return; case 'E': /* X is a CR register. Print the number of the third bit of the CR */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) output_operand_lossage ("invalid %%E value"); fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3); break; case 'R': /* X is a CR register. Print the mask for `mtcrf'. */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) output_operand_lossage ("invalid %%R value"); else fprintf (file, "%d", 128 >> (REGNO (x) - 68)); return; case 'X': if (GET_CODE (x) == MEM && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0))) fprintf (file, "x"); return; case 'U': /* Print `u' is this has an auto-increment or auto-decrement. */ if (GET_CODE (x) == MEM && (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -