📄 mmix.md
字号:
;; GCC machine description for MMIX;; Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.;; Contributed by Hans-Peter Nilsson (hp@bitrange.com);; This file is part of GCC.;; GCC 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.;; GCC 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 GCC; see the file COPYING. If not, write to;; the Free Software Foundation, 59 Temple Place - Suite 330,;; Boston, MA 02111-1307, USA.;; The original PO technology requires these to be ordered by speed,;; so that assigner will pick the fastest.;; See file "rtl.def" for documentation on define_insn, match_*, et al.;; Uses of UNSPEC in this file:;; UNSPEC_VOLATILE:;;;; 0 sync_icache (sync icache before trampoline jump);; 1 nonlocal_goto_receiver;;;; The order of insns is as in Node: Standard Names, with smaller modes;; before bigger modes.(define_constants [(MMIX_rJ_REGNUM 259) (MMIX_rR_REGNUM 260) (MMIX_fp_rO_OFFSET -24)]);; FIXME: Can we remove the reg-to-reg for smaller modes? Shouldn't they;; be synthesized ok?(define_insn "movqi" [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r ,r,x ,r,r,m,??r") (match_operand:QI 1 "general_operand" "r,LS,K,rI,x,m,r,n"))] "" "@ SET %0,%1 %s1 %0,%v1 NEGU %0,0,%n1 PUT %0,%1 GET %0,%1 LDB%U0 %0,%1 STBU %1,%0 %r0%I1")(define_insn "movhi" [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r ,r ,x,r,r,m,??r") (match_operand:HI 1 "general_operand" "r,LS,K,r,x,m,r,n"))] "" "@ SET %0,%1 %s1 %0,%v1 NEGU %0,0,%n1 PUT %0,%1 GET %0,%1 LDW%U0 %0,%1 STWU %1,%0 %r0%I1");; gcc.c-torture/compile/920428-2.c fails if there's no "n".(define_insn "movsi" [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r ,r,x,r,r,m,??r") (match_operand:SI 1 "general_operand" "r,LS,K,r,x,m,r,n"))] "" "@ SET %0,%1 %s1 %0,%v1 NEGU %0,0,%n1 PUT %0,%1 GET %0,%1 LDT%U0 %0,%1 STTU %1,%0 %r0%I1");; We assume all "s" are addresses. Does that hold?(define_insn "movdi" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r ,r,x,r,m,r,m,r,r,??r") (match_operand:DI 1 "general_operand" "r,LS,K,r,x,I,m,r,R,s,n"))] "" "@ SET %0,%1 %s1 %0,%v1 NEGU %0,0,%n1 PUT %0,%1 GET %0,%1 STCO %1,%0 LDO %0,%1 STOU %1,%0 GETA %0,%1 LDA %0,%1 %r0%I1");; Note that we move around the float as a collection of bits; no;; conversion to double.(define_insn "movsf" [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r") (match_operand:SF 1 "general_operand" "r,G,r,x,m,r,F"))] "" "@ SET %0,%1 SETL %0,0 PUT %0,%1 GET %0,%1 LDT %0,%1 STTU %1,%0 %r0%I1")(define_insn "movdf" [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,x,r,r,m,??r") (match_operand:DF 1 "general_operand" "r,G,r,x,m,r,F"))] "" "@ SET %0,%1 SETL %0,0 PUT %0,%1 GET %0,%1 LDO %0,%1 STOU %1,%0 %r0%I1")(define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r") (plus:DI (match_operand:DI 1 "register_operand" "%r,r,0") (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,K,LS")))] "" "@ ADDU %0,%1,%2 SUBU %0,%1,%n2 %i2 %0,%v2")(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=r") (plus:DF (match_operand:DF 1 "register_operand" "%r") (match_operand:DF 2 "register_operand" "r")))] "" "FADD %0,%1,%2");; Insn canonicalization *should* have removed the need for an integer;; in operand 2.(define_insn "subdi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (minus:DI (match_operand:DI 1 "mmix_reg_or_8bit_operand" "r,I") (match_operand:DI 2 "register_operand" "r,r")))] "" "@ SUBU %0,%1,%2 NEGU %0,%1,%2")(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=r") (minus:DF (match_operand:DF 1 "register_operand" "r") (match_operand:DF 2 "register_operand" "r")))] "" "FSUB %0,%1,%2");; FIXME: Should we define_expand and match 2, 4, 8 (etc) with shift (or;; %{something}2ADDU %0,%1,0)? Hopefully GCC should still handle it, so;; we don't have to taint the machine description. If results are bad;; enough, we may have to do it anyway.(define_insn "muldi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (mult:DI (match_operand:DI 1 "register_operand" "%r,r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "O,rI"))) (clobber (match_scratch:DI 3 "=X,z"))] "" "@ %m2ADDU %0,%1,%1 MULU %0,%1,%2")(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=r") (mult:DF (match_operand:DF 1 "register_operand" "r") (match_operand:DF 2 "register_operand" "r")))] "" "FMUL %0,%1,%2")(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=r") (div:DF (match_operand:DF 1 "register_operand" "r") (match_operand:DF 2 "register_operand" "r")))] "" "FDIV %0,%1,%2");; FIXME: Is "frem" doing the right operation for moddf3?(define_insn "moddf3" [(set (match_operand:DF 0 "register_operand" "=r") (mod:DF (match_operand:DF 1 "register_operand" "r") (match_operand:DF 2 "register_operand" "r")))] "" "FREM %0,%1,%2");; FIXME: Should we define_expand for smin, smax, umin, umax using a;; nifty conditional sequence?;; FIXME: The cuter andn combinations don't get here, presumably because;; they ended up in the constant pool. Check: still?(define_insn "anddi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (and:DI (match_operand:DI 1 "register_operand" "%r,0") (match_operand:DI 2 "mmix_reg_or_constant_operand" "rI,NT")))] "" "@ AND %0,%1,%2 %A2 %0,%V2")(define_insn "iordi3" [(set (match_operand:DI 0 "register_operand" "=r,r") (ior:DI (match_operand:DI 1 "register_operand" "%r,0") (match_operand:DI 2 "mmix_reg_or_constant_operand" "rH,LS")))] "" "@ OR %0,%1,%2 %o2 %0,%v2")(define_insn "xordi3" [(set (match_operand:DI 0 "register_operand" "=r") (xor:DI (match_operand:DI 1 "register_operand" "%r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] "" "XOR %0,%1,%2");; FIXME: When TImode works for other reasons (like cross-compiling from;; a 32-bit host), add back umulditi3 and umuldi3_highpart here.;; FIXME: Check what's really reasonable for the mod part.;; One day we might persuade GCC to expand divisions with constants the;; way MMIX does; giving the remainder the sign of the divisor. But even;; then, it might be good to have an option to divide the way "everybody;; else" does. Perhaps then, this option can be on by default. However,;; it's not likely to happen because major (C, C++, Fortran) language;; standards in effect at 2002-04-29 reportedly demand that the sign of;; the remainder must follow the sign of the dividend.(define_insn "divmoddi4" [(set (match_operand:DI 0 "register_operand" "=r") (div:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))) (set (match_operand:DI 3 "register_operand" "=y") (mod:DI (match_dup 1) (match_dup 2)))] ;; Do the library stuff later. "TARGET_KNUTH_DIVISION" "DIV %0,%1,%2")(define_insn "udivmoddi4" [(set (match_operand:DI 0 "register_operand" "=r") (udiv:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI"))) (set (match_operand:DI 3 "register_operand" "=y") (umod:DI (match_dup 1) (match_dup 2)))] "" "DIVU %0,%1,%2")(define_expand "divdi3" [(parallel [(set (match_operand:DI 0 "register_operand" "=&r") (div:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r"))) (clobber (scratch:DI)) (clobber (scratch:DI)) (clobber (reg:DI MMIX_rR_REGNUM))])] "! TARGET_KNUTH_DIVISION" "");; The %2-is-%1-case is there just to make sure things don't fail. Could;; presumably happen with optimizations off; no evidence.(define_insn "*divdi3_nonknuth" [(set (match_operand:DI 0 "register_operand" "=&r,r") (div:DI (match_operand:DI 1 "register_operand" "r,r") (match_operand:DI 2 "register_operand" "1,r"))) (clobber (match_scratch:DI 3 "=1,1")) (clobber (match_scratch:DI 4 "=2,2")) (clobber (reg:DI MMIX_rR_REGNUM))] "! TARGET_KNUTH_DIVISION" "@ SETL %0,1 XOR $255,%1,%2\;NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU %0,0,%1\;CSN %1,%1,%0\;\DIVU %0,%1,%2\;NEGU %1,0,%0\;CSN %0,$255,%1")(define_expand "moddi3" [(parallel [(set (match_operand:DI 0 "register_operand" "=&r") (mod:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r"))) (clobber (scratch:DI)) (clobber (scratch:DI)) (clobber (reg:DI MMIX_rR_REGNUM))])] "! TARGET_KNUTH_DIVISION" "");; The %2-is-%1-case is there just to make sure things don't fail. Could;; presumably happen with optimizations off; no evidence.(define_insn "*moddi3_nonknuth" [(set (match_operand:DI 0 "register_operand" "=&r,r") (mod:DI (match_operand:DI 1 "register_operand" "r,r") (match_operand:DI 2 "register_operand" "1,r"))) (clobber (match_scratch:DI 3 "=1,1")) (clobber (match_scratch:DI 4 "=2,2")) (clobber (reg:DI MMIX_rR_REGNUM))] "! TARGET_KNUTH_DIVISION" "@ SETL %0,0 NEGU %0,0,%2\;CSN %2,%2,%0\;NEGU $255,0,%1\;CSN %1,%1,$255\;\DIVU %1,%1,%2\;GET %0,:rR\;NEGU %2,0,%0\;CSNN %0,$255,%2")(define_insn "ashldi3" [(set (match_operand:DI 0 "register_operand" "=r") (ashift:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] "" "SLU %0,%1,%2")(define_insn "ashrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] "" "SR %0,%1,%2")(define_insn "lshrdi3" [(set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "mmix_reg_or_8bit_operand" "rI")))] "" "SRU %0,%1,%2")(define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=r") (neg:DI (match_operand:DI 1 "register_operand" "r")))] "" "NEGU %0,0,%1")(define_expand "negdf2" [(parallel [(set (match_operand:DF 0 "register_operand" "=r") (neg:DF (match_operand:DF 1 "register_operand" "r"))) (use (match_dup 2))])] ""{ /* Emit bit-flipping sequence to be IEEE-safe wrt. -+0. */ operands[2] = force_reg (DImode, GEN_INT ((HOST_WIDE_INT) 1 << 63));})(define_insn "*expanded_negdf2" [(set (match_operand:DF 0 "register_operand" "=r") (neg:DF (match_operand:DF 1 "register_operand" "r"))) (use (match_operand:DI 2 "register_operand" "r"))] "" "XOR %0,%1,%2");; FIXME: define_expand for absdi2?(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=r") (abs:DF (match_operand:DF 1 "register_operand" "0")))] "" "ANDNH %0,#8000")(define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=r") (sqrt:DF (match_operand:DF 1 "register_operand" "r")))] "" "FSQRT %0,%1");; FIXME: define_expand for ffssi2? (not ffsdi2 since int is SImode).(define_insn "one_cmpldi2" [(set (match_operand:DI 0 "register_operand" "=r") (not:DI (match_operand:DI 1 "register_operand" "r")))] "" "NOR %0,%1,0");; Since we don't have cc0, we do what is recommended in the manual;;; store away the operands for use in the branch, scc or movcc insn.(define_expand "cmpdi" [(match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "mmix_reg_or_8bit_operand" "")] "" "{ mmix_compare_op0 = operands[0]; mmix_compare_op1 = operands[1]; DONE;}")(define_expand "cmpdf" [(match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" "")] "" "{ mmix_compare_op0 = operands[0]; mmix_compare_op1 = operands[1]; DONE;}");; When the user-patterns expand, the resulting insns will match the;; patterns below.;; We can fold the signed-compare where the register value is;; already equal to (compare:CCTYPE (reg) (const_int 0)).;; We can't do that at all for floating-point, due to NaN, +0.0;; and -0.0, and we can only do it for the non/zero test of;; unsigned, so that has to be done another way.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -