📄 tahoe.md
字号:
;;- Machine description for GNU compiler;;- Tahoe version;; Copyright (C) 1989 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.; File: tahoe.md;; This port made at the University of Buffalo by Devon Bowen,; Dale Wiles and Kevin Zachmann.;; Mail bugs reports or fixes to: gcc@cs.buffalo.edu; movdi must call the output_move_double routine to move it around since; the tahoe doesn't efficiently support 8 bit moves.(define_insn "movdi" [(set (match_operand:DI 0 "general_operand" "=g") (match_operand:DI 1 "general_operand" "g"))] "" "*{ CC_STATUS_INIT; return output_move_double (operands);}"); The trick in the movsi is accessing the contents of the sp register. The; tahoe doesn't allow you to access it directly so you have to access the; address of the top of the stack instead.(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=g") (match_operand:SI 1 "general_operand" "g"))] "" "*{ rtx link; if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) && ! XEXP (link, 0)->volatil && GET_CODE (XEXP (link, 0)) != NOTE && no_labels_between_p (XEXP (link, 0), insn)) return \"incl %0\"; if (GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) { if (push_operand (operands[0], SImode)) return \"pushab %a1\"; return \"movab %a1,%0\"; } if (operands[1] == const0_rtx) return \"clrl %0\"; if (push_operand (operands[0], SImode)) return \"pushl %1\"; if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 14) return \"moval (sp),%0\"; return \"movl %1,%0\";}")(define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=g") (match_operand:HI 1 "general_operand" "g"))] "" "*{ rtx link; if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) && ! XEXP (link, 0)->volatil && GET_CODE (XEXP (link, 0)) != NOTE && no_labels_between_p (XEXP (link, 0), insn)) return \"incw %0\"; if (operands[1] == const0_rtx) return \"clrw %0\"; return \"movw %1,%0\";}")(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=g") (match_operand:QI 1 "general_operand" "g"))] "" "*{ if (operands[1] == const0_rtx) return \"clrb %0\"; return \"movb %1,%0\";}"); movsf has three cases since they can move from one place to another; or to/from the fpp and since different instructions are needed for; each case. The fpp related instructions don't set the flags properly.(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=g,=a,=g") (match_operand:SF 1 "general_operand" "g,g,a"))] "" "*{ CC_STATUS_INIT; switch (which_alternative) { case 0: return \"movl %1,%0\"; case 1: return \"ldf %1\"; case 2: return \"stf %0\"; }}"); movdf has a number of different cases. If it's going to or from; the fpp, use the special instructions to do it. If not, use the; output_move_double function.(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=a,=g,?=g") (match_operand:DF 1 "general_operand" "g,a,g"))] "" "*{ CC_STATUS_INIT; switch (which_alternative) { case 0: return \"ldd %1\"; case 1: if (push_operand (operands[0], DFmode)) return \"pushd\"; else return \"std %0\"; case 2: return output_move_double (operands); }}")(define_insn "addsi3" [(set (match_operand:SI 0 "general_operand" "=g") (plus:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incl %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"decl %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl2 $%n2,%0\"; return \"addl2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addl2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == REG) { if (push_operand (operands[0], SImode)) return \"pushab %c2(%1)\"; return \"movab %c2(%1),%0\"; } if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subl3 $%n2,%1,%0\"; return \"addl3 %1,%2,%0\";}")(define_insn "addhi3" [(set (match_operand:HI 0 "general_operand" "=g") (plus:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incw %0\"; if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == -1) return \"decw %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subw2 $%n2,%0\"; return \"addw2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addw2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subw3 $%n2,%1,%0\"; return \"addw3 %1,%2,%0\";}")(define_insn "addqi3" [(set (match_operand:QI 0 "general_operand" "=g") (plus:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"incb %0\"; if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == -1) return \"decb %0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subb2 $%n2,%0\"; return \"addb2 %2,%0\"; } if (rtx_equal_p (operands[0], operands[2])) return \"addb2 %1,%0\"; if (GET_CODE (operands[2]) == CONST_INT && (unsigned) (- INTVAL (operands[2])) < 64) return \"subb3 $%n2,%1,%0\"; return \"addb3 %1,%2,%0\";}"); addsf3 can only add into the fpp register since the fpp is treated; as a separate unit in the machine. It also doesn't set the flags at; all.(define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=a") (plus:SF (match_operand:SF 1 "register_operand" "%0") (match_operand:SF 2 "general_operand" "g")))] "" "*{ CC_STATUS_INIT; return \"addf %2\";}"); adddf3 can only add into the fpp reg since the fpp is treated as a; separate entity. Doubles can only be read from a register or memory; since a double is not an immediate mode. Flags are not set by this; instruction.(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=a") (plus:DF (match_operand:DF 1 "register_operand" "%0") (match_operand:DF 2 "general_operand" "rm")))] "" "*{ CC_STATUS_INIT; return \"addd %2\";}"); Subtraction from the sp (needed by the built in alloc funtion) needs; to be different since the sp cannot be directly read on the tahoe.; If it's a simple constant, you just use displacment. Otherwise, you; push the sp, and then do the subtraction off the stack.(define_insn "subsi3" [(set (match_operand:SI 0 "general_operand" "=g") (minus:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decl %0\"; if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 14) if (GET_CODE (operands[2]) == CONST_INT) return \"movab %n2(sp),sp\"; else return \"pushab (sp)\;subl3 %2,(sp),sp\"; return \"subl2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrl %0\"; return \"subl3 %2,%1,%0\";}")(define_insn "subhi3" [(set (match_operand:HI 0 "general_operand" "=g") (minus:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decw %0\"; return \"subw2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrw %0\"; return \"subw3 %2,%1,%0\";}")(define_insn "subqi3" [(set (match_operand:QI 0 "general_operand" "=g") (minus:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) { if (operands[2] == const1_rtx) return \"decb %0\"; return \"subb2 %2,%0\"; } if (rtx_equal_p (operands[1], operands[2])) return \"clrb %0\"; return \"subb3 %2,%1,%0\";}"); subsf3 can only subtract into the fpp accumulator due to the way; the fpp reg is limited by the instruction set. This also doesn't; bother setting up flags.(define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=a") (minus:SF (match_operand:SF 1 "register_operand" "0") (match_operand:SF 2 "general_operand" "g")))] "" "*{ CC_STATUS_INIT; return \"subf %2\";}"); subdf3 is set up to subtract into the fpp reg due to limitations; of the fpp instruction set. Doubles can not be immediate. This; instruction does not set the flags.(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=a") (minus:DF (match_operand:DF 1 "register_operand" "0") (match_operand:DF 2 "general_operand" "rm")))] "" "*{ CC_STATUS_INIT; return \"subd %2\";}")(define_insn "mulsi3" [(set (match_operand:SI 0 "general_operand" "=g") (mult:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[0], operands[1])) return \"mull2 %2,%0\"; if (rtx_equal_p (operands[0], operands[2])) return \"mull2 %1,%0\"; return \"mull3 %1,%2,%0\";}"); mulsf3 can only multiply into the fpp accumulator due to limitations; of the fpp. It also does not set the condition codes properly.(define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=a") (mult:SF (match_operand:SF 1 "register_operand" "%0") (match_operand:SF 2 "general_operand" "g")))] "" "*{ CC_STATUS_INIT; return \"mulf %2\";}"); muldf3 can only multiply into the fpp reg since the fpp is limited; from the rest. Doubles may not be immediate mode. This does not set; the flags like GCC would expect.(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=a") (mult:DF (match_operand:DF 1 "register_operand" "%0") (match_operand:DF 2 "general_operand" "rm")))] "" "*{ CC_STATUS_INIT; return \"muld %2\";}")(define_insn "divsi3" [(set (match_operand:SI 0 "general_operand" "=g") (div:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "*{ if (rtx_equal_p (operands[1], operands[2])) return \"movl $1,%0\"; if (operands[1] == const0_rtx) return \"clrl %0\"; if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -1) return \"mnegl %1,%0\"; if (rtx_equal_p (operands[0], operands[1])) return \"divl2 %2,%0\"; return \"divl3 %2,%1,%0\";}"); divsf3 must divide into the fpp accumulator. Flags are not set by; this instruction, so they are cleared.(define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=a") (div:SF (match_operand:SF 1 "register_operand" "0") (match_operand:SF 2 "general_operand" "g")))] "" "*{ CC_STATUS_INIT; return \"divf %2\";}"); divdf3 also must divide into the fpp reg so optimization isn't; possible. Note that doubles cannot be immediate. The flags here; are not set correctly so they must be ignored.(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=a") (div:DF (match_operand:DF 1 "register_operand" "0") (match_operand:DF 2 "general_operand" "rm")))] "" "*{ CC_STATUS_INIT; return \"divd %2\";}")(define_insn "andsi3" [(set (match_operand:SI 0 "general_operand" "=g") (and:SI (match_operand:SI 1 "general_operand" "g") (match_operand:SI 2 "general_operand" "g")))] "" "andl3 %2,%1,%0")(define_insn "andhi3" [(set (match_operand:HI 0 "general_operand" "=g") (and:HI (match_operand:HI 1 "general_operand" "g") (match_operand:HI 2 "general_operand" "g")))] "" "andw3 %1,%2,%0")(define_insn "andqi3" [(set (match_operand:QI 0 "general_operand" "=g") (and:QI (match_operand:QI 1 "general_operand" "g") (match_operand:QI 2 "general_operand" "g")))] "" "andb3 %1,%2,%0")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -