📄 cris.md
字号:
[(set (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r,r") (match_operand:SI 1 "const_int_operand" "n,n")) (match_operand:SI 2 "register_operand" "r,r"))) (const_int 0)) (set (match_operand:SI 3 "register_operand" "=*2,r") (plus:SI (mult:SI (match_dup 0) (match_dup 1)) (match_dup 2)))] "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)" "@ # clear.w [%3=%2+%0%T1]");; clear.w [ry=rz+i](define_insn "*clear_sidehi" [(set (mem:HI (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r") (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))) (const_int 0)) (set (match_operand:SI 2 "register_operand" "=*0,r,r") (plus:SI (match_dup 0) (match_dup 1)))] "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)" "*{ if (which_alternative == 0 && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) > 127 || INTVAL (operands[1]) < -128 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N') || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J'))) return \"#\"; return \"clear.w [%2=%0%S1]\";}");; clear.b [ry=rx+rw.s2](define_insn "*clear_sideqi_biap" [(set (mem:QI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r,r") (match_operand:SI 1 "const_int_operand" "n,n")) (match_operand:SI 2 "register_operand" "r,r"))) (const_int 0)) (set (match_operand:SI 3 "register_operand" "=*2,r") (plus:SI (mult:SI (match_dup 0) (match_dup 1)) (match_dup 2)))] "cris_side_effect_mode_ok (MULT, operands, 3, 2, 0, 1, -1)" "@ # clear.b [%3=%2+%0%T1]");; clear.b [ry=rz+i](define_insn "*clear_sideqi" [(set (mem:QI (plus:SI (match_operand:SI 0 "cris_bdap_operand" "%r,r,r") (match_operand:SI 1 "cris_bdap_operand" "r>Rn,r,>Rn"))) (const_int 0)) (set (match_operand:SI 2 "register_operand" "=*0,r,r") (plus:SI (match_dup 0) (match_dup 1)))] "cris_side_effect_mode_ok (PLUS, operands, 2, 0, 1, -1, -1)" "*{ if (which_alternative == 0 && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) > 127 || INTVAL (operands[1]) < -128 || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'N') || CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'J'))) return \"#\"; return \"clear.b [%2=%0%S1]\";}");; To appease test-case gcc.c-torture/execute/920501-2.c (and others) at;; -O0, we need a movdi as a temporary measure. Here's how things fail:;; A cmpdi RTX needs reloading (global):;; (insn 185 326 186 (set (cc0);; (compare (mem/f:DI (reg/v:SI 22) 0);; (const_int 1 [0x1]))) 4 {cmpdi} (nil);; (nil));; Now, reg 22 is reloaded for input address, and the mem is also moved;; out of the instruction (into a register), since one of the operands;; must be a register. Reg 22 is reloaded (into reg 10), and the mem is;; moved out and synthesized in SImode parts (reg 9, reg 10 - should be ok;; wrt. overlap). The bad things happen with the synthesis in;; emit_move_insn_1; the location where to substitute reg 10 is lost into;; two new RTX:es, both still having reg 22. Later on, the left-over reg;; 22 is recognized to have an equivalent in memory which is substituted;; straight in, and we end up with an unrecognizable insn:;; (insn 325 324 326 (set (reg:SI 9 r9);; (mem/f:SI (mem:SI (plus:SI (reg:SI 8 r8);; (const_int -84 [0xffffffac])) 0) 0)) -1 (nil);; (nil));; which is the first part of the reloaded synthesized "movdi".;; The right thing would be to add equivalent replacement locations for;; insn with pseudos that need more reloading. The question is where.;; Normal move patterns from SI on.(define_expand "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "cris_general_operand_or_symbol" ""))] "" "{ /* If the output goes to a MEM, make sure we have zero or a register as input. */ if (GET_CODE (operands[0]) == MEM && ! REG_S_P (operands[1]) && operands[1] != const0_rtx && ! no_new_pseudos) operands[1] = force_reg (SImode, operands[1]); /* If we're generating PIC and have an incoming symbol, validize it to a general operand or something that will match a special pattern. FIXME: Do we *have* to recognize anything that would normally be a valid symbol? Can we exclude global PIC addresses with an added offset? */ if (flag_pic && CONSTANT_ADDRESS_P (operands[1]) && cris_symbol (operands[1])) { /* We must have a register as destination for what we're about to do, and for the patterns we generate. */ if (! REG_S_P (operands[0])) { if (no_new_pseudos) abort (); operands[1] = force_reg (SImode, operands[1]); } else { /* Mark a needed PIC setup for a LABEL_REF:s coming in here: they are so rare not-being-branch-targets that we don't mark a function as needing PIC setup just because we have inspected LABEL_REF:s as operands. It is only in __builtin_setjmp and such that we can get a LABEL_REF assigned to a register. */ if (GET_CODE (operands[1]) == LABEL_REF) current_function_uses_pic_offset_table = 1; /* We don't have to do anything for global PIC operands; they look just like ``[rPIC+sym]''. */ if (! cris_got_symbol (operands[1]) /* We don't do anything for local PIC operands; we match that with a special alternative. */ && ! cris_gotless_symbol (operands[1])) { /* We get here when we have to change something that would be recognizable if it wasn't PIC. A ``sym'' is ok for PIC symbols both with and without a GOT entry. And ``sym + offset'' is ok for local symbols, so the only thing it could be, is a global symbol with an offset. Check and abort if not. */ rtx sym = get_related_value (operands[1]); HOST_WIDE_INT offs = get_integer_term (operands[1]); if (sym == NULL_RTX || offs == 0) abort (); emit_move_insn (operands[0], sym); if (expand_binop (SImode, add_optab, operands[0], GEN_INT (offs), operands[0], 0, OPTAB_LIB_WIDEN) != operands[0]) abort (); DONE; } } }}")(define_insn "*movsi_internal" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,Q>,r,Q>,g,r,r,r,g") (match_operand:SI 1 ;; FIXME: We want to put S last, but apparently g matches S. ;; It's a bug: an S is not a general_operand and shouldn't match g. "cris_general_operand_or_gotless_symbol" "r,Q>,M,M,I,r,M,n,!S,g,r"))] "" "*{ /* Better to have c-switch here; it is worth it to optimize the size of move insns. The alternative would be to try to find more constraint letters. FIXME: Check again. It seems this could shrink a bit. */ switch (which_alternative) { case 0: case 1: case 5: case 9: case 10: return \"move.d %1,%0\"; case 2: case 3: case 6: return \"clear.d %0\"; /* Constants -32..31 except 0. */ case 4: return \"moveq %1,%0\"; /* We can win a little on constants -32768..-33, 32..65535. */ case 7: if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) < 65536) { if (INTVAL (operands[1]) < 256) return \"movu.b %1,%0\"; return \"movu.w %1,%0\"; } else if (INTVAL (operands[1]) >= -32768 && INTVAL (operands[1]) < 32768) { if (INTVAL (operands[1]) >= -128 && INTVAL (operands[1]) < 128) return \"movs.b %1,%0\"; return \"movs.w %1,%0\"; } return \"move.d %1,%0\"; case 8: /* FIXME: Try and split this into pieces GCC makes better code of, than this multi-insn pattern. Synopsis: wrap the GOT-relative symbol into an unspec, and when PIC, recognize the unspec everywhere a symbol is normally recognized. (The PIC register should be recognized by GCC as pic_offset_table_rtx when needed and similar for PC.) Each component can then be optimized with the rest of the code; it should be possible to have a constant term added on an unspec. Don't forget to add a REG_EQUAL (or is it REG_EQUIV) note to the destination. It might not be worth it. Measure. Note that the 'v' modifier makes PLT references be output as sym:PLT rather than [rPIC+sym:GOTPLT]. */ return \"move.d %v1,%0\;add.d %P1,%0\"; default: return \"BOGUS: %1 to %0\"; }}" [(set_attr "slottable" "yes,yes,yes,yes,yes,yes,no,no,no,no,no")]);; Extend operations with side-effect from mem to register, using;; MOVS/MOVU. These are from mem to register only.;;;; [rx=ry+rz.S];;;; QImode to HImode;;;; FIXME: Can we omit extend to HImode, since GCC should truncate for;; HImode by itself? Perhaps use only anonymous modes?(define_insn "*ext_sideqihi_biap" [(set (match_operand:HI 0 "register_operand" "=r,r") (match_operator:HI 5 "cris_extend_operator" [(mem:QI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "const_int_operand" "n,n")) (match_operand:SI 3 "register_operand" "r,r")))])) (set (match_operand:SI 4 "register_operand" "=*3,r") (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3)))] "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" "@ # mov%e5.%m5 [%4=%3+%1%T2],%0");; QImode to SImode(define_insn "*ext_sideqisi_biap" [(set (match_operand:SI 0 "register_operand" "=r,r") (match_operator:SI 5 "cris_extend_operator" [(mem:QI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "const_int_operand" "n,n")) (match_operand:SI 3 "register_operand" "r,r")))])) (set (match_operand:SI 4 "register_operand" "=*3,r") (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3)))] "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" "@ # mov%e5.%m5 [%4=%3+%1%T2],%0");; HImode to SImode(define_insn "*ext_sidehisi_biap" [(set (match_operand:SI 0 "register_operand" "=r,r") (match_operator:SI 5 "cris_extend_operator" [(mem:HI (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "r,r") (match_operand:SI 2 "const_int_operand" "n,n")) (match_operand:SI 3 "register_operand" "r,r")))])) (set (match_operand:SI 4 "register_operand" "=*3,r") (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3)))] "cris_side_effect_mode_ok (MULT, operands, 4, 3, 1, 2, 0)" "@ # mov%e5.%m5 [%4=%3+%1%T2],%0");; Same but [rx=ry+i];; QImode to HImode(define_insn "*ext_sideqihi" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (match_operator:HI 4 "cris_extend_operator" [(mem:QI (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r") (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))])) (set (match_operand:SI 3 "register_operand" "=*1,r,r") (plus:SI (match_dup 1) (match_dup 2)))] "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" "*{ if (which_alternative == 0 && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 127 || INTVAL (operands[2]) < -128 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N') || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))) return \"#\"; return \"mov%e4.%m4 [%3=%1%S2],%0\";}");; QImode to SImode(define_insn "*ext_sideqisi" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (match_operator:SI 4 "cris_extend_operator" [(mem:QI (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r") (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))])) (set (match_operand:SI 3 "register_operand" "=*1,r,r") (plus:SI (match_dup 1) (match_dup 2)))] "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" "*{ if (which_alternative == 0 && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 127 || INTVAL (operands[2]) < -128 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N') || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))) return \"#\"; return \"mov%e4.%m4 [%3=%1%S2],%0\";}");; HImode to SImode(define_insn "*ext_sidehisi" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (match_operator:SI 4 "cris_extend_operator" [(mem:HI (plus:SI (match_operand:SI 1 "cris_bdap_operand" "%r,r,r") (match_operand:SI 2 "cris_bdap_operand" "r>Rn,r,>Rn")))])) (set (match_operand:SI 3 "register_operand" "=*1,r,r") (plus:SI (match_dup 1) (match_dup 2)))] "cris_side_effect_mode_ok (PLUS, operands, 3, 1, 2, -1, 0)" "*{ if (which_alternative == 0 && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 127 || INTVAL (operands[2]) < -128 || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'N') || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))) return \"#\"; return \"mov%e4.%m4 [%3=%1%S2],%0\";}");; FIXME: See movsi.(define_insn "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,Q>,r,Q>,r,r,r,g,g,r") (match_operand:HI 1 "general_operand" "r,Q>,M,M,I,r,L,O,n,M,r,g"))] "" "*{ switch (which_alternative) { case 0: case 1: case 5: case 10: case 11: return \"move.w %1,%0\"; case 2: case 3:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -