From aee10b6405072d7783d4613b7c31492b419ae512 Mon Sep 17 00:00:00 2001 From: ciceron Date: Fri, 4 May 2001 18:22:00 +0000 Subject: [PATCH] * config/m68hc11/m68hc11.md (*tbne, *tbeq): New patterns for 68HC12. (extendqisi2, extendqihi2, extendhisi2): Use sex for 68HC12. (uminqi3, umaxqi3, uminhi3, umaxhi3): New pattern for 68HC12. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@41836 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 ++ gcc/config/m68hc11/m68hc11.md | 215 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 215 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 47cdf86..5d4139a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2001-05-04 Stephane Carrez + * config/m68hc11/m68hc11.md (*tbne, *tbeq): New patterns for 68HC12. + (extendqisi2, extendqihi2, extendhisi2): Use sex for 68HC12. + (uminqi3, umaxqi3, uminhi3, umaxhi3): New pattern for 68HC12. + +2001-05-04 Stephane Carrez + * config/m68hc11/m68hc11.h (CONST_COSTS): Make the cost of constants cheap after reload. * config/m68hc11/m68hc11.c (m68hc11_shift_cost): Shift by 16 and 32 diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index a4380c3..46bfad8 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -1273,6 +1273,20 @@ rtx ops[3]; int need_tst = 0; + /* The 68HC12 has a sign-extension instruction. Use it when the + destination is the register (X,D). First sign-extend the low + part and fill X with the sign-extension of the high part. */ + if (TARGET_M6812 && X_REG_P (operands[0])) + { + if (!D_REG_P (operands[1])) + { + ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); + ops[1] = operands[1]; + m68hc11_gen_movqi (insn, ops); + } + return \"sex\\tb,d\\n\\tsex\\ta,x\"; + } + ops[2] = gen_label_rtx (); if (X_REG_P (operands[1])) @@ -1368,6 +1382,16 @@ ops[0] = gen_label_rtx (); if (D_REG_P (operands[0])) { + if (TARGET_M6812) + { + if (!D_REG_P (operands[1])) + { + ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); + ops[1] = operands[1]; + m68hc11_gen_movqi (insn, ops); + } + return \"sex\\tb,d\"; + } output_asm_insn (\"clra\", operands); if (H_REG_P (operands[1])) { @@ -1426,14 +1450,12 @@ "* { extern rtx ix_reg; - rtx ops[1]; + rtx ops[2]; int x_reg_used; if (Y_REG_P (operands[1])) return \"#\"; - ops[0] = gen_label_rtx (); - if (X_REG_P (operands[1])) { output_asm_insn (\"xgdx\", operands); @@ -1446,9 +1468,29 @@ x_reg_used = reg_mentioned_p (ix_reg, operands[1]); if (x_reg_used) { - output_asm_insn (\"ldd\\t%1\", operands); + ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = operands[1]; + m68hc11_gen_movhi (insn, ops); } } + + CC_STATUS_INIT; + if (TARGET_M6812 && 0) + { + /* This sequence of code is larger than the one for 68HC11. + Don't use it; keep it for documentation. */ + if (!D_REG_P (operands[1]) && !x_reg_used) + { + ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = operands[1]; + m68hc11_gen_movhi (insn, ops); + } + output_asm_insn (\"sex\\ta,x\", operands); + output_asm_insn (\"xgdx\", operands); + output_asm_insn (\"sex\\ta,d\", operands); + return \"xgdx\"; + } + output_asm_insn (\"ldx\\t#0\", operands); if (D_REG_P (operands[1]) || x_reg_used) { @@ -1456,18 +1498,107 @@ } else { - output_asm_insn (\"ldd\\t%1\", operands); + ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = operands[1]; + m68hc11_gen_movhi (insn, ops); } + + ops[0] = gen_label_rtx (); output_asm_insn (\"bpl\\t%l0\", ops); output_asm_insn (\"dex\", operands); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); - CC_STATUS_INIT; return \"\"; }") ;;-------------------------------------------------------------------- +;;- Min and Max instructions (68HC12). +;;-------------------------------------------------------------------- +(define_insn "uminqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") + (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "m,d")))] + "TARGET_M6812" + "* +{ + /* Flags are set according to (sub:QI (operand 1) (operand2)). + The mina/minm use A as the source or destination. This is the + high part of D. There is no way to express that in the pattern + so we must use 'exg a,b' to put the operand in the good register. */ + CC_STATUS_INIT; + if (D_REG_P (operands[0])) + { + return \"exg\\ta,b\\n\\tmina\\t%2\\n\\texg\\ta,b\"; + } + else + { + return \"exg\\ta,b\\n\\tminm\\t%0\\n\\texg\\ta,b\"; + } +}") + +(define_insn "umaxqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") + (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "m,d")))] + "TARGET_M6812" + "* +{ + /* Flags are set according to (sub:QI (operand 1) (operand2)). + The maxa/maxm use A as the source or destination. This is the + high part of D. There is no way to express that in the pattern + so we must use 'exg a,b' to put the operand in the good register. */ + CC_STATUS_INIT; + if (D_REG_P (operands[0])) + { + return \"exg\\ta,b\\n\\tmaxa\\t%2\\n\\texg\\ta,b\"; + } + else + { + return \"exg\\ta,b\\n\\tmaxm\\t%0\\n\\texg\\ta,b\"; + } +}") + +(define_insn "uminhi3" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") + (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "m,d")))] + "TARGET_M6812" + "* +{ + /* Flags are set according to (sub:HI (operand 1) (operand2)). */ + CC_STATUS_INIT; + if (D_REG_P (operands[0])) + { + return \"emind\\t%2\"; + } + else + { + return \"eminm\\t%0\"; + } +}") + +(define_insn "umaxhi3" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") + (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "m,d")))] + "TARGET_M6812" + "* +{ + /* Flags are set according to (sub:HI (operand 1) (operand2)). */ + CC_STATUS_INIT; + if (D_REG_P (operands[0])) + { + return \"emaxd\\t%2\"; + } + else + { + return \"emaxm\\t%0\"; + } +}") + + +;;-------------------------------------------------------------------- ;;- Add instructions. ;;-------------------------------------------------------------------- ;; 64-bit: Use a library call because what GCC generates is huge. @@ -5218,6 +5349,78 @@ DONE; }") +;; +;; Test and branch instructions for 68HC12 for EQ and NE. +;; 'z' must not appear in the constraints because the z replacement +;; pass does not know how to restore the replacement register. +;; +(define_insn "*tbeq" + [(set (pc) + (if_then_else (eq (match_operand:HI 0 "register_operand" "dxy") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_M6812" + "* +{ + /* If the flags are already set correctly, use 'bne/beq' which are + smaller and a little bit faster. This happens quite often due + to reloading of operands[0]. In that case, flags are set correctly + due to the load instruction. */ + if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + return \"beq\\t%l1\"; + else + return \"tbeq\\t%0,%l1\"; +}") + +(define_insn "*tbne" + [(set (pc) + (if_then_else (ne (match_operand:HI 0 "register_operand" "dxy") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_M6812" + "* +{ + if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + return \"bne\\t%l1\"; + else + return \"tbne\\t%0,%l1\"; +}") + +;; +;; Test and branch with 8-bit register. Register must be B (or A). +;; +(define_insn "*tbeq8" + [(set (pc) + (if_then_else (eq (match_operand:QI 0 "register_operand" "d") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_M6812" + "* +{ + if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + return \"beq\\t%l1\"; + else + return \"tbeq\\tb,%l1\"; +}") + +(define_insn "*tbne8" + [(set (pc) + (if_then_else (ne (match_operand:QI 0 "register_operand" "d") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "TARGET_M6812" + "* +{ + if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + return \"bne\\t%l1\"; + else + return \"tbne\\tb,%l1\"; +}") + (define_insn "*beq" [(set (pc) (if_then_else (eq (cc0) -- 2.7.4