📄 vax.md
字号:
(const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" "jlequ %l0");; Recognize reversed jumps.(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(cc0) (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "" "j%C0 %l1") ; %C0 negates condition;; Recognize jbs, jlbs, jbc and jlbc instructions. Note that the operand;; of jlbs and jlbc insns are SImode in the hardware. However, if it is;; memory, we use QImode in the insn. So we can't use those instructions;; for mode-dependent addresses.(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,g") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbs %0,%l2 jbs %1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,g") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbc %0,%l2 jbc %1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbs %0,%l2 jbs %1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r,r") (const_int 1) (match_operand:SI 1 "general_operand" "I,g")) (const_int 0)) (label_ref (match_operand 2 "" "")) (pc)))] "" "@ jlbc %0,%l2 jbc %1,%0,%l2");; Subtract-and-jump and Add-and-jump insns.;; These are not used when output is for the Unix assembler;; because it does not know how to modify them to reach far.;; Normal sob insns.(define_insn "" [(set (pc) (if_then_else (gt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "!TARGET_UNIX_ASM" "jsobgtr %0,%l1")(define_insn "" [(set (pc) (if_then_else (ge (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "!TARGET_UNIX_ASM" "jsobgeq %0,%l1");; Normal aob insns. Define a version for when operands[1] is a constant.(define_insn "" [(set (pc) (if_then_else (lt (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM" "jaoblss %1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (lt (match_operand:SI 0 "nonimmediate_operand" "+g") (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM && GET_CODE (operands[1]) == CONST_INT" "jaoblss %P1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (le (plus:SI (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int 1)) (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM" "jaobleq %1,%0,%l2")(define_insn "" [(set (pc) (if_then_else (le (match_operand:SI 0 "nonimmediate_operand" "+g") (match_operand:SI 1 "general_operand" "g")) (label_ref (match_operand 2 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))] "!TARGET_UNIX_ASM && GET_CODE (operands[1]) == CONST_INT" "jaobleq %P1,%0,%l2");; Something like a sob insn, but compares against -1.;; This finds `while (foo--)' which was changed to `while (--foo != -1)'.(define_insn "" [(set (pc) (if_then_else (ne (match_operand:SI 0 "nonimmediate_operand" "+g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "" "decl %0\;jgequ %l1")(define_expand "call_pop" [(parallel [(call (match_operand:QI 0 "memory_operand" "") (match_operand:SI 1 "const_int_operand" "")) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 3 "immediate_operand" "")))])] ""{ if (INTVAL (operands[3]) > 255 * 4 || INTVAL (operands[3]) % 4) abort (); /* Operand 1 is the number of bytes to be popped by DW_CFA_GNU_args_size during EH unwinding. We must include the argument count pushed by the calls instruction. */ operands[1] = GEN_INT (INTVAL (operands[3]) + 4);})(define_insn "*call_pop" [(call (match_operand:QI 0 "memory_operand" "m") (match_operand:SI 1 "const_int_operand" "n")) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 2 "immediate_operand" "i")))] ""{ operands[1] = GEN_INT ((INTVAL (operands[1]) - 4) / 4); return "calls %1,%0";})(define_expand "call_value_pop" [(parallel [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "") (match_operand:SI 2 "const_int_operand" ""))) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 4 "immediate_operand" "")))])] ""{ if (INTVAL (operands[4]) > 255 * 4 || INTVAL (operands[4]) % 4) abort (); /* Operand 2 is the number of bytes to be popped by DW_CFA_GNU_args_size during EH unwinding. We must include the argument count pushed by the calls instruction. */ operands[2] = GEN_INT (INTVAL (operands[4]) + 4);})(define_insn "*call_value_pop" [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:SI 2 "const_int_operand" "n"))) (set (reg:SI 14) (plus:SI (reg:SI 14) (match_operand:SI 3 "immediate_operand" "i")))] "" "*{ operands[2] = GEN_INT ((INTVAL (operands[2]) - 4) / 4); return \"calls %2,%1\";}")(define_expand "call" [(call (match_operand:QI 0 "memory_operand" "") (match_operand:SI 1 "const_int_operand" ""))] "" "{ /* Operand 1 is the number of bytes to be popped by DW_CFA_GNU_args_size during EH unwinding. We must include the argument count pushed by the calls instruction. */ operands[1] = GEN_INT (INTVAL (operands[1]) + 4);}")(define_insn "*call" [(call (match_operand:QI 0 "memory_operand" "m") (match_operand:SI 1 "const_int_operand" ""))] "" "calls $0,%0")(define_expand "call_value" [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "") (match_operand:SI 2 "const_int_operand" "")))] "" "{ /* Operand 2 is the number of bytes to be popped by DW_CFA_GNU_args_size during EH unwinding. We must include the argument count pushed by the calls instruction. */ operands[2] = GEN_INT (INTVAL (operands[2]) + 4);}")(define_insn "*call_value" [(set (match_operand 0 "" "") (call (match_operand:QI 1 "memory_operand" "m") (match_operand:SI 2 "const_int_operand" "")))] "" "calls $0,%1");; Call subroutine returning any type.(define_expand "untyped_call" [(parallel [(call (match_operand 0 "" "") (const_int 0)) (match_operand 1 "" "") (match_operand 2 "" "")])] "" "{ int i; emit_call_insn (gen_call_pop (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { rtx set = XVECEXP (operands[2], 0, i); emit_move_insn (SET_DEST (set), SET_SRC (set)); } /* The optimizer does not know that the call sets the function value registers we stored in the result block. We avoid problems by claiming that all hard registers are used and clobbered at this point. */ emit_insn (gen_blockage ()); DONE;}");; UNSPEC_VOLATILE is considered to use and clobber all hard registers and;; all of memory. This blocks insns from being moved across this point.(define_insn "blockage" [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)] "" "")(define_insn "return" [(return)] "" "ret")(define_expand "epilogue" [(return)] "" "{ emit_jump_insn (gen_return ()); DONE;}")(define_insn "nop" [(const_int 0)] "" "nop");; This had a wider constraint once, and it had trouble.;; If you are tempted to try `g', please don't--it's not worth;; the risk we will reopen the same bug.(define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "register_operand" "r"))] "" "jmp (%0)");; This is here to accept 5 arguments (as passed by expand_end_case);; and pass the first 4 along to the casesi1 pattern that really does;; the actual casesi work. We emit a jump here to the default label;; _before_ the casesi so that we can be sure that the casesi never;; drops through.;; This is suboptimal perhaps, but so is much of the rest of this;; machine description. For what it's worth, HPPA uses the same trick.;;;; operand 0 is index;; operand 1 is the minimum bound (a const_int);; operand 2 is the maximum bound - minimum bound + 1 (also a const_int);; operand 3 is CODE_LABEL for the table;;; operand 4 is the CODE_LABEL to go to if index out of range (ie. default).;;;; We emit:;; i = index - minimum_bound;; if (i > (maximum_bound - minimum_bound + 1) goto default;;; casesi (i, 0, table);;;(define_expand "casesi" [(match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "") (match_operand 3 "" "") (match_operand 4 "" "")] ""{ /* i = index - minimum_bound; But only if the lower bound is not already zero. */ if (operands[1] != const0_rtx) { rtx index = gen_reg_rtx (SImode); emit_insn (gen_addsi3 (index, operands[0], GEN_INT (-INTVAL (operands[1])))); operands[0] = index; } /* if (i > (maximum_bound - minimum_bound + 1) goto default; */ emit_insn (gen_cmpsi (operands[0], operands[2])); emit_jump_insn (gen_bgtu (operands[4])); /* casesi (i, 0, table); */ emit_jump_insn (gen_casesi1 (operands[0], operands[2], operands[3])); DONE;});; This insn is a bit of a lier. It actually falls through if no case;; matches. But, we prevent that from ever happening by emiting a jump;; before this, see the define_expand above.(define_insn "casesi1" [(match_operand:SI 1 "const_int_operand" "n") (set (pc) (plus:SI (sign_extend:SI (mem:HI (plus:SI (mult:SI (match_operand:SI 0 "general_operand" "g") (const_int 2)) (pc)))) (label_ref:SI (match_operand 2 "" ""))))] "" "casel %0,$0,%1");;- load or push effective address ;; These come after the move and add/sub patterns;; because we don't want pushl $1 turned into pushad 1.;; or addl3 r1,r2,r3 turned into movab 0(r1)[r2],r3.;; It does not work to use constraints to distinguish pushes from moves,;; because < matches any autodecrement, not just a push.(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:QI 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushab %a1\"; else return \"movab %a1,%0\";}")(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:HI 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushaw %a1\"; else return \"movaw %a1,%0\";}")(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:SI 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushal %a1\"; else return \"moval %a1,%0\";}")(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:DI 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushaq %a1\"; else return \"movaq %a1,%0\";}")(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:SF 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushaf %a1\"; else return \"movaf %a1,%0\";}")(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=g") (match_operand:DF 1 "address_operand" "p"))] "" "*{ if (push_operand (operands[0], SImode)) return \"pushad %a1\"; else return \"movad %a1,%0\";}");; These used to be peepholes, but it is more straightforward to do them;; as single insns. However, we must force the output to be a register;; if it is not an offsettable address so that we know that we can assign;; to it twice. ;; If we had a good way of evaluating the relative costs, these could be;; machine-independent.;; Optimize extzv ...,z; andl2 ...,z;; or ashl ...,z; andl2 ...,z;; with other operands constant. This is what the combiner converts the;; above sequences to before attempting to recognize the new insn.(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=ro") (and:SI (ashiftrt:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "(INTVAL (operands[3]) & ~((1 << (32 - INTVAL (operands[2]))) - 1)) == 0" "*{ unsigned long mask1 = INTVAL (operands[3]); unsigned long mask2 = (1 << (32 - INTVAL (operands[2]))) - 1; if ((mask1 & mask2) != mask1) operands[3] = GEN_INT (mask1 & mask2); return \"rotl %R2,%1,%0\;bicl2 %N3,%0\";}");; left-shift and mask;; The only case where `ashl' is better is if the mask only turns off;; bits that the ashl would anyways, in which case it should have been;; optimized away.(define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" "=ro") (and:SI (ashift:SI (match_operand:SI 1 "general_operand" "g") (match_operand:QI 2 "const_int_operand" "n")) (match_operand:SI 3 "const_int_operand" "n")))] "" "*{ operands[3] = GEN_INT (INTVAL (operands[3]) & ~((1 << INTVAL (operands[2])) - 1)); return \"rotl %2,%1,%0\;bicl2 %N3,%0\";}");; Instruction sequence to sync the VAX instruction stream.(define_insn "sync_istream" [(unspec_volatile [(const_int 0)] VUNSPEC_SYNC_ISTREAM)] "" "movpsl -(%|sp)\;pushal 1(%|pc)\;rei")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -