📄 frv.md
字号:
;; For example, in the common case where branch and call insns require a single;; delay slot, which may contain any insn other than a branch or call, the;; following would be placed in the `md' file:;; (define_delay (eq_attr "type" "branch,call");; [(eq_attr "type" "!branch,call") (nil) (nil)]);; Multiple `define_delay' expressions may be specified. In this case, each;; such expression specifies different delay slot requirements and there must;; be no insn for which tests in two `define_delay' expressions are both true.;; For example, if we have a machine that requires one delay slot for branches;; but two for calls, no delay slot can contain a branch or call insn, and any;; valid insn in the delay slot for the branch can be annulled if the branch is;; true, we might represent this as follows:;; (define_delay (eq_attr "type" "branch");; [(eq_attr "type" "!branch,call");; (eq_attr "type" "!branch,call");; (nil)]);;;; (define_delay (eq_attr "type" "call");; [(eq_attr "type" "!branch,call") (nil) (nil);; (eq_attr "type" "!branch,call") (nil) (nil)]);; Note - it is the backend's responsibility to fill any unfilled delay slots;; at assembler generation time. This is usually done by adding a special print;; operand to the delayed insrtuction, and then in the PRINT_OPERAND function;; calling dbr_sequence_length() to determine how many delay slots were filled.;; For example:;;;; --------------<machine>.md-----------------;; (define_insn "call";; [(call (match_operand 0 "memory_operand" "m");; (match_operand 1 "" ""))];; "";; "call_delayed %0,%1,%2%#";; [(set_attr "length" "4");; (set_attr "type" "call")]);;;; -------------<machine>.h-------------------;; #define PRINT_OPERAND_PUNCT_VALID_P(CODE) (CODE == '#');;;; ------------<machine>.c------------------;; void;; machine_print_operand (file, x, code);; FILE * file;;; rtx x;;; int code;;; {;; switch (code);; {;; case '#':;; if (dbr_sequence_length () == 0);; fputs ("\n\tnop", file);;; return;;; ::::::::::::::::::::;; ::;; :: Notes on Patterns;; ::;; ::::::::::::::::::::;; If you need to construct a sequence of assembler instructions in order;; to implement a pattern be sure to escape any backslashes and double quotes;; that you use, eg:;;;; (define_insn "an example";; [(some rtl)];; "";; "*;; { static char buffer [100];;; sprintf (buffer, \"insn \\t %d\", REGNO (operands[1]));;; return buffer;;; }";; );;;; Also if there is more than one instruction, they can be separated by \\;;; which is a space saving synonym for \\n\\t:;;;; (define_insn "another example";; [(some rtl)];; "";; "*;; { static char buffer [100];;; sprintf (buffer, \"insn1 \\t %d\\;insn2 \\t %%1\",;; REGNO (operands[1]));;; return buffer;;; }";; );;;; ::::::::::::::::::::;; ::;; :: Moves;; ::;; ::::::::::::::::::::;; Wrap moves in define_expand to prevent memory->memory moves from being;; generated at the RTL level, which generates better code for most machines;; which can't do mem->mem moves.;; If operand 0 is a `subreg' with mode M of a register whose own mode is wider;; than M, the effect of this instruction is to store the specified value in;; the part of the register that corresponds to mode M. The effect on the rest;; of the register is undefined.;; This class of patterns is special in several ways. First of all, each of;; these names *must* be defined, because there is no other way to copy a datum;; from one place to another.;; Second, these patterns are not used solely in the RTL generation pass. Even;; the reload pass can generate move insns to copy values from stack slots into;; temporary registers. When it does so, one of the operands is a hard;; register and the other is an operand that can need to be reloaded into a;; register.;; Therefore, when given such a pair of operands, the pattern must;; generate RTL which needs no reloading and needs no temporary;; registers--no registers other than the operands. For example, if;; you support the pattern with a `define_expand', then in such a;; case the `define_expand' mustn't call `force_reg' or any other such;; function which might generate new pseudo registers.;; This requirement exists even for subword modes on a RISC machine;; where fetching those modes from memory normally requires several;; insns and some temporary registers. Look in `spur.md' to see how;; the requirement can be satisfied.;; During reload a memory reference with an invalid address may be passed as an;; operand. Such an address will be replaced with a valid address later in the;; reload pass. In this case, nothing may be done with the address except to;; use it as it stands. If it is copied, it will not be replaced with a valid;; address. No attempt should be made to make such an address into a valid;; address and no routine (such as `change_address') that will do so may be;; called. Note that `general_operand' will fail when applied to such an;; address.;;;; The global variable `reload_in_progress' (which must be explicitly declared;; if required) can be used to determine whether such special handling is;; required.;;;; The variety of operands that have reloads depends on the rest of;; the machine description, but typically on a RISC machine these can;; only be pseudo registers that did not get hard registers, while on;; other machines explicit memory references will get optional;; reloads.;;;; If a scratch register is required to move an object to or from memory, it;; can be allocated using `gen_reg_rtx' prior to reload. But this is;; impossible during and after reload. If there are cases needing scratch;; registers after reload, you must define `SECONDARY_INPUT_RELOAD_CLASS' and;; perhaps also `SECONDARY_OUTPUT_RELOAD_CLASS' to detect them, and provide;; patterns `reload_inM' or `reload_outM' to handle them.;; The constraints on a `moveM' must permit moving any hard register to any;; other hard register provided that `HARD_REGNO_MODE_OK' permits mode M in;; both registers and `REGISTER_MOVE_COST' applied to their classes returns a;; value of 2.;; It is obligatory to support floating point `moveM' instructions;; into and out of any registers that can hold fixed point values,;; because unions and structures (which have modes `SImode' or;; `DImode') can be in those registers and they may have floating;; point members.;; There may also be a need to support fixed point `moveM' instructions in and;; out of floating point registers. Unfortunately, I have forgotten why this;; was so, and I don't know whether it is still true. If `HARD_REGNO_MODE_OK';; rejects fixed point values in floating point registers, then the constraints;; of the fixed point `moveM' instructions must be designed to avoid ever;; trying to reload into a floating point register.(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] "" "{ if (!reload_in_progress && !reload_completed && !register_operand (operands[0], QImode) && !reg_or_0_operand (operands[1], QImode)) operands[1] = copy_to_mode_reg (QImode, operands[1]);}")(define_insn "*movqi_load" [(set (match_operand:QI 0 "register_operand" "=d,f") (match_operand:QI 1 "frv_load_operand" "m,m"))] "" "* return output_move_single (operands, insn);" [(set_attr "length" "4") (set_attr "type" "gload,fload")])(define_insn "*movqi_internal" [(set (match_operand:QI 0 "move_destination_operand" "=d,d,m,m,?f,?f,?d,?m,f") (match_operand:QI 1 "move_source_operand" "L,d,d,O, d, f, f, f,GO"))] "register_operand(operands[0], QImode) || reg_or_0_operand (operands[1], QImode)" "* return output_move_single (operands, insn);" [(set_attr "length" "4") (set_attr "type" "int,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")])(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ if (!reload_in_progress && !reload_completed && !register_operand (operands[0], HImode) && !reg_or_0_operand (operands[1], HImode)) operands[1] = copy_to_mode_reg (HImode, operands[1]);}")(define_insn "*movhi_load" [(set (match_operand:HI 0 "register_operand" "=d,f") (match_operand:HI 1 "frv_load_operand" "m,m"))] "" "* return output_move_single (operands, insn);" [(set_attr "length" "4") (set_attr "type" "gload,fload")])(define_insn "*movhi_internal" [(set (match_operand:HI 0 "move_destination_operand" "=d,d,d,m,m,?f,?f,?d,?m,f") (match_operand:HI 1 "move_source_operand" "L,i,d,d,O, d, f, f, f,GO"))] "register_operand(operands[0], HImode) || reg_or_0_operand (operands[1], HImode)" "* return output_move_single (operands, insn);" [(set_attr "length" "4,8,4,4,4,4,4,4,4,4") (set_attr "type" "int,multi,int,gstore,gstore,movgf,fsconv,movfg,fstore,movgf")]);; Split 2 word load of constants into sethi/setlo instructions(define_split [(set (match_operand:HI 0 "integer_register_operand" "") (match_operand:HI 1 "int_2word_operand" ""))] "reload_completed" [(set (match_dup 0) (high:HI (match_dup 1))) (set (match_dup 0) (lo_sum:HI (match_dup 0) (match_dup 1)))] "")(define_insn "movhi_high" [(set (match_operand:HI 0 "integer_register_operand" "=d") (high:HI (match_operand:HI 1 "int_2word_operand" "i")))] "" "sethi #hi(%1), %0" [(set_attr "type" "sethi") (set_attr "length" "4")])(define_insn "movhi_lo_sum" [(set (match_operand:HI 0 "integer_register_operand" "+d") (lo_sum:HI (match_dup 0) (match_operand:HI 1 "int_2word_operand" "i")))] "" "setlo #lo(%1), %0" [(set_attr "type" "setlo") (set_attr "length" "4")])(define_expand "movsi" [(set (match_operand:SI 0 "move_destination_operand" "") (match_operand:SI 1 "move_source_operand" ""))] "" "{ if (frv_emit_movsi (operands[0], operands[1])) DONE;}");; Note - it is best to only have one movsi pattern and to handle;; all the various contingencies by the use of alternatives. This;; allows reload the greatest amount of flexability (since reload will;; only choose amoungst alternatives for a selected insn, it will not;; replace the insn with another one).;; Unfortunately, we do have to separate out load-type moves from the rest,;; and only allow memory source operands in the former. If we do memory and;; constant loads in a single pattern, reload will be tempted to force;; constants into memory when the destination is a floating-point register.;; That may make a function use a PIC pointer when it didn't before, and we;; cannot change PIC usage (and hence stack layout) so late in the game.;; The resulting sequences for loading cosntants into FPRs are preferable;; even when we're not generating PIC code.(define_insn "*movsi_load" [(set (match_operand:SI 0 "register_operand" "=d,f") (match_operand:SI 1 "frv_load_operand" "m,m"))] "" "* return output_move_single (operands, insn);" [(set_attr "length" "4") (set_attr "type" "gload,fload")])(define_insn "*movsi_internal" [(set (match_operand:SI 0 "move_destination_operand" "=d,d,d,m,m,z,d,d,f,f,m,?f,?z") (match_operand:SI 1 "move_source_operand" "LQ,i,d,d,O,d,z,f,d,f,f,GO,GO"))] "register_operand (operands[0], SImode) || reg_or_0_operand (operands[1], SImode)" "* return output_move_single (operands, insn);" [(set_attr "length" "4,8,4,4,4,4,4,4,4,4,4,4,4") (set_attr "type" "int,multi,int,gstore,gstore,spr,spr,movfg,movgf,fsconv,fstore,movgf,spr")])(define_insn "*movsi_lda_sdata" [(set (match_operand:SI 0 "integer_register_operand" "=d") (plus:SI (match_operand:SI 1 "small_data_register_operand" "d") (match_operand:SI 2 "small_data_symbolic_operand" "Q")))] "" "addi %1, #gprel12(%2), %0" [(set_attr "type" "int") (set_attr "length" "4")]);; Split 2 word load of constants into sethi/setlo instructions(define_split [(set (match_operand:SI 0 "integer_register_operand" "") (match_operand:SI 1 "int_2word_operand" ""))] "reload_completed" [(set (match_dup 0) (high:SI (match_dup 1))) (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 1)))] "")(define_insn "movsi_high" [(set (match_operand:SI 0 "integer_register_operand" "=d") (high:SI (match_operand:SI 1 "int_2word_operand" "i")))] "" "sethi #hi(%1), %0" [(set_attr "type" "sethi") (set_attr "length" "4")])(define_insn "movsi_lo_sum" [(set (match_operand:SI 0 "integer_register_operand" "+d") (lo_sum:SI (match_dup 0) (match_operand:SI 1 "int_2word_operand" "i")))] "" "setlo #lo(%1), %0" [(set_attr "type" "setlo") (set_attr "length" "4")]);; Split loads of addresses with PIC specified into 3 separate instructions(define_insn_and_split "*movsi_pic" [(set (match_operand:SI 0 "integer_register_operand" "=d") (plus:SI (match_operand:SI 1 "pic_register_operand" "d") (match_operand:SI 2 "pic_symbolic_operand" "")))] "" "#" "reload_completed" [(set (match_dup 0) (high:SI (match_dup 2))) (set (match_dup 0) (lo_sum:SI (match_dup 0) (match_dup 2))) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] "" [(set_attr "type" "multi") (set_attr "length" "12")])(define_insn "movsi_high_pic" [(set (match_operand:SI 0 "integer_register_operand" "=d") (high:SI (match_operand:SI 1 "pic_symbolic_operand" "")))]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -