📄 mips.md
字号:
;; Mips.md Naive version of Machine Description for MIPS;; Contributed by A. Lichnewsky, lich@inria.inria.fr;; Changes by Michael Meissner, meissner@osf.org;; Copyright (C) 1989, 1990 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 1, 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, 675 Mass Ave, Cambridge, MA 02139, USA.;;;;------------------------------------------------------------------------;;;;;; ....................;;;; Peephole Optimizations for;;;; ARITHMETIC;;;; ....................;; ;;- The following peepholes are ;;- motivated by the fact that ;;- stack movement result in some ;;- cases in embarrassing sequences ;;- of addiu SP,SP,int ;;- addiu SP,SP,other_int ;;- -------------------- ;;- REMARK: this would be done better ;;- by analysis of dependencies in ;;- basic blocks, prior to REG ALLOC, ;;- and simplification of trees: ;;- (+ (+ REG const) const) ;;- -> (+ REG newconst) ;;- -------------------- ;;- Merged peephole code from ;;- raeburn@ATHENA.MIT.EDU(define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operator 1 "additive_op" [(match_operand:SI 2 "register_operand" "r") (match_operand:SI 3 "small_int" "I")])) (set (match_operand:SI 4 "register_operand" "=r") (match_operator 5 "additive_op" [(match_dup 0) (match_operand:SI 6 "small_int" "I")]))] "(REGNO (operands[0]) == REGNO (operands[4]) || dead_or_set_p (insn, operands[0]))" "*{ int addend; /* compute sum, with signs */ addend = INTVAL (operands[3]) * (GET_CODE (operands[1]) == PLUS ? 1 : -1); addend += INTVAL (operands[6]) * (GET_CODE (operands[5]) == PLUS ? 1 : -1); if (addend != 0) { operands[0] = gen_rtx (CONST_INT, VOIDmode, addend); return \"addi%:\\t%4,%2,%0\"; } /* value is zero; copy */ if (REGNO (operands[4]) != REGNO (operands[2])) return \"add%:\\t%4,%2,$0\"; /* copying to self; punt */ return \" # null operation: additive operands cancel (%0,%2)\";}");;;; ....................;;;; ARITHMETIC;;;; ....................;;(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=f") (plus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "add.d\\t%0,%1,%2")(define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=f") (plus:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "add.s\\t%0,%1,%2");; The following is generated when omiting the frame pointer;; and for referencing large auto arrays during optimization.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "immediate_operand" "i")))] "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx" "*{ int number; if (GET_CODE (operands[2]) != CONST_INT) return \"add%:\\t%0,%1,%2\"; number = INTVAL (operands[2]); if (((unsigned) (number + 0x8000) > 0xffff)) { operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tadd%:\\t%0,%1,%3\\n\\t.set\\tat\"; } return (number < 0) ? \"sub%:\\t%0,%1,%n2\" : \"add%:\\t%0,%1,%2\";}")(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_operand:SI 1 "arith_operand" "%r") (match_operand:SI 2 "arith_operand" "rI")))] "" "*{ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ? \"sub%:\\t%0,%1,%n2\" : \"add%:\\t%0,%1,%2\";}");;- All kinds of subtract instructions.(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=f") (minus:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "sub.d\\t%0,%1,%2")(define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=f") (minus:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "sub.s\\t%0,%1,%2");; The following is generated when omiting the frame pointer;; and for referencing large auto arrays during optimization.(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "%r") (match_operand:SI 2 "immediate_operand" "i")))] "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx" "*{ int number; if (GET_CODE (operands[2]) != CONST_INT) return \"sub%:\\t%0,%1,%2\"; number = INTVAL (operands[2]); if (((unsigned) (number + 0x8000) > 0xffff)) { operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tsub%:\\t%0,%1,%3\\n\\t.set\\tat\"; } return (number < 0) ? \"add%:\\t%0,%1,%n2\" : \"sub%:\\t%0,%1,%2\";}")(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=r") (minus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" "*{ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) ? \"add%:\\t%0,%1,%n2\" : \"sub%:\\t%0,%1,%2\";}");;- Multiply instructions.(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=f") (mult:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "mul.d\\t%0,%1,%2")(define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=f") (mult:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "mul.s\\t%0,%1,%2")(define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mult:SI (match_operand:SI 1 "arith_operand" "%r") (match_operand:SI 2 "arith_operand" "rI")))] "" "mul\\t%0,%1,%2");;- Divide instructions.(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=f") (div:DF (match_operand:DF 1 "register_operand" "f") (match_operand:DF 2 "register_operand" "f")))] "" "div.d\\t%0,%1,%2")(define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=f") (div:SF (match_operand:SF 1 "register_operand" "f") (match_operand:SF 2 "register_operand" "f")))] "" "div.s\\t%0,%1,%2")(define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=r") (div:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI"))) (set (match_operand:SI 3 "register_operand" "=r") (mod:SI (match_dup 1) (match_dup 2)))] "" "div\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")(define_insn "divsi3" [(set (match_operand:SI 0 "register_operand" "=r") (div:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" "div\\t%0,%1,%2")(define_insn "udivmodsi4" [(set (match_operand:SI 0 "register_operand" "=r") (udiv:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI"))) (set (match_operand:SI 3 "register_operand" "=r") (umod:SI (match_dup 1) (match_dup 2)))] "" "divu\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")(define_insn "udivsi3" [(set (match_operand:SI 0 "register_operand" "=r") (udiv:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" "divu\\t%0,%1,%2");; Remainder instructions(define_insn "modsi3" [(set (match_operand:SI 0 "register_operand" "=r") (mod:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" "rem\\t%0,%1,%2")(define_insn "umodsi3" [(set (match_operand:SI 0 "register_operand" "=r") (umod:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "arith_operand" "rI")))] "" "remu\\t%0,%1,%2");; Absoluate value instructions -- Don't use the integer abs,;; since that signals an exception on -2147483648 (sigh).(define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "register_operand" "f")))] "" "abs.s\\t%0,%1")(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "register_operand" "f")))] "" "abs.d\\t%0,%1");;;; ....................;;;; LOGICAL;;;; ....................;;(define_insn "anddi3" [(set (match_operand:DI 0 "register_operand" "=&r") (and:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")))] "" "and\\t%0,%1,%2\;and\\t%D0,%D1,%D2")(define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=r") (and:SI (match_operand:SI 1 "uns_arith_operand" "%r") (match_operand:SI 2 "uns_arith_operand" "rK")))] "" "*{ return (GET_CODE (operands[2]) == CONST_INT) ? \"andi\\t%0,%1,%x2\" : \"and\\t%0,%1,%2\";}");; Simple hack to recognize the "nor" instruction on the MIPS;; [rms: I don't think the following is actually required.];; This must appear before the normal or patterns, so that the;; combiner will correctly fold things.(define_insn "" [(set (match_operand:DI 0 "register_operand" "=r") (not:DI (ior:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r"))))] "" "nor\\t%0,%1,%2\;nor\\t%D0,%D1,%D2")(define_insn "" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (ior:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "register_operand" "r"))))] "" "nor\\t%0,%1,%2")(define_insn "iordi3" [(set (match_operand:DI 0 "register_operand" "=&r") (ior:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")))] "" "or\\t%0,%1,%2\;or\\t%D0,%D1,%D2")(define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI (match_operand:SI 1 "uns_arith_operand" "%r") (match_operand:SI 2 "uns_arith_operand" "rJ")))] "" "*{ return (GET_CODE (operands[2]) == CONST_INT) ? \"ori\\t%0,%1,%x2\" : \"or\\t%0,%1,%2\";}")(define_insn "xordi3" [(set (match_operand:DI 0 "register_operand" "=&r") (xor:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "register_operand" "r")))] "" "xor\\t%0,%1,%2\;xor\\t%D0,%D1,%D2")(define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=r") (xor:SI (match_operand:SI 1 "uns_arith_operand" "%r") (match_operand:SI 2 "uns_arith_operand" "rK")))] "" "*{ return (GET_CODE (operands[2]) == CONST_INT) ? \"xori\\t%0,%1,%x2\" : \"xor\\t%0,%1,%2\";}");;;; ....................;;;; TRUNCATION;;;; ....................;; Extension and truncation insns.;; Those for integer source operand;; are ordered widest source type first.(define_insn "truncsiqi2" [(set (match_operand:QI 0 "register_operand" "=r") (truncate:QI (match_operand:SI 1 "register_operand" "r")))] "" "andi\\t%0,%1,0xff\\t#truncsiqi2\\t %1 -> %0")(define_insn "truncsihi2" [(set (match_operand:HI 0 "register_operand" "=r") (truncate:HI (match_operand:SI 1 "register_operand" "r")))] "" "* output_asm_insn (\"sll\\t%0,%1,0x10\\t#truncsihi2\\t %1 -> %0\", operands); return \"sra\\t%0,%0,0x10\\t#truncsihi2\\t %1 -> %0\";")(define_insn "trunchiqi2" [(set (match_operand:QI 0 "register_operand" "=r") (truncate:QI (match_operand:HI 1 "register_operand" "r")))] "" "andi\\t%0,%1,0xff\\t#trunchiqi2\\t %1 -> %0")(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "" "cvt.s.d\\t%0,%1\\t#truncdfsf2\\t %1 -> %0");;;; ....................;;;; ZERO EXTENSION;;;; ....................;; Extension insns.;; Those for integer source operand;; are ordered widest source type first.(define_insn "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extend:SI (match_operand:HI 1 "general_operand" "r,m")))] "" "*{ if (which_alternative == 0) { output_asm_insn (\"sll\\t%0,%1,0x10\\t#zero_extendhisi2\\t %1 -> %0\", operands); return \"srl\\t%0,%0,0x10\\t#zero_extendhisi2\\t %1 -> %0\"; } else return \"lhu\\t%0,%1\\t#zero extendhisi2 %1 -> %0\";}")(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "* output_asm_insn (\"sll\\t%0,%1,0x18\\t#zero_extendqihi2\\t %1 -> %0\", operands); return \"srl\\t%0,%0,0x18\\t#zero_extendqihi2\\t %1 -> %0\"; ")(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extend:SI (match_operand:QI 1 "general_operand" "r,m")))] "" "*{ if (which_alternative == 0) { return \"andi\\t%0,%1,0xff\\t#zero_extendqisi2\\t %1 -> %0\"; } else return \"lbu\\t%0,%1\\t#zero extendqisi2 %1 -> %0\";}");;;; ....................;;;; SIGN EXTENSION;;;; ....................;; Extension insns.;; Those for integer source operand;; are ordered widest source type first.(define_insn "extendhisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (sign_extend:SI (match_operand:HI 1 "general_operand" "r,m")))] "" "*{ if (which_alternative == 0) { output_asm_insn (\"sll\\t%0,%1,0x10\\t#sign extendhisi2\\t %1 -> %0\", operands); return \"sra\\t%0,%0,0x10\\t#sign extendhisi2\\t %1 -> %0\"; } else return \"lh\\t%0,%1\\t#sign extendhisi2 %1 -> %0\";}")(define_insn "extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "* output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqihi2\\t %1 -> %0\", operands); return \"sra\\t%0,%0,0x18\\t#sign extendqihi2\\t %1 -> %0\";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -