📄 m88k.md
字号:
;; Recognize bcnd instructions for integer values. This is distinguished;; from a conditional branch instruction (below) with SImode instead of;; CCmode.(define_insn "" [(set (pc) (if_then_else (match_operator 0 "relop_no_unsigned" [(match_operand:SI 1 "register_operand" "r") (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%B0,%1,%P2%P3" [(set_attr "type" "branch")]);; Recognize tests for sign and zero.(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(match_operand:SI 1 "register_operand" "r") (const_int -2147483648)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%E0,%1,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(zero_extract:SI (match_operand:SI 1 "register_operand" "r") (const_int 31) (const_int 1)) (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%D0,%1,%P2%P3" [(set_attr "type" "branch")]);; Recognize bcnd instructions for double integer values(define_insn "" [(set (pc) (if_then_else (match_operator 0 "relop_no_unsigned" [(sign_extend:DI (match_operand:SI 1 "register_operand" "r")) (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%B0,%1,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(zero_extend:DI (match_operand:SI 1 "register_operand" "r")) (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%B0,%1,%P2%P3" [(set_attr "type" "branch")]); @@ I doubt this is interesting until cmpdi is provided. Anyway, it needs; to be reworked.;;(define_insn ""; [(set (pc); (if_then_else; (match_operator 0 "relop_no_unsigned"; [(match_operand:DI 1 "register_operand" "r"); (const_int 0)]); (match_operand 2 "pc_or_label_ref" ""); (match_operand 3 "pc_or_label_ref" "")))]; ""; "*;{; switch (GET_CODE (operands[0])); {; case EQ:; case NE:; /* I'm not sure if it's safe to use .n here. */; return \"or %!,%1,%d1\;bcnd %R3%B0,%!,%P2%P3\";; case GE:; case LT:; return \"bcnd%. %R3%B0,%1,%P2%P3\";; case GT:; {; rtx op2 = operands[2];; operands[2] = operands[3];; operands[3] = op2;; }; case LE:; if (GET_CODE (operands[3]) == LABEL_REF); {; int label_num;; operands[2] = gen_label_rtx ();; label_num = XINT (operands[2], 3);; output_asm_insn; (\"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#ne0,%!,%3\", operands);; output_label (label_num);; return \"\";; }; else; return \"bcnd%. %#lt0,%1,%2\;or %!,%1,%d1\;bcnd %#eq0,%!,%2\";; };}");; Recognize bcnd instructions for single precision float values;; Exclude relational operations as they must signal NaNs.;; @@ These bcnd insns for float and double values don't seem to be recognized.(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(float_extend:DF (match_operand:SF 1 "register_operand" "r")) (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%D0,%1,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(match_operand:SF 1 "register_operand" "r") (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bcnd%. %R3%D0,%1,%P2%P3" [(set_attr "type" "branch")]);; Recognize bcnd instructions for double precision float values;; Exclude relational operations as they must signal NaNs.(define_insn "" [(set (pc) (if_then_else (match_operator 0 "equality_op" [(match_operand:DF 1 "register_operand" "r") (const_int 0)]) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "*{ int label_num; if (GET_CODE (operands[0]) == NE) { rtx op2 = operands[2]; operands[2] = operands[3]; operands[3] = op2; } if (GET_CODE (operands[3]) == LABEL_REF) return \"bcnd 0x5,%1,%3\;bcnd %#ne0,%d1,%3\"; operands[3] = gen_label_rtx (); label_num = XINT (operands[3], 3); output_asm_insn (\"bcnd 0x5,%1,%3\;bcnd %#eq0,%d1,%2\", operands); output_label (label_num); return \"\";}" [(set_attr "type" "weird") (set_attr "length" "3")]);; Recognize bb0 and bb1 instructions. These use two unusual template;; patterns, %Lx and %Px. %Lx outputs a 1 if operand `x' is a LABEL_REF;; otherwise it outputs a 0. It then may print ".n" if the delay slot;; is used. %Px does noting if `x' is PC and outputs the operand if `x';; is a LABEL_REF.(define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "int5_operand" "")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bb%L2 (31-%1),%0,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "int5_operand" "")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bb%L3 (31-%1),%0,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "int5_operand" "")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bb%L2 (31-%1),%0,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r") (const_int 1) (match_operand:SI 1 "int5_operand" "")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "" "bb%L3 (31-%1),%0,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (eq (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "(GET_CODE (operands[0]) == CONST_INT) != (GET_CODE (operands[1]) == CONST_INT)" "bb%L3 %p1,%0,%P2%P3" [(set_attr "type" "branch")])(define_insn "" [(set (pc) (if_then_else (ne (and:SI (match_operand:SI 0 "reg_or_bbx_mask_operand" "%r") (match_operand:SI 1 "reg_or_bbx_mask_operand" "n")) (const_int 0)) (match_operand 2 "pc_or_label_ref" "") (match_operand 3 "pc_or_label_ref" "")))] "(GET_CODE (operands[0]) == CONST_INT) != (GET_CODE (operands[1]) == CONST_INT)" "bb%L2 %p1,%0,%P2%P3" [(set_attr "type" "branch")]);; The comparison operations store the comparison into a register and;; record that register. The following Bxx or Sxx insn uses that;; register as an input. To facilitate use of bcnd instead of cmp/bb1,;; cmpsi records its operands and produces no code when any operand;; is constant. In this case, the Bxx insns use gen_bcnd and the;; Sxx insns use gen_test to ensure a cmp has been emitted.;;;; This could also be done for SFmode and DFmode having only beq and bne;; use gen_bcnd. The others must signal NaNs. It seems though that zero;; has already been copied into a register.;;;; cmpsi/beq and cmpsi/bne can always be done with bcnd if any operand;; is a constant. (This idea is due to Torbjorn Granlund.) Others can;; use bcnd only if an operand is zero.;;;; It is necessary to distinguish a register holding condition codes.;; This is done by context.(define_expand "test" [(set (match_dup 2) (compare:CC (match_operand 0 "" "") (match_operand 1 "" "")))] "" "{ if (m88k_compare_reg) abort (); if (GET_CODE (operands[0]) == CONST_INT && ! SMALL_INT (operands[0])) operands[0] = force_reg (SImode, operands[0]); if (GET_CODE (operands[1]) == CONST_INT && ! SMALL_INT (operands[1])) operands[1] = force_reg (SImode, operands[1]); operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);}"); @@ The docs say don't do this. It's probably a nop since the insn looks; identical to cmpsi against zero. Is there an advantage to providing; this, perhaps with a different form?;(define_expand "tstsi"; [(set (match_dup 1); (compare:CC (match_operand:SI 0 "register_operand" ""); (const_int 0)))]; ""; ";{; m88k_compare_reg = 0;; m88k_compare_op0 = operands[0];; m88k_compare_op1 = const0_rtx;; DONE;;}")(define_expand "cmpsi" [(set (match_dup 2) (compare:CC (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "arith32_operand" "")))] "" "{ if (GET_CODE (operands[0]) == CONST_INT || GET_CODE (operands[1]) == CONST_INT) { m88k_compare_reg = 0; m88k_compare_op0 = operands[0]; m88k_compare_op1 = operands[1]; DONE; } operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);}")(define_expand "cmpsf" [(set (match_dup 2) (compare:CC (match_operand:SF 0 "register_operand" "") (match_operand:SF 1 "register_operand" "")))] "" "operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);")(define_expand "cmpdf" [(set (match_dup 2) (compare:CC (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "general_operand" "")))] "" "{ operands[0] = legitimize_operand (operands[0], DFmode); operands[1] = legitimize_operand (operands[1], DFmode); operands[2] = m88k_compare_reg = gen_reg_rtx (CCmode);}"); @@ Get back to this later on.;;(define_insn "cmpdi"; [(set (cc0); (compare:CC (match_operand:DI 0 "register_operand" "r"); (match_operand:DI 1 "register_operand" "r")))]; ""; "*;{; if ((cc_status.mdep & MDEP_LS_CHANGE) != 0); abort (); /* output_move_double MDEP_LS_CHANGE bits were set. */;; cc_status.mdep &= ~ MDEP_LS_MASK;;; operands[2] = gen_label_rtx ();; /* Remember, %! is the condition code register and %@ is the; literal synthesis register. */;; output_asm_insn (\"cmp %!,%0,%1\;bb0 %#eq,%!,%l2\;cmp %!,%d0,%d1\",; operands);;; output_asm_insn (\"extu %@,%!,4<8>\;clr %!,%!,4<4>\", operands);; output_asm_insn (\"mak %@,%@,4<4>\;or %!,%!,%@\", operands);; output_label (XINT (operands[2], 3));; return \"\";;}";; The actual compare instructions.(define_insn "" [(set (match_operand:CC 0 "register_operand" "=r") (compare:CC (match_operand:SI 1 "register_operand" "rO") (match_operand:SI 2 "arith_operand" "rI")))] "" "cmp %0,%r1,%2")(define_insn "" [(set (match_operand:CC 0 "register_operand" "=r,r,r,r") (compare:CC (match_operand:SF 1 "register_operand" "r,r,x,x") (match_operand:SF 2 "real_or_0_operand" "r,G,x,G")))] "" "@ fcmp.sss %0,%1,%2 fcmp.sss %0,%1,%#r0 fcmp.sss %0,%1,%2 fcmp.sss %0,%1,%#x0" [(set_attr "type" "spcmp")])(define_insn "" [(set (match_operand:CC 0 "register_operand" "=r,r") (compare:CC (match_operand:DF 1 "register_operand" "r,x") (float_extend:DF (match_operand:SF 2 "register_operand" "r,x"))))] "" "fcmp.sds %0,%1,%2" [(set_attr "type" "dpcmp")])(define_insn "" [(set (match_operand:CC 0 "register_operand" "=r,r") (compare:CC (float_extend:DF (match_operand:SF 1 "register_operand" "r,x")) (match_operand:DF 2 "register_operand" "r,x")))] "" "fcmp.ssd %0,%1,%2" [(set_attr "type" "dpcmp")])(define_insn ""
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -