📄 m68k.md
字号:
;;- Machine description for GNU compiler;;- Motorola 68000 Version;; Copyright (C) 1987, 1988 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.;;- 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.;;- 'x' if one of the Sun FPA registers ;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).;;- 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).;;- 'H' one of the standard FPA constant values;;;; 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' -128 .. 127;;- 'L' -8 .. -1;;- FPA port explanation:;;- Usage of the Sun FPA and the 68881 together;;- The current port of gcc to the sun fpa disallows use of the m68881;;- instructions completely if code is targetted for the fpa. This is;;- for the following reasons:;;- 1) Expressing the preference hierarchy (ie. use the fpa if you;;- can, the 68881 otherwise, and data registers only if you are;;- forced to it) is a bitch with the current constraint scheme,;;- especially since it would have to work for any combination of;;- -mfpa, -m68881.;;- 2) There are no instructions to move between the two types of;;- registers; the stack must be used as an intermediary.;;- It could indeed be done; I think the best way would be to have;;- seperate patterns for TARGET_FPA (which implies a 68881),;;- TARGET_68881, and no floating point co-processor. Use;;- define_expands for all of the named instruction patterns, and;;- include code in the FPA instruction to deal with the 68881 with;;- preferences specifically set to favor the fpa. Some of this has;;- already been done:;;-;;- 1) Separation of most of the patterns out into a TARGET_FPA;;- case and a TARGET_68881 case (the exceptions are the patterns;;- which would need one define_expand and three define_insn's under;;- it (with alot of duplicate code between them) to replace the;;- current single define_insn. These are mov{[ds]f,[ds]i} and the;;- first two patterns in the md.;;-;;- Some would still have to be done:;;-;;- 1) Add code to the fpa patterns which correspond to 68881;;- patterns to deal with the 68881 case (including preferences!).;;- What you might actually do here is combine the fpa and 68881 code;;- back together into one pattern for those instructions where it's;;- absolutely necessary and save yourself some duplicate code. I'm;;- not completely sure as to whether you could get away with doing;;- this only for the mov* insns, or if you'd have to do it for all;;- named insns.;;- 2) Add code to the mov{[ds]f,[ds]i} instructions to handle;;- moving between fpa regs and 68881 regs.;;- Since the fpa is more powerful than the 68881 and also has more;;- registers, and since I think the reultant md would be medium ugly;;- (lot's of duplicate code, ugly constraint strings), I elected not;;- to do this change.;;- Another reason why someone *might* want to do the change is to;;- control which register classes are accessed in a slightly cleaner;;- way than I have. See the blurb on CONDITIONAL_REGISTER_USAGE in;;- the internals manual.;;- Yet another reason why someone might want to do this change is to;;- allow use of some of the 68881 insns which have no equivalent on;;- the fpa. The sqrt instruction comes fairly quickly to mind.;;- If this is ever done, don't forget to change tm-sun3.h so that;;- it *will* define __HAVE_68881__ when the FPA is in use.;;- Condition code hack;;- When a floating point compare is done in the fpa, the resulting;;- condition codes are left in the fpastatus register. The values in;;- this register must be moved into the 68000 cc register before any;;- jump is executed. Once this has been done, regular jump;;- instructions are fine (ie. floating point jumps are not necessary.;;- They are only done if the cc is in the 68881).;;- The instructions that move the fpastatus register to the 68000;;- register clobber a data register (the move cannot be done direct).;;- These instructions might be bundled either with the compare;;- instruction, or the branch instruction. If we were using both the;;- fpa and the 68881 together, we would wish to only mark the;;- register clobbered if we were doing the compare in the fpa, but I;;- think that that decision (whether to clobber the register or not);;- must be done before register allocation (makes sense) and hence we;;- can't know if the floating point compare will be done in the fpa;;- or the fp. So whenever we are asked for code that uses the fpa,;;- we will mark a data register as clobbered. This is reasonable, as;;- almost all floating point compare operations done with fpa code;;- enabled will be done in the fpa. It's even more reasonable since;;- we decided to make the 68881 and the fpa mutually exclusive.;;- We place to code to move the fpastatus register inside of a;;- define_expand so that we can do it conditionally based on whether;;- we are tagetting an fpa or not.;;- This still leaves us with the question of where we wish to put the;;- code to move the fpastatus reg. If we put it in the compare;;- instruction, we can restrict the clobbering of the register to;;- floating point compares, but we can't take advantage of floating;;- point subtracts & etc. that alter the fpastatus register. If we;;- put it in the branch instruction, all branches compiled with fpa;;- code enabled will clobber a data register, but we will be able to;;- take advantage of fpa subtracts. This balance favors putting the;;- code in with the compare instruction.;;- Note that if some enterprising hacker should decide to switch;;- this, he'll need to modify the code in NOTICE_UPDATE_CC.;;- Usage of the top 16 fpa registers;;- The only locations which we may transfer fpa registers 16-31 from;;- or to are the fpa registers 0-15. (68000 registers and memory;;- locations are impossible). This causes problems in gcc, which;;- assumes that mov?? instructions require no additional registers;;- (see section 11.7) and since floating point moves *must* be;;- supported into general registers (see section 12.3 under;;- HARD_REGNO_OK_FOR_MODE_P) from anywhere.;;- My solution was to reserve fpa0 for moves into or out of these top;;- 16 registers and to disparage the choice to reload into or out of;;- these registers as much as I could. That alternative is always;;- last in the list, so it will not be used unless all else fails. I;;- will note that according to my current information, sun's compiler;;- doesn't use these top 16 registers at all.;;- There is another possible way to do it. I *believe* that if you;;- make absolutely sure that the code will not be exectued in the;;- reload pass, you can support the mov?? names with define_expands;;- which require new registers. This may be possible by the;;- appropriate juggling of constraints. I may come back to this later.;;- Usage of constant RAM;;- This has been handled correctly (I believe) but the way I've done;;- it could use a little explanation. The constant RAM can only be;;- accessed when the instruction is in "command register" mode.;;- "command register" mode means that no accessing of memory or the;;- 68000 registers is being done. This can be expressed easily in;;- constraints, so generally the mode of the instruction is;;- determined by a branch off of which_alternative. In outputing;;- instructions, a 'w' means to output an access to the constant ram;;- (if the arg is CONST_DOUBLE and is one of the available;;- constants), and 'x' means to output a register pair (if the arg is;;- a 68000 register) and a 'y' is the combination of the above two;;- processies. You use a 'y' in two operand DF instructions where you;;- *know* the other operand is an fpa register, you use an 'x' in DF;;- instructions where the arg might be a 68000 register and the;;- instruction is *not* in "command register" mode, and you use a 'w';;- in two situations: 1) The instruction *is* in command register;;- mode (and hence won't be accessing 68000 registers), or 2) The;;- instruction is a two operand SF instruction where you know the;;- other operand is an fpa register.;;- Optimization issues;;- I actually think that I've included all of the fpa instructions;;- that should be included. Note that if someone is interested in;;- doing serious floating point work on the sun fpa, I would advise;;- the use of the "asm" instruction in gcc to allow you to use the;;- sin, cos, and exponential functions on the fpa board.;;- END FPA Explanation Section.;;- Some of these insn's are composites of several m68000 op codes.;;- The assembler (or final @@??) insures that the appropriate one is;;- selected.(define_insn "" [(set (match_operand:DF 0 "push_operand" "=m") (match_operand:DF 1 "general_operand" "ro<>fyF"))] "" "*{ if (FP_REG_P (operands[1])) return \"fmove%.d %f1,%0\"; if (FPA_REG_P (operands[1])) return \"fpmove%.d %1, %x0\"; return output_move_double (operands);}")(define_insn "" [(set (match_operand:DI 0 "push_operand" "=m") (match_operand:DI 1 "general_operand" "ro<>Fy"))] "" "*{ return output_move_double (operands);}");; Put tstsi first among test insns so it matches a CONST_INT operand.(define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "general_operand" "rm"))] "" "*{#ifdef ISI_OV /* ISI's assembler fails to handle tstl a0. */ if (! ADDRESS_REG_P (operands[0]))#else if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))#endif 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. */#ifdef HPUX_ASM return \"cmp%.w %0,%#0\";#else return \"cmp%.w %#0,%0\";#endif}")(define_insn "tsthi" [(set (cc0) (match_operand:HI 0 "general_operand" "rm"))] "" "*{#ifdef ISI_OV if (! ADDRESS_REG_P (operands[0]))#else if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))#endif return \"tst%.w %0\";#ifdef HPUX_ASM return \"cmp%.w %0,%#0\";#else return \"cmp%.w %#0,%0\";#endif}")(define_insn "tstqi" [(set (cc0) (match_operand:QI 0 "general_operand" "dm"))] "" "tst%.b %0") (define_expand "tstsf" [(set (cc0) (match_operand:SF 0 "general_operand" ""))] "TARGET_68881 || TARGET_FPA" "{ if (TARGET_FPA) { emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, gen_rtx (SET, VOIDmode, cc0_rtx, operands[0]), gen_rtx (CLOBBER, VOIDmode, gen_reg_rtx (SImode))))); DONE; }}")(define_insn "" [(set (cc0) (match_operand:SF 0 "general_operand" "xmdF")) (clobber (match_operand:SI 1 "general_operand" "d"))] "TARGET_FPA" "fptst%.s %x0\;fpmove fpastatus,%1\;movw %1,cc")(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 || TARGET_FPA" "{ if (TARGET_FPA) { emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, gen_rtx (SET, VOIDmode, cc0_rtx, operands[0]), gen_rtx (CLOBBER, VOIDmode, gen_reg_rtx (SImode))))); DONE; }}")(define_insn "" [(set (cc0) (match_operand:DF 0 "general_operand" "xrmF")) (clobber (match_operand:SI 1 "general_operand" "d"))] "TARGET_FPA" "fptst%.d %x0\;fpmove fpastatus,%1\;movw %1,cc")(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.;; Put cmpsi first among compare insns so it matches two CONST_INT operands.;; A composite of the cmp, cmpa, & cmpi m68000 op codes.(define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "general_operand" "rKs,mr,>") (match_operand:SI 1 "general_operand" "mr,Ksr,>")))] "" "*{ 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;#ifdef HPUX_ASM return \"cmp%.l %d1,%d0\";#else return \"cmp%.l %d0,%d1\"; #endif }#ifdef HPUX_ASM return \"cmp%.l %d0,%d1\";#else return \"cmp%.l %d1,%d0\";#endif}")(define_insn "cmphi" [(set (cc0) (compare (match_operand:HI 0 "general_operand" "rnm,d,n,m") (match_operand:HI 1 "general_operand" "d,rnm,m,n")))] "" "*{ 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;#ifdef HPUX_ASM return \"cmp%.w %d1,%d0\";#else return \"cmp%.w %d0,%d1\"; #endif }#ifdef HPUX_ASM return \"cmp%.w %d0,%d1\";#else return \"cmp%.w %d1,%d0\";#endif}")(define_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "general_operand" "dn,md,>") (match_operand:QI 1 "general_operand" "dm,nd,>")))] "" "*{ 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;#ifdef HPUX_ASM return \"cmp%.b %d1,%d0\";#else return \"cmp%.b %d0,%d1\";#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -