📄 clipper.md
字号:
;;- Machine description for GNU compiler, Clipper Version;; Copyright (C) 1987, 88, 91, 93, 94, 1997 Free Software Foundation, Inc.;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de);; This file is part of GNU CC.;; GNU CC is free software; you can redistribute it and/or modify;; it under the terms of the GNU General Public License as published by;; the Free Software Foundation; either version 2, or (at your option);; any later version.;; GNU CC is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License;; along with GNU CC; see the file COPYING. If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;;- Instruction patterns. When multiple patterns apply,;;- the first one in the file is chosen.;;-;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.;;-;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code;;- updates for most instructions.;;;; define attributes;;;; instruction type;;;; unknown is temporary in order to generate 'cc clobber' until attribute;; assignment is consistent;;(define_attr "type" "load,store,arith,fp,branch,unknown" (const_string "unknown"));; condition code setting;;;; clobber destroyed;; unchanged;; set1 set cc_status.value1, e.g. sub r0,r1;; set2 set value1 and value2, e.g. mov r0,r1;; change0 may be side effect, i.e. load mem,r0;;;; note: loadi and loadq are 'arith' instructions that set the condition codes;; mul,div,mod do NOT set the condition codes;;(define_attr "cc" "clobber,unchanged,set1,set2,change0" (cond [(eq_attr "type" "load") (const_string "change0") (eq_attr "type" "store,branch") (const_string "unchanged") (eq_attr "type" "arith") (if_then_else (match_operand:SI 0 "" "") (const_string "set1") (const_string "clobber")) ] (const_string "clobber")));;;; clipper seems to be a traditional risc processor;; we define a functional unit 'memory';;(define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0) ;; We don't want to allow a constant operand for test insns because;; (set (cc0) (const_int foo)) has no mode information. Such insns will;; be folded while optimizing anyway.(define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "int_reg_operand" "r"))] "" "cmpq $0,%0")(define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "r,r,n") (match_operand:SI 1 "nonmemory_operand" "r,n,r")))] "" "*{ int val; if (which_alternative == 0) return \"cmpw %1,%0\"; if (which_alternative == 1) { val = INTVAL (operands[1]); if (0 <= val && val < 16) return \"cmpq %1,%0\"; return \"cmpi %1,%0\"; } cc_status.flags |= CC_REVERSED; /* immediate must be first */ val = INTVAL (operands[0]); if (0 <= val && val < 16) return \"cmpq %0,%1\"; return \"cmpi %0,%1\";}")(define_insn "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "fp_reg_operand" "f") (match_operand:DF 1 "fp_reg_operand" "f")))] "" "cmpd %1,%0")(define_insn "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "fp_reg_operand" "f") (match_operand:SF 1 "fp_reg_operand" "f")))] "" "cmps %1,%0");;;; double and single float move;;(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_DOUBLE) operands[1] = force_reg (DFmode, force_const_mem (DFmode, operands[1])); else if (GET_CODE (operands[1]) != REG) operands[1] = force_reg (DFmode, operands[1]); } else if (GET_CODE (operands[1]) == CONST_DOUBLE) operands[1] = force_const_mem (DFmode, operands[1]);}");;;; provide two patterns with different predicates as we don't want combine;; to recombine a mem -> mem move;; (define_insn "" [(set (match_operand:DF 0 "register_operand" "=*rf") (match_operand:DF 1 "nonimmediate_operand" "*rfo"))] "" "*{#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16) if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) /* f -> f */ return \"movd %1,%0\"; if (GET_CODE (operands[1]) == REG) /* r -> f */ return \"movld %1,%0\"; return \"loadd %1,%0\"; /* m -> f */ } if (FP_REG_P (operands[1])) { if (GET_CODE (operands[0]) == REG) /* f -> r */ return \"movdl %1,%0\"; abort (); } if (GET_CODE (operands[1]) == MEM) /* m -> r */ { rtx xops[4]; xops[0] = operands[0]; xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); xops[2] = operands[1]; xops[3] = adj_offsettable_operand (operands[1], 4); output_asm_insn (\"loadw %2,%0\;loadw %3,%1\", xops); return \"\"; } if (GET_CODE (operands[1]) == REG) /* r -> r */ { rtx xops[4]; xops[0] = operands[0]; xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); xops[2] = operands[1]; xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"movw %2,%0\;movw %3,%1\", xops); return \"\"; } abort ();#undef FP_REG_P}")(define_insn "" [(set (match_operand:DF 0 "memory_operand" "=o,m") (match_operand:DF 1 "register_operand" "*rf,f"))] "" "*{ rtx xops[4]; if (REGNO (operands[1]) >= 16) /* f -> m */ return \"stord %1,%0\"; xops[0] = operands[0]; /* r -> o */ xops[1] = adj_offsettable_operand (operands[0], 4); xops[2] = operands[1]; xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops); return \"\";}"[(set_attr "type" "store,store") (set_attr "cc" "clobber,unchanged")])(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_DOUBLE) operands[1] = force_reg (SFmode, force_const_mem (SFmode, operands[1])); else if (GET_CODE (operands[1]) != REG) operands[1] = force_reg (SFmode, operands[1]); } else if (GET_CODE (operands[1]) == CONST_DOUBLE) operands[1] = force_const_mem (SFmode, operands[1]);}");;;; provide two patterns with different predicates as we don't want combine;; to recombine a mem -> mem move;; (define_insn "" [(set (match_operand:SF 0 "register_operand" "=*rf") (match_operand:SF 1 "nonimmediate_operand" "*rfm"))] "" "*{#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16) if (FP_REG_P (operands[0])) { if (FP_REG_P (operands[1])) /* f -> f */ return \"movs %1,%0\"; if (GET_CODE (operands[1]) == REG) /* r -> f */ return \"subq $8,sp\;storw %1,(sp)\;loads (sp),%0\;addq $8,sp\"; return \"loads %1,%0\"; /* m -> f */ } if (FP_REG_P (operands[1])) { if (GET_CODE (operands[0]) == REG) /* f -> r */ return \"subq $8,sp\;stors %1,(sp)\;loadw (sp),%0\;addq $8,sp\"; abort (); } if (GET_CODE (operands[1]) == MEM) /* m -> r */ return \"loadw %1,%0\"; if (GET_CODE (operands[1]) == REG) /* r -> r */ return \"movw %1,%0\"; abort ();#undef FP_REG_P}")(define_insn "" [(set (match_operand:SF 0 "memory_operand" "=m") (match_operand:SF 1 "register_operand" "*rf"))] "" "*{ if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= 16) return \"stors %1,%0\"; /* f-> m */ return \"storw %1,%0\"; /* r -> m */}"[(set_attr "type" "store")])(define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG) operands[1] = force_reg (DImode, operands[1]);}");; If an operand is a MEM but not offsettable, we can't load it into;; a register, so we must force the third alternative to be the one;; reloaded. Hence we show the first as more expensive.(define_insn "" [(set (match_operand:DI 0 "register_operand" "=?r,r,r") (match_operand:DI 1 "general_operand" "r,n,o"))] "" "*{ rtx xoperands[2],yoperands[2]; xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); if (which_alternative == 0) /* r -> r */ { output_asm_insn (\"movw %1,%0\", operands); xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"movw %1,%0\", xoperands); return \"\"; } if (which_alternative == 1) /* n -> r */ { if (GET_CODE (operands[1]) == CONST_INT) { output_asm_insn (\"loadi %1,%0\", operands); output_asm_insn (\"loadq $0,%0\", xoperands); return \"\"; } if (GET_CODE (operands[1]) != CONST_DOUBLE) abort (); yoperands[0] = operands[0]; yoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1])); output_asm_insn (\"loadi %1,%0\", yoperands); xoperands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])); output_asm_insn (\"loadi %1,%0\", xoperands); return \"\"; } /* m -> r */ output_asm_insn (\"loadw %1,%0\", operands); xoperands[1] = adj_offsettable_operand (operands[1], 4); output_asm_insn (\"loadw %1,%0\", xoperands); return \"\";}" [(set_attr "type" "arith,arith,load") (set_attr "cc" "clobber,clobber,clobber")])(define_insn "" [(set (match_operand:DI 0 "memory_operand" "=o") (match_operand:DI 1 "register_operand" "r"))] "" "*{ rtx xops[4]; xops[0] = operands[0]; xops[1] = adj_offsettable_operand (operands[0], 4); xops[2] = operands[1]; xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops); return \"\";}"[(set_attr "type" "store") (set_attr "cc" "clobber")])(define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG) operands[1] = force_reg (SImode, operands[1]);}");; Reject both args with `general_operand' if not reloading because a;; mem -> mem move that was split by 'movsi' can be recombined to;; mem -> mem by the combiner.;;;; As a pseudo register can end up in a stack slot during reloading we must;; allow a r->m move for the next pattern. ;; The first predicate must be `general_operand' because a predicate must;; be true for each constraint.;; (define_insn "" [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m") (match_operand:SI 1 "general_operand" "r,m,n,i,r"))] "reload_in_progress || register_operand (operands[0], SImode)" "*{ int val; if (which_alternative == 0) return \"movw %1,%0\"; /* reg -> reg */ if (which_alternative == 1) return \"loadw %1,%0\"; /* mem -> reg */ if (which_alternative == 2) { val = INTVAL (operands[1]); /* known const ->reg */ if (val == -1) return \"notq $0,%0\"; if (val < 0 || val >= 16) return \"loadi %1,%0\"; return \"loadq %1,%0\"; } if (which_alternative == 3) /* unknown const */ return \"loada %a1,%0\"; return \"storw %1,%0\";}"[(set_attr "type" "arith,load,arith,load,store") (set_attr "cc" "set2,change0,set1,change0,unchanged")])(define_insn "" [(set (match_operand:SI 0 "memory_operand" "=m") (match_operand:SI 1 "int_reg_operand" "r"))] "" "storw %1,%0"[(set_attr "type" "store")]);; movhi;;;; loadh mem to reg;; storh reg to mem;;;;(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ if (GET_CODE (operands[0]) == MEM && ! register_operand (operands[1], HImode)) operands[1] = force_reg (HImode, operands[1]);}")(define_insn "" [(set (match_operand:HI 0 "register_operand" "=r,r,r") (match_operand:HI 1 "general_operand" "r,m,n"))] "" "@ movw %1,%0 loadh %1,%0 loadi %1,%0"[(set_attr "type" "arith,load,arith")])(define_insn "" [(set (match_operand:HI 0 "memory_operand" "=m") (match_operand:HI 1 "register_operand" "r"))] "" "storh %1,%0" [(set_attr "type" "store")]);; movqi
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -