📄 xtensa.md
字号:
})(define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "") (match_dup 1))] ""{ operands[1] = gen_rtx_GT (SImode, branch_cmp[0], branch_cmp[1]); if (!xtensa_expand_scc (operands)) FAIL; DONE;})(define_expand "sge" [(set (match_operand:SI 0 "register_operand" "") (match_dup 1))] ""{ operands[1] = gen_rtx_GE (SImode, branch_cmp[0], branch_cmp[1]); if (!xtensa_expand_scc (operands)) FAIL; DONE;})(define_expand "slt" [(set (match_operand:SI 0 "register_operand" "") (match_dup 1))] ""{ operands[1] = gen_rtx_LT (SImode, branch_cmp[0], branch_cmp[1]); if (!xtensa_expand_scc (operands)) FAIL; DONE;})(define_expand "sle" [(set (match_operand:SI 0 "register_operand" "") (match_dup 1))] ""{ operands[1] = gen_rtx_LE (SImode, branch_cmp[0], branch_cmp[1]); if (!xtensa_expand_scc (operands)) FAIL; DONE;});; Conditional moves.(define_expand "movsicc" [(set (match_operand:SI 0 "register_operand" "") (if_then_else:SI (match_operand 1 "comparison_operator" "") (match_operand:SI 2 "register_operand" "") (match_operand:SI 3 "register_operand" "")))] ""{ if (!xtensa_expand_conditional_move (operands, 0)) FAIL; DONE;})(define_expand "movsfcc" [(set (match_operand:SF 0 "register_operand" "") (if_then_else:SF (match_operand 1 "comparison_operator" "") (match_operand:SF 2 "register_operand" "") (match_operand:SF 3 "register_operand" "")))] ""{ if (!xtensa_expand_conditional_move (operands, 1)) FAIL; DONE;})(define_insn "movsicc_internal0" [(set (match_operand:SI 0 "register_operand" "=a,a") (if_then_else:SI (match_operator 4 "branch_operator" [(match_operand:SI 1 "register_operand" "r,r") (const_int 0)]) (match_operand:SI 2 "register_operand" "r,0") (match_operand:SI 3 "register_operand" "0,r")))] ""{ if (which_alternative == 0) { switch (GET_CODE (operands[4])) { case EQ: return "moveqz\t%0, %2, %1"; case NE: return "movnez\t%0, %2, %1"; case LT: return "movltz\t%0, %2, %1"; case GE: return "movgez\t%0, %2, %1"; default: break; } } else { switch (GET_CODE (operands[4])) { case EQ: return "movnez\t%0, %3, %1"; case NE: return "moveqz\t%0, %3, %1"; case LT: return "movgez\t%0, %3, %1"; case GE: return "movltz\t%0, %3, %1"; default: break; } } abort (); return "";} [(set_attr "type" "move,move") (set_attr "mode" "SI") (set_attr "length" "3,3")])(define_insn "movsicc_internal1" [(set (match_operand:SI 0 "register_operand" "=a,a") (if_then_else:SI (match_operator 4 "boolean_operator" [(match_operand:CC 1 "register_operand" "b,b") (const_int 0)]) (match_operand:SI 2 "register_operand" "r,0") (match_operand:SI 3 "register_operand" "0,r")))] "TARGET_BOOLEANS"{ int isEq = (GET_CODE (operands[4]) == EQ); switch (which_alternative) { case 0: if (isEq) return "movf\t%0, %2, %1"; return "movt\t%0, %2, %1"; case 1: if (isEq) return "movt\t%0, %3, %1"; return "movf\t%0, %3, %1"; } abort (); return "";} [(set_attr "type" "move,move") (set_attr "mode" "SI") (set_attr "length" "3,3")])(define_insn "movsfcc_internal0" [(set (match_operand:SF 0 "register_operand" "=a,a,f,f") (if_then_else:SF (match_operator 4 "branch_operator" [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) (match_operand:SF 2 "register_operand" "r,0,f,0") (match_operand:SF 3 "register_operand" "0,r,0,f")))] ""{ if (which_alternative == 0) { switch (GET_CODE (operands[4])) { case EQ: return "moveqz\t%0, %2, %1"; case NE: return "movnez\t%0, %2, %1"; case LT: return "movltz\t%0, %2, %1"; case GE: return "movgez\t%0, %2, %1"; default: break; } } else if (which_alternative == 1) { switch (GET_CODE (operands[4])) { case EQ: return "movnez\t%0, %3, %1"; case NE: return "moveqz\t%0, %3, %1"; case LT: return "movgez\t%0, %3, %1"; case GE: return "movltz\t%0, %3, %1"; default: break; } } else if (which_alternative == 2) { switch (GET_CODE (operands[4])) { case EQ: return "moveqz.s %0, %2, %1"; case NE: return "movnez.s %0, %2, %1"; case LT: return "movltz.s %0, %2, %1"; case GE: return "movgez.s %0, %2, %1"; default: break; } } else if (which_alternative == 3) { switch (GET_CODE (operands[4])) { case EQ: return "movnez.s %0, %3, %1"; case NE: return "moveqz.s %0, %3, %1"; case LT: return "movgez.s %0, %3, %1"; case GE: return "movltz.s %0, %3, %1"; default: break; } } abort (); return "";} [(set_attr "type" "move,move,move,move") (set_attr "mode" "SF") (set_attr "length" "3,3,3,3")])(define_insn "movsfcc_internal1" [(set (match_operand:SF 0 "register_operand" "=a,a,f,f") (if_then_else:SF (match_operator 4 "boolean_operator" [(match_operand:CC 1 "register_operand" "b,b,b,b") (const_int 0)]) (match_operand:SF 2 "register_operand" "r,0,f,0") (match_operand:SF 3 "register_operand" "0,r,0,f")))] "TARGET_BOOLEANS"{ int isEq = (GET_CODE (operands[4]) == EQ); switch (which_alternative) { case 0: if (isEq) return "movf\t%0, %2, %1"; return "movt\t%0, %2, %1"; case 1: if (isEq) return "movt\t%0, %3, %1"; return "movf\t%0, %3, %1"; case 2: if (isEq) return "movf.s\t%0, %2, %1"; return "movt.s\t%0, %2, %1"; case 3: if (isEq) return "movt.s\t%0, %3, %1"; return "movf.s\t%0, %3, %1"; } abort (); return "";} [(set_attr "type" "move,move,move,move") (set_attr "mode" "SF") (set_attr "length" "3,3,3,3")]);; Floating-point comparisons.(define_insn "seq_sf" [(set (match_operand:CC 0 "register_operand" "=b") (eq:CC (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "oeq.s\t%0, %1, %2" [(set_attr "type" "farith") (set_attr "mode" "BL") (set_attr "length" "3")])(define_insn "slt_sf" [(set (match_operand:CC 0 "register_operand" "=b") (lt:CC (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "olt.s\t%0, %1, %2" [(set_attr "type" "farith") (set_attr "mode" "BL") (set_attr "length" "3")])(define_insn "sle_sf" [(set (match_operand:CC 0 "register_operand" "=b") (le:CC (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "TARGET_HARD_FLOAT" "ole.s\t%0, %1, %2" [(set_attr "type" "farith") (set_attr "mode" "BL") (set_attr "length" "3")]);; Unconditional branches.(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "j\t%l0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "3")])(define_expand "indirect_jump" [(set (pc) (match_operand 0 "register_operand" ""))] ""{ rtx dest = operands[0]; if (GET_CODE (dest) != REG || GET_MODE (dest) != Pmode) operands[0] = copy_to_mode_reg (Pmode, dest); emit_jump_insn (gen_indirect_jump_internal (dest)); DONE;})(define_insn "indirect_jump_internal" [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" "jx\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "3")])(define_expand "tablejump" [(use (match_operand:SI 0 "register_operand" "")) (use (label_ref (match_operand 1 "" "")))] ""{ rtx target = operands[0]; if (flag_pic) { /* For PIC, the table entry is relative to the start of the table. */ rtx label = gen_reg_rtx (SImode); target = gen_reg_rtx (SImode); emit_move_insn (label, gen_rtx_LABEL_REF (SImode, operands[1])); emit_insn (gen_addsi3 (target, operands[0], label)); } emit_jump_insn (gen_tablejump_internal (target, operands[1])); DONE;})(define_insn "tablejump_internal" [(set (pc) (match_operand:SI 0 "register_operand" "r")) (use (label_ref (match_operand 1 "" "")))] "" "jx\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "3")]);; Function calls.(define_expand "sym_PLT" [(const (unspec [(match_operand:SI 0 "" "")] UNSPEC_PLT))] "" "")(define_expand "call" [(call (match_operand 0 "memory_operand" "") (match_operand 1 "" ""))] ""{ rtx addr = XEXP (operands[0], 0); if (flag_pic && GET_CODE (addr) == SYMBOL_REF && (!SYMBOL_REF_LOCAL_P (addr) || SYMBOL_REF_EXTERNAL_P (addr))) addr = gen_sym_PLT (addr); if (!call_insn_operand (addr, VOIDmode)) XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);})(define_insn "call_internal" [(call (mem (match_operand:SI 0 "call_insn_operand" "n,i,r")) (match_operand 1 "" "i,i,i"))] ""{ return xtensa_emit_call (0, operands);} [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "3")])(define_expand "call_value" [(set (match_operand 0 "register_operand" "") (call (match_operand 1 "memory_operand" "") (match_operand 2 "" "")))] ""{ rtx addr = XEXP (operands[1], 0); if (flag_pic && GET_CODE (addr) == SYMBOL_REF && (!SYMBOL_REF_LOCAL_P (addr) || SYMBOL_REF_EXTERNAL_P (addr))) addr = gen_sym_PLT (addr); if (!call_insn_operand (addr, VOIDmode)) XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);});; Cannot combine constraints for operand 0 into "afvb":;; reload.c:find_reloads seems to assume that grouped constraints somehow;; specify related register classes, and when they don't the constraints;; fail to match. By not grouping the constraints, we get the correct;; behavior.(define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=af,af,af,v,v,v,b,b,b") (call (mem (match_operand:SI 1 "call_insn_operand" "n,i,r,n,i,r,n,i,r")) (match_operand 2 "" "i,i,i,i,i,i,i,i,i")))] ""{ return xtensa_emit_call (1, operands);} [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "3")])(define_insn "entry" [(set (reg:SI A1_REG) (unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "i") (match_operand:SI 1 "const_int_operand" "i")] UNSPECV_ENTRY))] ""{ if (frame_pointer_needed) output_asm_insn (".frame\ta7, %0", operands); else output_asm_insn (".frame\tsp, %0", operands); return "entry\tsp, %1";} [(set_attr "type" "move") (set_attr "mode" "SI") (set_attr "length" "3")])(define_insn "return" [(return) (use (reg:SI A0_REG))] "reload_completed"{ return (TARGET_DENSITY ? "retw.n" : "retw");} [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "2")]);; Miscellaneous instructions.(define_expand "prologue" [(const_int 0)] ""{ xtensa_expand_prologue (); DONE;})(define_expand "epilogue" [(return)] ""{ emit_jump_insn (gen_return ()); DONE;})(define_insn "nop" [(const_int 0)] ""{ return (TARGET_DENSITY ? "nop.n" : "nop");} [(set_attr "type" "nop") (set_attr "mode" "none") (set_attr "length" "3")])(define_expand "nonlocal_goto" [(match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "") (match_operand:SI 3 "" "")] ""{ xtensa_expand_nonlocal_goto (operands); DONE;});; Setting up a frame pointer is tricky for Xtensa because GCC doesn't;; know if a frame pointer is required until the reload pass, and;; because there may be an incoming argument value in the hard frame;; pointer register (a7). If there is an incoming argument in that;; register, the "set_frame_ptr" insn gets inserted immediately after;; the insn that copies the incoming argument to a pseudo or to the;; stack. This serves several purposes here: (1) it keeps the;; optimizer from copy-propagating or scheduling the use of a7 as an;; incoming argument away from the beginning of the function; (2) we;; can use a post-reload splitter to expand away the insn if a frame;; pointer is not required, so that the post-reload scheduler can do;; the right thing; and (3) it makes it easy for the prologue expander;; to search for this insn to determine whether it should add a new insn;; to set up the frame pointer.(define_insn "set_frame_ptr" [(set (reg:SI A7_REG) (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_FP))] ""{ if (frame_pointer_needed) return "mov\ta7, sp"; return "";} [(set_attr "type" "move") (set_attr "mode" "SI") (set_attr "length" "3")]);; Post-reload splitter to remove fp assignment when it's not needed.(define_split [(set (reg:SI A7_REG) (unspec_volatile:SI [(const_int 0)] UNSPECV_SET_FP))] "reload_completed && !frame_pointer_needed" [(unspec [(const_int 0)] UNSPEC_NOP)] "");; The preceding splitter needs something to split the insn into;;; things start breaking if the result is just a "use" so instead we;; generate the following insn.(define_insn "*unspec_nop" [(unspec [(const_int 0)] UNSPEC_NOP)] "" "" [(set_attr "type" "nop") (set_attr "mode" "none") (set_attr "length" "0")]);; The fix_return_addr pattern sets the high 2 bits of an address in a;; register to match the high bits of the current PC.(define_insn "fix_return_addr" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(match_operand:SI 1 "register_operand" "r")] UNSPEC_RET_ADDR)) (clobber (match_scratch:SI 2 "=r")) (clobber (match_scratch:SI 3 "=r"))] "" "mov\t%2, a0\;call0\t0f\;.align\t4\;0:\;mov\t%3, a0\;mov\ta0, %2\;\srli\t%3, %3, 30\;slli\t%0, %1, 2\;ssai\t2\;src\t%0, %3, %0" [(set_attr "type" "multi") (set_attr "mode" "SI") (set_attr "length" "24")]);; Instructions for the Xtensa "boolean" option.(define_insn "*booltrue" [(set (pc) (if_then_else (match_operator 2 "boolean_operator" [(match_operand:CC 0 "register_operand" "b") (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "TARGET_BOOLEANS"{ if (GET_CODE (operands[2]) == EQ) return "bf\t%0, %1"; else return "bt\t%0, %1";} [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "3")])(define_insn "*boolfalse" [(set (pc) (if_then_else (match_operator 2 "boolean_operator" [(match_operand:CC 0 "register_operand" "b") (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "TARGET_BOOLEANS"{ if (GET_CODE (operands[2]) == EQ) return "bt\t%0, %1"; else return "bf\t%0, %1";} [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "3")])
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -