From 932657df232f3a98b665dd251db6e6441ab12025 Mon Sep 17 00:00:00 2001 From: Stephane Carrez Date: Fri, 15 Mar 2002 23:04:49 +0100 Subject: [PATCH] m68hc11.c (m68hc11_symbolic_p): New function. * config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function. (m68hc11_indirect_p): New function. (m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12. (m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of TARGET_M6812. (asm_print_register): Likewise. * config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare. (m68hc11_indirect_p): Declare. * config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'. (TARGET_NO_DIRECT_MODE, TARGET_RELAX): New. (TARGET_SWITCHES): New option -mrelax. * config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for destination. ("iorsi3", "xorsi3"): Likewise. ("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand. ("*andhi3_mem"): New to handle destination in memory with bclr and a scratch register. ("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise. ("*andhi3_const"): New when operand2 is constant. ("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise. ("*andhi3_gen"): Cleanup of the old "andhi3". ("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise. ("xorqi3"): Update constraints. From-SVN: r50843 --- gcc/ChangeLog | 26 ++ gcc/config/m68hc11/m68hc11-protos.h | 2 + gcc/config/m68hc11/m68hc11.c | 44 +- gcc/config/m68hc11/m68hc11.h | 9 +- gcc/config/m68hc11/m68hc11.md | 603 ++++++++++++++++++++-------- 5 files changed, 504 insertions(+), 180 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a3619d8ce6d..2aa5993c477 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2002-03-15 Stephane Carrez + + * config/m68hc11/m68hc11.c (m68hc11_symbolic_p): New function. + (m68hc11_indirect_p): New function. + (m68hc11_override_options): Must set MASK_NO_DIRECT_MODE for 68HC12. + (m68hc11_gen_highpart): Use TARGET_NO_DIRECT_MODE instead of + TARGET_M6812. + (asm_print_register): Likewise. + * config/m68hc11/m68hc11-protos.h (m68hc11_symbolic_p): Declare. + (m68hc11_indirect_p): Declare. + * config/m68hc11/m68hc11.h (EXTRA_CONSTRAINT): New constraint 'R', 'Q'. + (TARGET_NO_DIRECT_MODE, TARGET_RELAX): New. + (TARGET_SWITCHES): New option -mrelax. + * config/m68hc11/m68hc11.md ("andsi3"): Allow soft register for + destination. + ("iorsi3", "xorsi3"): Likewise. + ("andhi3", "andqi3", "iorhi3", "iorqi3"): Use a define_expand. + ("*andhi3_mem"): New to handle destination in memory with bclr + and a scratch register. + ("*andqi3_mem", "*iorhi3_mem", "*iorqi3_mem"): Likewise. + ("*andhi3_const"): New when operand2 is constant. + ("*andqi3_const", "*iorhi3_const", "*iorqi3_const"): Likewise. + ("*andhi3_gen"): Cleanup of the old "andhi3". + ("*andqi3_gen", "*iorhi3_gen", "*iorqi3_gen"): Likewise. + ("xorqi3"): Update constraints. + 2002-03-15 Stephane Carrez * config/m68hc11/m68hc11.c (m68hc11_small_indexed_indirect_p): Look diff --git a/gcc/config/m68hc11/m68hc11-protos.h b/gcc/config/m68hc11/m68hc11-protos.h index e974348a317..27358b7b62f 100644 --- a/gcc/config/m68hc11/m68hc11-protos.h +++ b/gcc/config/m68hc11/m68hc11-protos.h @@ -106,6 +106,8 @@ extern void m68hc11_emit_libcall PARAMS((const char*, enum rtx_code, enum machine_mode, enum machine_mode, int, rtx*)); extern int m68hc11_small_indexed_indirect_p PARAMS((rtx, enum machine_mode)); +extern int m68hc11_symbolic_p PARAMS((rtx, enum machine_mode)); +extern int m68hc11_indirect_p PARAMS((rtx, enum machine_mode)); extern int go_if_legitimate_address2 PARAMS((rtx, enum machine_mode, int)); extern int reg_or_indexed_operand PARAMS((rtx,enum machine_mode)); diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c index bcaeae61664..041b596e282 100644 --- a/gcc/config/m68hc11/m68hc11.c +++ b/gcc/config/m68hc11/m68hc11.c @@ -276,6 +276,7 @@ m68hc11_override_options () m68hc11_sp_correction = 0; m68hc11_tmp_regs_class = TMP_REGS; target_flags &= ~MASK_M6811; + target_flags |= MASK_NO_DIRECT_MODE; if (m68hc11_soft_reg_count == 0) m68hc11_soft_reg_count = "2"; } @@ -926,6 +927,42 @@ reg_or_some_mem_operand (operand, mode) return register_operand (operand, mode); } +int +m68hc11_symbolic_p (operand, mode) + rtx operand; + enum machine_mode mode; +{ + if (GET_CODE (operand) == MEM) + { + rtx op = XEXP (operand, 0); + + if (symbolic_memory_operand (op, mode)) + return 1; + } + return 0; +} + +int +m68hc11_indirect_p (operand, mode) + rtx operand; + enum machine_mode mode; +{ + if (GET_CODE (operand) == MEM) + { + rtx op = XEXP (operand, 0); + + if (symbolic_memory_operand (op, mode)) + return 0; + + if (reload_in_progress) + return 1; + + operand = XEXP (operand, 0); + return register_indirect_p (operand, mode, reload_completed); + } + return 0; +} + int stack_register_operand (operand, mode) rtx operand; @@ -1950,8 +1987,9 @@ m68hc11_gen_highpart (mode, x) { int pos; - /* For 68HC12, avoid the '*' for direct addressing mode. */ - pos = TARGET_M6812 ? 1 : 0; + /* Avoid the '*' for direct addressing mode when this + addressing mode is disabled. */ + pos = TARGET_NO_DIRECT_MODE ? 1 : 0; return gen_rtx (MEM, QImode, gen_rtx (SYMBOL_REF, Pmode, ®_names[REGNO (x)][pos])); @@ -2079,7 +2117,7 @@ asm_print_register (file, regno) { const char *name = reg_names[regno]; - if (TARGET_M6812 && name[0] == '*') + if (TARGET_NO_DIRECT_MODE && name[0] == '*') name++; asm_fprintf (file, "%s", name); diff --git a/gcc/config/m68hc11/m68hc11.h b/gcc/config/m68hc11/m68hc11.h index ee2a805b2ef..865e2ebd424 100644 --- a/gcc/config/m68hc11/m68hc11.h +++ b/gcc/config/m68hc11/m68hc11.h @@ -118,12 +118,15 @@ extern short *reg_renumber; /* def in local_alloc.c */ #define MASK_AUTO_INC_DEC 0004 #define MASK_M6811 0010 #define MASK_M6812 0020 +#define MASK_NO_DIRECT_MODE 0040 #define TARGET_OP_TIME (optimize && optimize_size == 0) #define TARGET_SHORT (target_flags & MASK_SHORT) #define TARGET_M6811 (target_flags & MASK_M6811) #define TARGET_M6812 (target_flags & MASK_M6812) #define TARGET_AUTO_INC_DEC (target_flags & MASK_AUTO_INC_DEC) +#define TARGET_NO_DIRECT_MODE (target_flags & MASK_NO_DIRECT_MODE) +#define TARGET_RELAX (TARGET_NO_DIRECT_MODE) /* Default target_flags if no switches specified. */ #ifndef TARGET_DEFAULT @@ -156,6 +159,8 @@ extern short *reg_renumber; /* def in local_alloc.c */ N_("Auto pre/post decrement increment allowed")}, \ { "noauto-incdec", - MASK_AUTO_INC_DEC, \ N_("Auto pre/post decrement increment not allowed")}, \ + { "relax", MASK_NO_DIRECT_MODE, \ + N_("Do not use direct addressing mode for soft registers")},\ { "68hc11", MASK_M6811, \ N_("Compile for a 68HC11")}, \ { "68hc12", MASK_M6812, \ @@ -830,7 +835,9 @@ extern enum reg_class m68hc11_tmp_regs_class; /* 'U' represents certain kind of memory indexed operand for 68HC12. and any memory operand for 68HC11. */ #define EXTRA_CONSTRAINT(OP, C) \ -((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) : 0) +((C) == 'U' ? m68hc11_small_indexed_indirect_p (OP, GET_MODE (OP)) \ + : (C) == 'Q' ? m68hc11_symbolic_p (OP, GET_MODE (OP)) \ + : (C) == 'R' ? m68hc11_indirect_p (OP, GET_MODE (OP)) : 0) diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index 7f13e69cfb0..1871d47e6d2 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -65,9 +65,20 @@ ;; ;; Other constraints: ;; -;; T an operand that can be accessed with 68HC1X direct addressing -;; mode. For 68HC11 this includes the pseudo soft registers and -;; any memory operand that is a direct addressing (.page0). +;; Q an operand which is in memory but whose address is constant +;; (ie, a (MEM (SYMBOL_REF x))). This constraint is used by +;; bset/bclr instructions together with linker relaxation. The +;; operand can be translated to a page0 addressing mode if the +;; symbol address is in page0 (0..255). +;; +;; R an operand which is in memory and whose address is expressed +;; with 68HC11/68HC12 indexed addressing mode. In general this +;; is any valid (MEM) except a (MEM (SYMBOL_REF x)). +;; +;; U an operand which is in memory and if it uses the 68HC12 indexed +;; addressing mode, the offset is in the range -16..+15. This is +;; used by 68HC12 movb/movw instructions since they do not accept +;; the full 16-bit offset range (as other insn do). ;; ;; ;; Immediate integer operand constraints: @@ -94,9 +105,9 @@ ;; some values in bad registers. ;; ;; 32/64-bit Patterns: -;; The 68HC11 does not support 32/64-bit operations. Most of the +;; The 68HC11 does not support 32/64-bit operations. Most of the ;; 32/64-bit patterns are defined to split the instruction in -;; 16-bits patterns. Providing split patterns generates better code +;; 16-bits patterns. Providing split patterns generates better code ;; than letting GCC implement the 32/64-bit operation itself. ;; ;; @@ -111,7 +122,7 @@ ;; them correctly (it would treat the X, Y or D register as dead sometimes). ;; ;; o Some split pattern generate instructions that operate on 'a' or 'b' -;; register directory (high part and low part of D respectively). +;; register directly (high part and low part of D respectively). ;; Such split pattern must also be valid when z_replacement_completed == 2 ;; because flow/cse is not aware that D is composed of {a, b}. ;; @@ -3027,139 +3038,261 @@ "#") (define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (and:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (and:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" "#") -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A") - (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))] +(define_expand "andhi3" + [(set (match_operand:HI 0 "register_operand" "") + (and:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + "") + +(define_insn "*andhi3_mem" + [(set (match_operand:HI 0 "memory_operand" "=Q,R") + (and:HI (match_dup 0) + (match_operand:HI 1 "immediate_operand" "i,i"))) + (clobber (match_scratch:HI 2 "=xy,X"))] + "TARGET_RELAX && !TARGET_M6812" + "* +{ + int val = INTVAL (operands[1]) & 0x0FFFF; + + if (val == 0x0ffff) + { + cc_status = cc_prev_status; + return \"\"; + } + + CC_STATUS_INIT; + + /* The bclr instruction uses an inverted mask. */ + operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FFFF); + + /* When destination is a global variable, generate a .relax instruction + and load the address in the clobber register. That load can be + eliminated by the linker if the address is in page0. */ + if (which_alternative == 0) + { + rtx ops[3]; + + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + if ((val & 0x0FF) != 0x0FF) + output_asm_insn (\"bclr\\t1,%2, %b1\", operands); + + if ((val & 0x0FF00) != 0x0FF00) + output_asm_insn (\"bclr\\t0,%2, %h1\", operands); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + + if ((val & 0x0FF) != 0x0FF) + output_asm_insn (\"bclr\\t%b0, %b1\", operands); + + if ((val & 0x0FF00) != 0x0FF00) + output_asm_insn (\"bclr\\t%h0, %h1\", operands); + + return \"\"; +}") + +(define_insn "*andhi3_const" + [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") + (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:HI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FFFF; + int lowpart_zero = 0; + int highpart_zero = 0; + int lowpart_unknown = 0; + int highpart_unknown = 0; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0x0ffff) + { + cc_status = cc_prev_status; + return \"\"; + } + + /* First, try to clear the low and high part. + If that's possible, the second 'and' will give + the good status flags and we can avoid a tsthi. */ + if ((val & 0x0FF) == 0) + { + if (D_REG_P (operands[0])) + output_asm_insn (\"clrb\", operands); + else + output_asm_insn (\"clr\\t%b0\", operands); + lowpart_zero = 1; + } + if ((val & 0x0FF00) == 0) + { + if (D_REG_P (operands[0])) + output_asm_insn (\"clra\", operands); + else + output_asm_insn (\"clr\\t%h0\", operands); + highpart_zero = 1; + } + + if ((val & 0x0FF) == 0x0FF) + { + lowpart_unknown = 1; + } + else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0])) + { + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); + output_asm_insn (\"bclr\\t%b0, %1\", ops); + } + else if ((val & 0x0FF) != 0) + { + output_asm_insn (\"andb\\t%b2\", operands); + } + + if ((val & 0x0FF00) == 0x0FF00) + { + highpart_unknown = 1; + } + else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0])) + { + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8); + output_asm_insn (\"bclr\\t%h0, %1\", ops); + } + else if ((val & 0x0FF00) != 0) + { + output_asm_insn (\"anda\\t%h2\", operands); + } + + if (highpart_unknown || lowpart_unknown) + CC_STATUS_INIT; + else if (highpart_zero == 0 && lowpart_zero == 0) + CC_STATUS_INIT; + + return \"\"; +}") + +(define_insn "*andhi3_gen" + [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") + (and:HI (match_operand:HI 1 "register_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))] "" "* { if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) - { - int val = INTVAL (operands[2]) & 0x0FFFF; - char lowpart_zero = 0; - char lowpart_unknown = 0; - char highpart_zero = 0; - char highpart_unknown = 0; - - if (val == 0xFFFF) - { - cc_status = cc_prev_status; - return \"\"; - } - - /* First, try to clear the low and high part. - If that's possible, the second 'and' will give - the good status flags and we can avoid a tsthi. */ - if ((val & 0x0FF) == 0) - { - if (D_REG_P (operands[0])) - output_asm_insn (\"clrb\", operands); - else - output_asm_insn (\"clr\\t%b0\", operands); - lowpart_zero = 1; - } - if ((val & 0x0FF00) == 0) - { - if (D_REG_P (operands[0])) - output_asm_insn (\"clra\", operands); - else - output_asm_insn (\"clr\\t%h0\", operands); - highpart_zero = 1; - } - - if ((val & 0x0FF) == 0x0FF) - { - lowpart_unknown = 1; - } - else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0])) - { - rtx ops[2]; - - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); - output_asm_insn (\"bclr\\t%b0, %1\", ops); - } - else if ((val & 0x0FF) != 0) - { - output_asm_insn (\"andb\\t%b2\", operands); - } - - if ((val & 0x0FF00) == 0x0FF00) - { - highpart_unknown = 1; - } - else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0])) - { - rtx ops[2]; - - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8); - output_asm_insn (\"bclr\\t%h0, %1\", ops); - } - else if ((val & 0x0FF00) != 0) - { - output_asm_insn (\"anda\\t%h2\", operands); - } - - if (highpart_unknown || lowpart_unknown) - CC_STATUS_INIT; - else if (highpart_zero == 0 && lowpart_zero == 0) - CC_STATUS_INIT; - - return \"\"; - } - CC_STATUS_INIT; return \"andb\\t%b2\\n\\tanda\\t%h2\"; }") -(define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q") - (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))] +(define_expand "andqi3" + [(set (match_operand:QI 0 "register_operand" "") + (and:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "" + "") + +(define_insn "*andqi3_mem" + [(set (match_operand:QI 0 "memory_operand" "=Q,R") + (and:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" "i,i"))) + (clobber (match_scratch:HI 2 "=xy,X"))] + "TARGET_RELAX && !TARGET_M6812" + "* +{ + int val = INTVAL (operands[1]) & 0x0FF; + + if (val == 0x0ff) + { + cc_status = cc_prev_status; + return \"\"; + } + + /* The bclr instruction uses an inverted mask. */ + operands[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); + + /* When destination is a global variable, generate a .relax instruction + and load the address in the clobber register. That load can be + eliminated by the linker if the address is in page0. */ + if (which_alternative == 0) + { + rtx ops[3]; + + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + output_asm_insn (\"bclr\\t0,%2, %1\", operands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + return \"bclr\\t%b0, %1\"; +}") + +(define_insn "*andqi3_const" + [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") + (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:QI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FF; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0x0ff) + { + cc_status = cc_prev_status; + return \"\"; + } + if (!H_REG_P (operands[0])) + { + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); + output_asm_insn (\"bclr\\t%b0, %b1\", ops); + return \"\"; + } + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) + return \"andb\\t%b2\"; + else if (DA_REG_P (operands[0])) + return \"anda\\t%b2\"; + else + fatal_insn (\"Invalid operand in the instruction\", insn); +}") + +(define_insn "*andqi3_gen" + [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") + (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") + (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))] "" "* { if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) - { - int val = INTVAL (operands[2]) & 0x0FF; - - if (val == 0xFF) - { - cc_status = cc_prev_status; - return \"\"; - } - if (val == 0) - { - if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) - return \"clrb\"; - else if (DA_REG_P (operands[0])) - return \"clra\"; - else - return \"clr\\t%b0\"; - } - if (!H_REG_P (operands[0])) - { - rtx ops[2]; - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); - output_asm_insn (\"bclr\\t%b0, %b1\", ops); - return \"\"; - } - } if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) return \"andb\\t%b2\"; else if (DA_REG_P (operands[0])) @@ -3181,79 +3314,177 @@ "#") (define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (ior:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" "#") -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A") - (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))] +(define_expand "iorhi3" + [(set (match_operand:HI 0 "register_operand" "") + (ior:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + "") + +(define_insn "*iorhi3_mem" + [(set (match_operand:HI 0 "memory_operand" "=Q,R") + (ior:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (clobber (match_scratch:HI 2 "=xy,X"))] + "TARGET_RELAX && !TARGET_M6812" + "* +{ + int val = INTVAL (operands[1]) & 0x0FFFF; + + if (val == 0) + { + cc_status = cc_prev_status; + return \"\"; + } + CC_STATUS_INIT; + if (which_alternative == 0) + { + rtx ops[3]; + + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + if ((val & 0x0FF) != 0) + output_asm_insn (\"bset\\t1,%2, %b1\", operands); + + if ((val & 0x0FF00) != 0) + output_asm_insn (\"bset\\t0,%2, %h1\", operands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + + if ((val & 0x0FF) != 0) + output_asm_insn (\"bset\\t%b0, %b1\", operands); + + if ((val & 0x0FF00) != 0) + output_asm_insn (\"bset\\t%h0, %h1\", operands); + + return \"\"; +}") + +(define_insn "*iorhi3_const" + [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") + (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:HI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FFFF; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0) + { + cc_status = cc_prev_status; + return \"\"; + } + + if ((val & 0x0FF) != 0) + { + if (!H_REG_P (operands[0])) + output_asm_insn (\"bset\\t%b0, %b2\", operands); + else + output_asm_insn (\"orab\\t%b2\", operands); + } + + if ((val & 0x0FF00) != 0) + { + if (!H_REG_P (operands[0])) + output_asm_insn (\"bset\\t%h0, %h2\", operands); + else + output_asm_insn (\"oraa\\t%h2\", operands); + } + + CC_STATUS_INIT; + return \"\"; +}") + +(define_insn "*iorhi3_gen" + [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") + (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0") + (match_operand:HI 2 "general_operand" "mi,!u*A,!um*A")))] "" "* { if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) - { - int val = INTVAL (operands[2]) & 0x0FFFF; - - if (val == 0) - { - cc_status = cc_prev_status; - return \"\"; - } - if ((val & 0x0FF) != 0) - { - if (!H_REG_P (operands[0])) - output_asm_insn (\"bset\\t%b0, %b2\", operands); - else - output_asm_insn (\"orab\\t%b2\", operands); - } - - if ((val & 0x0FF00) != 0) - { - if (!H_REG_P (operands[0])) - output_asm_insn (\"bset\\t%h0, %h2\", operands); - else - output_asm_insn (\"oraa\\t%h2\", operands); - } - - CC_STATUS_INIT; - return \"\"; - } - CC_STATUS_INIT; return \"orab\\t%b2\\n\\toraa\\t%h2\"; }") -(define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q") - (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))] +(define_expand "iorqi3" + [(set (match_operand:QI 0 "register_operand" "") + (ior:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "" + "") + +(define_insn "*iorqi3_mem" + [(set (match_operand:QI 0 "memory_operand" "=Q,R") + (ior:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" ""))) + (clobber (match_scratch:HI 2 "=xy,X"))] + "TARGET_RELAX && !TARGET_M6812" + "* +{ + int val = INTVAL (operands[1]) & 0x0FF; + + if (val == 0) + { + cc_status = cc_prev_status; + return \"\"; + } + if (which_alternative == 0) + { + rtx ops[3]; + + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + output_asm_insn (\"bset\\t0,%2, %1\", operands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + return \"bset\\t%b0, %1\"; +}") + +(define_insn "*iorqi3_const" + [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") + (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:QI 2 "const_int_operand" "")))] "" "* { + int val = INTVAL (operands[2]) & 0x0FF; + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) + if (val == 0) { - int val = INTVAL (operands[2]) & 0x0FF; - - if (val == 0) - { - cc_status = cc_prev_status; - return \"\"; - } - if (!H_REG_P (operands[0])) - { - return \"bset\\t%b0, %2\"; - } + cc_status = cc_prev_status; + return \"\"; } + if (!H_REG_P (operands[0])) + { + return \"bset\\t%b0, %2\"; + } + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) return \"orab\\t%b2\"; else if (DA_REG_P (operands[0])) @@ -3262,6 +3493,25 @@ fatal_insn (\"Invalid operand in the instruction\", insn); }") +(define_insn "*iorqi3_gen" + [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") + (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") + (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))] + "" + "* +{ + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) + return \"orab\\t%b2\"; + else if (DA_REG_P (operands[0])) + return \"oraa\\t%b2\"; + else + fatal_insn (\"Invalid operand in the instruction\", insn); +}") + + ;;-------------------------------------------------------------------- ;;- xor instructions. ;;-------------------------------------------------------------------- @@ -3275,9 +3525,10 @@ "#") (define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (xor:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" "#") @@ -3329,7 +3580,7 @@ (define_insn "xorqi3" [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))] + (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))] "" "* {