📄 alpha.md
字号:
;; Machine description for DEC Alpha for GNU C compiler;; Copyright (C) 1992, 93, 94, 95, 96, 1997 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.;; Processor type -- this attribute must exactly match the processor_type;; enumeration in alpha.h.(define_attr "cpu" "ev4,ev5,ev6" (const (symbol_ref "alpha_cpu")));; Define an insn type attribute. This is used in function unit delay;; computations, among other purposes. For the most part, we use the names;; defined in the EV4 documentation, but add a few that we have to know about;; separately.(define_attr "type" "ld,st,ibr,fbr,jsr,iadd,ilog,shift,cmov,icmp,imull,imulq,fadd,fmul,fcpys,fdivs,fdivt,ldsym,isubr" (const_string "iadd"));; The TRAP_TYPE attribute marks instructions that may generate traps;; (which are imprecise and may need a trapb if software completion;; is desired).(define_attr "trap" "yes,no" (const_string "no"));; For the EV4 we include four function units: ABOX, which computes the address,;; BBOX, used for branches, EBOX, used for integer operations, and FBOX,;; used for FP operations.;;;; We assume that we have been successful in getting double issues and;; hence multiply all costs by two insns per cycle. The minimum time in;; a function unit is 2 cycle, which will tend to produce the double;; issues.;; Memory delivers its result in three cycles.(define_function_unit "ev4_abox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "ld,st")) 6 2);; Branches have no delay cost, but do tie up the unit for two cycles.(define_function_unit "ev4_bbox" 1 1 (and (eq_attr "cpu" "ev4") (eq_attr "type" "ibr,fbr,jsr")) 4 4);; Arithmetic insns are normally have their results available after two;; cycles. There are a number of exceptions. They are encoded in;; ADJUST_COST. Some of the other insns have similar exceptions.(define_function_unit "ev4_ebox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "iadd,ilog,ldsym,shift,cmov,icmp")) 4 2);; These really don't take up the integer pipeline, but they do occupy;; IBOX1; we approximate here.(define_function_unit "ev4_ebox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "imull")) 42 2)(define_function_unit "ev4_ebox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "imulq")) 46 2)(define_function_unit "ev4_imult" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "imull")) 42 38)(define_function_unit "ev4_imult" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "imulq")) 46 42)(define_function_unit "ev4_fbox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "fadd,fmul,fcpys")) 12 2)(define_function_unit "ev4_fbox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "fdivs")) 68 0)(define_function_unit "ev4_fbox" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "fdivt")) 126 0)(define_function_unit "ev4_divider" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "fdivs")) 68 60)(define_function_unit "ev4_divider" 1 0 (and (eq_attr "cpu" "ev4") (eq_attr "type" "fdivt")) 126 118);; EV5 scheduling. EV5 can issue 4 insns per clock.;; Multiply all costs by 4. We consider the EV6 and EV5 for now.;; EV5 has two integer units.(define_function_unit "ev5_ebox" 2 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "iadd,ilog,icmp,ldsym")) 4 4);; Memory takes at least 2 clocks.;; Conditional moves always take 2 ticks.(define_function_unit "ev5_ebox" 2 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "ld,cmov")) 8 4);; Loads can dual issue. Store cannot; nor can loads + stores.;; Model this with a mythical load/store unit.(define_function_unit "ev5_ldst" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "ld")) 8 4 [(eq_attr "type" "st")])(define_function_unit "ev5_ldst" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "st")) 4 4)(define_function_unit "ev5_ebox" 2 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "imull")) 32 4)(define_function_unit "ev5_ebox" 2 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "imulq")) 48 4);; Multiplies also use the integer multiplier.(define_function_unit "ev5_imult" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "imull")) 16 8)(define_function_unit "ev5_imult" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "imulq")) 48 32);; There is only 1 shifter/zapper.(define_function_unit "ev5_shift" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "shift")) 4 4);; We pretend EV5 has symmetrical 2 fpus,;; even though cpys is the only insn that can issue on either unit.(define_function_unit "ev5_fpu" 2 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fadd,fmul,fcpys")) 16 4) ;; Multiplies (resp. adds) also use the fmul (resp. fadd) units.(define_function_unit "ev5_fpmul" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fmul")) 16 4)(define_function_unit "ev5_fpadd" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fadd")) 16 4)(define_function_unit "ev5_fpadd" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fbr")) 4 4)(define_function_unit "ev5_fpadd" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fdivs")) 60 4)(define_function_unit "ev5_fpadd" 1 0 (and (eq_attr "cpu" "ev5,ev6") (eq_attr "type" "fdivt")) 88 4);; First define the arithmetic insns. Note that the 32-bit forms also;; sign-extend.;; Note that we can do sign extensions in both FP and integer registers.;; However, the result must be in the same type of register as the input.;; The register preferencing code can't handle this case very well, so, for;; now, don't let the FP case show up here for preferencing. Also,;; sign-extends in FP registers take two instructions.(define_insn "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r,r,*f") (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,m,*f")))] "" "@ addl %1,$31,%0 ldl %0,%1 cvtql %1,%0\;cvtlq %0,%0" [(set_attr "type" "iadd,ld,fadd")]);; Do addsi3 the way expand_binop would do if we didn't have one. This;; generates better code. We have the anonymous addsi3 pattern below in;; case combine wants to make it.(define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "reg_or_0_operand" "") (match_operand:SI 2 "add_operand" "")))] "" "{ emit_insn (gen_rtx (SET, VOIDmode, gen_lowpart (DImode, operands[0]), gen_rtx (PLUS, DImode, gen_lowpart (DImode, operands[1]), gen_lowpart (DImode, operands[2])))); DONE;} ")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") (match_operand:SI 2 "add_operand" "rI,O,K,L")))] "" "@ addl %r1,%2,%0 subl %r1,%n2,%0 lda %0,%2(%r1) ldah %0,%h2(%r1)")(define_split [(set (match_operand:SI 0 "register_operand" "") (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" "")))] "! add_operand (operands[2], SImode)" [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] "{ HOST_WIDE_INT val = INTVAL (operands[2]); HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); HOST_WIDE_INT rest = val - low; operands[3] = GEN_INT (rest); operands[4] = GEN_INT (low);}")(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (sign_extend:DI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ,rJ") (match_operand:SI 2 "sext_add_operand" "rI,O"))))] "" "@ addl %r1,%2,%0 subl %r1,%n2,%0")(define_split [(set (match_operand:DI 0 "register_operand" "") (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" "")))) (clobber (match_operand:SI 3 "register_operand" ""))] "! sext_add_operand (operands[2], SImode) && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) % 4 == 0" [(set (match_dup 3) (match_dup 4)) (set (match_dup 0) (sign_extend:DI (plus:SI (mult:SI (match_dup 3) (match_dup 5)) (match_dup 1))))] "{ HOST_WIDE_INT val = INTVAL (operands[2]) / 4; int mult = 4; if (val % 2 == 0) val /= 2, mult = 8; operands[4] = GEN_INT (val); operands[5] = GEN_INT (mult);}")(define_split [(set (match_operand:DI 0 "register_operand" "") (sign_extend:DI (plus:SI (match_operator:SI 1 "comparison_operator" [(match_operand 2 "" "") (match_operand 3 "" "")]) (match_operand:SI 4 "add_operand" "")))) (clobber (match_operand:DI 5 "register_operand" ""))] "" [(set (match_dup 5) (match_dup 6)) (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 7) (match_dup 4))))] "{ operands[6] = gen_rtx (GET_CODE (operands[1]), DImode, operands[2], operands[3]); operands[7] = gen_lowpart (SImode, operands[5]);}")(define_insn "adddi3" [(set (match_operand:DI 0 "register_operand" "=r,r,r,r") (plus:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ,rJ,rJ,rJ") (match_operand:DI 2 "add_operand" "rI,O,K,L")))] "" "@ addq %r1,%2,%0 subq %r1,%n2,%0 lda %0,%2(%r1) ldah %0,%h2(%r1)");; Don't do this if we are adjusting SP since we don't want to do;; it in two steps. (define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "const_int_operand" "")))] "! add_operand (operands[2], DImode) && REGNO (operands[0]) != STACK_POINTER_REGNUM" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))] "{ HOST_WIDE_INT val = INTVAL (operands[2]); HOST_WIDE_INT low = (val & 0xffff) - 2 * (val & 0x8000); HOST_WIDE_INT rest = val - low; operands[3] = GEN_INT (rest); operands[4] = GEN_INT (low);}")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r,r") (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ") (match_operand:SI 2 "const48_operand" "I,I")) (match_operand:SI 3 "sext_add_operand" "rI,O")))] "" "@ s%2addl %r1,%3,%0 s%2subl %r1,%n3,%0")(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (sign_extend:DI (plus:SI (mult:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,rJ") (match_operand:SI 2 "const48_operand" "I,I")) (match_operand:SI 3 "sext_add_operand" "rI,O"))))] "" "@ s%2addl %r1,%3,%0 s%2subl %r1,%n3,%0")(define_split [(set (match_operand:DI 0 "register_operand" "") (sign_extend:DI (plus:SI (mult:SI (match_operator:SI 1 "comparison_operator" [(match_operand 2 "" "") (match_operand 3 "" "")]) (match_operand:SI 4 "const48_operand" "")) (match_operand:SI 5 "add_operand" "")))) (clobber (match_operand:DI 6 "register_operand" ""))] "" [(set (match_dup 6) (match_dup 7)) (set (match_dup 0) (sign_extend:DI (plus:SI (mult:SI (match_dup 8) (match_dup 4)) (match_dup 5))))] "{ operands[7] = gen_rtx (GET_CODE (operands[1]), DImode, operands[2], operands[3]); operands[8] = gen_lowpart (SImode, operands[6]);}")(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r,r") (plus:DI (mult:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,rJ") (match_operand:DI 2 "const48_operand" "I,I")) (match_operand:DI 3 "reg_or_8bit_operand" "rI,O")))] "" "@ s%2addq %r1,%3,%0 s%2subq %1,%n3,%0");; These variants of the above insns can occur if the third operand;; is the frame pointer. This is a kludge, but there doesn't;; seem to be a way around it. Only recognize them while reloading.(define_insn "" [(set (match_operand:DI 0 "some_operand" "=&r") (plus:DI (plus:DI (match_operand:DI 1 "some_operand" "r") (match_operand:DI 2 "some_operand" "r")) (match_operand:DI 3 "some_operand" "rIOKL")))] "reload_in_progress" "#")(define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")) (match_operand:DI 3 "add_operand" "")))] "reload_completed" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))] "") (define_insn ""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -