📄 romp.md
字号:
"*{ switch (which_alternative) { case 0: if (REGNO (operands[0]) == REGNO (operands[1]) + 1) return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; else return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; case 1: /* Here we must see which word to load first. We default to the low-order word unless it occurs in the address. */ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; else return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; case 2: return \"get %O0,$%1\;ls %0,0(%O0)\;ls %O0,4(%O0)\"; case 3: return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; default: abort(); }}" [(set_attr "type" "multi") (set_attr "cc" "change0,change0,change0,none") (set_attr "length" "4,12,8,8")])(define_insn "storedi" [(set (match_operand:DI 0 "memory_operand" "=Q,m") (match_operand:DI 1 "register_operand" "r,r")) (clobber (match_scratch:SI 2 "=X,&b"))] "" "@ st%M0 %1,%0\;st%M0 %O1,%O0 get %2,$%0\;sts %1,0(%2)\;sts %O1,4(%2)" [(set_attr "type" "multi,multi") (set_attr "cc" "none,none") (set_attr "length" "8,12")])(define_expand "reload_outdi" [(parallel [(set (match_operand:DI 0 "symbolic_memory_operand" "=m") (match_operand:DI 1 "" "r")) (clobber (match_operand:SI 2 "" "=&b"))])] "" "");; Split symbolic memory operands differently. We first load the address;; into a register and then do the two loads or stores. We can only do;; this if operand_subword won't produce a SUBREG, which is only when;; operands[0] is a hard register. Thus, these won't be used during the;; first insn scheduling pass.(define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "symbolic_memory_operand" ""))] "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5)) (set (match_dup 6) (match_dup 7))] "{ operands[2] = operand_subword (operands[0], 1, 0, DImode); operands[3] = XEXP (operands[1], 0); operands[4] = operand_subword (operands[0], 0, 0, DImode); operands[5] = gen_rtx_MEM (SImode, operands[2]); operands[6] = operands[2]; operands[7] = gen_rtx_MEM (SImode, plus_constant (operands[2], 4)); if (operands[2] == 0 || operands[4] == 0) FAIL;}")(define_split [(set (match_operand:DI 0 "symbolic_memory_operand" "") (match_operand:DI 1 "register_operand" "")) (clobber (match_operand:SI 2 "register_operand" ""))] "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5)) (set (match_dup 6) (match_dup 7))] "{ operands[3] = XEXP (operands[0], 0); operands[4] = gen_rtx_MEM (SImode, operands[2]); operands[5] = operand_subword (operands[1], 0, 0, DImode); operands[6] = gen_rtx_MEM (SImode, plus_constant (operands[4], 4)); operands[7] = operand_subword (operands[1], 1, 0, DImode); if (operands[5] == 0 || operands[7] == 0) FAIL;}");; If the output is a register and the input is memory, we have to be careful;; and see which word needs to be loaded first.;;;; Note that this case doesn't have a CLOBBER. Therefore, we must either;; be after reload or operand[0] must not be a MEM. So we don't need a;; CLOBBER on the new insns either.;;;; Due to a bug in sched.c, we do not want to split this insn if both;; operands are registers and they overlap unless reload has completed.(define_split [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "! symbolic_memory_operand (operands[0], DImode) && ! symbolic_memory_operand (operands[1], DImode) && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG && ! reload_completed && reg_overlap_mentioned_p (operands[0], operands[1]))" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (match_dup 5))] "{ if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { operands[2] = operand_subword (operands[0], 0, 0, DImode); operands[3] = operand_subword (operands[1], 0, 0, DImode); operands[4] = operand_subword (operands[0], 1, 0, DImode); operands[5] = operand_subword (operands[1], 1, 0, DImode); } else { operands[2] = operand_subword (operands[0], 1, 0, DImode); operands[3] = operand_subword (operands[1], 1, 0, DImode); operands[4] = operand_subword (operands[0], 0, 0, DImode); operands[5] = operand_subword (operands[1], 0, 0, DImode); } if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL;}")(define_split [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" "")) (clobber (match_operand:SI 6 "register_operand" ""))] "! symbolic_memory_operand (operands[0], DImode) && ! symbolic_memory_operand (operands[1], DImode) && ! (GET_CODE (operands[0]) == REG && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER) && ! (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG && ! reload_completed && reg_overlap_mentioned_p (operands[0], operands[1]))" [(parallel [(set (match_dup 2) (match_dup 3)) (clobber (match_dup 7))]) (parallel [(set (match_dup 4) (match_dup 5)) (clobber (match_dup 8))])] "{ if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { operands[2] = operand_subword (operands[0], 0, 0, DImode); operands[3] = operand_subword (operands[1], 0, 0, DImode); operands[4] = operand_subword (operands[0], 1, 0, DImode); operands[5] = operand_subword (operands[1], 1, 0, DImode); } else { operands[2] = operand_subword (operands[0], 1, 0, DImode); operands[3] = operand_subword (operands[1], 1, 0, DImode); operands[4] = operand_subword (operands[0], 0, 0, DImode); operands[5] = operand_subword (operands[1], 0, 0, DImode); } if (operands[2] == 0 || operands[3] == 0 || operands[4] == 0 || operands[5] == 0) FAIL; /* We must be sure to make two different SCRATCH operands, since they are not allowed to be shared. After reload, however, we only have a SCRATCH if we won't use the operand, so it is allowed to share it then. */ if (reload_completed || GET_CODE (operands[6]) != SCRATCH) operands[7] = operands[8] = operands[6]; else { operands[7] = gen_rtx_SCRATCH (SImode); operands[8] = gen_rtx_SCRATCH (SImode); }}");; Define move insns for SF, and DF.;;;; For register-register copies or a copy of something to itself, emit a;; single SET insn since it will likely be optimized away.;;;; Otherwise, emit a floating-point move operation unless both input and;; output are either constant, memory, or a non-floating-point hard register.(define_expand "movdf" [(parallel [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))])] "" "{ rtx op0 = operands[0]; rtx op1 = operands[1]; if (op0 == op1) { emit_insn (gen_rtx_SET (VOIDmode, op0, op1)); DONE; } if ((GET_CODE (op0) == MEM || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER && ! FP_REGNO_P (REGNO (op0)))) && (GET_CODE (op1) == MEM || GET_CODE (op1) == CONST_DOUBLE || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER && ! FP_REGNO_P (REGNO (op1)) && ! rtx_equal_p (op0, op1)))) { rtx insns; if (GET_CODE (op1) == CONST_DOUBLE) op1 = force_const_mem (DFmode, op1); start_sequence (); if (GET_CODE (operands[0]) != REG || ! refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) { emit_move_insn (operand_subword (op0, 0, 1, DFmode), operand_subword_force (op1, 0, DFmode)); emit_move_insn (operand_subword (op0, 1, 1, DFmode), operand_subword_force (op1, 1, DFmode)); } else { emit_move_insn (operand_subword (op0, 1, 1, DFmode), operand_subword_force (op1, 1, DFmode)); emit_move_insn (operand_subword (op0, 0, 1, DFmode), operand_subword_force (op1, 0, DFmode)); } insns = get_insns (); end_sequence (); emit_no_conflict_block (insns, op0, op1, 0, op1); DONE; }}")(define_expand "movsf" [(parallel [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))])] "" "{ rtx op0 = operands[0]; rtx op1 = operands[1]; if (op0 == op1) { emit_insn (gen_rtx_SET (VOIDmode, op0, op1)); DONE; } if ((GET_CODE (op0) == MEM || (GET_CODE (op0) == REG && REGNO (op0) < FIRST_PSEUDO_REGISTER && ! FP_REGNO_P (REGNO (op0)))) && (GET_CODE (op1) == MEM || GET_CODE (op1) == CONST_DOUBLE || (GET_CODE (op1) == REG && REGNO (op1) < FIRST_PSEUDO_REGISTER && ! FP_REGNO_P (REGNO (op1))))) { rtx last; if (GET_CODE (op1) == CONST_DOUBLE) op1 = force_const_mem (SFmode, op1); last = emit_move_insn (operand_subword (op0, 0, 1, SFmode), operand_subword_force (op1, 0, SFmode)); REG_NOTES (last) = gen_rtx_EXPR_LIST (REG_EQUAL, op1, REG_NOTES (last)); DONE; }}");; Define the move insns for SF and DF. Check for all general regs;; in the FP insns and make them non-FP if so. Do the same if the input and;; output are the same (the insn will be deleted in this case and we don't;; want to think there are FP insns when there might not be).(define_insn "" [(set (match_operand:SF 0 "general_operand" "=*frg") (match_dup 0))] "" "nopr r0" [(set_attr "type" "address") (set_attr "length" "2")])(define_insn "" [(set (match_operand:SF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") (match_operand:SF 1 "general_operand" "r,0,Q,m,r,r,frg")) (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] "" "*{ switch (which_alternative) { case 0: return \"cas %0,%1,r0\"; case 1: return \"nopr r0\"; case 2: return \"l%M1 %0,%1\"; case 3: return \"load %0,%1\"; case 4: return \"st%M0 %1,%0\"; case 5: return \"store %1,%0,%3\"; default: return output_fpop (SET, operands[0], operands[1], 0, insn); }}" [(set_attr "type" "address,address,load,load,store,store,fp") (set_attr "length" "2,2,*,*,*,*,*")])(define_insn "" [(set (match_operand:DF 0 "general_operand" "=*frg") (match_dup 0))] "" "nopr r0" [(set_attr "type" "address") (set_attr "length" "2")])(define_insn "" [(set (match_operand:DF 0 "general_operand" "=r,*fr,r,r,Q,m,frg") (match_operand:DF 1 "general_operand" "r,0,Q,m,r,r,*frg")) (clobber (match_operand:SI 2 "reg_0_operand" "=&z,z,z,z,z,z,z")) (clobber (match_operand:SI 3 "reg_15_operand" "=&t,t,t,t,t,t,t"))] "" "*{ switch (which_alternative) { case 0: if (REGNO (operands[0]) == REGNO (operands[1]) + 1) return \"cas %O0,%O1,r0\;cas %0,%1,r0\"; else return \"cas %0,%1,r0\;cas %O0,%O1,r0\"; case 1: return \"nopr r0\"; case 2: /* Here we must see which word to load first. We default to the low-order word unless it occurs in the address. */ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1, operands[1], 0)) return \"l%M1 %O0,%O1\;l%M1 %0,%1\"; else return \"l%M1 %0,%1\;l%M1 %O0,%O1\"; case 3: return \"get %3,$%1\;ls %0,0(%3)\;ls %O0,4(%3)\"; case 4: return \"st%M0 %1,%0\;st%M0 %O1,%O0\"; case 5: return \"get %3,$%0\;sts %1,0(%3)\;sts %O1,4(%3)\"; default: return output_fpop (SET, operands[0], operands[1], 0, insn); }}" [(set_attr "type" "address,multi,multi,multi,multi,multi,fp") (set_attr "length" "2,4,*,*,*,*,*")]);; Split all the above cases that involve multiple insns and no floating-point;; data block. If before reload, we can make a SCRATCH. Otherwise, use;; register 15.(define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "symbolic_memory_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "GET_CODE (operands[0]) == REG && REGNO (operands[0]) < 16" [(set (reg:SI 15) (match_dup 2)) (set (match_dup 3) (match_dup 4)) (set (match_dup 5) (match_dup 6))] "{ operands[2] = XEXP (operands[1], 0); operands[3] = operand_subword (operands[0], 0, 0, DFmode); operands[4] = gen_rtx_MEM (SImode, gen_rtx (REG, SImode, 15)); operands[5] = operand_subword (operands[0], 1, 0, DFmode); operands[6] = gen_rtx_MEM (SImode, plus_constant (gen_rtx (REG, SImode, 15), 4)); if (operands[3] == 0 || operands[5] == 0) FAIL;}")(define_split [(set (match_operand:DF 0 "symbolic_memory_operand" "") (match_operand:DF 1 "register_operand" "")) (clobber (reg:SI 0)) (clobber (reg:SI 15))] "GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 16" [(set (reg:SI 15) (match_dup 2)) (set (match_dup 3) (match_dup 4)) (set (match_dup 5) (match_dup 6))] "{ operands[2] = XEXP (operands[0], 0); operands[3] = gen_rtx_MEM (SImode, gen_rtx (REG, SImode, 15)); operands[4] = operand_subword (operands[1], 0, 0, DFmode); operands[5] = gen_rtx_MEM (SImode, plus_constant (gen_rtx_REG (SImode, 15), 4)); operands[6] = operand_subword (operands[1], 1, 0, DFmode); if (operands[4] == 0 || operands[6] == 0) FAIL;}")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -