📄 xtensa.md
字号:
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; } } fatal_insn (\"unexpected cmov operator\", operands[4]); 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; } } fatal_insn (\"unexpected cmov operator\", operands[4]); 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_FLAG (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_FLAG (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 "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")]);;;; ....................;;;; MISC.;;;; ....................;;(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 xtensa_reorg() 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 [(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 [(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")]);;;; ....................;;;; BOOLEANS;;;; ....................;;;; branch patterns(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 + -