📄 sparc.md
字号:
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) return output_load_floating (operands); if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) return \"fmovs %1,%0\"; if (GET_CODE (operands[1]) == REG) return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\"; if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\"; } return \"ld %1,%0\"; } if (FP_REG_P (operands[1])) { if (GET_CODE (operands[0]) == REG) return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\"; if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) { if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && XEXP (operands[0], 0) == cc_prev_status.mdep)) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[0], 0); output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands); } return \"st %r1,[%%g1+%%lo(%m0)]\"; } return \"st %r1,%0\"; } if (GET_CODE (operands[0]) == MEM) return \"st %r1,%0\"; if (GET_CODE (operands[1]) == MEM) return \"ld %1,%0\"; return \"mov %1,%0\";}");;- truncation instructions(define_insn "truncsiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:SI 1 "register_operand" "r")))] "" "*{ if (GET_CODE (operands[0]) == MEM) if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) { if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && XEXP (operands[0], 0) == cc_prev_status.mdep)) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[0], 0); output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands); } return \"stb %1,[%%g1+%%lo(%m0)]\"; } else return \"stb %1,%0\"; return \"mov %1,%0\";}")(define_insn "trunchiqi2" [(set (match_operand:QI 0 "general_operand" "=g") (truncate:QI (match_operand:HI 1 "register_operand" "r")))] "" "*{ if (GET_CODE (operands[0]) == MEM) if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) { if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && XEXP (operands[0], 0) == cc_prev_status.mdep)) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[0], 0); output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands); } return \"stb %1,[%%g1+%%lo(%m0)]\"; } else return \"stb %1,%0\"; return \"mov %1,%0\";}")(define_insn "truncsihi2" [(set (match_operand:HI 0 "general_operand" "=g") (truncate:HI (match_operand:SI 1 "register_operand" "r")))] "" "*{ if (GET_CODE (operands[0]) == MEM) if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) { if (! ((cc_prev_status.flags & CC_KNOW_HI_G1) && XEXP (operands[0], 0) == cc_prev_status.mdep)) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[0], 0); output_asm_insn (\"sethi %%hi(%m0),%%g1\", operands); } return \"sth %1,[%%g1+%%lo(%m0)]\"; } else return \"sth %1,%0\"; return \"mov %1,%0\";}");;- zero extension instructions;; Note that the one starting from HImode comes before those for QImode;; so that a constant operand will match HImode, not QImode.(define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:HI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"sll %1,0x10,%0\;srl %0,0x10,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;lduh [%%g1+%%lo(%m1)],%0\"; } else return \"lduh %1,%0\";}")(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"and %1,0xff,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xff); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\"; } else return \"ldub %1,%0\";}")(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (zero_extend:SI (match_operand:QI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"and %1,0xff,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xff); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldub [%%g1+%%lo(%m1)],%0\"; } else return \"ldub %1,%0\";}");;- sign extension instructions;; Note that the one starting from HImode comes before those for QImode;; so that a constant operand will match HImode, not QImode.(define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:HI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"sll %1,0x10,%0\;sra %0,0x10,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { int i = (short)INTVAL (operands[1]); operands[1] = gen_rtx (CONST_INT, VOIDmode, i); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldsh [%%g1+%%lo(%m1)],%0\"; } else return \"ldsh %1,%0\";}")(define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"sll %1,0x18,%0\;sra %0,0x18,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { int i = (char)INTVAL (operands[1]); operands[1] = gen_rtx (CONST_INT, VOIDmode, i); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\"; } else return \"ldsb %1,%0\";}")(define_insn "extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r") (sign_extend:SI (match_operand:QI 1 "general_operand" "g")))] "" "*{ if (REG_P (operands[1])) return \"sll %1,0x18,%0\;sra %0,0x18,%0\"; if (GET_CODE (operands[1]) == CONST_INT) { int i = (char)INTVAL (operands[1]); operands[1] = gen_rtx (CONST_INT, VOIDmode, i); output_asm_insn (\"set %1,%0\", operands); return \"\"; } if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ldsb [%%g1+%%lo(%m1)],%0\"; } else return \"ldsb %1,%0\";}");; Signed bitfield extractions come out looking like;; (shiftrt (shift (sign_extend <Y>) <C1>) <C2>);; which we expand poorly as four shift insns.;; These patters yeild two shifts:;; (shiftrt (shift <Y> <C3>) <C4>)(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (sign_extend:SI (match_operand:QI 1 "register_operand" "r")) (match_operand:SI 2 "small_int" "n")))] "" "sll %1,0x18,%0\;sra %0,0x18+%2,%0")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (sign_extend:SI (subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "small_int" "n")) 0)) (match_operand:SI 3 "small_int" "n")))] "" "sll %1,0x18+%2,%0\;sra %0,0x18+%3,%0");; Special patterns for optimizing bit-field instructions.;; First two patterns are for bitfields that came from memory;; testing only the high bit. They work with old combiner.;; @@ Actually, the second pattern does not work if we;; @@ need to set the N bit.(define_insn "" [(set (cc0) (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r") (const_int 7)) 0)))] "0" "andcc %0,128,%%g0")(define_insn "" [(set (cc0) (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r") (const_int 7)) 0)))] "0" "andcc %0,128,%%g0");; next two patterns are good for bitfields coming from memory;; (via pseudo-register) or from a register, though this optimization;; is only good for values contained wholly within the bottom 13 bits(define_insn "" [(set (cc0) (and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "small_int" "n")) (match_operand:SI 2 "small_int" "n")))] "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000" "andcc %0,%2<<%1,%%g0")(define_insn "" [(set (cc0) (and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "small_int" "n")) (match_operand:SI 2 "small_int" "n")))] "(unsigned)((INTVAL (operands[2]) << INTVAL (operands[1])) + 0x1000) < 0x2000" "andcc %0,%2<<%1,%%g0");; Conversions between float and double.(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "fstod %1,%0")(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "" "fdtos %1,%0");; Conversion between fixed point and floating point.;; Note that among the fix-to-float insns;; the ones that start with SImode come first.;; That is so that an operand that is a CONST_INT;; (and therefore lacks a specific machine mode).;; will be recognized as SImode (which is always valid);; rather than as QImode or HImode.;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...)));; to be reloaded by putting the constant into memory.;; It must come before the more general floatsisf2 pattern.(define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") (float:SF (match_operand 1 "" "m")))] "GET_CODE (operands[1]) == CONST_INT" "*{ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\"; } return \"ld %1,%0\;fitos %0,%0\";}")(define_insn "floatsisf2" [(set (match_operand:SF 0 "general_operand" "=f,f") (float:SF (match_operand:SI 1 "general_operand" "r,fm")))] "" "*{ if (GET_CODE (operands[1]) == MEM) if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitos %0,%0\"; } else return \"ld %1,%0\;fitos %0,%0\"; else if (FP_REG_P (operands[1])) return \"fitos %1,%0\"; return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitos %0,%0\";}");; This pattern forces (set (reg:DF ...) (float:DF (const_int ...)));; to be reloaded by putting the constant into memory.;; It must come before the more general floatsidf2 pattern.(define_insn "" [(set (match_operand:DF 0 "general_operand" "=f") (float:DF (match_operand 1 "" "m")))] "GET_CODE (operands[1]) == CONST_INT" "*{ if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\"; } return \"ld %1,%0\;fitod %0,%0\";}")(define_insn "floatsidf2" [(set (match_operand:DF 0 "general_operand" "=f,f") (float:DF (match_operand:SI 1 "general_operand" "r,fm")))] "" "*{ if (GET_CODE (operands[1]) == MEM) if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) { cc_status.flags |= CC_KNOW_HI_G1; cc_status.mdep = XEXP (operands[1], 0); return \"sethi %%hi(%m1),%%g1\;ld [%%g1+%%lo(%m1)],%0\;fitod %0,%0\"; } else return \"ld %1,%0\;fitod %0,%0\"; else if (FP_REG_P (operands[1])) return \"fitod %1,%0\"; else return \"st %r1,[%%fp-4]\;ld [%%fp-4],%0\;fitod %0,%0\";}");; Convert a float to an actual integer.;; Truncation is performed as part of the conversion.(define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "general_operand" "=rm") (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))] "" "*{ cc_status.flags &= ~(CC_F1_IS_0); if (FP_REG_P (operands[1]))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -