📄 rs6000.c
字号:
/* 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) { fputs ("31", file); 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 'N': /* Write the number of elements in the vector times 4. */ if (GET_CODE (x) != PARALLEL) output_operand_lossage ("invalid %%N value"); fprintf (file, "%d", XVECLEN (x, 0) * 4); return; case 'O': /* Similar, but subtract 1 first. */ if (GET_CODE (x) != PARALLEL) output_operand_lossage ("invalid %%N value"); fprintf (file, "%d", (XVECLEN (x, 0) - 1) * 4); 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 'P': /* The operand must be an indirect memory reference. The result is the register number. */ if (GET_CODE (x) != MEM || GET_CODE (XEXP (x, 0)) != REG || REGNO (XEXP (x, 0)) >= 32) output_operand_lossage ("invalid %%P value"); fprintf (file, "%d", REGNO (XEXP (x, 0))); return; 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 '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 't': /* Write 12 if this jump operation will branch if true, 4 otherwise. All floating-point operations except NE branch true and integer EQ, LT, GT, LTU and GTU also branch true. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%t value"); else if ((GET_MODE (XEXP (x, 0)) == CCFPmode && GET_CODE (x) != NE) || GET_CODE (x) == EQ || GET_CODE (x) == LT || GET_CODE (x) == GT || GET_CODE (x) == LTU || GET_CODE (x) == GTU) fputs ("12", file); else putc ('4', file); return; case 'T': /* Opposite of 't': write 4 if this jump operation will branch if true, 12 otherwise. */ if (GET_RTX_CLASS (GET_CODE (x)) != '<') output_operand_lossage ("invalid %%t value"); else if ((GET_MODE (XEXP (x, 0)) == CCFPmode && GET_CODE (x) != NE) || GET_CODE (x) == EQ || GET_CODE (x) == LT || GET_CODE (x) == GT || GET_CODE (x) == LTU || GET_CODE (x) == GTU) putc ('4', file); else fputs ("12", file); return; case 'u': /* High-order 16 bits of constant. */ if (! INT_P (x)) output_operand_lossage ("invalid %%u value"); fprintf (file, "0x%x", (INT_LOWPART (x) >> 16) & 0xffff); return; case 'U': /* Print `u' if 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)) putc ('u', file); 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 'X': if (GET_CODE (x) == MEM && LEGITIMATE_INDEXED_ADDRESS_P (XEXP (x, 0))) putc ('x', file); return; case 'Y': /* Like 'L', for third word of TImode */ if (GET_CODE (x) == REG) fprintf (file, "%d", REGNO (x) + 2); else if (GET_CODE (x) == MEM) { if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) output_address (plus_constant (XEXP (XEXP (x, 0), 0), 8)); else output_address (plus_constant (XEXP (x, 0), 8)); } return; case 'z': /* X is a SYMBOL_REF. Write out the name preceded by a period and without any trailing data in brackets. Used for function names. If we are configured for System V (or the embedded ABI) on the PowerPC, do not emit the period, since those systems do not use TOCs and the like. */ if (GET_CODE (x) != SYMBOL_REF) abort ();#ifndef USING_SVR4_H putc ('.', file);#endif RS6000_OUTPUT_BASENAME (file, XSTR (x, 0)); return; case 'Z': /* Like 'L', for last word of TImode. */ if (GET_CODE (x) == REG) fprintf (file, "%d", REGNO (x) + 3); else if (GET_CODE (x) == MEM) { if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) output_address (plus_constant (XEXP (XEXP (x, 0), 0), 12)); else output_address (plus_constant (XEXP (x, 0), 12)); } return; case 0: if (GET_CODE (x) == REG) fprintf (file, "%s", reg_names[REGNO (x)]); else if (GET_CODE (x) == MEM) { /* We need to handle PRE_INC and PRE_DEC here, since we need to know the width from the mode. */ if (GET_CODE (XEXP (x, 0)) == PRE_INC) fprintf (file, "%d(%d)", GET_MODE_SIZE (GET_MODE (x)), REGNO (XEXP (XEXP (x, 0), 0))); else if (GET_CODE (XEXP (x, 0)) == PRE_DEC) fprintf (file, "%d(%d)", - GET_MODE_SIZE (GET_MODE (x)), REGNO (XEXP (XEXP (x, 0), 0))); else output_address (XEXP (x, 0)); } else output_addr_const (file, x); return; default: output_operand_lossage ("invalid %%xn code"); }}/* Print the address of an operand. */voidprint_operand_address (file, x) FILE *file; register rtx x;{ if (GET_CODE (x) == REG) fprintf (file, "0(%s)", reg_names[ REGNO (x) ]); else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST) { output_addr_const (file, x); /* When TARGET_MINIMAL_TOC, use the indirected toc table pointer instead of the toc pointer. */#ifdef TARGET_NO_TOC if (TARGET_NO_TOC) ; else#endif fprintf (file, "(%s)", reg_names[ TARGET_MINIMAL_TOC ? 30 : 2 ]); } else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG) { if (REGNO (XEXP (x, 0)) == 0) fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ], reg_names[ REGNO (XEXP (x, 0)) ]); else fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ], reg_names[ REGNO (XEXP (x, 1)) ]); } else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) fprintf (file, "%d(%s)", INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]); else if (TARGET_ELF && !TARGET_64BIT && GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG && CONSTANT_P (XEXP (x, 1))) { output_addr_const (file, XEXP (x, 1)); fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); } else abort ();}/* This page contains routines that are used to determine what the function prologue and epilogue code will do and write them out. *//* Return the first fixed-point register that is required to be saved. 32 if none. */intfirst_reg_to_save (){ int first_reg; /* Find lowest numbered live register. */ for (first_reg = 13; first_reg <= 31; first_reg++) if (regs_ever_live[first_reg]) break; /* If profiling, then we must save/restore every register that contains a parameter before/after the .mcount call. Use registers from 30 down to 23 to do this. Don't use the frame pointer in reg 31. For now, save enough room for all of the parameter registers. */#ifndef USING_SVR4_H if (profile_flag) if (first_reg > 23) first_reg = 23;#endif return first_reg;}/* Similar, for FP regs. */intfirst_fp_reg_to_save (){ int first_reg; /* Find lowest numbered live register. */ for (first_reg = 14 + 32; first_reg <= 63; first_reg++) if (regs_ever_live[first_reg]) break; return first_reg;}/* Return non-zero if this function makes calls. */intrs6000_makes_calls (){ rtx insn; /* If we are profiling, we will be making a call to mcount. */ if (profile_flag) return 1; for (insn = get_insns (); insn; insn = next_insn (insn)) if (GET_CODE (insn) == CALL_INSN) return 1; return 0;}/* Calculate the stack information for the current function. This is complicated by having two separate calling sequences, the AIX calling sequence and the V.4 calling sequence. AIX stack frames look like: SP----> +---------------------------------------+ | back chain to caller | 0 +---------------------------------------+ | saved CR | 4 +---------------------------------------+ | saved LR | 8 +---------------------------------------+ | reserved for compilers | 12 +---------------------------------------+ | reserved for binders | 16 +---------------------------------------+ | saved TOC pointer | 20 +---------------------------------------+ | Parameter save area (P) | 24 +---------------------------------------+ | Alloca space (A) | 24+P +---------------------------------------+ | Local variable space (L) | 24+P+A +---------------------------------------+ | Save area for GP registers (G) | 24+P+A+L +---------------------------------------+ | Save area for FP registers (F) | 24+P+A+L+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+ V.4 stack frames look like: SP----> +---------------------------------------+ | back chain to caller | 0 +---------------------------------------+ | caller's saved LR | 4 +---------------------------------------+ | Parameter save area (P) | 8 +---------------------------------------+ | Alloca space (A) | 8+P +---------------------------------------+ | Varargs save area (V) | 8+P+A +---------------------------------------+ | Local variable space (L) | 8+P+A+V +---------------------------------------+ | saved CR (C) | 8+P+A+V+L +---------------------------------------+ | Save area for GP registers (G) | 8+P+A+V+L+C +---------------------------------------+ | Save area for FP registers (F) | 8+P+A+V+L+C+G +---------------------------------------+ old SP->| back chain to caller's caller | +---------------------------------------+*/rs6000_stack_t *rs6000_stack_info (){ static rs6000_stack_t info, zero_info; rs6000_stack_t *info_ptr = &info; int reg_size = TARGET_64BIT ? 8 : 4; enum rs6000_abi abi; /* Zero all fields portably */ info = zero_info; /* Select which calling sequence */#ifdef TARGET_V4_CALLS if (TARGET_V4_CALLS) abi = ABI_V4; else#endif abi = ABI_AIX; info_ptr->abi = abi; /* Calculate which registers need to be saved & save area size */ info_ptr->first_gp_reg_save = first_reg_to_save (); info_ptr->gp_size = reg_size * (32 - info_ptr->first_gp_reg_save); info_ptr->first_fp_reg_save = first_fp_reg_to_save (); info_ptr->fp_size = 8 * (64 - info_ptr->first_fp_reg_save); /* Does this function call anything? */ info_ptr->calls_p = rs6000_makes_calls (); /* Determine if we need to save the link register */ if (regs_ever_live[65] || profile_flag#ifdef TARGET_RELOCATABLE || (TARGET_RELOCATABLE && (get_pool_size () != 0))#endif || (info_ptr->first_fp_reg_save != 64 && !FP_SAVE_INLINE (info_ptr->first_fp_reg_save)) || (abi == ABI_V4 && current_function_calls_alloca) || info_ptr->calls_p) { info_ptr->lr_save_p = 1; regs_ever_live[65] = 1; } /* Determine if we need to save the condition code registers */ if (regs_ever_live[70] || regs_ever_live[71] || regs_ever_live[72]) { info_ptr->cr_save_p = 1; if (abi == ABI_V4) info_ptr->cr_size = reg_size; } /* Determine various sizes */ info_ptr->reg_size = reg_size; info_ptr->fixed_size = RS6000_SAVE_AREA; info_ptr->varargs_size = RS6000_VARARG
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -