📄 i860.md
字号:
;;- Machine description for Intel 860 chip for GNU C compiler;; Copyright (C) 1989, 1990, 1997 Free Software Foundation, Inc.;; 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.;;- 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.;;- Operand classes for the register allocator:/* Bit-test instructions. */(define_insn "" [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "logic_operand" "rL")) (const_int 0)))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"and %1,%0,%?r0\";}")(define_insn "" [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "logic_operand" "rL")) (const_int 0)))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"and %1,%0,%?r0\";}")(define_insn "" [(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "immediate_operand" "i")) (const_int 0)))] "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0" "*{ CC_STATUS_PARTIAL_INIT; return \"andh %H1,%0,%?r0\";}")(define_insn "" [(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "immediate_operand" "i")) (const_int 0)))] "GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"andh %H1,%0,%?r0\";}")(define_insn "" [(set (cc0) (eq (ashiftrt:SI (sign_extend:SI (ashift:QI (match_operand:QI 0 "register_operand" "r") (match_operand:QI 1 "logic_int" "n"))) (match_operand:SI 2 "logic_int" "n")) (const_int 0)))] "" "*{ int width = 8 - INTVAL (operands[2]); int pos = 8 - width - INTVAL (operands[1]); CC_STATUS_PARTIAL_INIT; operands[2] = GEN_INT (~((-1) << width) << pos); return \"and %2,%0,%?r0\";}");; -------------------------------------------------------------------------;; SImode signed integer comparisons;; -------------------------------------------------------------------------(define_insn "cmpeqsi" [(set (cc0) (eq (match_operand:SI 0 "logic_operand" "r,rL") (match_operand:SI 1 "logic_operand" "L,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; if (REG_P (operands[0])) return \"xor %1,%0,%?r0\"; else return \"xor %0,%1,%?r0\";}")(define_insn "cmpnesi" [(set (cc0) (ne (match_operand:SI 0 "logic_operand" "r,rL") (match_operand:SI 1 "logic_operand" "L,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; if (REG_P (operands[0])) return \"xor %1,%0,%?r0\"; else return \"xor %0,%1,%?r0\";}")(define_insn "cmpltsi" [(set (cc0) (lt (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; if (REG_P (operands[1])) return \"subs %0,%1,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[1] = GEN_INT (- INTVAL (operands[1])); return \"adds %1,%0,%?r0\"; }}")(define_insn "cmpgtsi" [(set (cc0) (gt (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; if (REG_P (operands[0])) return \"subs %1,%0,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[0] = GEN_INT (- INTVAL (operands[0])); return \"adds %0,%1,%?r0\"; }}")(define_insn "cmplesi" [(set (cc0) (le (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; if (REG_P (operands[0])) return \"subs %1,%0,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[0] = GEN_INT (- INTVAL (operands[0])); return \"adds %0,%1,%?r0\"; }}")(define_insn "cmpgesi" [(set (cc0) (ge (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; if (REG_P (operands[1])) return \"subs %0,%1,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[1] = GEN_INT (- INTVAL (operands[1])); return \"adds %1,%0,%?r0\"; }}");; -------------------------------------------------------------------------;; SImode unsigned integer comparisons;; -------------------------------------------------------------------------;; WARNING! There is a small i860 hardware limitation (bug?) which we;; may run up against (if we are not careful) when we are trying to do;; unsigned comparisons like (x >= 0), (x < 0), (0 <= x), and (0 > x).;; Specifically, we must avoid using an `addu' instruction to perform;; such comparisons because the result (in the CC bit register) will;; come out wrong. (This fact is documented in a footnote on page 7-10;; of the 1991 version of the i860 Microprocessor Family Programmer's;; Reference Manual). Note that unsigned comparisons of this sort are;; always redundant anyway, because an unsigned quantity can never be;; less than zero. When we see cases like this, we generate an;; `or K,%r0,%r0' instruction instead (where K is a constant 0 or -1);; so as to get the CC bit register set properly for any subsequent;; conditional jump instruction.(define_insn "cmpgeusi" [(set (cc0) (geu (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; if (REG_P (operands[1])) return \"subu %0,%1,%?r0\"; else { if (INTVAL (operands[1]) == 0) return \"or 0,%?r0,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[1] = GEN_INT (- INTVAL (operands[1])); return \"addu %1,%0,%?r0\"; } }}")(define_insn "cmpleusi" [(set (cc0) (leu (match_operand:SI 0 "arith_operand" "r,rI") (match_operand:SI 1 "arith_operand" "I,r")))] "" "*{ CC_STATUS_PARTIAL_INIT; if (REG_P (operands[0])) return \"subu %1,%0,%?r0\"; else { if (INTVAL (operands[0]) == 0) return \"or 0,%?r0,%?r0\"; else { cc_status.flags |= CC_REVERSED; operands[0] = GEN_INT (- INTVAL (operands[0])); return \"addu %0,%1,%?r0\"; } }}");; -------------------------------------------------------------------------;; SFmode floating-point comparisons;; -------------------------------------------------------------------------(define_insn "cmpeqsf" [(set (cc0) (eq (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfeq.ss %r0,%r1,%?f0\";}")(define_insn "cmpnesf" [(set (cc0) (ne (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfeq.ss %r1,%r0,%?f0\";}");; NOTE: The i860 Programmer's Reference Manual says that when we are;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these;; in order to be IEEE compliant (in case a trap occurs during these;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we;; must use pfle to be IEEE compliant.(define_insn "cmpltsf" [(set (cc0) (lt (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfgt.ss %r1,%r0,%?f0\";}")(define_insn "cmpgtsf" [(set (cc0) (gt (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfgt.ss %r0,%r1,%?f0\";}");; NOTE: The pfle opcode doesn't do what you think it does. It is;; bass-ackwards. It *clears* the CC flag if the first operand is;; less than or equal to the second. Thus, we have to set CC_NEGATED;; for the following two patterns.(define_insn "cmplesf" [(set (cc0) (le (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfle.ss %r0,%r1,%?f0\";}")(define_insn "cmpgesf" [(set (cc0) (ge (match_operand:SF 0 "reg_or_0_operand" "fG") (match_operand:SF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfle.ss %r1,%r0,%?f0\";}");; -------------------------------------------------------------------------;; DFmode floating-point comparisons;; -------------------------------------------------------------------------(define_insn "cmpeqdf" [(set (cc0) (eq (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfeq.dd %r0,%r1,%?f0\";}")(define_insn "cmpnedf" [(set (cc0) (ne (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfeq.dd %r1,%r0,%?f0\";}");; NOTE: The i860 Programmer's Reference Manual says that when we are;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these;; in order to be IEEE compliant (in case a trap occurs during these;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we;; must use pfle to be IEEE compliant.(define_insn "cmpltdf" [(set (cc0) (lt (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfgt.dd %r1,%r0,%?f0\";}")(define_insn "cmpgtdf" [(set (cc0) (gt (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; return \"pfgt.dd %r0,%r1,%?f0\";}");; NOTE: The pfle opcode doesn't do what you think it does. It is;; bass-ackwards. It *clears* the CC flag if the first operand is;; less than or equal to the second. Thus, we have to set CC_NEGATED;; for the following two patterns.(define_insn "cmpledf" [(set (cc0) (le (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfle.dd %r0,%r1,%?f0\";}")(define_insn "cmpgedf" [(set (cc0) (ge (match_operand:DF 0 "reg_or_0_operand" "fG") (match_operand:DF 1 "reg_or_0_operand" "fG")))] "" "*{ CC_STATUS_PARTIAL_INIT; cc_status.flags |= CC_NEGATED; return \"pfle.dd %r1,%r0,%?f0\";}");; ------------------------------------------------------------------------;; Integer EQ/NE comparisons against constant values which will fit in the;; 16-bit immediate field of an instruction. These are made by combining.;; ------------------------------------------------------------------------(define_insn "" [(set (cc0) (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m")) (match_operand:SI 1 "small_int" "I")))] "INTVAL (operands[1]) >= 0" "*{ CC_STATUS_PARTIAL_INIT; return \"ld.s %0,%?r31\;xor %1,%?r31,%?r0\";}")(define_insn "" [(set (cc0) (eq (match_operand:SI 0 "small_int" "I") (zero_extend:SI (match_operand:HI 1 "load_operand" "m"))))] "INTVAL (operands[0]) >= 0" "*{ CC_STATUS_PARTIAL_INIT; return \"ld.s %1,%?r31\;xor %0,%?r31,%?r0\";}");; ------------------------------------------------------------------------;; Define the real conditional branch instructions.;; ------------------------------------------------------------------------(define_insn "cbranch" [(set (pc) (if_then_else (eq (cc0) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "*{ if ((cc_prev_status.flags & CC_NEGATED) == 0) return \"bnc %l0\"; else return \"bc %l0\";}")(define_insn "flipped_cbranch" [(set (pc) (if_then_else (ne (cc0) (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "" "*{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -