📄 a29k.md
字号:
;;- Machine description for AMD Am29000 for GNU C compiler;; Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu);; 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.;; The insns in this file are presented in the same order as the AMD 29000;; User's Manual (i.e., alphabetical by machine op-code).;;;; DEFINE_EXPAND's are located near the first occurrence of the major insn;; that they generate.;; The only attribute we have is the type. We only care about calls, branches,;; loads, stores, floating-point operations, and multi-word insns.;; Everything else is miscellaneous.(define_attr "type" "call,branch,load,store,fadd,fmul,fam,fdiv,fsqrt,dmul,dam,ddiv,dsqrt,multi,misc" (const_string "misc"));; ASM insns cannot go into a delay slot, so call them "multi".(define_asm_attributes [(set_attr "type" "multi")])(define_attr "in_delay_slot" "yes,no" (if_then_else (eq_attr "type" "call,branch,multi") (const_string "no") (const_string "yes")));; Branch and call insns require a single delay slot. Annulling is not;; supported.(define_delay (eq_attr "type" "call,branch") [(eq_attr "in_delay_slot" "yes") (nil) (nil)]);; Define the function unit usages. We first define memory as a unit.(define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 5 [(eq_attr "type" "load")])(define_function_unit "memory" 1 0 (eq_attr "type" "load") 6 6 [(eq_attr "type" "store")])(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0);; Now define the function units for the floating-point support. Most;; units are pipelined and can accept an input every cycle.;;;; Note that we have an inaccuracy here. If a fmac insn is issued, followed;; 2 cycles later by a fadd, there will be a conflict for the floating;; adder that we can't represent. Also, all insns will conflict for the;; floating-point rounder. It isn't clear how to represent this.(define_function_unit "multiplier" 1 0 (eq_attr "type" "fmul") 3 0)(define_function_unit "multiplier" 1 0 (eq_attr "type" "dmul") 6 4)(define_function_unit "multiplier" 1 0 (eq_attr "type" "fam") 6 0)(define_function_unit "multiplier" 1 0 (eq_attr "type" "dam") 9 4)(define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0)(define_function_unit "divider" 1 0 (eq_attr "type" "fdiv") 11 10)(define_function_unit "divider" 1 0 (eq_attr "type" "fsqrt") 28 27)(define_function_unit "divider" 1 0 (eq_attr "type" "ddiv") 18 17)(define_function_unit "divider" 1 0 (eq_attr "type" "dsqrt") 57 56);; ADD(define_insn "addsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") (match_operand:SI 2 "add_operand" "rI,N")))] "" "@ add %0,%1,%2 sub %0,%1,%n2")(define_insn "adddi3" [(set (match_operand:DI 0 "gpc_reg_operand" "=r") (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r") (match_operand:DI 2 "gpc_reg_operand" "r")))] "" "add %L0,%L1,%L2\;addc %0,%1,%2" [(set_attr "type" "multi")]);; AND/ANDN(define_insn "andsi3" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r") (match_operand:SI 2 "and_operand" "rI,K")))] "" "@ and %0,%1,%2 andn %0,%1,%C2")(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")) (match_operand:SI 2 "cmplsrcb_operand" "r,K")))] "" "@ andn %0,%2,%1 nor %0,%1,%C2");; CALLI;;;; Each call pattern is duplicated so that we can add CLOBBERs to the;; resulting insn.;;;; We indicate that LR0 is clobbered in the CALL_INSN itself. Otherwise,;; reorg will think it is just clobbered by the called function.(define_expand "call" [(use (match_operand:SI 0 "" "")) (use (match_operand 1 "" "")) (use (match_operand 2 "" ""))] "" "{ rtx insn = emit_call_insn (gen_call_internal (operands[0], operands[1])); a29k_clobbers_to (insn, operands[2]); DONE;}") (define_expand "call_internal" [(parallel [(call (match_operand:SI 0 "" "") (match_operand 1 "" "")) (clobber (scratch:SI))])] "" "{ if (GET_CODE (operands[0]) != MEM) abort (); /* We tell here whether this is a recursive call, since this insn may later be inlined into another function. */ if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) operands[0] = gen_rtx (MEM, SImode, force_reg (Pmode, XEXP (operands[0], 0)));}") (define_expand "call_value" [(use (match_operand:SI 0 "gpc_reg_operand" "")) (use (match_operand:SI 1 "" "")) (use (match_operand 2 "" "")) (use (match_operand 3 "" ""))] "" "{ rtx insn = emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2])); a29k_clobbers_to (insn, operands[3]); DONE;}") (define_expand "call_value_internal" [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") (call (match_operand:SI 1 "" "") (match_operand 2 "" ""))) (clobber (scratch:SI))])] "" "{ if (GET_CODE (operands[1]) != MEM) abort (); /* We tell here whether this is a recursive call, since this insn may later be inlined into another function. */ if (! TARGET_SMALL_MEMORY && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) operands[1] = gen_rtx (MEM, SImode, force_reg (Pmode, XEXP (operands[1], 0)));}") (define_insn "" [(call (match_operand:SI 0 "memory_operand" "m") (match_operand 1 "" "")) (clobber (match_scratch:SI 2 "=&l"))] "GET_CODE (XEXP (operands[0], 0)) != CONST_INT" "calli lr0,%0%#" [(set_attr "type" "call")])(define_insn "" [(call (mem:SI (match_operand:SI 0 "call_operand" "i")) (match_operand:SI 1 "general_operand" "g")) (clobber (match_scratch:SI 2 "=&l"))] "" "call lr0,%F0" [(set_attr "type" "call")])(define_insn "" [(set (match_operand 0 "gpc_reg_operand" "=r") (call (match_operand:SI 1 "memory_operand" "m") (match_operand 2 "" ""))) (clobber (match_scratch:SI 3 "=&l"))] "GET_CODE (XEXP (operands[1], 0)) != CONST_INT" "calli lr0,%1%#" [(set_attr "type" "call")])(define_insn "" [(set (match_operand 0 "gpc_reg_operand" "=r") (call (mem:SI (match_operand:SI 1 "call_operand" "i")) (match_operand:SI 2 "general_operand" "g"))) (clobber (match_scratch:SI 3 "=&l"))] "" "call lr0,%F1" [(set_attr "type" "call")])(define_expand "probe" [(call (mem:SI (symbol_ref:SI "_msp_check")) (const_int 1))] "TARGET_STACK_CHECK" "");; This is used for internal routine calls via TPC. Currently used only;; in probe, above.(define_insn "" [(call (mem:SI (match_operand:SI 0 "immediate_operand" "s")) (const_int 1))] "" "call %*,%0" [(set_attr "type" "call")]);; CONST, CONSTH, CONSTN;;;; Many of these are generated from move insns.(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (and:SI (match_operand:SI 1 "immediate_operand" "i") (const_int 65535)))] "" "const %0,%1")(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) (match_operand:SI 1 "const_0_operand" "")) (ashiftrt:SI (match_operand:SI 2 "immediate_operand" "i") (const_int 16)))] "" "consth %0,%2")(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r") (const_int 16) (match_operand:SI 1 "const_0_operand" "")) (match_operand:SI 2 "cint_16_operand" "J"))] "" "consth %0,%m2")(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) (match_operand:SI 2 "const_int_operand" "n")))] "(INTVAL (operands[2]) & 0xffff) == 0" "consth %0,%2")(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (ior:SI (zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")) (and:SI (match_operand:SI 2 "immediate_operand" "i") (const_int -65536))))] "" "consth %0,%2");; CONVERT(define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (fix:SI (match_operand:SF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,3,0,1")(define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (fix:SI (match_operand:DF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,3,0,2")(define_insn "fixuns_truncsfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,1,3,0,1")(define_insn "fixuns_truncdfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,1,3,0,2")(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=r") (float_truncate:SF (match_operand:DF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,4,1,2")(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=r") (float_extend:DF (match_operand:SF 1 "register_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,4,2,1")(define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=r") (float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,4,1,0")(define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=r") (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,0,4,2,0")(define_insn "floatunssisf2" [(set (match_operand:SF 0 "register_operand" "=r") (unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,1,4,1,0")(define_insn "floatunssidf2" [(set (match_operand:DF 0 "register_operand" "=r") (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))] "! TARGET_SOFT_FLOAT" "convert %0,%1,1,4,2,0");; CPxxx, DEQ, DGT, DGE, FEQ, FGT, FGE(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (match_operator 3 "comparison_operator" [(match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "srcb_operand" "rI")]))] "" "cp%J3 %0,%1,%2")(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (match_operator 3 "fp_comparison_operator" [(match_operand:SF 1 "register_operand" "r") (match_operand:SF 2 "register_operand" "r")]))] "! TARGET_SOFT_FLOAT" "f%J3 %0,%1,%2" [(set_attr "type" "fadd")])(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (match_operator 3 "fp_comparison_operator" [(match_operand:DF 1 "register_operand" "r") (match_operand:DF 2 "register_operand" "r")]))] "! TARGET_SOFT_FLOAT" "d%J3 %0,%1,%2" [(set_attr "type" "fadd")]);; DADD(define_expand "adddf3" [(set (match_operand:DF 0 "register_operand" "") (plus:DF (match_operand:DF 1 "register_operand" "") (match_operand:DF 2 "register_operand" "")))] "! TARGET_SOFT_FLOAT" "")(define_insn "" [(set (match_operand:DF 0 "register_operand" "=r") (plus:DF (match_operand:DF 1 "register_operand" "%r") (match_operand:DF 2 "register_operand" "r")))] "! TARGET_29050 " "dadd %0,%1,%2" [(set_attr "type" "fadd")])(define_insn "" [(set (match_operand:DF 0 "register_operand" "=r,a") (plus:DF (match_operand:DF 1 "register_operand" "%r,r") (match_operand:DF 2 "register_operand" "r,0")))] "TARGET_29050" "@ dadd %0,%1,%2 dmac 8,%0,%1,%1" [(set_attr "type" "fadd,dam")]);; DDIV(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")))] "! TARGET_SOFT_FLOAT" "ddiv %0,%1,%2" [(set_attr "type" "ddiv")]);; DIVIDE;;;; We must set Q to the sign extension of the dividend first. For MOD, we;; must get the remainder from Q.;;;; For divmod: operand 1 is divided by operand 2; quotient goes to operand;; 0 and remainder to operand 3.(define_expand "divmodsi4" [(set (match_dup 4) (ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "") (const_int 31))) (parallel [(set (match_operand:SI 0 "gpc_reg_operand" "") (div:SI (match_dup 1) (match_operand:SI 2 "gpc_reg_operand" ""))) (set (match_operand:SI 3 "gpc_reg_operand" "") (mod:SI (match_dup 1) (match_dup 2))) (use (match_dup 4))])] "" "{ operands[4] = gen_reg_rtx (SImode);}")(define_insn "" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (div:SI (match_operand:SI 1 "gpc_reg_operand" "r") (match_operand:SI 2 "gpc_reg_operand" "r"))) (set (match_operand:SI 3 "register_operand" "=q") (mod:SI (match_dup 1) (match_dup 2)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -