📄 pa.c
字号:
{ if (mode == GET_MODE (orig)) return orig; if (REGNO (orig) >= FIRST_PSEUDO_REGISTER) abort (); return gen_rtx_REG (mode, REGNO (orig));}/* Emit insns to move operands[1] into operands[0]. Return 1 if we have written out everything that needs to be done to do the move. Otherwise, return 0 and the caller will emit the move normally. Note SCRATCH_REG may not be in the proper mode depending on how it will be used. This routine is resposible for creating a new copy of SCRATCH_REG in the proper mode. */intemit_move_sequence (operands, mode, scratch_reg) rtx *operands; enum machine_mode mode; rtx scratch_reg;{ register rtx operand0 = operands[0]; register rtx operand1 = operands[1]; register rtx tem; if (scratch_reg && reload_in_progress && GET_CODE (operand0) == REG && REGNO (operand0) >= FIRST_PSEUDO_REGISTER) operand0 = reg_equiv_mem[REGNO (operand0)]; else if (scratch_reg && reload_in_progress && GET_CODE (operand0) == SUBREG && GET_CODE (SUBREG_REG (operand0)) == REG && REGNO (SUBREG_REG (operand0)) >= FIRST_PSEUDO_REGISTER) { /* We must not alter SUBREG_BYTE (operand0) since that would confuse the code which tracks sets/uses for delete_output_reload. */ rtx temp = gen_rtx_SUBREG (GET_MODE (operand0), reg_equiv_mem [REGNO (SUBREG_REG (operand0))], SUBREG_BYTE (operand0)); operand0 = alter_subreg (&temp); } if (scratch_reg && reload_in_progress && GET_CODE (operand1) == REG && REGNO (operand1) >= FIRST_PSEUDO_REGISTER) operand1 = reg_equiv_mem[REGNO (operand1)]; else if (scratch_reg && reload_in_progress && GET_CODE (operand1) == SUBREG && GET_CODE (SUBREG_REG (operand1)) == REG && REGNO (SUBREG_REG (operand1)) >= FIRST_PSEUDO_REGISTER) { /* We must not alter SUBREG_BYTE (operand0) since that would confuse the code which tracks sets/uses for delete_output_reload. */ rtx temp = gen_rtx_SUBREG (GET_MODE (operand1), reg_equiv_mem [REGNO (SUBREG_REG (operand1))], SUBREG_BYTE (operand1)); operand1 = alter_subreg (&temp); } if (scratch_reg && reload_in_progress && GET_CODE (operand0) == MEM && ((tem = find_replacement (&XEXP (operand0, 0))) != XEXP (operand0, 0))) operand0 = gen_rtx_MEM (GET_MODE (operand0), tem); if (scratch_reg && reload_in_progress && GET_CODE (operand1) == MEM && ((tem = find_replacement (&XEXP (operand1, 0))) != XEXP (operand1, 0))) operand1 = gen_rtx_MEM (GET_MODE (operand1), tem); /* Handle secondary reloads for loads/stores of FP registers from REG+D addresses where D does not fit in 5 or 14 bits, including (subreg (mem (addr))) cases. */ if (fp_reg_operand (operand0, mode) && ((GET_CODE (operand1) == MEM && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode), XEXP (operand1, 0))) || ((GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == MEM && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode), XEXP (XEXP (operand1, 0), 0))))) && scratch_reg) { if (GET_CODE (operand1) == SUBREG) operand1 = XEXP (operand1, 0); /* SCRATCH_REG will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ scratch_reg = force_mode (word_mode, scratch_reg); /* D might not fit in 14 bits either; for such cases load D into scratch reg. */ if (!memory_address_p (Pmode, XEXP (operand1, 0))) { emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1)); emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)), Pmode, XEXP (XEXP (operand1, 0), 0), scratch_reg)); } else emit_move_insn (scratch_reg, XEXP (operand1, 0)); emit_insn (gen_rtx_SET (VOIDmode, operand0, gen_rtx_MEM (mode, scratch_reg))); return 1; } else if (fp_reg_operand (operand1, mode) && ((GET_CODE (operand0) == MEM && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode), XEXP (operand0, 0))) || ((GET_CODE (operand0) == SUBREG) && GET_CODE (XEXP (operand0, 0)) == MEM && !memory_address_p ((GET_MODE_SIZE (mode) == 4 ? SFmode : DFmode), XEXP (XEXP (operand0, 0), 0)))) && scratch_reg) { if (GET_CODE (operand0) == SUBREG) operand0 = XEXP (operand0, 0); /* SCRATCH_REG will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ scratch_reg = force_mode (word_mode, scratch_reg); /* D might not fit in 14 bits either; for such cases load D into scratch reg. */ if (!memory_address_p (Pmode, XEXP (operand0, 0))) { emit_move_insn (scratch_reg, XEXP (XEXP (operand0, 0), 1)); emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand0, 0)), Pmode, XEXP (XEXP (operand0, 0), 0), scratch_reg)); } else emit_move_insn (scratch_reg, XEXP (operand0, 0)); emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (mode, scratch_reg), operand1)); return 1; } /* Handle secondary reloads for loads of FP registers from constant expressions by forcing the constant into memory. use scratch_reg to hold the address of the memory location. The proper fix is to change PREFERRED_RELOAD_CLASS to return NO_REGS when presented with a const_int and an register class containing only FP registers. Doing so unfortunately creates more problems than it solves. Fix this for 2.5. */ else if (fp_reg_operand (operand0, mode) && CONSTANT_P (operand1) && scratch_reg) { rtx xoperands[2]; /* SCRATCH_REG will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ scratch_reg = force_mode (word_mode, scratch_reg); /* Force the constant into memory and put the address of the memory location into scratch_reg. */ xoperands[0] = scratch_reg; xoperands[1] = XEXP (force_const_mem (mode, operand1), 0); emit_move_sequence (xoperands, Pmode, 0); /* Now load the destination register. */ emit_insn (gen_rtx_SET (mode, operand0, gen_rtx_MEM (mode, scratch_reg))); return 1; } /* Handle secondary reloads for SAR. These occur when trying to load the SAR from memory, FP register, or with a constant. */ else if (GET_CODE (operand0) == REG && REGNO (operand0) < FIRST_PSEUDO_REGISTER && REGNO_REG_CLASS (REGNO (operand0)) == SHIFT_REGS && (GET_CODE (operand1) == MEM || GET_CODE (operand1) == CONST_INT || (GET_CODE (operand1) == REG && FP_REG_CLASS_P (REGNO_REG_CLASS (REGNO (operand1))))) && scratch_reg) { /* D might not fit in 14 bits either; for such cases load D into scratch reg. */ if (GET_CODE (operand1) == MEM && !memory_address_p (Pmode, XEXP (operand1, 0))) { /* We are reloading the address into the scratch register, so we want to make sure the scratch register is a full register. */ scratch_reg = force_mode (word_mode, scratch_reg); emit_move_insn (scratch_reg, XEXP (XEXP (operand1, 0), 1)); emit_move_insn (scratch_reg, gen_rtx_fmt_ee (GET_CODE (XEXP (operand1, 0)), Pmode, XEXP (XEXP (operand1, 0), 0), scratch_reg)); /* Now we are going to load the scratch register from memory, we want to load it in the same width as the original MEM, which must be the same as the width of the ultimate destination, OPERAND0. */ scratch_reg = force_mode (GET_MODE (operand0), scratch_reg); emit_move_insn (scratch_reg, gen_rtx_MEM (GET_MODE (operand0), scratch_reg)); } else { /* We want to load the scratch register using the same mode as the ultimate destination. */ scratch_reg = force_mode (GET_MODE (operand0), scratch_reg); emit_move_insn (scratch_reg, operand1); } /* And emit the insn to set the ultimate destination. We know that the scratch register has the same mode as the destination at this point. */ emit_move_insn (operand0, scratch_reg); return 1; } /* Handle most common case: storing into a register. */ else if (register_operand (operand0, mode)) { if (register_operand (operand1, mode) || (GET_CODE (operand1) == CONST_INT && cint_ok_for_move (INTVAL (operand1))) || (operand1 == CONST0_RTX (mode)) || (GET_CODE (operand1) == HIGH && !symbolic_operand (XEXP (operand1, 0), VOIDmode)) /* Only `general_operands' can come here, so MEM is ok. */ || GET_CODE (operand1) == MEM) { /* Run this case quickly. */ emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); return 1; } } else if (GET_CODE (operand0) == MEM) { if (mode == DFmode && operand1 == CONST0_RTX (mode) && !(reload_in_progress || reload_completed)) { rtx temp = gen_reg_rtx (DFmode); emit_insn (gen_rtx_SET (VOIDmode, temp, operand1)); emit_insn (gen_rtx_SET (VOIDmode, operand0, temp)); return 1; } if (register_operand (operand1, mode) || operand1 == CONST0_RTX (mode)) { /* Run this case quickly. */ emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1)); return 1; } if (! (reload_in_progress || reload_completed)) { operands[0] = validize_mem (operand0); operands[1] = operand1 = force_reg (mode, operand1); } } /* Simplify the source if we need to. Note we do have to handle function labels here, even though we do not consider them legitimate constants. Loop optimizations can call the emit_move_xxx with one as a source. */ if ((GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode)) || function_label_operand (operand1, mode) || (GET_CODE (operand1) == HIGH && symbolic_operand (XEXP (operand1, 0), mode))) { int ishighonly = 0; if (GET_CODE (operand1) == HIGH) { ishighonly = 1; operand1 = XEXP (operand1, 0); } if (symbolic_operand (operand1, mode)) { /* Argh. The assembler and linker can't handle arithmetic involving plabels. So we force the plabel into memory, load operand0 from the memory location, then add in the constant part. */ if ((GET_CODE (operand1) == CONST && GET_CODE (XEXP (operand1, 0)) == PLUS && function_label_operand (XEXP (XEXP (operand1, 0), 0), Pmode)) || function_label_operand (operand1, mode)) { rtx temp, const_part; /* Figure out what (if any) scratch register to use. */ if (reload_in_progress || reload_completed) { scratch_reg = scratch_reg ? scratch_reg : operand0; /* SCRATCH_REG will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ scratch_reg = force_mode (word_mode, scratch_reg); } else if (flag_pic) scratch_reg = gen_reg_rtx (Pmode); if (GET_CODE (operand1) == CONST) { /* Save away the constant part of the expression. */ const_part = XEXP (XEXP (operand1, 0), 1); if (GET_CODE (const_part) != CONST_INT) abort (); /* Force the function label into memory. */ temp = force_const_mem (mode, XEXP (XEXP (operand1, 0), 0)); } else { /* No constant part. */ const_part = NULL_RTX; /* Force the function label into memory. */ temp = force_const_mem (mode, operand1); } /* Get the address of the memory location. PIC-ify it if necessary. */ temp = XEXP (temp, 0); if (flag_pic) temp = legitimize_pic_address (temp, mode, scratch_reg); /* Put the address of the memory location into our destination register. */ operands[1] = temp; emit_move_sequence (operands, mode, scratch_reg); /* Now load from the memory location into our destination register. */ operands[1] = gen_rtx_MEM (Pmode, operands[0]); emit_move_sequence (operands, mode, scratch_reg); /* And add back in the constant part. */ if (const_part != NULL_RTX) expand_inc (operand0, const_part); return 1; } if (flag_pic) { rtx temp; if (reload_in_progress || reload_completed) { temp = scratch_reg ? scratch_reg : operand0; /* TEMP will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ temp = force_mode (word_mode, temp); } else temp = gen_reg_rtx (Pmode); /* (const (plus (symbol) (const_int))) must be forced to memory during/after reload if the const_int will not fit in 14 bits. */ if (GET_CODE (operand1) == CONST && GET_CODE (XEXP (operand1, 0)) == PLUS && GET_CODE (XEXP (XEXP (operand1, 0), 1)) == CONST_INT && !INT_14_BITS (XEXP (XEXP (operand1, 0), 1)) && (reload_completed || reload_in_progress) && flag_pic) { operands[1] = force_const_mem (mode, operand1); operands[1] = legitimize_pic_address (XEXP (operands[1], 0), mode, temp); operands[1] = gen_rtx_MEM (mode, operands[1]); emit_move_sequence (operands, mode, temp); } else { operands[1] = legitimize_pic_address (operand1, mode, temp); emit_insn (gen_rtx_SET (VOIDmode, operand0, operands[1])); } } /* On the HPPA, references to data space are supposed to use dp, register 27, but showing it in the RTL inhibits various cse and loop optimizations. */ else { rtx temp, set; if (reload_in_progress || reload_completed) { temp = scratch_reg ? scratch_reg : operand0; /* TEMP will hold an address and maybe the actual data. We want it in WORD_MODE regardless of what mode it was originally given to us. */ temp = force_mode (word_mode, temp); } else temp = gen_reg_rtx (mode); /* Loading a SYMBOL_REF into a register makes that register safe to be used as the base in an indexed address. Don't mark hard registers though. That loses. */ if (GET_CODE (operand0) == REG && REGNO (operand0) >= FIRST_PSEUDO_REGISTER) REG_POINTER (operand0) = 1; if (REGNO (temp) >= FIRST_PSEUDO_REGISTER) REG_POINTER (temp) = 1; if (ishighonly) set = gen_rtx_SET (mode, operand0, temp); else set = gen_rtx_SET (VOIDmode, operand0, gen_rtx_LO_SUM (mode, temp, operand1)); emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (mode, operand1))); emit_insn (set); } return 1; } else if (GET_CODE (operand1) != CONST_INT || ! cint_ok_for_move (INTVAL (operand1))) { rtx extend = NULL_RTX; rtx temp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -