📄 ia64.md
字号:
emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first])); emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first])); DONE;} [(set_attr "itanium_class" "unknown") (set_attr "predicable" "no")])(define_expand "reload_inti" [(parallel [(set (match_operand:TI 0 "register_operand" "=r") (match_operand:TI 1 "" "m")) (clobber (match_operand:TI 2 "register_operand" "=&r"))])] ""{ unsigned int s_regno = REGNO (operands[2]); if (s_regno == REGNO (operands[0])) s_regno += 1; operands[2] = gen_rtx_REG (DImode, s_regno);})(define_expand "reload_outti" [(parallel [(set (match_operand:TI 0 "" "=m") (match_operand:TI 1 "register_operand" "r")) (clobber (match_operand:TI 2 "register_operand" "=&r"))])] ""{ unsigned int s_regno = REGNO (operands[2]); if (s_regno == REGNO (operands[1])) s_regno += 1; operands[2] = gen_rtx_REG (DImode, s_regno);});; Floating Point Moves;;;; Note - Patterns for SF mode moves are compulsory, but;; patterns for DF are optional, as GCC can synthesize them.(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] ""{ rtx op1 = ia64_expand_move (operands[0], operands[1]); if (!op1) DONE; operands[1] = op1;})(define_insn "*movsf_internal" [(set (match_operand:SF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m") (match_operand:SF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))] "ia64_move_ok (operands[0], operands[1])" "@ mov %0 = %F1 ldfs %0 = %1%P1 stfs %0 = %F1%P0 getf.s %0 = %F1 setf.s %0 = %1 mov %0 = %1 ld4%O1 %0 = %1%P1 st4%Q0 %0 = %1%P0" [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")])(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] ""{ rtx op1 = ia64_expand_move (operands[0], operands[1]); if (!op1) DONE; operands[1] = op1;})(define_insn "*movdf_internal" [(set (match_operand:DF 0 "destination_operand" "=f,f, Q,*r, f,*r,*r, m") (match_operand:DF 1 "general_operand" "fG,Q,fG,fG,*r,*r, m,*r"))] "ia64_move_ok (operands[0], operands[1])" "@ mov %0 = %F1 ldfd %0 = %1%P1 stfd %0 = %F1%P0 getf.d %0 = %F1 setf.d %0 = %1 mov %0 = %1 ld8%O1 %0 = %1%P1 st8%Q0 %0 = %1%P0" [(set_attr "itanium_class" "fmisc,fld,stf,frfr,tofr,ialu,ld,st")]);; With no offsettable memory references, we've got to have a scratch;; around to play with the second word if the variable winds up in GRs.(define_expand "movtf" [(set (match_operand:TF 0 "general_operand" "") (match_operand:TF 1 "general_operand" ""))] "INTEL_EXTENDED_IEEE_FORMAT"{ /* We must support TFmode loads into general registers for stdarg/vararg and unprototyped calls. We split them into DImode loads for convenience. We don't need TFmode stores from general regs, because a stdarg/vararg routine does a block store to memory of unnamed arguments. */ if (GET_CODE (operands[0]) == REG && GR_REGNO_P (REGNO (operands[0]))) { /* We're hoping to transform everything that deals with TFmode quantities and GR registers early in the compiler. */ if (no_new_pseudos) abort (); /* Struct to register can just use TImode instead. */ if ((GET_CODE (operands[1]) == SUBREG && GET_MODE (SUBREG_REG (operands[1])) == TImode) || (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))) { emit_move_insn (gen_rtx_REG (TImode, REGNO (operands[0])), SUBREG_REG (operands[1])); DONE; } if (GET_CODE (operands[1]) == CONST_DOUBLE) { emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])), operand_subword (operands[1], 0, 0, TFmode)); emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1), operand_subword (operands[1], 1, 0, TFmode)); DONE; } /* If the quantity is in a register not known to be GR, spill it. */ if (register_operand (operands[1], TFmode)) operands[1] = spill_tfmode_operand (operands[1], 1); if (GET_CODE (operands[1]) == MEM) { rtx out[2]; out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])); out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])+1); emit_move_insn (out[0], adjust_address (operands[1], DImode, 0)); emit_move_insn (out[1], adjust_address (operands[1], DImode, 8)); DONE; } abort (); } if (! reload_in_progress && ! reload_completed) { operands[0] = spill_tfmode_operand (operands[0], 0); operands[1] = spill_tfmode_operand (operands[1], 0); if (! ia64_move_ok (operands[0], operands[1])) operands[1] = force_reg (TFmode, operands[1]); }});; ??? There's no easy way to mind volatile acquire/release semantics.(define_insn "*movtf_internal" [(set (match_operand:TF 0 "destination_tfmode_operand" "=f,f, m") (match_operand:TF 1 "general_tfmode_operand" "fG,m,fG"))] "INTEL_EXTENDED_IEEE_FORMAT && ia64_move_ok (operands[0], operands[1])" "@ mov %0 = %F1 ldfe %0 = %1%P1 stfe %0 = %F1%P0" [(set_attr "itanium_class" "fmisc,fld,stf")]);; ::::::::::::::::::::;; ::;; :: Conversions;; ::;; ::::::::::::::::::::;; Signed conversions from a smaller integer to a larger integer(define_insn "extendqidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (sign_extend:DI (match_operand:QI 1 "gr_register_operand" "r")))] "" "sxt1 %0 = %1" [(set_attr "itanium_class" "xtd")])(define_insn "extendhidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r") (sign_extend:DI (match_operand:HI 1 "gr_register_operand" "r")))] "" "sxt2 %0 = %1" [(set_attr "itanium_class" "xtd")])(define_insn "extendsidi2" [(set (match_operand:DI 0 "grfr_register_operand" "=r,?f") (sign_extend:DI (match_operand:SI 1 "grfr_register_operand" "r,f")))] "" "@ sxt4 %0 = %1 fsxt.r %0 = %1, %1" [(set_attr "itanium_class" "xtd,fmisc")]);; Unsigned conversions from a smaller integer to a larger integer(define_insn "zero_extendqidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (zero_extend:DI (match_operand:QI 1 "gr_nonimmediate_operand" "r,m")))] "" "@ zxt1 %0 = %1 ld1%O1 %0 = %1%P1" [(set_attr "itanium_class" "xtd,ld")])(define_insn "zero_extendhidi2" [(set (match_operand:DI 0 "gr_register_operand" "=r,r") (zero_extend:DI (match_operand:HI 1 "gr_nonimmediate_operand" "r,m")))] "" "@ zxt2 %0 = %1 ld2%O1 %0 = %1%P1" [(set_attr "itanium_class" "xtd,ld")])(define_insn "zero_extendsidi2" [(set (match_operand:DI 0 "grfr_register_operand" "=r,r,?f") (zero_extend:DI (match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))] "" "@ zxt4 %0 = %1 ld4%O1 %0 = %1%P1 fmix.r %0 = f0, %1" [(set_attr "itanium_class" "xtd,ld,fmisc")]);; Convert between floating point types of different sizes.;; At first glance, it would appear that emitting fnorm for an extending;; conversion is unnecessary. However, the stf and getf instructions work;; correctly only if the input is properly rounded for its type. In;; particular, we get the wrong result for getf.d/stfd if the input is a;; denorm single. Since we don't know what the next instruction will be, we;; have to emit an fnorm.;; ??? Optimization opportunity here. Get rid of the insn altogether;; when we can. Should probably use a scheme like has been proposed;; for ia32 in dealing with operands that match unary operators. This;; would let combine merge the thing into adjacent insns. See also how the;; mips port handles SIGN_EXTEND as operands to integer arithmetic insns via;; se_register_operand.(define_insn "extendsfdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_extend:DF (match_operand:SF 1 "fr_register_operand" "f")))] "" "fnorm.d %0 = %1" [(set_attr "itanium_class" "fmac")])(define_insn "extendsftf2" [(set (match_operand:TF 0 "fr_register_operand" "=f") (float_extend:TF (match_operand:SF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fnorm %0 = %1" [(set_attr "itanium_class" "fmac")])(define_insn "extenddftf2" [(set (match_operand:TF 0 "fr_register_operand" "=f") (float_extend:TF (match_operand:DF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fnorm %0 = %1" [(set_attr "itanium_class" "fmac")])(define_insn "truncdfsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "fr_register_operand" "f")))] "" "fnorm.s %0 = %1" [(set_attr "itanium_class" "fmac")])(define_insn "trunctfsf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (float_truncate:SF (match_operand:TF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fnorm.s %0 = %1" [(set_attr "itanium_class" "fmac")])(define_insn "trunctfdf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (float_truncate:DF (match_operand:TF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fnorm.d %0 = %1" [(set_attr "itanium_class" "fmac")]);; Convert between signed integer types and floating point.(define_insn "floatditf2" [(set (match_operand:TF 0 "fr_register_operand" "=f") (float:TF (match_operand:DI 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fcvt.xf %0 = %1" [(set_attr "itanium_class" "fcvtfx")]);; ??? Suboptimal. This should be split somehow.(define_insn "floatdidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:DI 1 "register_operand" "f")))] "!INTEL_EXTENDED_IEEE_FORMAT" "fcvt.xf %0 = %1\;;;\;%,fnorm.d %0 = %0" [(set_attr "itanium_class" "fcvtfx")]);; ??? Suboptimal. This should be split somehow.(define_insn "floatdisf2" [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:DI 1 "register_operand" "f")))] "!INTEL_EXTENDED_IEEE_FORMAT" "fcvt.xf %0 = %1\;;;\;%,fnorm.s %0 = %0" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fix_truncsfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:SF 1 "fr_register_operand" "f")))] "" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fix_truncdfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:DF 1 "fr_register_operand" "f")))] "" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fix_trunctfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:TF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fcvt.fx.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fix_trunctfdi2_alts" [(set (match_operand:DI 0 "fr_register_operand" "=f") (fix:DI (match_operand:TF 1 "fr_register_operand" "f"))) (use (match_operand:SI 2 "const_int_operand" ""))] "INTEL_EXTENDED_IEEE_FORMAT" "fcvt.fx.trunc.s%2 %0 = %1" [(set_attr "itanium_class" "fcvtfx")]);; Convert between unsigned integer types and floating point.(define_insn "floatunsdisf2" [(set (match_operand:SF 0 "fr_register_operand" "=f") (unsigned_float:SF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xuf.s %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "floatunsdidf2" [(set (match_operand:DF 0 "fr_register_operand" "=f") (unsigned_float:DF (match_operand:DI 1 "fr_register_operand" "f")))] "" "fcvt.xuf.d %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "floatunsditf2" [(set (match_operand:TF 0 "fr_register_operand" "=f") (unsigned_float:TF (match_operand:DI 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fcvt.xuf %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fixuns_truncsfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:SF 1 "fr_register_operand" "f")))] "" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fixuns_truncdfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:DF 1 "fr_register_operand" "f")))] "" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fixuns_trunctfdi2" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:TF 1 "fr_register_operand" "f")))] "INTEL_EXTENDED_IEEE_FORMAT" "fcvt.fxu.trunc %0 = %1" [(set_attr "itanium_class" "fcvtfx")])(define_insn "fixuns_trunctfdi2_alts" [(set (match_operand:DI 0 "fr_register_operand" "=f") (unsigned_fix:DI (match_operand:TF 1 "fr_register_operand" "f")))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -