📄 m68k.md
字号:
;;- Machine description for GNU compiler, Motorola 68000 Version;; Copyright (C) 1987, 1988, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001,;; 2002, 2003, 2004;; Free Software Foundation, Inc.;; 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.;;- Information about MCF5200 port.;;- The MCF5200 "ColdFire" architecture is a reduced version of the;;- 68k ISA. Differences include reduced support for byte and word;;- operands and the removal of BCD, bitfield, rotate, and integer;;- divide instructions. The TARGET_COLDFIRE flag turns the use of the;;- removed opcodes and addressing modes off.;;- ;;- instruction definitions;;- @@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.;;- When naming insn's (operand 0 of define_insn) be careful about using;;- names from other targets machine descriptions.;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code;;- updates for most instructions.;;- Operand classes for the register allocator:;;- 'a' one of the address registers can be used.;;- 'd' one of the data registers can be used.;;- 'f' one of the m68881 registers can be used;;- 'r' either a data or an address register can be used.;;- Immediate Floating point operator constraints;;- 'G' a floating point constant that is *NOT* one of the standard;; 68881 constant values (to force calling output_move_const_double;; to get it from rom if it is a 68881 constant).;;;; See the functions standard_XXX_constant_p in output-m68k.c for more;; info.;;- Immediate integer operand constraints:;;- 'I' 1 .. 8;;- 'J' -32768 .. 32767;;- 'K' all integers EXCEPT -128 .. 127;;- 'L' -8 .. -1;;- 'M' all integers EXCEPT -256 .. 255;;- 'N' 24 .. 31;;- 'O' 16;;- 'P' 8 .. 15;;- Assembler specs:;;- "%." size separator ("." or "") move%.l d0,d1;;- "%-" push operand "sp@-" move%.l d0,%-;;- "%+" pop operand "sp@+" move%.l d0,%+;;- "%@" top of stack "sp@" move%.l d0,%@;;- "%!" fpcr register;;- "%$" single-precision fp specifier ("s" or "") f%$add.x fp0,fp1;;- "%&" double-precision fp specifier ("d" or "") f%&add.x fp0,fp1;;- Information about 68040 port.;;- The 68040 executes all 68030 and 68881/2 instructions, but some must;;- be emulated in software by the OS. It is faster to avoid these;;- instructions and issue a library call rather than trapping into;;- the kernel. The affected instructions are fintrz and fscale. The;;- TARGET_68040 flag turns the use of the opcodes off.;;- The '040 also implements a set of new floating-point instructions;;- which specify the rounding precision in the opcode. This finally;;- permit the 68k series to be truly IEEE compliant, and solves all;;- issues of excess precision accumulating in the extended registers.;;- By default, GCC does not use these instructions, since such code will;;- not run on an '030. To use these instructions, use the -m68040-only;;- switch. By changing TARGET_DEFAULT to include TARGET_68040_ONLY,;;- you can make these instructions the default.;;- These new instructions aren't directly in the md. They are brought;;- into play by defining "%$" and "%&" to expand to "s" and "d" rather;;- than "".;;- Information about 68060 port.;;- The 68060 executes all 68030 and 68881/2 instructions, but some must;;- be emulated in software by the OS. It is faster to avoid these;;- instructions and issue a library call rather than trapping into;;- the kernel. The affected instructions are: divs.l <ea>,Dr:Dq;;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq; and;;- fscale. The TARGET_68060 flag turns the use of the opcodes off.;;- Some of these insn's are composites of several m68000 op codes.;;- The assembler (or final @@??) insures that the appropriate one is;;- selected.;; UNSPEC usage:(define_constants [(UNSPEC_SIN 1) (UNSPEC_COS 2) ]);; UNSPEC_VOLATILE usage:(define_constants [(UNSPECV_BLOCKAGE 0) ]);; Registers by name.(define_constants [(A0_REG 8) (SP_REG 15) ])(define_insn "" [(set (match_operand:DF 0 "push_operand" "=m") (match_operand:DF 1 "general_operand" "ro<>fyE"))] ""{ if (FP_REG_P (operands[1])) return "fmove%.d %f1,%0"; return output_move_double (operands);})(define_insn "pushdi" [(set (match_operand:DI 0 "push_operand" "=m") (match_operand:DI 1 "general_operand" "ro<>Fyi"))] ""{ return output_move_double (operands);});; We don't want to allow a constant operand for test insns because;; (set (cc0) (const_int foo)) has no mode information. Such insns will;; be folded while optimizing anyway.(define_expand "tstdi" [(parallel [(set (cc0) (match_operand:DI 0 "nonimmediate_operand" "")) (clobber (match_scratch:SI 1 "")) (clobber (match_scratch:DI 2 ""))])] "" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (match_operand:DI 0 "nonimmediate_operand" "am,d")) (clobber (match_scratch:SI 1 "=X,d")) (clobber (match_scratch:DI 2 "=d,X"))] ""{ if (which_alternative == 0) { rtx xoperands[2]; xoperands[0] = operands[2]; xoperands[1] = operands[0]; output_move_double (xoperands); cc_status.flags |= CC_REVERSED; return "neg%.l %R2\;negx%.l %2"; } if (find_reg_note (insn, REG_DEAD, operands[0])) { cc_status.flags |= CC_REVERSED; return "neg%.l %R0\;negx%.l %0"; } else /* 'sub' clears %1, and also clears the X cc bit 'tst' sets the Z cc bit according to the low part of the DImode operand 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part. */ return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";})(define_expand "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" ""))] "" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] ""{ if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0])) return "tst%.l %0"; /* If you think that the 68020 does not support tstl a0, reread page B-167 of the 68020 manual more carefully. */ /* On an address reg, cmpw may replace cmpl. */ return "cmp%.w #0,%0";});; This can't use an address register, because comparisons;; with address registers as second operand always test the whole word.(define_expand "tsthi" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" ""))] "" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "dm"))] "" "tst%.w %0")(define_expand "tstqi" [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" ""))] "" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (match_operand:QI 0 "nonimmediate_operand" "dm"))] "" "tst%.b %0")(define_expand "tstsf" [(set (cc0) (match_operand:SF 0 "general_operand" ""))] "TARGET_68881"{ m68k_last_compare_had_fp_operands = 1;})(define_insn "" [(set (cc0) (match_operand:SF 0 "general_operand" "fdm"))] "TARGET_68881"{ cc_status.flags = CC_IN_68881; if (FP_REG_P (operands[0])) return "ftst%.x %0"; return "ftst%.s %0";})(define_expand "tstdf" [(set (cc0) (match_operand:DF 0 "general_operand" ""))] "TARGET_68881"{ m68k_last_compare_had_fp_operands = 1;})(define_insn "" [(set (cc0) (match_operand:DF 0 "general_operand" "fm"))] "TARGET_68881"{ cc_status.flags = CC_IN_68881; if (FP_REG_P (operands[0])) return "ftst%.x %0"; return "ftst%.d %0";});; compare instructions.(define_expand "cmpdi" [(parallel [(set (cc0) (compare (match_operand:DI 0 "nonimmediate_operand" "") (match_operand:DI 1 "general_operand" ""))) (clobber (match_dup 2))])] "" "m68k_last_compare_had_fp_operands = 0; operands[2] = gen_reg_rtx (DImode);")(define_insn "" [(set (cc0) (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") (match_operand:DI 2 "general_operand" "d,0"))) (clobber (match_operand:DI 0 "register_operand" "=d,d"))] ""{ if (rtx_equal_p (operands[0], operands[1])) return "sub%.l %R2,%R0\;subx%.l %2,%0"; else { cc_status.flags |= CC_REVERSED; return "sub%.l %R1,%R0\;subx%.l %1,%0"; }});; This is the second "hook" for PIC code (in addition to movsi). See;; comment of movsi for a description of PIC handling.(define_expand "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" "")))] ""{ m68k_last_compare_had_fp_operands = 0; if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode)) { /* The source is an address which requires PIC relocation. Call legitimize_pic_address with the source, mode, and a relocation register (a new pseudo, or the final destination if reload_in_progress is set). Then fall through normally */ rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); operands[1] = legitimize_pic_address (operands[1], SImode, temp); }});; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.(define_insn "" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mSr,mSa,>") (match_operand:SI 1 "general_src_operand" "mSr,mSa,KTr,Ksr,>")))] "!TARGET_COLDFIRE"{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.l %1,%0"; if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return "cmp%.l %d0,%d1"; } if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) return "cmp%.w %1,%0"; return "cmp%.l %d1,%d0";})(define_insn "" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r") (match_operand:SI 1 "general_operand" "r,mrKs")))] "TARGET_COLDFIRE"{ if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return "cmp%.l %d0,%d1"; } return "cmp%.l %d1,%d0";})(define_expand "cmphi" [(set (cc0) (compare (match_operand:HI 0 "nonimmediate_src_operand" "") (match_operand:HI 1 "general_src_operand" "")))] "!TARGET_COLDFIRE" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (compare (match_operand:HI 0 "nonimmediate_src_operand" "rnmS,d,n,mS,>") (match_operand:HI 1 "general_src_operand" "d,rnmS,mS,n,>")))] "!TARGET_COLDFIRE"{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.w %1,%0"; if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1])) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return "cmp%.w %d0,%d1"; } return "cmp%.w %d1,%d0";})(define_expand "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "nonimmediate_src_operand" "") (match_operand:QI 1 "general_src_operand" "")))] "!TARGET_COLDFIRE" "m68k_last_compare_had_fp_operands = 0;")(define_insn "" [(set (cc0) (compare (match_operand:QI 0 "nonimmediate_src_operand" "dn,dmS,>") (match_operand:QI 1 "general_src_operand" "dmS,nd,>")))] "!TARGET_COLDFIRE"{ if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.b %1,%0"; if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; return "cmp%.b %d0,%d1"; } return "cmp%.b %d1,%d0";})(define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" "")))] "TARGET_68881"{ m68k_last_compare_had_fp_operands = 1;})(define_insn ""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -