⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c4x.md

📁 gcc编译工具没有什么特别
💻 MD
📖 第 1 页 / 共 5 页
字号:
(define_attr "setlda_ir1" ""       (cond [(eq_attr "type" "lda")                       (if_then_else (match_operand 0 "ir1_reg_operand" "")                                     (const_int 1) (const_int 0))]             (const_int 0)))(define_attr "useir1" ""       (cond [(eq_attr "type" "compare,store")                       (if_then_else (match_operand 0 "ir1_mem_operand" "")                                     (const_int 1) (const_int 0))              (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc")                       (if_then_else (match_operand 1 "ir1_mem_operand" "")                                     (const_int 1) (const_int 0))              (eq_attr "type" "binary,binarycc")                       (if_then_else (match_operand 2 "ir1_mem_operand" "")                                     (const_int 1) (const_int 0))]             (const_int 0))); With the C3x, things are simpler, but slower, i.e. more pipeline conflicts :(; There are three functional groups:; (1) AR0-AR7, IR0-IR1, BK; (2) DP; (3) SP;; When a register in one of these functional groups is loaded,; the contents of that or any other register in its group; will not be available to the next instruction for 2 machine cycles.; Similarly, when a register in one of the functional groups is read; excepting (IR0-IR1, BK, DP) the contents of that or any other register; in its group will not be available to the next instruction for; 1 machine cycle.;; Let's ignore functional groups 2 and 3 for now, since they are not; so important.;(define_function_unit "group1" 1 0;       (and (eq_attr "cpu" "c3x");            (and (eq_attr "setgroup1" "1");                 (eq_attr "usegroup1" "1")));       3 1);(define_function_unit "group1" 1 0;       (and (eq_attr "cpu" "c3x");            (and (eq_attr "usegroup1" "1");                 (eq_attr "readarx" "1")));       2 1)(define_attr "setgroup1" ""       (cond [(eq_attr "type" "lda,unary,binary")                  (if_then_else (match_operand 0 "group1_reg_operand" "")                                (const_int 1) (const_int 0))]             (const_int 0)))(define_attr "usegroup1" ""       (cond [(eq_attr "type" "compare,store,store_store,store_load")              (if_then_else (match_operand 0 "group1_mem_operand" "")                            (const_int 1) (const_int 0))              (eq_attr "type" "compare,lda,unary,unarycc,binary,binarycc,load_load,load_store")              (if_then_else (match_operand 1 "group1_mem_operand" "")                            (const_int 1) (const_int 0))              (eq_attr "type" "store_store,load_store")              (if_then_else (match_operand 2 "group1_mem_operand" "")                            (const_int 1) (const_int 0))              (eq_attr "type" "load_load,store_load")              (if_then_else (match_operand 3 "group1_mem_operand" "")                            (const_int 1) (const_int 0))]             (const_int 0)))(define_attr "readarx" ""       (cond [(eq_attr "type" "compare")              (if_then_else (match_operand 0 "arx_reg_operand" "")                            (const_int 1) (const_int 0))              (eq_attr "type" "compare,store,lda,unary,unarycc,binary,binarycc")              (if_then_else (match_operand 1 "arx_reg_operand" "")                            (const_int 1) (const_int 0))              (eq_attr "type" "binary,binarycc")              (if_then_else (match_operand 2 "arx_reg_operand" "")                            (const_int 1) (const_int 0))]             (const_int 0)));; C4x INSN PATTERNS:;; Note that the movMM and addP patterns can be called during reload; so we need to take special care with theses patterns since; we cannot blindly clobber CC or generate new pseudo registers.;; TWO OPERAND INTEGER INSTRUCTIONS;;; LDP/LDPK;(define_insn "set_ldp"  [(set (match_operand:QI 0 "dp_reg_operand" "=z")        (high:QI (match_operand:QI 1 "" "")))]  "! TARGET_SMALL"  "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"  [(set_attr "type" "ldp")])(define_insn "set_high"  [(set (match_operand:QI 0 "std_reg_operand" "=c")        (high:QI (match_operand:QI 1 "symbolic_address_operand" "")))]  "! TARGET_C3X "  "ldhi\\t^%H1,%0"  [(set_attr "type" "unary")])(define_insn "set_lo_sum"  [(set (match_operand:QI 0 "std_reg_operand" "=c")        (lo_sum:QI (match_dup 0)                   (match_operand:QI 1 "symbolic_address_operand" "")))]  ""  "or\\t#%H1,%0"  [(set_attr "type" "unary")])(define_split  [(set (match_operand:QI 0 "std_reg_operand" "")        (match_operand:QI 1 "symbolic_address_operand" ""))]  "! TARGET_C3X"  [(set (match_dup 0) (high:QI (match_dup 1)))   (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))]  "")(define_split  [(set (match_operand:QI 0 "std_reg_operand" "")	(match_operand:QI 1 "const_int_operand" ""))]  "! TARGET_C3X   && (INTVAL (operands[1]) & ~0xffff) != 0   && (INTVAL (operands[1]) & 0xffff) != 0"  [(set (match_dup 0) (match_dup 2))   (set (match_dup 0) (ior:QI (match_dup 0) (match_dup 3)))]  "{   operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & ~0xffff);   operands[3] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 0xffff);}"); CC has been selected to load a symbolic address.  We force the address; into memory and then generate LDP and LDIU insns.; This is also required for the C30 if we pretend that we can ; easily load symbolic addresses into a register.(define_split  [(set (match_operand:QI 0 "reg_operand" "")        (match_operand:QI 1 "symbolic_address_operand" ""))]  "! TARGET_SMALL    && (TARGET_C3X || (reload_completed                      && ! std_reg_operand (operands[0], QImode)))"  [(set (match_dup 2) (high:QI (match_dup 3)))   (set (match_dup 0) (match_dup 4))   (use (match_dup 1))]  "{   rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);   operands[2] = dp_reg;   operands[3] = force_const_mem (Pmode, operands[1]);   operands[4] = change_address (operands[3], QImode,			         gen_rtx_LO_SUM (Pmode, dp_reg,                                                 XEXP (operands[3], 0)));   operands[3] = XEXP (operands[3], 0);}"); This pattern is similar to the above but does not emit a LDP; for the small memory model.(define_split  [(set (match_operand:QI 0 "reg_operand" "")        (match_operand:QI 1 "symbolic_address_operand" ""))]  "TARGET_SMALL   && (TARGET_C3X || (reload_completed                      && ! std_reg_operand (operands[0], QImode)))"  [(set (match_dup 0) (match_dup 2))   (use (match_dup 1))]  "{     rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);   operands[2] = force_const_mem (Pmode, operands[1]);   operands[2] = change_address (operands[2], QImode,			         gen_rtx_LO_SUM (Pmode, dp_reg,                                                 XEXP (operands[2], 0)));}")(define_insn "load_immed_address"  [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r")        (match_operand:QI 1 "symbolic_address_operand" ""))]   "TARGET_LOAD_ADDRESS"  "#"  [(set_attr "type" "multi")]);; LDIU/LDA/STI/STIK;; The following moves will not set the condition codes register.;; This must come before the general case(define_insn "*movqi_stik"  [(set (match_operand:QI 0 "memory_operand" "=m")        (match_operand:QI 1 "stik_const_operand" "K"))]  "! TARGET_C3X"  "stik\\t%1,%0"  [(set_attr "type" "store")]); We must provide an alternative to store to memory in case we have to; spill a register.(define_insn "movqi_noclobber"  [(set (match_operand:QI 0 "src_operand" "=d,*c,m,r")        (match_operand:QI 1 "src_hi_operand" "rIm,rIm,r,O"))]  "(REG_P (operands[0]) || REG_P (operands[1])    || GET_CODE (operands[0]) == SUBREG    || GET_CODE (operands[1]) == SUBREG)    && ! symbolic_address_operand (operands[1], QImode)"  "*   if (which_alternative == 2)     return \"sti\\t%1,%0\";   if (! TARGET_C3X && which_alternative == 3)     {       operands[1] = GEN_INT ((INTVAL (operands[1]) >> 16) & 0xffff);       return \"ldhi\\t%1,%0\";     }   /* The lda instruction cannot use the same register as source      and destination.  */   if (! TARGET_C3X && which_alternative == 1       && (   IS_ADDR_REG (REGNO (operands[0]))           || IS_INDEX_REG (REGNO (operands[0]))           || IS_SP_REG (REGNO (operands[0])))       && (REGNO (operands[0]) != REGNO (operands[1])))      return \"lda\\t%1,%0\";   return \"ldiu\\t%1,%0\";  "  [(set_attr "type" "unary,lda,store,unary")   (set_attr "data" "int16,int16,int16,high_16")]);; LDI;; We shouldn't need these peepholes, but the combiner seems to miss them...(define_peephole  [(set (match_operand:QI 0 "ext_reg_operand" "=d")        (match_operand:QI 1 "src_operand" "rIm"))   (set (reg:CC 21)        (compare:CC (match_dup 0) (const_int 0)))]  ""  "@  ldi\\t%1,%0"  [(set_attr "type" "unarycc")   (set_attr "data" "int16")])(define_insn "*movqi_set"  [(set (reg:CC 21)        (compare:CC (match_operand:QI 1 "src_operand" "rIm")                     (const_int 0)))   (set (match_operand:QI 0 "ext_reg_operand" "=d")        (match_dup 1))]  ""  "@  ldi\\t%1,%0"  [(set_attr "type" "unarycc")   (set_attr "data" "int16")]); This pattern probably gets in the way and requires a scratch register; when a simple compare with zero will suffice.;(define_insn "*movqi_test"; [(set (reg:CC 21);       (compare:CC (match_operand:QI 1 "src_operand" "rIm") ;                   (const_int 0)));  (clobber (match_scratch:QI 0 "=d"))]; ""; "@;  ldi\\t%1,%0";  [(set_attr "type" "unarycc");   (set_attr "data" "int16")]);  If one of the operands is not a register, then we should;  emit two insns, using a scratch register.  This will produce;  better code in loops if the source operand is invariant, since;  the source reload can be optimised out.  During reload we cannot;  use change_address or force_reg which will allocate new pseudo regs.;  Unlike most other insns, the move insns can't be split with;  different predicates, because register spilling and other parts of;  the compiler, have memoized the insn number already.(define_expand "movqi"  [(set (match_operand:QI 0 "general_operand" "")        (match_operand:QI 1 "general_operand" ""))]  ""  "{  if (c4x_emit_move_sequence (operands, QImode))    DONE;}")(define_insn "*movqi_update"  [(set (match_operand:QI 0 "reg_operand" "=r")         (mem:QI (plus:QI (match_operand:QI 1 "addr_reg_operand" "a")                         (match_operand:QI 2 "index_reg_operand" "x"))))   (set (match_dup 1)        (plus:QI (match_dup 1) (match_dup 2)))]  ""  "ldiu\\t*%1++(%2),%0"  [(set_attr "type" "unary")   (set_attr "data" "int16")])(define_insn "movqi_parallel"  [(set (match_operand:QI 0 "parallel_operand" "=q,S<>,q,S<>")        (match_operand:QI 1 "parallel_operand" "S<>,q,S<>,q"))   (set (match_operand:QI 2 "parallel_operand" "=q,S<>,S<>,q")        (match_operand:QI 3 "parallel_operand" "S<>,q,q,S<>"))]  "valid_parallel_load_store (operands, QImode)"  "@   ldi1\\t%1,%0\\n||\\tldi2\\t%3,%2   sti1\\t%1,%0\\n||\\tsti2\\t%3,%2   ldi\\t%1,%0\\n||\\tsti\\t%3,%2   ldi\\t%3,%2\\n||\\tsti\\t%1,%0"  [(set_attr "type" "load_load,store_store,load_store,store_load")]);; PUSH/POP;(define_insn "*pushqi"  [(set (mem:QI (pre_inc:QI (reg:QI 20)))        (match_operand:QI 0 "reg_operand" "r"))]  ""  "push\\t%0"  [(set_attr "type" "push")])(define_insn "*popqi"  [(set (match_operand:QI 0 "reg_operand" "=r")        (mem:QI (post_dec:QI (reg:QI 20))))   (clobber (reg:CC 21))]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -